https://github.com/torvalds/linux
Revision 40fea92ffb5fa0ef26d10ae0fe5688bc8e61c791 authored by Stephen Boyd on 13 August 2013, 21:12:40 UTC, committed by Rafael J. Wysocki on 13 August 2013, 22:42:05 UTC
pm_qos_update_request_timeout() updates a qos and then schedules
a delayed work item to bring the qos back down to the default
after the timeout. When the work item runs, pm_qos_work_fn() will
call pm_qos_update_request() and deadlock because it tries to
cancel itself via cancel_delayed_work_sync(). Future callers of
that qos will also hang waiting to cancel the work that is
canceling itself. Let's extract the little bit of code that does
the real work of pm_qos_update_request() and call it from the
work function so that we don't deadlock.

Before ed1ac6e (PM: don't use [delayed_]work_pending()) this didn't
happen because the work function wouldn't try to cancel itself.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Tejun Heo <tj@kernel.org>
Cc: 3.9+ <stable@vger.kernel.org> # 3.9+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent d4e4ab8
Raw File
Tip revision: 40fea92ffb5fa0ef26d10ae0fe5688bc8e61c791 authored by Stephen Boyd on 13 August 2013, 21:12:40 UTC
PM / QoS: Fix workqueue deadlock when using pm_qos_update_request_timeout()
Tip revision: 40fea92
Makefile.host
# ==========================================================================
# Building binaries on the host system
# Binaries are used during the compilation of the kernel, for example
# to preprocess a data file.
#
# Both C and C++ are supported, but preferred language is C for such utilities.
#
# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
# hostprogs-y := bin2hex
# Will compile bin2hex.c and create an executable named bin2hex
#
# hostprogs-y    := lxdialog
# lxdialog-objs := checklist.o lxdialog.o
# Will compile lxdialog.c and checklist.c, and then link the executable
# lxdialog, based on checklist.o and lxdialog.o
#
# hostprogs-y      := qconf
# qconf-cxxobjs   := qconf.o
# qconf-objs      := menu.o
# Will compile qconf as a C++ program, and menu as a C program.
# They are linked as C++ code to the executable qconf

# hostprogs-y := conf
# conf-objs  := conf.o libkconfig.so
# libkconfig-objs := expr.o type.o
# Will create a shared library named libkconfig.so that consists of
# expr.o and type.o (they are both compiled as C code and the object files
# are made as position independent code).
# conf.c is compiled as a C program, and conf.o is linked together with
# libkconfig.so as the executable conf.
# Note: Shared libraries consisting of C++ files are not supported

__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))

# C code
# Executables compiled from a single .c file
host-csingle	:= $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))

# C executables linked based on several .o files
host-cmulti	:= $(foreach m,$(__hostprogs),\
		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))

# Object (.o) files compiled from .c files
host-cobjs	:= $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))

# C++ code
# C++ executables compiled from at least on .cc file
# and zero or more .c files
host-cxxmulti	:= $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))

# C++ Object (.o) files compiled from .cc files
host-cxxobjs	:= $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))

# Shared libaries (only .c supported)
# Shared libraries (.so) - all .so files referenced in "xxx-objs"
host-cshlib	:= $(sort $(filter %.so, $(host-cobjs)))
# Remove .so files from "xxx-objs"
host-cobjs	:= $(filter-out %.so,$(host-cobjs))

#Object (.o) files used by the shared libaries
host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))

# output directory for programs/.o files
# hostprogs-y := tools/build may have been specified. Retrieve directory
host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
# directory of .o files from prog-objs notation
host-objdirs += $(foreach f,$(host-cmulti),                  \
                    $(foreach m,$($(f)-objs),                \
                        $(if $(dir $(m)),$(dir $(m)))))
# directory of .o files from prog-cxxobjs notation
host-objdirs += $(foreach f,$(host-cxxmulti),                  \
                    $(foreach m,$($(f)-cxxobjs),                \
                        $(if $(dir $(m)),$(dir $(m)))))

host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))


__hostprogs     := $(addprefix $(obj)/,$(__hostprogs))
host-csingle	:= $(addprefix $(obj)/,$(host-csingle))
host-cmulti	:= $(addprefix $(obj)/,$(host-cmulti))
host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs))
host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti))
host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib))
host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs))
host-objdirs    := $(addprefix $(obj)/,$(host-objdirs))

obj-dirs += $(host-objdirs)

#####
# Handle options to gcc. Support building with separate output directory

_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   \
                 $(HOSTCFLAGS_$(basetarget).o)
_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
                 $(HOSTCXXFLAGS_$(basetarget).o)

ifeq ($(KBUILD_SRC),)
__hostc_flags	= $(_hostc_flags)
__hostcxx_flags	= $(_hostcxx_flags)
else
__hostc_flags	= -I$(obj) $(call flags,_hostc_flags)
__hostcxx_flags	= -I$(obj) $(call flags,_hostcxx_flags)
endif

hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)

#####
# Compile programs on the host

# Create executable from a single .c file
# host-csingle -> Executable
quiet_cmd_host-csingle 	= HOSTCC  $@
      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) -o $@ $< \
	  	$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-csingle): $(obj)/%: $(src)/%.c FORCE
	$(call if_changed_dep,host-csingle)

# Link an executable based on list of .o files, all plain c
# host-cmulti -> executable
quiet_cmd_host-cmulti	= HOSTLD  $@
      cmd_host-cmulti	= $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
			  $(addprefix $(obj)/,$($(@F)-objs)) \
			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE
	$(call if_changed,host-cmulti)

# Create .o file from a single .c file
# host-cobjs -> .o
quiet_cmd_host-cobjs	= HOSTCC  $@
      cmd_host-cobjs	= $(HOSTCC) $(hostc_flags) -c -o $@ $<
$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
	$(call if_changed_dep,host-cobjs)

# Link an executable based on list of .o files, a mixture of .c and .cc
# host-cxxmulti -> executable
quiet_cmd_host-cxxmulti	= HOSTLD  $@
      cmd_host-cxxmulti	= $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
			  $(foreach o,objs cxxobjs,\
			  $(addprefix $(obj)/,$($(@F)-$(o)))) \
			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
	$(call if_changed,host-cxxmulti)

# Create .o file from a single .cc (C++) file
quiet_cmd_host-cxxobjs	= HOSTCXX $@
      cmd_host-cxxobjs	= $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
	$(call if_changed_dep,host-cxxobjs)

# Compile .c file, create position independent .o file
# host-cshobjs -> .o
quiet_cmd_host-cshobjs	= HOSTCC  -fPIC $@
      cmd_host-cshobjs	= $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
	$(call if_changed_dep,host-cshobjs)

# Link a shared library, based on position independent .o files
# *.o -> .so shared library (host-cshlib)
quiet_cmd_host-cshlib	= HOSTLLD -shared $@
      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
	$(call if_changed,host-cshlib)

targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
	   $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 

back to top