aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_plugin.c
diff options
context:
space:
mode:
authorJeremy Erickson <jerickso@cs.unc.edu>2012-08-30 21:01:47 -0400
committerJeremy Erickson <jerickso@cs.unc.edu>2012-08-30 21:01:47 -0400
commitb1e1fea67bca3796d5f9133a92c300ec4fa93a4f (patch)
tree5cc1336e1fe1d6f93b1067e73e43381dd20db690 /litmus/sched_plugin.c
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Bjoern's Dissertation Code with Priority Donationwip-splitting-omlp-jerickso
Diffstat (limited to 'litmus/sched_plugin.c')
-rw-r--r--litmus/sched_plugin.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/litmus/sched_plugin.c b/litmus/sched_plugin.c
new file mode 100644
index 000000000000..950fe5e6a1ab
--- /dev/null
+++ b/litmus/sched_plugin.c
@@ -0,0 +1,233 @@
1/* sched_plugin.c -- core infrastructure for the scheduler plugin system
2 *
3 * This file includes the initialization of the plugin system, the no-op Linux
4 * scheduler plugin, some dummy functions, and some helper functions.
5 */
6
7#include <linux/list.h>
8#include <linux/spinlock.h>
9#include <linux/sched.h>
10
11#include <litmus/litmus.h>
12#include <litmus/sched_plugin.h>
13#include <litmus/preempt.h>
14#include <litmus/jobs.h>
15
16/*
17 * Generic function to trigger preemption on either local or remote cpu
18 * from scheduler plugins. The key feature is that this function is
19 * non-preemptive section aware and does not invoke the scheduler / send
20 * IPIs if the to-be-preempted task is actually non-preemptive.
21 */
22void preempt_if_preemptable(struct task_struct* t, int cpu)
23{
24 /* t is the real-time task executing on CPU on_cpu If t is NULL, then
25 * on_cpu is currently scheduling background work.
26 */
27
28 int reschedule = 0;
29
30 if (!t)
31 /* move non-real-time task out of the way */
32 reschedule = 1;
33 else {
34 if (smp_processor_id() == cpu) {
35 /* local CPU case */
36 /* check if we need to poke userspace */
37 if (is_user_np(t))
38 /* Yes, poke it. This doesn't have to be atomic since
39 * the task is definitely not executing. */
40 request_exit_np(t);
41 else if (!is_kernel_np(t))
42 /* only if we are allowed to preempt the
43 * currently-executing task */
44 reschedule = 1;
45 } else {
46 /* Remote CPU case. Only notify if it's not a kernel
47 * NP section and if we didn't set the userspace
48 * flag. */
49 reschedule = !(is_kernel_np(t) || request_exit_np_atomic(t));
50 }
51 }
52 if (likely(reschedule))
53 litmus_reschedule(cpu);
54}
55
56
57/*************************************************************
58 * Dummy plugin functions *
59 *************************************************************/
60
61static void litmus_dummy_finish_switch(struct task_struct * prev)
62{
63}
64
65static struct task_struct* litmus_dummy_schedule(struct task_struct * prev)
66{
67 sched_state_task_picked();
68 return NULL;
69}
70
71static void litmus_dummy_tick(struct task_struct* tsk)
72{
73}
74
75static long litmus_dummy_admit_task(struct task_struct* tsk)
76{
77 printk(KERN_CRIT "LITMUS^RT: Linux plugin rejects %s/%d.\n",
78 tsk->comm, tsk->pid);
79 return -EINVAL;
80}
81
82static void litmus_dummy_task_new(struct task_struct *t, int on_rq, int running)
83{
84}
85
86static void litmus_dummy_task_wake_up(struct task_struct *task)
87{
88}
89
90static void litmus_dummy_task_block(struct task_struct *task)
91{
92}
93
94static void litmus_dummy_task_exit(struct task_struct *task)
95{
96}
97
98static void litmus_dummy_pre_setsched(struct task_struct *task, int policy)
99{
100}
101
102
103static long litmus_dummy_complete_job(void)
104{
105 return -ENOSYS;
106}
107
108static long litmus_dummy_activate_plugin(void)
109{
110 return 0;
111}
112
113static long litmus_dummy_deactivate_plugin(void)
114{
115 return 0;
116}
117
118#ifdef CONFIG_LITMUS_LOCKING
119
120static long litmus_dummy_allocate_lock(struct litmus_lock **lock, int type,
121 void* __user config)
122{
123 return -ENXIO;
124}
125
126#endif
127
128
129/* The default scheduler plugin. It doesn't do anything and lets Linux do its
130 * job.
131 */
132struct sched_plugin linux_sched_plugin = {
133 .plugin_name = "Linux",
134 .tick = litmus_dummy_tick,
135 .task_new = litmus_dummy_task_new,
136 .task_exit = litmus_dummy_task_exit,
137 .task_wake_up = litmus_dummy_task_wake_up,
138 .task_block = litmus_dummy_task_block,
139 .complete_job = litmus_dummy_complete_job,
140 .schedule = litmus_dummy_schedule,
141 .finish_switch = litmus_dummy_finish_switch,
142 .activate_plugin = litmus_dummy_activate_plugin,
143 .deactivate_plugin = litmus_dummy_deactivate_plugin,
144#ifdef CONFIG_LITMUS_LOCKING
145 .allocate_lock = litmus_dummy_allocate_lock,
146#endif
147 .admit_task = litmus_dummy_admit_task
148};
149
150/*
151 * The reference to current plugin that is used to schedule tasks within
152 * the system. It stores references to actual function implementations
153 * Should be initialized by calling "init_***_plugin()"
154 */
155struct sched_plugin *litmus = &linux_sched_plugin;
156
157/* the list of registered scheduling plugins */
158static LIST_HEAD(sched_plugins);
159static DEFINE_RAW_SPINLOCK(sched_plugins_lock);
160
161#define CHECK(func) {\
162 if (!plugin->func) \
163 plugin->func = litmus_dummy_ ## func;}
164
165/* FIXME: get reference to module */
166int register_sched_plugin(struct sched_plugin* plugin)
167{
168 printk(KERN_INFO "Registering LITMUS^RT plugin %s.\n",
169 plugin->plugin_name);
170
171 /* make sure we don't trip over null pointers later */
172 CHECK(finish_switch);
173 CHECK(schedule);
174 CHECK(tick);
175 CHECK(task_wake_up);
176 CHECK(task_exit);
177 CHECK(task_block);
178 CHECK(task_new);
179 CHECK(complete_job);
180 CHECK(activate_plugin);
181 CHECK(deactivate_plugin);
182#ifdef CONFIG_LITMUS_LOCKING
183 CHECK(allocate_lock);
184#endif
185 CHECK(admit_task);
186 CHECK(pre_setsched);
187
188 if (!plugin->release_at)
189 plugin->release_at = release_at;
190
191 raw_spin_lock(&sched_plugins_lock);
192 list_add(&plugin->list, &sched_plugins);
193 raw_spin_unlock(&sched_plugins_lock);
194
195 return 0;
196}
197
198
199/* FIXME: reference counting, etc. */
200struct sched_plugin* find_sched_plugin(const char* name)
201{
202 struct list_head *pos;
203 struct sched_plugin *plugin;
204
205 raw_spin_lock(&sched_plugins_lock);
206 list_for_each(pos, &sched_plugins) {
207 plugin = list_entry(pos, struct sched_plugin, list);
208 if (!strcmp(plugin->plugin_name, name))
209 goto out_unlock;
210 }
211 plugin = NULL;
212
213out_unlock:
214 raw_spin_unlock(&sched_plugins_lock);
215 return plugin;
216}
217
218int print_sched_plugins(char* buf, int max)
219{
220 int count = 0;
221 struct list_head *pos;
222 struct sched_plugin *plugin;
223
224 raw_spin_lock(&sched_plugins_lock);
225 list_for_each(pos, &sched_plugins) {
226 plugin = list_entry(pos, struct sched_plugin, list);
227 count += snprintf(buf + count, max - count, "%s\n", plugin->plugin_name);
228 if (max - count <= 0)
229 break;
230 }
231 raw_spin_unlock(&sched_plugins_lock);
232 return count;
233}