diff options
| -rw-r--r-- | include/linux/spinlock.h | 37 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 9 | ||||
| -rw-r--r-- | kernel/timer.c | 8 |
3 files changed, 45 insertions, 9 deletions
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 61fef376ed2e..a946176db638 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -283,6 +283,43 @@ do { \ | |||
| 283 | }) | 283 | }) |
| 284 | 284 | ||
| 285 | /* | 285 | /* |
| 286 | * Locks two spinlocks l1 and l2. | ||
| 287 | * l1_first indicates if spinlock l1 should be taken first. | ||
| 288 | */ | ||
| 289 | static inline void double_spin_lock(spinlock_t *l1, spinlock_t *l2, | ||
| 290 | bool l1_first) | ||
| 291 | __acquires(l1) | ||
| 292 | __acquires(l2) | ||
| 293 | { | ||
| 294 | if (l1_first) { | ||
| 295 | spin_lock(l1); | ||
| 296 | spin_lock(l2); | ||
| 297 | } else { | ||
| 298 | spin_lock(l2); | ||
| 299 | spin_lock(l1); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | /* | ||
| 304 | * Unlocks two spinlocks l1 and l2. | ||
| 305 | * l1_taken_first indicates if spinlock l1 was taken first and therefore | ||
| 306 | * should be released after spinlock l2. | ||
| 307 | */ | ||
| 308 | static inline void double_spin_unlock(spinlock_t *l1, spinlock_t *l2, | ||
| 309 | bool l1_taken_first) | ||
| 310 | __releases(l1) | ||
| 311 | __releases(l2) | ||
| 312 | { | ||
| 313 | if (l1_taken_first) { | ||
| 314 | spin_unlock(l2); | ||
| 315 | spin_unlock(l1); | ||
| 316 | } else { | ||
| 317 | spin_unlock(l1); | ||
| 318 | spin_unlock(l2); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | /* | ||
| 286 | * Pull the atomic_t declaration: | 323 | * Pull the atomic_t declaration: |
| 287 | * (asm-mips/atomic.h needs above definitions) | 324 | * (asm-mips/atomic.h needs above definitions) |
| 288 | */ | 325 | */ |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 476cb0c0b4a4..de93a8176ca6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -1355,17 +1355,16 @@ static void migrate_hrtimers(int cpu) | |||
| 1355 | tick_cancel_sched_timer(cpu); | 1355 | tick_cancel_sched_timer(cpu); |
| 1356 | 1356 | ||
| 1357 | local_irq_disable(); | 1357 | local_irq_disable(); |
| 1358 | 1358 | double_spin_lock(&new_base->lock, &old_base->lock, | |
| 1359 | spin_lock(&new_base->lock); | 1359 | smp_processor_id() < cpu); |
| 1360 | spin_lock(&old_base->lock); | ||
| 1361 | 1360 | ||
| 1362 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { | 1361 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { |
| 1363 | migrate_hrtimer_list(&old_base->clock_base[i], | 1362 | migrate_hrtimer_list(&old_base->clock_base[i], |
| 1364 | &new_base->clock_base[i]); | 1363 | &new_base->clock_base[i]); |
| 1365 | } | 1364 | } |
| 1366 | spin_unlock(&old_base->lock); | ||
| 1367 | spin_unlock(&new_base->lock); | ||
| 1368 | 1365 | ||
| 1366 | double_spin_unlock(&new_base->lock, &old_base->lock, | ||
| 1367 | smp_processor_id() < cpu); | ||
| 1369 | local_irq_enable(); | 1368 | local_irq_enable(); |
| 1370 | put_cpu_var(hrtimer_bases); | 1369 | put_cpu_var(hrtimer_bases); |
| 1371 | } | 1370 | } |
diff --git a/kernel/timer.c b/kernel/timer.c index 6663a87f7304..8ad384253ef2 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -1651,8 +1651,8 @@ static void __devinit migrate_timers(int cpu) | |||
| 1651 | new_base = get_cpu_var(tvec_bases); | 1651 | new_base = get_cpu_var(tvec_bases); |
| 1652 | 1652 | ||
| 1653 | local_irq_disable(); | 1653 | local_irq_disable(); |
| 1654 | spin_lock(&new_base->lock); | 1654 | double_spin_lock(&new_base->lock, &old_base->lock, |
| 1655 | spin_lock(&old_base->lock); | 1655 | smp_processor_id() < cpu); |
| 1656 | 1656 | ||
| 1657 | BUG_ON(old_base->running_timer); | 1657 | BUG_ON(old_base->running_timer); |
| 1658 | 1658 | ||
| @@ -1665,8 +1665,8 @@ static void __devinit migrate_timers(int cpu) | |||
| 1665 | migrate_timer_list(new_base, old_base->tv5.vec + i); | 1665 | migrate_timer_list(new_base, old_base->tv5.vec + i); |
| 1666 | } | 1666 | } |
| 1667 | 1667 | ||
| 1668 | spin_unlock(&old_base->lock); | 1668 | double_spin_unlock(&new_base->lock, &old_base->lock, |
| 1669 | spin_unlock(&new_base->lock); | 1669 | smp_processor_id() < cpu); |
| 1670 | local_irq_enable(); | 1670 | local_irq_enable(); |
| 1671 | put_cpu_var(tvec_bases); | 1671 | put_cpu_var(tvec_bases); |
| 1672 | } | 1672 | } |
