diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-02-03 19:42:02 -0500 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-29 17:26:19 -0400 |
commit | f3a6cb9af5cdb01f29ad32b01aa56a14f0da144e (patch) | |
tree | 89a514e925a1e6f6cb1e97c1e9a8df999a403927 /litmus/sched_plugin.c | |
parent | fb95c290fe461de794c984bc4130741f04f9142d (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.
Diffstat (limited to 'litmus/sched_plugin.c')
-rw-r--r-- | litmus/sched_plugin.c | 60 |
1 files changed, 59 insertions, 1 deletions
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 | */ | ||
21 | void 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 | *************************************************************/ |