diff options
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/Kconfig | 2 | ||||
-rw-r--r-- | kernel/power/process.c | 29 | ||||
-rw-r--r-- | kernel/power/snapshot.c | 41 |
3 files changed, 47 insertions, 25 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 79833170bb9c..6233f3b4ae66 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -190,7 +190,7 @@ config APM_EMULATION | |||
190 | notification of APM "events" (e.g. battery status change). | 190 | notification of APM "events" (e.g. battery status change). |
191 | 191 | ||
192 | In order to use APM, you will need supporting software. For location | 192 | In order to use APM, you will need supporting software. For location |
193 | and more information, read <file:Documentation/pm.txt> and the | 193 | and more information, read <file:Documentation/power/pm.txt> and the |
194 | Battery Powered Linux mini-HOWTO, available from | 194 | Battery Powered Linux mini-HOWTO, available from |
195 | <http://www.tldp.org/docs.html#howto>. | 195 | <http://www.tldp.org/docs.html#howto>. |
196 | 196 | ||
diff --git a/kernel/power/process.c b/kernel/power/process.c index 7c2118f9597f..f1d0b345c9ba 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -75,22 +75,15 @@ void refrigerator(void) | |||
75 | __set_current_state(save); | 75 | __set_current_state(save); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void fake_signal_wake_up(struct task_struct *p, int resume) | 78 | static void fake_signal_wake_up(struct task_struct *p) |
79 | { | 79 | { |
80 | unsigned long flags; | 80 | unsigned long flags; |
81 | 81 | ||
82 | spin_lock_irqsave(&p->sighand->siglock, flags); | 82 | spin_lock_irqsave(&p->sighand->siglock, flags); |
83 | signal_wake_up(p, resume); | 83 | signal_wake_up(p, 0); |
84 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 84 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
85 | } | 85 | } |
86 | 86 | ||
87 | static void send_fake_signal(struct task_struct *p) | ||
88 | { | ||
89 | if (task_is_stopped(p)) | ||
90 | force_sig_specific(SIGSTOP, p); | ||
91 | fake_signal_wake_up(p, task_is_stopped(p)); | ||
92 | } | ||
93 | |||
94 | static int has_mm(struct task_struct *p) | 87 | static int has_mm(struct task_struct *p) |
95 | { | 88 | { |
96 | return (p->mm && !(p->flags & PF_BORROWED_MM)); | 89 | return (p->mm && !(p->flags & PF_BORROWED_MM)); |
@@ -121,7 +114,7 @@ static int freeze_task(struct task_struct *p, int with_mm_only) | |||
121 | if (freezing(p)) { | 114 | if (freezing(p)) { |
122 | if (has_mm(p)) { | 115 | if (has_mm(p)) { |
123 | if (!signal_pending(p)) | 116 | if (!signal_pending(p)) |
124 | fake_signal_wake_up(p, 0); | 117 | fake_signal_wake_up(p); |
125 | } else { | 118 | } else { |
126 | if (with_mm_only) | 119 | if (with_mm_only) |
127 | ret = 0; | 120 | ret = 0; |
@@ -135,7 +128,7 @@ static int freeze_task(struct task_struct *p, int with_mm_only) | |||
135 | } else { | 128 | } else { |
136 | if (has_mm(p)) { | 129 | if (has_mm(p)) { |
137 | set_freeze_flag(p); | 130 | set_freeze_flag(p); |
138 | send_fake_signal(p); | 131 | fake_signal_wake_up(p); |
139 | } else { | 132 | } else { |
140 | if (with_mm_only) { | 133 | if (with_mm_only) { |
141 | ret = 0; | 134 | ret = 0; |
@@ -182,15 +175,17 @@ static int try_to_freeze_tasks(int freeze_user_space) | |||
182 | if (frozen(p) || !freezeable(p)) | 175 | if (frozen(p) || !freezeable(p)) |
183 | continue; | 176 | continue; |
184 | 177 | ||
185 | if (task_is_traced(p) && frozen(p->parent)) { | ||
186 | cancel_freezing(p); | ||
187 | continue; | ||
188 | } | ||
189 | |||
190 | if (!freeze_task(p, freeze_user_space)) | 178 | if (!freeze_task(p, freeze_user_space)) |
191 | continue; | 179 | continue; |
192 | 180 | ||
193 | if (!freezer_should_skip(p)) | 181 | /* |
182 | * Now that we've done set_freeze_flag, don't | ||
183 | * perturb a task in TASK_STOPPED or TASK_TRACED. | ||
184 | * It is "frozen enough". If the task does wake | ||
185 | * up, it will immediately call try_to_freeze. | ||
186 | */ | ||
187 | if (!task_is_stopped_or_traced(p) && | ||
188 | !freezer_should_skip(p)) | ||
194 | todo++; | 189 | todo++; |
195 | } while_each_thread(g, p); | 190 | } while_each_thread(g, p); |
196 | read_unlock(&tasklist_lock); | 191 | read_unlock(&tasklist_lock); |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 72a020cabb4c..5f91a07c4eac 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) | |||
447 | * of @bm->cur_zone_bm are updated. | 447 | * of @bm->cur_zone_bm are updated. |
448 | */ | 448 | */ |
449 | 449 | ||
450 | static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, | 450 | static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, |
451 | void **addr, unsigned int *bit_nr) | 451 | void **addr, unsigned int *bit_nr) |
452 | { | 452 | { |
453 | struct zone_bitmap *zone_bm; | 453 | struct zone_bitmap *zone_bm; |
@@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, | |||
461 | while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) { | 461 | while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) { |
462 | zone_bm = zone_bm->next; | 462 | zone_bm = zone_bm->next; |
463 | 463 | ||
464 | BUG_ON(!zone_bm); | 464 | if (!zone_bm) |
465 | return -EFAULT; | ||
465 | } | 466 | } |
466 | bm->cur.zone_bm = zone_bm; | 467 | bm->cur.zone_bm = zone_bm; |
467 | } | 468 | } |
@@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, | |||
479 | pfn -= bb->start_pfn; | 480 | pfn -= bb->start_pfn; |
480 | *bit_nr = pfn % BM_BITS_PER_CHUNK; | 481 | *bit_nr = pfn % BM_BITS_PER_CHUNK; |
481 | *addr = bb->data + pfn / BM_BITS_PER_CHUNK; | 482 | *addr = bb->data + pfn / BM_BITS_PER_CHUNK; |
483 | return 0; | ||
482 | } | 484 | } |
483 | 485 | ||
484 | static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) | 486 | static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) |
485 | { | 487 | { |
486 | void *addr; | 488 | void *addr; |
487 | unsigned int bit; | 489 | unsigned int bit; |
490 | int error; | ||
488 | 491 | ||
489 | memory_bm_find_bit(bm, pfn, &addr, &bit); | 492 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
493 | BUG_ON(error); | ||
490 | set_bit(bit, addr); | 494 | set_bit(bit, addr); |
491 | } | 495 | } |
492 | 496 | ||
497 | static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn) | ||
498 | { | ||
499 | void *addr; | ||
500 | unsigned int bit; | ||
501 | int error; | ||
502 | |||
503 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); | ||
504 | if (!error) | ||
505 | set_bit(bit, addr); | ||
506 | return error; | ||
507 | } | ||
508 | |||
493 | static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | 509 | static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) |
494 | { | 510 | { |
495 | void *addr; | 511 | void *addr; |
496 | unsigned int bit; | 512 | unsigned int bit; |
513 | int error; | ||
497 | 514 | ||
498 | memory_bm_find_bit(bm, pfn, &addr, &bit); | 515 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
516 | BUG_ON(error); | ||
499 | clear_bit(bit, addr); | 517 | clear_bit(bit, addr); |
500 | } | 518 | } |
501 | 519 | ||
@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
503 | { | 521 | { |
504 | void *addr; | 522 | void *addr; |
505 | unsigned int bit; | 523 | unsigned int bit; |
524 | int error; | ||
506 | 525 | ||
507 | memory_bm_find_bit(bm, pfn, &addr, &bit); | 526 | error = memory_bm_find_bit(bm, pfn, &addr, &bit); |
527 | BUG_ON(error); | ||
508 | return test_bit(bit, addr); | 528 | return test_bit(bit, addr); |
509 | } | 529 | } |
510 | 530 | ||
@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm) | |||
709 | region->end_pfn << PAGE_SHIFT); | 729 | region->end_pfn << PAGE_SHIFT); |
710 | 730 | ||
711 | for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++) | 731 | for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++) |
712 | if (pfn_valid(pfn)) | 732 | if (pfn_valid(pfn)) { |
713 | memory_bm_set_bit(bm, pfn); | 733 | /* |
734 | * It is safe to ignore the result of | ||
735 | * mem_bm_set_bit_check() here, since we won't | ||
736 | * touch the PFNs for which the error is | ||
737 | * returned anyway. | ||
738 | */ | ||
739 | mem_bm_set_bit_check(bm, pfn); | ||
740 | } | ||
714 | } | 741 | } |
715 | } | 742 | } |
716 | 743 | ||