aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index b001c133c359..589e7308c615 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4614,6 +4614,67 @@ need_resched:
4614} 4614}
4615EXPORT_SYMBOL(schedule); 4615EXPORT_SYMBOL(schedule);
4616 4616
4617#ifdef CONFIG_SMP
4618/*
4619 * Look out! "owner" is an entirely speculative pointer
4620 * access and not reliable.
4621 */
4622int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
4623{
4624 unsigned int cpu;
4625 struct rq *rq;
4626
4627 if (!sched_feat(OWNER_SPIN))
4628 return 0;
4629
4630#ifdef CONFIG_DEBUG_PAGEALLOC
4631 /*
4632 * Need to access the cpu field knowing that
4633 * DEBUG_PAGEALLOC could have unmapped it if
4634 * the mutex owner just released it and exited.
4635 */
4636 if (probe_kernel_address(&owner->cpu, cpu))
4637 goto out;
4638#else
4639 cpu = owner->cpu;
4640#endif
4641
4642 /*
4643 * Even if the access succeeded (likely case),
4644 * the cpu field may no longer be valid.
4645 */
4646 if (cpu >= nr_cpumask_bits)
4647 goto out;
4648
4649 /*
4650 * We need to validate that we can do a
4651 * get_cpu() and that we have the percpu area.
4652 */
4653 if (!cpu_online(cpu))
4654 goto out;
4655
4656 rq = cpu_rq(cpu);
4657
4658 for (;;) {
4659 /*
4660 * Owner changed, break to re-assess state.
4661 */
4662 if (lock->owner != owner)
4663 break;
4664
4665 /*
4666 * Is that owner really running on that cpu?
4667 */
4668 if (task_thread_info(rq->curr) != owner || need_resched())
4669 return 0;
4670
4671 cpu_relax();
4672 }
4673out:
4674 return 1;
4675}
4676#endif
4677
4617#ifdef CONFIG_PREEMPT 4678#ifdef CONFIG_PREEMPT
4618/* 4679/*
4619 * this is the entry point to schedule() from in-kernel preemption 4680 * this is the entry point to schedule() from in-kernel preemption