diff options
| author | Jens Axboe <axboe@fb.com> | 2014-11-19 05:43:46 +0300 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2014-11-19 05:43:46 +0300 |
| commit | b3521729769ec71567a2e32a38609f87e781e41b (patch) | |
| tree | 66a8494968706420c3eb043caa5868702d440d18 /kernel/cpu.c | |
| parent | 139768895309c6c1d6913e909e9c9422f81a1640 (diff) | |
| parent | fc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff) | |
| download | linux-b3521729769ec71567a2e32a38609f87e781e41b.tar.xz | |
Merge branch 'master' into for-3.19/drivers
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 356450f09c1f..90a3d017b90c 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -64,6 +64,8 @@ static struct { * an ongoing cpu hotplug operation. */ int refcount; + /* And allows lockless put_online_cpus(). */ + atomic_t puts_pending; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; @@ -113,7 +115,11 @@ void put_online_cpus(void) { if (cpu_hotplug.active_writer == current) return; - mutex_lock(&cpu_hotplug.lock); + if (!mutex_trylock(&cpu_hotplug.lock)) { + atomic_inc(&cpu_hotplug.puts_pending); + cpuhp_lock_release(); + return; + } if (WARN_ON(!cpu_hotplug.refcount)) cpu_hotplug.refcount++; /* try to fix things up */ @@ -155,6 +161,12 @@ void cpu_hotplug_begin(void) cpuhp_lock_acquire(); for (;;) { mutex_lock(&cpu_hotplug.lock); + if (atomic_read(&cpu_hotplug.puts_pending)) { + int delta; + + delta = atomic_xchg(&cpu_hotplug.puts_pending, 0); + cpu_hotplug.refcount -= delta; + } if (likely(!cpu_hotplug.refcount)) break; __set_current_state(TASK_UNINTERRUPTIBLE); |
