diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /kernel/power/process.c | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'kernel/power/process.c')
| -rw-r--r-- | kernel/power/process.c | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c index 28de118f7a0b..8ac7c35fad77 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
| @@ -12,11 +12,12 @@ | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/suspend.h> | 13 | #include <linux/suspend.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/syscalls.h> | ||
| 15 | 16 | ||
| 16 | /* | 17 | /* |
| 17 | * Timeout for stopping processes | 18 | * Timeout for stopping processes |
| 18 | */ | 19 | */ |
| 19 | #define TIMEOUT (6 * HZ) | 20 | #define TIMEOUT (20 * HZ) |
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | static inline int freezeable(struct task_struct * p) | 23 | static inline int freezeable(struct task_struct * p) |
| @@ -54,38 +55,62 @@ void refrigerator(void) | |||
| 54 | current->state = save; | 55 | current->state = save; |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 58 | static inline void freeze_process(struct task_struct *p) | ||
| 59 | { | ||
| 60 | unsigned long flags; | ||
| 61 | |||
| 62 | if (!freezing(p)) { | ||
| 63 | freeze(p); | ||
| 64 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
| 65 | signal_wake_up(p, 0); | ||
| 66 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 57 | /* 0 = success, else # of processes that we failed to stop */ | 70 | /* 0 = success, else # of processes that we failed to stop */ |
| 58 | int freeze_processes(void) | 71 | int freeze_processes(void) |
| 59 | { | 72 | { |
| 60 | int todo; | 73 | int todo, nr_user, user_frozen; |
| 61 | unsigned long start_time; | 74 | unsigned long start_time; |
| 62 | struct task_struct *g, *p; | 75 | struct task_struct *g, *p; |
| 63 | unsigned long flags; | 76 | unsigned long flags; |
| 64 | 77 | ||
| 65 | printk( "Stopping tasks: " ); | 78 | printk( "Stopping tasks: " ); |
| 66 | start_time = jiffies; | 79 | start_time = jiffies; |
| 80 | user_frozen = 0; | ||
| 67 | do { | 81 | do { |
| 68 | todo = 0; | 82 | nr_user = todo = 0; |
| 69 | read_lock(&tasklist_lock); | 83 | read_lock(&tasklist_lock); |
| 70 | do_each_thread(g, p) { | 84 | do_each_thread(g, p) { |
| 71 | if (!freezeable(p)) | 85 | if (!freezeable(p)) |
| 72 | continue; | 86 | continue; |
| 73 | if (frozen(p)) | 87 | if (frozen(p)) |
| 74 | continue; | 88 | continue; |
| 75 | 89 | if (p->mm && !(p->flags & PF_BORROWED_MM)) { | |
| 76 | freeze(p); | 90 | /* The task is a user-space one. |
| 77 | spin_lock_irqsave(&p->sighand->siglock, flags); | 91 | * Freeze it unless there's a vfork completion |
| 78 | signal_wake_up(p, 0); | 92 | * pending |
| 79 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 93 | */ |
| 80 | todo++; | 94 | if (!p->vfork_done) |
| 95 | freeze_process(p); | ||
| 96 | nr_user++; | ||
| 97 | } else { | ||
| 98 | /* Freeze only if the user space is frozen */ | ||
| 99 | if (user_frozen) | ||
| 100 | freeze_process(p); | ||
| 101 | todo++; | ||
| 102 | } | ||
| 81 | } while_each_thread(g, p); | 103 | } while_each_thread(g, p); |
| 82 | read_unlock(&tasklist_lock); | 104 | read_unlock(&tasklist_lock); |
| 105 | todo += nr_user; | ||
| 106 | if (!user_frozen && !nr_user) { | ||
| 107 | sys_sync(); | ||
| 108 | start_time = jiffies; | ||
| 109 | } | ||
| 110 | user_frozen = !nr_user; | ||
| 83 | yield(); /* Yield is okay here */ | 111 | yield(); /* Yield is okay here */ |
| 84 | if (todo && time_after(jiffies, start_time + TIMEOUT)) { | 112 | if (todo && time_after(jiffies, start_time + TIMEOUT)) |
| 85 | printk( "\n" ); | ||
| 86 | printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo ); | ||
| 87 | break; | 113 | break; |
| 88 | } | ||
| 89 | } while(todo); | 114 | } while(todo); |
| 90 | 115 | ||
| 91 | /* This does not unfreeze processes that are already frozen | 116 | /* This does not unfreeze processes that are already frozen |
| @@ -94,8 +119,14 @@ int freeze_processes(void) | |||
| 94 | * but it cleans up leftover PF_FREEZE requests. | 119 | * but it cleans up leftover PF_FREEZE requests. |
| 95 | */ | 120 | */ |
| 96 | if (todo) { | 121 | if (todo) { |
| 122 | printk( "\n" ); | ||
| 123 | printk(KERN_ERR " stopping tasks timed out " | ||
| 124 | "after %d seconds (%d tasks remaining):\n", | ||
| 125 | TIMEOUT / HZ, todo); | ||
| 97 | read_lock(&tasklist_lock); | 126 | read_lock(&tasklist_lock); |
| 98 | do_each_thread(g, p) | 127 | do_each_thread(g, p) { |
| 128 | if (freezeable(p) && !frozen(p)) | ||
| 129 | printk(KERN_ERR " %s\n", p->comm); | ||
| 99 | if (freezing(p)) { | 130 | if (freezing(p)) { |
| 100 | pr_debug(" clean up: %s\n", p->comm); | 131 | pr_debug(" clean up: %s\n", p->comm); |
| 101 | p->flags &= ~PF_FREEZE; | 132 | p->flags &= ~PF_FREEZE; |
| @@ -103,7 +134,7 @@ int freeze_processes(void) | |||
| 103 | recalc_sigpending_tsk(p); | 134 | recalc_sigpending_tsk(p); |
| 104 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 135 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
| 105 | } | 136 | } |
| 106 | while_each_thread(g, p); | 137 | } while_each_thread(g, p); |
| 107 | read_unlock(&tasklist_lock); | 138 | read_unlock(&tasklist_lock); |
| 108 | return todo; | 139 | return todo; |
| 109 | } | 140 | } |
