diff options
Diffstat (limited to 'kernel/power/process.c')
-rw-r--r-- | kernel/power/process.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c index 3bd0d261818f..28de118f7a0b 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -38,7 +38,6 @@ void refrigerator(void) | |||
38 | processes around? */ | 38 | processes around? */ |
39 | long save; | 39 | long save; |
40 | save = current->state; | 40 | save = current->state; |
41 | current->state = TASK_UNINTERRUPTIBLE; | ||
42 | pr_debug("%s entered refrigerator\n", current->comm); | 41 | pr_debug("%s entered refrigerator\n", current->comm); |
43 | printk("="); | 42 | printk("="); |
44 | 43 | ||
@@ -47,8 +46,10 @@ void refrigerator(void) | |||
47 | recalc_sigpending(); /* We sent fake signal, clean it up */ | 46 | recalc_sigpending(); /* We sent fake signal, clean it up */ |
48 | spin_unlock_irq(¤t->sighand->siglock); | 47 | spin_unlock_irq(¤t->sighand->siglock); |
49 | 48 | ||
50 | while (frozen(current)) | 49 | while (frozen(current)) { |
50 | current->state = TASK_UNINTERRUPTIBLE; | ||
51 | schedule(); | 51 | schedule(); |
52 | } | ||
52 | pr_debug("%s left refrigerator\n", current->comm); | 53 | pr_debug("%s left refrigerator\n", current->comm); |
53 | current->state = save; | 54 | current->state = save; |
54 | } | 55 | } |
@@ -80,13 +81,33 @@ int freeze_processes(void) | |||
80 | } while_each_thread(g, p); | 81 | } while_each_thread(g, p); |
81 | read_unlock(&tasklist_lock); | 82 | read_unlock(&tasklist_lock); |
82 | yield(); /* Yield is okay here */ | 83 | yield(); /* Yield is okay here */ |
83 | if (time_after(jiffies, start_time + TIMEOUT)) { | 84 | if (todo && time_after(jiffies, start_time + TIMEOUT)) { |
84 | printk( "\n" ); | 85 | printk( "\n" ); |
85 | printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo ); | 86 | printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo ); |
86 | return todo; | 87 | break; |
87 | } | 88 | } |
88 | } while(todo); | 89 | } while(todo); |
89 | 90 | ||
91 | /* This does not unfreeze processes that are already frozen | ||
92 | * (we have slightly ugly calling convention in that respect, | ||
93 | * and caller must call thaw_processes() if something fails), | ||
94 | * but it cleans up leftover PF_FREEZE requests. | ||
95 | */ | ||
96 | if (todo) { | ||
97 | read_lock(&tasklist_lock); | ||
98 | do_each_thread(g, p) | ||
99 | if (freezing(p)) { | ||
100 | pr_debug(" clean up: %s\n", p->comm); | ||
101 | p->flags &= ~PF_FREEZE; | ||
102 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
103 | recalc_sigpending_tsk(p); | ||
104 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
105 | } | ||
106 | while_each_thread(g, p); | ||
107 | read_unlock(&tasklist_lock); | ||
108 | return todo; | ||
109 | } | ||
110 | |||
90 | printk( "|\n" ); | 111 | printk( "|\n" ); |
91 | BUG_ON(in_atomic()); | 112 | BUG_ON(in_atomic()); |
92 | return 0; | 113 | return 0; |