diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/futex.c | 16 | ||||
-rw-r--r-- | kernel/hrtimer.c | 2 | ||||
-rw-r--r-- | kernel/panic.c | 1 | ||||
-rw-r--r-- | kernel/timer.c | 41 | ||||
-rw-r--r-- | kernel/workqueue.c | 33 |
5 files changed, 40 insertions, 53 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index c2b2e0b83abf..d4633c588f33 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -297,7 +297,7 @@ static int futex_handle_fault(unsigned long address, int attempt) | |||
297 | struct vm_area_struct * vma; | 297 | struct vm_area_struct * vma; |
298 | struct mm_struct *mm = current->mm; | 298 | struct mm_struct *mm = current->mm; |
299 | 299 | ||
300 | if (attempt >= 2 || !(vma = find_vma(mm, address)) || | 300 | if (attempt > 2 || !(vma = find_vma(mm, address)) || |
301 | vma->vm_start > address || !(vma->vm_flags & VM_WRITE)) | 301 | vma->vm_start > address || !(vma->vm_flags & VM_WRITE)) |
302 | return -EFAULT; | 302 | return -EFAULT; |
303 | 303 | ||
@@ -747,8 +747,10 @@ retry: | |||
747 | */ | 747 | */ |
748 | if (attempt++) { | 748 | if (attempt++) { |
749 | if (futex_handle_fault((unsigned long)uaddr2, | 749 | if (futex_handle_fault((unsigned long)uaddr2, |
750 | attempt)) | 750 | attempt)) { |
751 | ret = -EFAULT; | ||
751 | goto out; | 752 | goto out; |
753 | } | ||
752 | goto retry; | 754 | goto retry; |
753 | } | 755 | } |
754 | 756 | ||
@@ -1322,9 +1324,10 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, | |||
1322 | * still holding the mmap_sem. | 1324 | * still holding the mmap_sem. |
1323 | */ | 1325 | */ |
1324 | if (attempt++) { | 1326 | if (attempt++) { |
1325 | if (futex_handle_fault((unsigned long)uaddr, attempt)) | 1327 | if (futex_handle_fault((unsigned long)uaddr, attempt)) { |
1328 | ret = -EFAULT; | ||
1326 | goto out_unlock_release_sem; | 1329 | goto out_unlock_release_sem; |
1327 | 1330 | } | |
1328 | goto retry_locked; | 1331 | goto retry_locked; |
1329 | } | 1332 | } |
1330 | 1333 | ||
@@ -1506,9 +1509,10 @@ pi_faulted: | |||
1506 | * still holding the mmap_sem. | 1509 | * still holding the mmap_sem. |
1507 | */ | 1510 | */ |
1508 | if (attempt++) { | 1511 | if (attempt++) { |
1509 | if (futex_handle_fault((unsigned long)uaddr, attempt)) | 1512 | if (futex_handle_fault((unsigned long)uaddr, attempt)) { |
1513 | ret = -EFAULT; | ||
1510 | goto out_unlock; | 1514 | goto out_unlock; |
1511 | 1515 | } | |
1512 | goto retry_locked; | 1516 | goto retry_locked; |
1513 | } | 1517 | } |
1514 | 1518 | ||
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index be989efc7856..21c38a7e666b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -187,7 +187,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base) | |||
187 | { | 187 | { |
188 | struct hrtimer_base *new_base; | 188 | struct hrtimer_base *new_base; |
189 | 189 | ||
190 | new_base = &__get_cpu_var(hrtimer_bases[base->index]); | 190 | new_base = &__get_cpu_var(hrtimer_bases)[base->index]; |
191 | 191 | ||
192 | if (base != new_base) { | 192 | if (base != new_base) { |
193 | /* | 193 | /* |
diff --git a/kernel/panic.c b/kernel/panic.c index d8a0bca21233..9b8dcfd1ca93 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/nmi.h> | 19 | #include <linux/nmi.h> |
20 | #include <linux/kexec.h> | 20 | #include <linux/kexec.h> |
21 | #include <linux/debug_locks.h> | ||
21 | 22 | ||
22 | int panic_on_oops; | 23 | int panic_on_oops; |
23 | int tainted; | 24 | int tainted; |
diff --git a/kernel/timer.c b/kernel/timer.c index b650f04888ed..1d7dd6267c2d 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1324,46 +1324,19 @@ asmlinkage long sys_getpid(void) | |||
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | /* | 1326 | /* |
1327 | * Accessing ->group_leader->real_parent is not SMP-safe, it could | 1327 | * Accessing ->real_parent is not SMP-safe, it could |
1328 | * change from under us. However, rather than getting any lock | 1328 | * change from under us. However, we can use a stale |
1329 | * we can use an optimistic algorithm: get the parent | 1329 | * value of ->real_parent under rcu_read_lock(), see |
1330 | * pid, and go back and check that the parent is still | 1330 | * release_task()->call_rcu(delayed_put_task_struct). |
1331 | * the same. If it has changed (which is extremely unlikely | ||
1332 | * indeed), we just try again.. | ||
1333 | * | ||
1334 | * NOTE! This depends on the fact that even if we _do_ | ||
1335 | * get an old value of "parent", we can happily dereference | ||
1336 | * the pointer (it was and remains a dereferencable kernel pointer | ||
1337 | * no matter what): we just can't necessarily trust the result | ||
1338 | * until we know that the parent pointer is valid. | ||
1339 | * | ||
1340 | * NOTE2: ->group_leader never changes from under us. | ||
1341 | */ | 1331 | */ |
1342 | asmlinkage long sys_getppid(void) | 1332 | asmlinkage long sys_getppid(void) |
1343 | { | 1333 | { |
1344 | int pid; | 1334 | int pid; |
1345 | struct task_struct *me = current; | ||
1346 | struct task_struct *parent; | ||
1347 | 1335 | ||
1348 | parent = me->group_leader->real_parent; | 1336 | rcu_read_lock(); |
1349 | for (;;) { | 1337 | pid = rcu_dereference(current->real_parent)->tgid; |
1350 | pid = parent->tgid; | 1338 | rcu_read_unlock(); |
1351 | #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) | ||
1352 | { | ||
1353 | struct task_struct *old = parent; | ||
1354 | 1339 | ||
1355 | /* | ||
1356 | * Make sure we read the pid before re-reading the | ||
1357 | * parent pointer: | ||
1358 | */ | ||
1359 | smp_rmb(); | ||
1360 | parent = me->group_leader->real_parent; | ||
1361 | if (old != parent) | ||
1362 | continue; | ||
1363 | } | ||
1364 | #endif | ||
1365 | break; | ||
1366 | } | ||
1367 | return pid; | 1340 | return pid; |
1368 | } | 1341 | } |
1369 | 1342 | ||
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 448e8f7b342d..835fe28b87a8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -68,7 +68,7 @@ struct workqueue_struct { | |||
68 | 68 | ||
69 | /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove | 69 | /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove |
70 | threads to each one as cpus come/go. */ | 70 | threads to each one as cpus come/go. */ |
71 | static DEFINE_SPINLOCK(workqueue_lock); | 71 | static DEFINE_MUTEX(workqueue_mutex); |
72 | static LIST_HEAD(workqueues); | 72 | static LIST_HEAD(workqueues); |
73 | 73 | ||
74 | static int singlethread_cpu; | 74 | static int singlethread_cpu; |
@@ -320,10 +320,10 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) | |||
320 | } else { | 320 | } else { |
321 | int cpu; | 321 | int cpu; |
322 | 322 | ||
323 | lock_cpu_hotplug(); | 323 | mutex_lock(&workqueue_mutex); |
324 | for_each_online_cpu(cpu) | 324 | for_each_online_cpu(cpu) |
325 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); | 325 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); |
326 | unlock_cpu_hotplug(); | 326 | mutex_unlock(&workqueue_mutex); |
327 | } | 327 | } |
328 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(flush_workqueue); | 329 | EXPORT_SYMBOL_GPL(flush_workqueue); |
@@ -371,8 +371,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
371 | } | 371 | } |
372 | 372 | ||
373 | wq->name = name; | 373 | wq->name = name; |
374 | /* We don't need the distraction of CPUs appearing and vanishing. */ | 374 | mutex_lock(&workqueue_mutex); |
375 | lock_cpu_hotplug(); | ||
376 | if (singlethread) { | 375 | if (singlethread) { |
377 | INIT_LIST_HEAD(&wq->list); | 376 | INIT_LIST_HEAD(&wq->list); |
378 | p = create_workqueue_thread(wq, singlethread_cpu); | 377 | p = create_workqueue_thread(wq, singlethread_cpu); |
@@ -381,9 +380,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
381 | else | 380 | else |
382 | wake_up_process(p); | 381 | wake_up_process(p); |
383 | } else { | 382 | } else { |
384 | spin_lock(&workqueue_lock); | ||
385 | list_add(&wq->list, &workqueues); | 383 | list_add(&wq->list, &workqueues); |
386 | spin_unlock(&workqueue_lock); | ||
387 | for_each_online_cpu(cpu) { | 384 | for_each_online_cpu(cpu) { |
388 | p = create_workqueue_thread(wq, cpu); | 385 | p = create_workqueue_thread(wq, cpu); |
389 | if (p) { | 386 | if (p) { |
@@ -393,7 +390,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
393 | destroy = 1; | 390 | destroy = 1; |
394 | } | 391 | } |
395 | } | 392 | } |
396 | unlock_cpu_hotplug(); | 393 | mutex_unlock(&workqueue_mutex); |
397 | 394 | ||
398 | /* | 395 | /* |
399 | * Was there any error during startup? If yes then clean up: | 396 | * Was there any error during startup? If yes then clean up: |
@@ -434,17 +431,15 @@ void destroy_workqueue(struct workqueue_struct *wq) | |||
434 | flush_workqueue(wq); | 431 | flush_workqueue(wq); |
435 | 432 | ||
436 | /* We don't need the distraction of CPUs appearing and vanishing. */ | 433 | /* We don't need the distraction of CPUs appearing and vanishing. */ |
437 | lock_cpu_hotplug(); | 434 | mutex_lock(&workqueue_mutex); |
438 | if (is_single_threaded(wq)) | 435 | if (is_single_threaded(wq)) |
439 | cleanup_workqueue_thread(wq, singlethread_cpu); | 436 | cleanup_workqueue_thread(wq, singlethread_cpu); |
440 | else { | 437 | else { |
441 | for_each_online_cpu(cpu) | 438 | for_each_online_cpu(cpu) |
442 | cleanup_workqueue_thread(wq, cpu); | 439 | cleanup_workqueue_thread(wq, cpu); |
443 | spin_lock(&workqueue_lock); | ||
444 | list_del(&wq->list); | 440 | list_del(&wq->list); |
445 | spin_unlock(&workqueue_lock); | ||
446 | } | 441 | } |
447 | unlock_cpu_hotplug(); | 442 | mutex_unlock(&workqueue_mutex); |
448 | free_percpu(wq->cpu_wq); | 443 | free_percpu(wq->cpu_wq); |
449 | kfree(wq); | 444 | kfree(wq); |
450 | } | 445 | } |
@@ -515,11 +510,13 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info) | |||
515 | if (!works) | 510 | if (!works) |
516 | return -ENOMEM; | 511 | return -ENOMEM; |
517 | 512 | ||
513 | mutex_lock(&workqueue_mutex); | ||
518 | for_each_online_cpu(cpu) { | 514 | for_each_online_cpu(cpu) { |
519 | INIT_WORK(per_cpu_ptr(works, cpu), func, info); | 515 | INIT_WORK(per_cpu_ptr(works, cpu), func, info); |
520 | __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), | 516 | __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), |
521 | per_cpu_ptr(works, cpu)); | 517 | per_cpu_ptr(works, cpu)); |
522 | } | 518 | } |
519 | mutex_unlock(&workqueue_mutex); | ||
523 | flush_workqueue(keventd_wq); | 520 | flush_workqueue(keventd_wq); |
524 | free_percpu(works); | 521 | free_percpu(works); |
525 | return 0; | 522 | return 0; |
@@ -635,6 +632,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
635 | 632 | ||
636 | switch (action) { | 633 | switch (action) { |
637 | case CPU_UP_PREPARE: | 634 | case CPU_UP_PREPARE: |
635 | mutex_lock(&workqueue_mutex); | ||
638 | /* Create a new workqueue thread for it. */ | 636 | /* Create a new workqueue thread for it. */ |
639 | list_for_each_entry(wq, &workqueues, list) { | 637 | list_for_each_entry(wq, &workqueues, list) { |
640 | if (!create_workqueue_thread(wq, hotcpu)) { | 638 | if (!create_workqueue_thread(wq, hotcpu)) { |
@@ -653,6 +651,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
653 | kthread_bind(cwq->thread, hotcpu); | 651 | kthread_bind(cwq->thread, hotcpu); |
654 | wake_up_process(cwq->thread); | 652 | wake_up_process(cwq->thread); |
655 | } | 653 | } |
654 | mutex_unlock(&workqueue_mutex); | ||
656 | break; | 655 | break; |
657 | 656 | ||
658 | case CPU_UP_CANCELED: | 657 | case CPU_UP_CANCELED: |
@@ -664,6 +663,15 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
664 | any_online_cpu(cpu_online_map)); | 663 | any_online_cpu(cpu_online_map)); |
665 | cleanup_workqueue_thread(wq, hotcpu); | 664 | cleanup_workqueue_thread(wq, hotcpu); |
666 | } | 665 | } |
666 | mutex_unlock(&workqueue_mutex); | ||
667 | break; | ||
668 | |||
669 | case CPU_DOWN_PREPARE: | ||
670 | mutex_lock(&workqueue_mutex); | ||
671 | break; | ||
672 | |||
673 | case CPU_DOWN_FAILED: | ||
674 | mutex_unlock(&workqueue_mutex); | ||
667 | break; | 675 | break; |
668 | 676 | ||
669 | case CPU_DEAD: | 677 | case CPU_DEAD: |
@@ -671,6 +679,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
671 | cleanup_workqueue_thread(wq, hotcpu); | 679 | cleanup_workqueue_thread(wq, hotcpu); |
672 | list_for_each_entry(wq, &workqueues, list) | 680 | list_for_each_entry(wq, &workqueues, list) |
673 | take_over_work(wq, hotcpu); | 681 | take_over_work(wq, hotcpu); |
682 | mutex_unlock(&workqueue_mutex); | ||
674 | break; | 683 | break; |
675 | } | 684 | } |
676 | 685 | ||