Messages in this thread Patch in this message | | | Date | Tue, 29 Apr 2008 18:33:57 +0530 | From | Gautham R Shenoy <> | Subject | [PATCH 7/8] cpu_hotplug: Introduce try_get_online_cpus() |
| |
cpu_hotplug: Introduce try_get_online_cpus()
From: Gautham R Shenoy <ego@in.ibm.com>
Subsystems such as workqueues currently cannot use get_online_cpus() since they deadlock with the workqueue CPU-Hotplug callback code.
For such cases, introduce a new API try_get_online_cpus() which returns 0 when a cpu-hotplug operation is in progress. It behaves like get_online_cpus() and returns 1 otherwise.
Based on the status of CPU-Hotplug, the subsystems can take appropriate action.
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com> ---
include/linux/cpu.h | 2 ++ kernel/cpu.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 0be8d65..d0be341 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -107,6 +107,7 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex) } extern void get_online_cpus(void); +extern int try_get_online_cpus(void); extern void put_online_cpus(void); #define hotcpu_notifier(fn, pri) { \ static struct notifier_block fn##_nb = \ @@ -126,6 +127,7 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex) #define get_online_cpus() do { } while (0) #define put_online_cpus() do { } while (0) +static inline int try_get_online_cpus(void) { return 1; } #define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0) /* These aren't inline functions due to a GCC bug. */ #define register_hotcpu_notifier(nb) ({ (void)(nb); 0; }) diff --git a/kernel/cpu.c b/kernel/cpu.c index 8f1718f..52c1e4e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -57,7 +57,29 @@ void __init cpu_hotplug_init(void) } #ifdef CONFIG_HOTPLUG_CPU +int try_get_online_cpus(void) +{ + spin_lock(&cpu_hotplug.lock); + if (cpu_hotplug.active_writer == current) + goto out_unlock; + + if (likely(!cpu_hotplug.active_writer)) + goto out_success; + + if (cpu_hotplug.refcount) + goto out_success; + + spin_unlock(&cpu_hotplug.lock); + return 0; + +out_success: + cpu_hotplug.refcount++; +out_unlock: + spin_unlock(&cpu_hotplug.lock); + cpu_hotplug_acquire_read(&cpu_hotplug.dep_map, 0, 1, _THIS_IP_); + return 1; +} void get_online_cpus(void) { might_sleep(); -- Thanks and Regards gautham
| |