aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2010-02-03 19:42:02 -0500
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-29 17:26:19 -0400
commitf3a6cb9af5cdb01f29ad32b01aa56a14f0da144e (patch)
tree89a514e925a1e6f6cb1e97c1e9a8df999a403927
parentfb95c290fe461de794c984bc4130741f04f9142d (diff)
Introduce generic NP-section aware preemption function
Dealing with preemptions across CPUs in the presence of non-preemptive sections can be tricky and should not be replicated across (event-driven) plugins. This patch introduces a generic preemption function that handles non-preemptive sections (hopefully) correctly.
-rw-r--r--include/litmus/litmus.h1
-rw-r--r--litmus/sched_plugin.c60
2 files changed, 60 insertions, 1 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index faaf83961dfa..62107e659c12 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -124,6 +124,7 @@ static inline lt_t litmus_clock(void)
124 (a)->rt_param.job_params.release,\ 124 (a)->rt_param.job_params.release,\
125 (b)->rt_param.job_params.release)) 125 (b)->rt_param.job_params.release))
126 126
127void preempt_if_preemptable(struct task_struct* t, int on_cpu);
127 128
128#ifdef CONFIG_SRP 129#ifdef CONFIG_SRP
129void srp_ceiling_block(void); 130void srp_ceiling_block(void);
diff --git a/litmus/sched_plugin.c b/litmus/sched_plugin.c
index 0be091ece569..bc7c0e93fb18 100644
--- a/litmus/sched_plugin.c
+++ b/litmus/sched_plugin.c
@@ -1,7 +1,7 @@
1/* sched_plugin.c -- core infrastructure for the scheduler plugin system 1/* sched_plugin.c -- core infrastructure for the scheduler plugin system
2 * 2 *
3 * This file includes the initialization of the plugin system, the no-op Linux 3 * This file includes the initialization of the plugin system, the no-op Linux
4 * scheduler plugin and some dummy functions. 4 * scheduler plugin, some dummy functions, and some helper functions.
5 */ 5 */
6 6
7#include <linux/list.h> 7#include <linux/list.h>
@@ -12,6 +12,64 @@
12 12
13#include <litmus/jobs.h> 13#include <litmus/jobs.h>
14 14
15/*
16 * Generic function to trigger preemption on either local or remote cpu
17 * from scheduler plugins. The key feature is that this function is
18 * non-preemptive section aware and does not invoke the scheduler / send
19 * IPIs if the to-be-preempted task is actually non-preemptive.
20 */
21void preempt_if_preemptable(struct task_struct* t, int on_cpu)
22{
23 /* t is the real-time task executing on CPU on_cpu If t is NULL, then
24 * on_cpu is currently scheduling background work.
25 */
26
27 int send_ipi;
28
29 if (smp_processor_id() == on_cpu) {
30 /* local CPU case */
31 if (t) {
32 /* check if we need to poke userspace */
33 if (is_user_np(t))
34 /* yes, poke it */
35 request_exit_np(t);
36 else
37 /* no, see if we are allowed to preempt the
38 * currently-executing task */
39 if (!is_kernel_np(t))
40 set_tsk_need_resched(t);
41 } else
42 /* move non-real-time task out of the way */
43 set_tsk_need_resched(current);
44 } else {
45 /* remote CPU case */
46 if (!t)
47 /* currently schedules non-real-time work */
48 send_ipi = 1;
49 else {
50 /* currently schedules real-time work */
51 if (is_user_np(t)) {
52 /* need to notify user space of delayed
53 * preemption */
54
55 /* to avoid a race, set the flag, then test
56 * again */
57 request_exit_np(t);
58 /* make sure it got written */
59 mb();
60 }
61 /* Only send an ipi if remote task might have raced our
62 * request, i.e., send an IPI to make sure if it exited
63 * its critical section.
64 */
65 send_ipi = !is_np(t) && !is_kernel_np(t);
66 }
67 if (likely(send_ipi))
68 smp_send_reschedule(on_cpu);
69 }
70}
71
72
15/************************************************************* 73/*************************************************************
16 * Dummy plugin functions * 74 * Dummy plugin functions *
17 *************************************************************/ 75 *************************************************************/