aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-i386
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2006-12-13 03:34:30 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-13 12:05:49 -0500
commit8a102eed9c4e1d21bad07a8fd97bd4fbf125d966 (patch)
tree9ec99f046b94971db46b08a87d7eab3e84c4acd4 /include/asm-i386
parent3df494a32b936aef76d893f5065f962ebd9b9437 (diff)
[PATCH] PM: Fix SMP races in the freezer
Currently, to tell a task that it should go to the refrigerator, we set the PF_FREEZE flag for it and send a fake signal to it. Unfortunately there are two SMP-related problems with this approach. First, a task running on another CPU may be updating its flags while the freezer attempts to set PF_FREEZE for it and this may leave the task's flags in an inconsistent state. Second, there is a potential race between freeze_process() and refrigerator() in which freeze_process() running on one CPU is reading a task's PF_FREEZE flag while refrigerator() running on another CPU has just set PF_FROZEN for the same task and attempts to reset PF_FREEZE for it. If the refrigerator wins the race, freeze_process() will state that PF_FREEZE hasn't been set for the task and will set it unnecessarily, so the task will go to the refrigerator once again after it's been thawed. To solve first of these problems we need to stop using PF_FREEZE to tell tasks that they should go to the refrigerator. Instead, we can introduce a special TIF_*** flag and use it for this purpose, since it is allowed to change the other tasks' TIF_*** flags and there are special calls for it. To avoid the freeze_process()-refrigerator() race we can make freeze_process() to always check the task's PF_FROZEN flag after it's read its "freeze" flag. We should also make sure that refrigerator() will always reset the task's "freeze" flag after it's set PF_FROZEN for it. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Cc: Russell King <rmk@arm.linux.org.uk> Cc: David Howells <dhowells@redhat.com> Cc: Andi Kleen <ak@muc.de> Cc: "Luck, Tony" <tony.luck@intel.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Paul Mundt <lethal@linux-sh.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/asm-i386')
-rw-r--r--include/asm-i386/thread_info.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 46d32ad92082..4b187bb377b4 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -134,6 +134,7 @@ static inline struct thread_info *current_thread_info(void)
134#define TIF_MEMDIE 16 134#define TIF_MEMDIE 16
135#define TIF_DEBUG 17 /* uses debug registers */ 135#define TIF_DEBUG 17 /* uses debug registers */
136#define TIF_IO_BITMAP 18 /* uses I/O bitmap */ 136#define TIF_IO_BITMAP 18 /* uses I/O bitmap */
137#define TIF_FREEZE 19 /* is freezing for suspend */
137 138
138#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 139#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
139#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 140#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -147,6 +148,7 @@ static inline struct thread_info *current_thread_info(void)
147#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) 148#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
148#define _TIF_DEBUG (1<<TIF_DEBUG) 149#define _TIF_DEBUG (1<<TIF_DEBUG)
149#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) 150#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
151#define _TIF_FREEZE (1<<TIF_FREEZE)
150 152
151/* work to do on interrupt/exception return */ 153/* work to do on interrupt/exception return */
152#define _TIF_WORK_MASK \ 154#define _TIF_WORK_MASK \