diff options
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 3619e939182e..d61ba88f34e5 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -21,6 +21,24 @@ EXPORT_SYMBOL_GPL(cpucontrol); | |||
| 21 | 21 | ||
| 22 | static struct notifier_block *cpu_chain; | 22 | static struct notifier_block *cpu_chain; |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | * Used to check by callers if they need to acquire the cpucontrol | ||
| 26 | * or not to protect a cpu from being removed. Its sometimes required to | ||
| 27 | * call these functions both for normal operations, and in response to | ||
| 28 | * a cpu being added/removed. If the context of the call is in the same | ||
| 29 | * thread context as a CPU hotplug thread, we dont need to take the lock | ||
| 30 | * since its already protected | ||
| 31 | * check drivers/cpufreq/cpufreq.c for its usage - Ashok Raj | ||
| 32 | */ | ||
| 33 | |||
| 34 | int current_in_cpu_hotplug(void) | ||
| 35 | { | ||
| 36 | return (current->flags & PF_HOTPLUG_CPU); | ||
| 37 | } | ||
| 38 | |||
| 39 | EXPORT_SYMBOL_GPL(current_in_cpu_hotplug); | ||
| 40 | |||
| 41 | |||
| 24 | /* Need to know about CPUs going up/down? */ | 42 | /* Need to know about CPUs going up/down? */ |
| 25 | int register_cpu_notifier(struct notifier_block *nb) | 43 | int register_cpu_notifier(struct notifier_block *nb) |
| 26 | { | 44 | { |
| @@ -94,6 +112,13 @@ int cpu_down(unsigned int cpu) | |||
| 94 | goto out; | 112 | goto out; |
| 95 | } | 113 | } |
| 96 | 114 | ||
| 115 | /* | ||
| 116 | * Leave a trace in current->flags indicating we are already in | ||
| 117 | * process of performing CPU hotplug. Callers can check if cpucontrol | ||
| 118 | * is already acquired by current thread, and if so not cause | ||
| 119 | * a dead lock by not acquiring the lock | ||
| 120 | */ | ||
| 121 | current->flags |= PF_HOTPLUG_CPU; | ||
| 97 | err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, | 122 | err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, |
| 98 | (void *)(long)cpu); | 123 | (void *)(long)cpu); |
| 99 | if (err == NOTIFY_BAD) { | 124 | if (err == NOTIFY_BAD) { |
| @@ -146,6 +171,7 @@ out_thread: | |||
| 146 | out_allowed: | 171 | out_allowed: |
| 147 | set_cpus_allowed(current, old_allowed); | 172 | set_cpus_allowed(current, old_allowed); |
| 148 | out: | 173 | out: |
| 174 | current->flags &= ~PF_HOTPLUG_CPU; | ||
| 149 | unlock_cpu_hotplug(); | 175 | unlock_cpu_hotplug(); |
| 150 | return err; | 176 | return err; |
| 151 | } | 177 | } |
| @@ -163,6 +189,12 @@ int __devinit cpu_up(unsigned int cpu) | |||
| 163 | ret = -EINVAL; | 189 | ret = -EINVAL; |
| 164 | goto out; | 190 | goto out; |
| 165 | } | 191 | } |
| 192 | |||
| 193 | /* | ||
| 194 | * Leave a trace in current->flags indicating we are already in | ||
| 195 | * process of performing CPU hotplug. | ||
| 196 | */ | ||
| 197 | current->flags |= PF_HOTPLUG_CPU; | ||
| 166 | ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); | 198 | ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); |
| 167 | if (ret == NOTIFY_BAD) { | 199 | if (ret == NOTIFY_BAD) { |
| 168 | printk("%s: attempt to bring up CPU %u failed\n", | 200 | printk("%s: attempt to bring up CPU %u failed\n", |
| @@ -185,6 +217,7 @@ out_notify: | |||
| 185 | if (ret != 0) | 217 | if (ret != 0) |
| 186 | notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); | 218 | notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); |
| 187 | out: | 219 | out: |
| 220 | current->flags &= ~PF_HOTPLUG_CPU; | ||
| 188 | up(&cpucontrol); | 221 | up(&cpucontrol); |
| 189 | return ret; | 222 | return ret; |
| 190 | } | 223 | } |
