diff options
| author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-04-29 04:00:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:11 -0400 |
| commit | d2ba7e2ae206e9ab24e8937d99d0d5513bfd08e5 (patch) | |
| tree | 4cdd43bbf03885705fed5c80e982d19d397afaeb /kernel/cpu.c | |
| parent | 1e35eaa2d86419470f3f3aed9acd85b8addff25c (diff) | |
simplify cpu_hotplug_begin()/put_online_cpus()
cpu_hotplug_begin() must be always called under cpu_add_remove_lock, this
means that only one process can be cpu_hotplug.active_writer. So we don't
need the cpu_hotplug.writer_queue, we can wake up the ->active_writer
directly.
Also, fix the comment.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Dipankar Sarma <dipankar@in.ibm.com>
Acked-by: Gautham R Shenoy <ego@in.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 30 |
1 files changed, 10 insertions, 20 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index f8f9468d17..a98f6ab16e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -33,17 +33,13 @@ static struct { | |||
| 33 | * an ongoing cpu hotplug operation. | 33 | * an ongoing cpu hotplug operation. |
| 34 | */ | 34 | */ |
| 35 | int refcount; | 35 | int refcount; |
| 36 | wait_queue_head_t writer_queue; | ||
| 37 | } cpu_hotplug; | 36 | } cpu_hotplug; |
| 38 | 37 | ||
| 39 | #define writer_exists() (cpu_hotplug.active_writer != NULL) | ||
| 40 | |||
| 41 | void __init cpu_hotplug_init(void) | 38 | void __init cpu_hotplug_init(void) |
| 42 | { | 39 | { |
| 43 | cpu_hotplug.active_writer = NULL; | 40 | cpu_hotplug.active_writer = NULL; |
| 44 | mutex_init(&cpu_hotplug.lock); | 41 | mutex_init(&cpu_hotplug.lock); |
| 45 | cpu_hotplug.refcount = 0; | 42 | cpu_hotplug.refcount = 0; |
| 46 | init_waitqueue_head(&cpu_hotplug.writer_queue); | ||
| 47 | } | 43 | } |
| 48 | 44 | ||
| 49 | #ifdef CONFIG_HOTPLUG_CPU | 45 | #ifdef CONFIG_HOTPLUG_CPU |
| @@ -65,11 +61,8 @@ void put_online_cpus(void) | |||
| 65 | if (cpu_hotplug.active_writer == current) | 61 | if (cpu_hotplug.active_writer == current) |
| 66 | return; | 62 | return; |
| 67 | mutex_lock(&cpu_hotplug.lock); | 63 | mutex_lock(&cpu_hotplug.lock); |
| 68 | cpu_hotplug.refcount--; | 64 | if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer)) |
| 69 | 65 | wake_up_process(cpu_hotplug.active_writer); | |
| 70 | if (unlikely(writer_exists()) && !cpu_hotplug.refcount) | ||
| 71 | wake_up(&cpu_hotplug.writer_queue); | ||
| 72 | |||
| 73 | mutex_unlock(&cpu_hotplug.lock); | 66 | mutex_unlock(&cpu_hotplug.lock); |
| 74 | 67 | ||
| 75 | } | 68 | } |
| @@ -98,8 +91,8 @@ void cpu_maps_update_done(void) | |||
| 98 | * Note that during a cpu-hotplug operation, the new readers, if any, | 91 | * Note that during a cpu-hotplug operation, the new readers, if any, |
| 99 | * will be blocked by the cpu_hotplug.lock | 92 | * will be blocked by the cpu_hotplug.lock |
| 100 | * | 93 | * |
| 101 | * Since cpu_maps_update_begin is always called after invoking | 94 | * Since cpu_hotplug_begin() is always called after invoking |
| 102 | * cpu_maps_update_begin, we can be sure that only one writer is active. | 95 | * cpu_maps_update_begin(), we can be sure that only one writer is active. |
| 103 | * | 96 | * |
| 104 | * Note that theoretically, there is a possibility of a livelock: | 97 | * Note that theoretically, there is a possibility of a livelock: |
| 105 | * - Refcount goes to zero, last reader wakes up the sleeping | 98 | * - Refcount goes to zero, last reader wakes up the sleeping |
| @@ -115,19 +108,16 @@ void cpu_maps_update_done(void) | |||
| 115 | */ | 108 | */ |
| 116 | static void cpu_hotplug_begin(void) | 109 | static void cpu_hotplug_begin(void) |
| 117 | { | 110 | { |
| 118 | DECLARE_WAITQUEUE(wait, current); | ||
| 119 | |||
| 120 | mutex_lock(&cpu_hotplug.lock); | ||
| 121 | |||
| 122 | cpu_hotplug.active_writer = current; | 111 | cpu_hotplug.active_writer = current; |
| 123 | add_wait_queue_exclusive(&cpu_hotplug.writer_queue, &wait); | 112 | |
| 124 | while (cpu_hotplug.refcount) { | 113 | for (;;) { |
| 125 | set_current_state(TASK_UNINTERRUPTIBLE); | 114 | mutex_lock(&cpu_hotplug.lock); |
| 115 | if (likely(!cpu_hotplug.refcount)) | ||
| 116 | break; | ||
| 117 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 126 | mutex_unlock(&cpu_hotplug.lock); | 118 | mutex_unlock(&cpu_hotplug.lock); |
| 127 | schedule(); | 119 | schedule(); |
| 128 | mutex_lock(&cpu_hotplug.lock); | ||
| 129 | } | 120 | } |
| 130 | remove_wait_queue_locked(&cpu_hotplug.writer_queue, &wait); | ||
| 131 | } | 121 | } |
| 132 | 122 | ||
| 133 | static void cpu_hotplug_done(void) | 123 | static void cpu_hotplug_done(void) |
