asmlinkage __visible void __sched notrace preempt_schedule(void)
这个函数用于检查当前thread是否可以主动让出cpu给其他thread 运行
其使用的例子如下:
static void torture_rwsem_write_delay(struct torture_random_state *trsp)
{
	const unsigned long longdelay_ms = 100;

	/* We want a long delay occasionally to force massive contention.  */
	if (!(torture_random(trsp) %
	      (cxt.nrealwriters_stress * 2000 * longdelay_ms)))
		mdelay(longdelay_ms * 10);
	else
		mdelay(longdelay_ms / 10);
#ifdef CONFIG_PREEMPT
	if (!(torture_random(trsp) % (cxt.nrealwriters_stress * 20000)))
		preempt_schedule();  /* Allow test to be preempted. */
#endif
}
这个例子中就通过preempt_schedule 来判断当前thread是否可以主动释放cpu
其源码分析如下:
asmlinkage __visible void __sched notrace preempt_schedule(void)
{
	/*
	 * If there is a non-zero preempt_count or interrupts are disabled,
	 * we do not want to preempt the current task. Just return..
	 */
	if (likely(!preemptible()))
		return;

	preempt_schedule_common();
}
首先这里判断当前thread是否可以让出cpu的条件是preemptible。
#define preemptible()	(preempt_count() == 0 && !irqs_disabled())
这个条件就是当前thrad 的preempt_count等于0,且没有禁止irq
不过这里用likely修饰!,所以这个条件一般会成立,也就是当前thread 不会主动让出cpu
假定条件成立,则调用preempt_schedule_common 来开始调度
static void __sched notrace preempt_schedule_common(void)
{
	do {
		/*
		 * Because the function tracer can trace preempt_count_sub()
		 * and it also uses preempt_enable/disable_notrace(), if
		 * NEED_RESCHED is set, the preempt_enable_notrace() called
		 * by the function tracer will call this function again and
		 * cause infinite recursion.
		 *
		 * Preemption must be disabled here before the function
		 * tracer can trace. Break up preempt_disable() into two
		 * calls. One to disable preemption without fear of being
		 * traced. The other to still record the preemption latency,
		 * which can also be traced by the function tracer.
		 */
		preempt_disable_notrace();
		preempt_latency_start(1);
		__schedule(true);
		preempt_latency_stop(1);
		preempt_enable_no_resched_notrace();

		/*
		 * Check again in case we missed a preemption opportunity
		 * between schedule and now.
		 */
	} while (need_resched());
}
这个函数的核心就是调用__schedule 来让出cpu。

更多推荐

进程调度API之preempt_schedule