diff options
author | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:23 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:23 -0500 |
commit | 8a32c441c1609f80e55df75422324a1151208f40 (patch) | |
tree | 73884b06cc2db3ea155af9a88815bb5105a4473e /drivers/platform | |
parent | a0acae0e886d44bd5ce6d2f173c1ace0fcf0d9f6 (diff) |
freezer: implement and use kthread_freezable_should_stop()
Writeback and thinkpad_acpi have been using thaw_process() to prevent
deadlock between the freezer and kthread_stop(); unfortunately, this
is inherently racy - nothing prevents freezing from happening between
thaw_process() and kthread_stop().
This patch implements kthread_freezable_should_stop() which enters
refrigerator if necessary but is guaranteed to return if
kthread_stop() is invoked. Both thaw_process() users are converted to
use the new function.
Note that this deadlock condition exists for many of freezable
kthreads. They need to be converted to use the new should_stop or
freezable workqueue.
Tested with synthetic test case.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7b828680b21..4b11fc91fa7 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -2456,8 +2456,9 @@ static int hotkey_kthread(void *data) | |||
2456 | u32 poll_mask, event_mask; | 2456 | u32 poll_mask, event_mask; |
2457 | unsigned int si, so; | 2457 | unsigned int si, so; |
2458 | unsigned long t; | 2458 | unsigned long t; |
2459 | unsigned int change_detector, must_reset; | 2459 | unsigned int change_detector; |
2460 | unsigned int poll_freq; | 2460 | unsigned int poll_freq; |
2461 | bool was_frozen; | ||
2461 | 2462 | ||
2462 | mutex_lock(&hotkey_thread_mutex); | 2463 | mutex_lock(&hotkey_thread_mutex); |
2463 | 2464 | ||
@@ -2488,14 +2489,14 @@ static int hotkey_kthread(void *data) | |||
2488 | t = 100; /* should never happen... */ | 2489 | t = 100; /* should never happen... */ |
2489 | } | 2490 | } |
2490 | t = msleep_interruptible(t); | 2491 | t = msleep_interruptible(t); |
2491 | if (unlikely(kthread_should_stop())) | 2492 | if (unlikely(kthread_freezable_should_stop(&was_frozen))) |
2492 | break; | 2493 | break; |
2493 | must_reset = try_to_freeze(); | 2494 | |
2494 | if (t > 0 && !must_reset) | 2495 | if (t > 0 && !was_frozen) |
2495 | continue; | 2496 | continue; |
2496 | 2497 | ||
2497 | mutex_lock(&hotkey_thread_data_mutex); | 2498 | mutex_lock(&hotkey_thread_data_mutex); |
2498 | if (must_reset || hotkey_config_change != change_detector) { | 2499 | if (was_frozen || hotkey_config_change != change_detector) { |
2499 | /* forget old state on thaw or config change */ | 2500 | /* forget old state on thaw or config change */ |
2500 | si = so; | 2501 | si = so; |
2501 | t = 0; | 2502 | t = 0; |
@@ -2528,10 +2529,6 @@ exit: | |||
2528 | static void hotkey_poll_stop_sync(void) | 2529 | static void hotkey_poll_stop_sync(void) |
2529 | { | 2530 | { |
2530 | if (tpacpi_hotkey_task) { | 2531 | if (tpacpi_hotkey_task) { |
2531 | if (frozen(tpacpi_hotkey_task) || | ||
2532 | freezing(tpacpi_hotkey_task)) | ||
2533 | thaw_process(tpacpi_hotkey_task); | ||
2534 | |||
2535 | kthread_stop(tpacpi_hotkey_task); | 2532 | kthread_stop(tpacpi_hotkey_task); |
2536 | tpacpi_hotkey_task = NULL; | 2533 | tpacpi_hotkey_task = NULL; |
2537 | mutex_lock(&hotkey_thread_mutex); | 2534 | mutex_lock(&hotkey_thread_mutex); |