/* * Generic function to trigger preemption on either local or remote cpu * from scheduler plugins. The key feature is that this function is * non-preemptive section aware and does not invoke the scheduler / send * IPIs if the to-be-preempted task is actually non-preemptive. */ void preempt_if_preemptable(struct task_struct* t, int cpu) { /* t is the real-time task executing on CPU on_cpu If t is NULL, then * on_cpu is currently scheduling background work. */ int reschedule = 0; if (!t) /* move non-real-time task out of the way */ reschedule = 1; else { if (smp_processor_id() == cpu) { /* local CPU case */ /* check if we need to poke userspace */ if (is_user_np(t)) /* Yes, poke it. This doesn't have to be atomic since * the task is definitely not executing. */ request_exit_np(t); else if (!is_kernel_np(t)) /* only if we are allowed to preempt the * currently-executing task */ reschedule = 1; } else { /* Remote CPU case. Only notify if it's not a kernel * NP section and if we didn't set the userspace * flag. */ reschedule = !(is_kernel_np(t) || request_exit_np_atomic(t)); } } if (likely(reschedule)) litmus_reschedule(cpu); }
static enum hrtimer_restart psnedf_simple_on_exhausted(struct task_struct *t, int in_schedule) { /* Assumption: t is scheduled on the CPU executing this callback */ if (budget_signalled(t) && !bt_flag_is_set(t, BTF_SIG_BUDGET_SENT)) { /* signal exhaustion */ send_sigbudget(t); /* will set BTF_SIG_BUDGET_SENT */ } if (budget_enforced(t) && !bt_flag_test_and_set(t, BTF_BUDGET_EXHAUSTED)) { if (!is_np(t)) { /* np tasks will be preempted when they become * preemptable again */ litmus_reschedule_local(); TRACE("%d is preemptable => FORCE_RESCHED\n", t->pid); } else if (is_user_np(t)) { TRACE("%d is non-preemptable, preemption delayed.\n", t->pid); request_exit_np(t); } } return HRTIMER_NORESTART; }