diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-04 12:49:19 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-04 12:49:19 -0500 |
commit | 28b1bd1cbc33cae95a309691d814399a69cf3070 (patch) | |
tree | 6474d10332662f5302be0df8527c9e9e31e32a95 /kernel/sched.c | |
parent | 2602c3ba4508f528db024c1d209256513ea05de6 (diff) | |
parent | 1075414b06109a99b0e87601e84c74a95bd45681 (diff) |
Merge branch 'core/locking' into tracing/ftrace
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 328f9c7448a5..e1f676e20119 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4543,15 +4543,13 @@ pick_next_task(struct rq *rq, struct task_struct *prev) | |||
4543 | /* | 4543 | /* |
4544 | * schedule() is the main scheduler function. | 4544 | * schedule() is the main scheduler function. |
4545 | */ | 4545 | */ |
4546 | asmlinkage void __sched schedule(void) | 4546 | asmlinkage void __sched __schedule(void) |
4547 | { | 4547 | { |
4548 | struct task_struct *prev, *next; | 4548 | struct task_struct *prev, *next; |
4549 | unsigned long *switch_count; | 4549 | unsigned long *switch_count; |
4550 | struct rq *rq; | 4550 | struct rq *rq; |
4551 | int cpu; | 4551 | int cpu; |
4552 | 4552 | ||
4553 | need_resched: | ||
4554 | preempt_disable(); | ||
4555 | cpu = smp_processor_id(); | 4553 | cpu = smp_processor_id(); |
4556 | rq = cpu_rq(cpu); | 4554 | rq = cpu_rq(cpu); |
4557 | rcu_qsctr_inc(cpu); | 4555 | rcu_qsctr_inc(cpu); |
@@ -4608,13 +4606,80 @@ need_resched_nonpreemptible: | |||
4608 | 4606 | ||
4609 | if (unlikely(reacquire_kernel_lock(current) < 0)) | 4607 | if (unlikely(reacquire_kernel_lock(current) < 0)) |
4610 | goto need_resched_nonpreemptible; | 4608 | goto need_resched_nonpreemptible; |
4609 | } | ||
4611 | 4610 | ||
4611 | asmlinkage void __sched schedule(void) | ||
4612 | { | ||
4613 | need_resched: | ||
4614 | preempt_disable(); | ||
4615 | __schedule(); | ||
4612 | preempt_enable_no_resched(); | 4616 | preempt_enable_no_resched(); |
4613 | if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) | 4617 | if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) |
4614 | goto need_resched; | 4618 | goto need_resched; |
4615 | } | 4619 | } |
4616 | EXPORT_SYMBOL(schedule); | 4620 | EXPORT_SYMBOL(schedule); |
4617 | 4621 | ||
4622 | #ifdef CONFIG_SMP | ||
4623 | /* | ||
4624 | * Look out! "owner" is an entirely speculative pointer | ||
4625 | * access and not reliable. | ||
4626 | */ | ||
4627 | int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner) | ||
4628 | { | ||
4629 | unsigned int cpu; | ||
4630 | struct rq *rq; | ||
4631 | |||
4632 | if (!sched_feat(OWNER_SPIN)) | ||
4633 | return 0; | ||
4634 | |||
4635 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
4636 | /* | ||
4637 | * Need to access the cpu field knowing that | ||
4638 | * DEBUG_PAGEALLOC could have unmapped it if | ||
4639 | * the mutex owner just released it and exited. | ||
4640 | */ | ||
4641 | if (probe_kernel_address(&owner->cpu, cpu)) | ||
4642 | goto out; | ||
4643 | #else | ||
4644 | cpu = owner->cpu; | ||
4645 | #endif | ||
4646 | |||
4647 | /* | ||
4648 | * Even if the access succeeded (likely case), | ||
4649 | * the cpu field may no longer be valid. | ||
4650 | */ | ||
4651 | if (cpu >= nr_cpumask_bits) | ||
4652 | goto out; | ||
4653 | |||
4654 | /* | ||
4655 | * We need to validate that we can do a | ||
4656 | * get_cpu() and that we have the percpu area. | ||
4657 | */ | ||
4658 | if (!cpu_online(cpu)) | ||
4659 | goto out; | ||
4660 | |||
4661 | rq = cpu_rq(cpu); | ||
4662 | |||
4663 | for (;;) { | ||
4664 | /* | ||
4665 | * Owner changed, break to re-assess state. | ||
4666 | */ | ||
4667 | if (lock->owner != owner) | ||
4668 | break; | ||
4669 | |||
4670 | /* | ||
4671 | * Is that owner really running on that cpu? | ||
4672 | */ | ||
4673 | if (task_thread_info(rq->curr) != owner || need_resched()) | ||
4674 | return 0; | ||
4675 | |||
4676 | cpu_relax(); | ||
4677 | } | ||
4678 | out: | ||
4679 | return 1; | ||
4680 | } | ||
4681 | #endif | ||
4682 | |||
4618 | #ifdef CONFIG_PREEMPT | 4683 | #ifdef CONFIG_PREEMPT |
4619 | /* | 4684 | /* |
4620 | * this is the entry point to schedule() from in-kernel preemption | 4685 | * this is the entry point to schedule() from in-kernel preemption |