diff options
author | Bjoern B. Brandenburg <bbb@jupiter-cs.cs.unc.edu> | 2007-02-01 17:35:46 -0500 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@jupiter-cs.cs.unc.edu> | 2007-02-01 17:35:46 -0500 |
commit | c72efb7abd520758e86317c8eb451ed607042ad9 (patch) | |
tree | d14e61b14ed2b01f683829eefd20d66fd3d549eb /kernel | |
parent | ad1e19d0fafe82cc5f8180c0f9221458d439d9fa (diff) |
Added litmus.c, made it compile.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/litmus.c | 588 |
2 files changed, 589 insertions, 1 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index f67634070a..103c1b1050 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -9,7 +9,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ | |||
9 | rcupdate.o extable.o params.o posix-timers.o \ | 9 | rcupdate.o extable.o params.o posix-timers.o \ |
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \ | 11 | hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \ |
12 | sched_plugin.o | 12 | sched_plugin.o litmus.o |
13 | 13 | ||
14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
15 | obj-y += time/ | 15 | obj-y += time/ |
diff --git a/kernel/litmus.c b/kernel/litmus.c new file mode 100644 index 0000000000..7e97df948a --- /dev/null +++ b/kernel/litmus.c | |||
@@ -0,0 +1,588 @@ | |||
1 | /* | ||
2 | * Variable and function definitions | ||
3 | * that help alter the underlying scheduler | ||
4 | * on the fly. | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | |||
9 | #include <asm/uaccess.h> | ||
10 | #include <linux/sysrq.h> | ||
11 | |||
12 | #include <linux/queuelock.h> | ||
13 | #include <linux/litmus.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/sched_plugin.h> | ||
16 | |||
17 | /*CLEANUP: Include when ported. | ||
18 | #include <linux/plugin_trace.h> | ||
19 | */ | ||
20 | |||
21 | |||
22 | /* External variables declared in plugin driver */ | ||
23 | extern sched_plugin_t *curr_sched_plugin; | ||
24 | extern sched_plugin_t linux_sched_plugin; | ||
25 | |||
26 | /* Variables that govern the scheduling process */ | ||
27 | spolicy sched_policy = SCHED_DEFAULT; | ||
28 | int sched_options = 0; | ||
29 | unsigned long slot_size = DEFAULT_SLOT_SIZE; | ||
30 | unsigned long stagger_offset = DEFAULT_STAGGER; /* TODO: get rid of software stagger */ | ||
31 | |||
32 | spinlock_t litmus_task_set_lock = SPIN_LOCK_UNLOCKED; | ||
33 | |||
34 | /* Use linux runqueues to store currently running CPU task by default */ | ||
35 | int sched_type = INDIRECT_SWITCH; | ||
36 | |||
37 | |||
38 | /* This is a flag for switching the system into RT mode when it is booted up | ||
39 | * In RT-mode non-realtime tasks are shut down and scheduled as spare time available | ||
40 | * Even though the system may switch scheduling plugin on the fly | ||
41 | * it must continue to mimic linux scheduler until rt_mode is explicitly | ||
42 | * enabled. | ||
43 | */ | ||
44 | |||
45 | /* The system is booting in non-realtime mode */ | ||
46 | atomic_t rt_mode = ATOMIC_INIT(MODE_NON_RT); | ||
47 | /* Here we specify a mode change to be made */ | ||
48 | atomic_t new_mode = ATOMIC_INIT(MODE_NON_RT); | ||
49 | /* Number of RT tasks that exist in the system */ | ||
50 | atomic_t n_rt_tasks = ATOMIC_INIT(0); | ||
51 | atomic_t *n_rt_tasks_ptr = &n_rt_tasks; | ||
52 | /* Only one process can perform mode change */ | ||
53 | static queuelock_t mode_change_lock; | ||
54 | /* A time instant when we switched to RT mode */ | ||
55 | volatile unsigned long rt_start_time = 0; | ||
56 | /** | ||
57 | * sys_set_rt_mode | ||
58 | * @newmode: new mode the scheduler must be switched to | ||
59 | * External syscall for setting the RT mode flag | ||
60 | * Returns EINVAL if mode is not recognized or mode transition is not permitted | ||
61 | * On success 0 is returned | ||
62 | * TODO: implement transition table | ||
63 | */ | ||
64 | asmlinkage long sys_set_rt_mode(int newmode) | ||
65 | { | ||
66 | |||
67 | if ((newmode == MODE_NON_RT) || (newmode == MODE_RT_RUN)) { | ||
68 | unsigned long flags; | ||
69 | local_irq_save(flags); | ||
70 | printk(KERN_INFO "real-time mode switch to %s\n", | ||
71 | (newmode == MODE_RT_RUN ? "rt" : "non-rt")); | ||
72 | local_irq_restore(flags); | ||
73 | atomic_set(&new_mode, newmode); | ||
74 | return 0; | ||
75 | } | ||
76 | return -EINVAL; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * sys_set_task_rt_param | ||
81 | * @pid: Pid of the task which scheduling parameters must be changed | ||
82 | * @param: New real-time extension parameters such as the execution cost and period | ||
83 | * Syscall for manipulating with task rt extension params | ||
84 | * Returns EFAULT if param is NULL. | ||
85 | * ESRCH if pid is not corrsponding | ||
86 | * to a valid task. | ||
87 | * EINVAL if either period or execution cost is <=0 | ||
88 | * 0 if success | ||
89 | * | ||
90 | * | ||
91 | * FIXME: This code is racy during real-time mode. | ||
92 | */ | ||
93 | asmlinkage long sys_set_rt_task_param(pid_t pid, rt_param_t __user * param) | ||
94 | { | ||
95 | rt_param_t tp; | ||
96 | struct task_struct *target; | ||
97 | int retval = -EINVAL; | ||
98 | |||
99 | if (pid < 0 || param == 0) { | ||
100 | goto out; | ||
101 | } | ||
102 | if (copy_from_user(&tp, param, sizeof(tp))) { | ||
103 | retval = -EFAULT; | ||
104 | goto out; | ||
105 | } | ||
106 | /* Task search and manipulation must be protected */ | ||
107 | |||
108 | |||
109 | read_lock_irq(&tasklist_lock); | ||
110 | if (!(target = find_task_by_pid(pid))) { | ||
111 | retval = -ESRCH; | ||
112 | goto out_unlock; | ||
113 | } | ||
114 | if (tp.exec_cost <= 0) | ||
115 | goto out_unlock; | ||
116 | if (tp.period <= 0) | ||
117 | goto out_unlock; | ||
118 | if (!cpu_online(tp.cpu)) | ||
119 | goto out_unlock; | ||
120 | if (tp.period < tp.exec_cost) | ||
121 | { | ||
122 | printk(KERN_INFO "litmus: real-time task %d rejected " | ||
123 | "because wcet > period\n", pid); | ||
124 | goto out_unlock; | ||
125 | } | ||
126 | |||
127 | /* Assign params */ | ||
128 | target->rt_param.basic_params = tp; | ||
129 | |||
130 | retval = 0; | ||
131 | out_unlock: | ||
132 | read_unlock_irq(&tasklist_lock); | ||
133 | out: | ||
134 | return retval; | ||
135 | } | ||
136 | |||
137 | /** Getter of task's RT params | ||
138 | * returns EINVAL if param or pid is NULL | ||
139 | * returns ESRCH if pid does not correspond to a valid task | ||
140 | * returns EFAULT if copying of parameters has failed. | ||
141 | */ | ||
142 | asmlinkage long sys_get_rt_task_param(pid_t pid, rt_param_t __user * param) | ||
143 | { | ||
144 | int retval = -EINVAL; | ||
145 | struct task_struct *source; | ||
146 | rt_param_t lp; | ||
147 | if (param == 0 || pid < 0) | ||
148 | goto out; | ||
149 | read_lock(&tasklist_lock); | ||
150 | if (!(source = find_task_by_pid(pid))) { | ||
151 | retval = -ESRCH; | ||
152 | goto out_unlock; | ||
153 | } | ||
154 | lp = source->rt_param.basic_params; | ||
155 | read_unlock(&tasklist_lock); | ||
156 | /* Do copying outside the lock */ | ||
157 | retval = | ||
158 | copy_to_user(param, &lp, sizeof(lp)) ? -EFAULT : 0; | ||
159 | return retval; | ||
160 | out_unlock: | ||
161 | read_unlock(&tasklist_lock); | ||
162 | out: | ||
163 | return retval; | ||
164 | |||
165 | } | ||
166 | |||
167 | /*static inline int get_ok_sched(int cpu) | ||
168 | { | ||
169 | return atomic_read(cpu_okay_to_sched(cpu)); | ||
170 | } | ||
171 | static inline void set_ok_sched(int cpu, int val) | ||
172 | { | ||
173 | atomic_set(cpu_okay_to_sched(cpu), val); | ||
174 | } | ||
175 | */ | ||
176 | |||
177 | /* Returns true if okay_to_sched for current CPU is set to 1 */ | ||
178 | |||
179 | /*inline int get_this_ok_sched(void) | ||
180 | { | ||
181 | return atomic_dec_and_test(thisoksched()); | ||
182 | } | ||
183 | inline void set_this_ok_sched(int val) | ||
184 | { | ||
185 | atomic_set(thisoksched(), val); | ||
186 | } | ||
187 | */ | ||
188 | /** | ||
189 | * sys_prepare_rt_task | ||
190 | * @pid: Pid of the task we want to prepare for RT mode | ||
191 | * Syscall for adding a task to RT queue, plugin dependent. | ||
192 | * Must be called before RT tasks are going to start up. | ||
193 | * Returns EPERM if current plugin does not define prepare operation | ||
194 | * or scheduling policy does not allow the operation. | ||
195 | * ESRCH if pid does not correspond to a valid task. | ||
196 | * EINVAL if a task is non-realtime or in invalid state | ||
197 | * from underlying plugin function | ||
198 | * EAGAIN if a task is not in the right state | ||
199 | * ENOMEM if there is no memory space to handle this task | ||
200 | * 0 if success | ||
201 | * | ||
202 | * | ||
203 | * FIXME:The cpu parameter is currently ignored. It s hould be removed | ||
204 | * altogether | ||
205 | */ | ||
206 | asmlinkage long sys_prepare_rt_task(pid_t pid, int dummy) | ||
207 | { | ||
208 | int retval = -EINVAL; | ||
209 | struct task_struct *target = 0; | ||
210 | /* If a plugin does not define preparation mode then nothing to do */ | ||
211 | if (curr_sched_plugin->prepare_task == 0 | ||
212 | || sched_policy == SCHED_DEFAULT) { | ||
213 | retval = -EPERM; | ||
214 | goto out_prepare; | ||
215 | } | ||
216 | read_lock_irq(&tasklist_lock); | ||
217 | if (!(target = find_task_by_pid(pid))) { | ||
218 | retval = -ESRCH; | ||
219 | goto out_prepare_unlock; | ||
220 | } | ||
221 | if (!cpu_online(get_partition(target))) | ||
222 | { | ||
223 | printk(KERN_WARNING "litmus prepare: cpu %d is not online\n", | ||
224 | get_partition(target)); | ||
225 | goto out_prepare_unlock; | ||
226 | } | ||
227 | retval = curr_sched_plugin->prepare_task(target); | ||
228 | if (!retval) { | ||
229 | atomic_inc(&n_rt_tasks); | ||
230 | target->rt_param.is_realtime = 1; | ||
231 | } | ||
232 | out_prepare_unlock: | ||
233 | read_unlock_irq(&tasklist_lock); | ||
234 | out_prepare: | ||
235 | return retval; | ||
236 | } | ||
237 | |||
238 | /* External reference to kill, probably need to move at the header */ | ||
239 | extern long sys_kill(pid_t, int); | ||
240 | /** | ||
241 | * Task tear down, removes a task from plugin structures, sets its | ||
242 | * properties to non-realtime and sends a signal (SIGKILL suggested, so that the task shuts down immediately) | ||
243 | * returns EINVAL if the task is not a realtime task | ||
244 | * returns EPERM if the task is current, or current kernel policy does not permit | ||
245 | * realtime operations | ||
246 | * returns ESRCH if the pid does not correspond to a valid task | ||
247 | * Otherwise the result of sys_kill is returned | ||
248 | */ | ||
249 | asmlinkage long sys_tear_down_task(pid_t pid, int sig) | ||
250 | { | ||
251 | int retval = -EINVAL; | ||
252 | struct task_struct *target = 0; | ||
253 | if (curr_sched_plugin->tear_down == 0 | ||
254 | || sched_policy == SCHED_DEFAULT) { | ||
255 | retval = -EPERM; | ||
256 | goto out; | ||
257 | } | ||
258 | read_lock_irq(&tasklist_lock); | ||
259 | if (!(target = find_task_by_pid(pid))) { | ||
260 | retval = -ESRCH; | ||
261 | goto out_unlock; | ||
262 | } | ||
263 | if (target == current) { | ||
264 | retval = -EPERM; | ||
265 | goto out_unlock; | ||
266 | } | ||
267 | printk(KERN_WARNING "task %d: use of sys_tear_down_task is deprecated! " | ||
268 | "Just use kill instead.\n", current->pid); | ||
269 | /* if (is_realtime(target)) { | ||
270 | // the task is not realtime now, there is no harm | ||
271 | // because it is going to be killed | ||
272 | retval = curr_sched_plugin->tear_down(target); | ||
273 | // drop all the RT params of the task | ||
274 | clear_task(target); | ||
275 | target->state = TASK_STOPPED; | ||
276 | } | ||
277 | */ | ||
278 | read_unlock_irq(&tasklist_lock); | ||
279 | |||
280 | // call syskill | ||
281 | return sys_kill(pid, sig); | ||
282 | out_unlock: | ||
283 | read_unlock_irq(&tasklist_lock); | ||
284 | out: | ||
285 | return retval; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * This is the crucial function for periodic task implementation, | ||
290 | * It checks if a task is periodic, checks if such kind of sleep is permitted | ||
291 | * and calls plugin-specific sleep, which puts the task into a wait array. | ||
292 | * returns 0 on successful wakeup | ||
293 | * returns EPERM if current conditions do not permit such sleep | ||
294 | * returns EINVAL if current task is not able to go to sleep | ||
295 | */ | ||
296 | asmlinkage long sys_sleep_next_period(void) | ||
297 | { | ||
298 | int retval = -EPERM; | ||
299 | // Periodic sleep is not permitted for linux scheduler | ||
300 | // because quantum runqueues are not merged | ||
301 | if (curr_sched_plugin->sleep_next_period == 0 | ||
302 | || sched_policy == SCHED_DEFAULT) { | ||
303 | goto out; | ||
304 | } | ||
305 | if (!is_realtime(current)) { | ||
306 | retval = -EINVAL; | ||
307 | goto out; | ||
308 | } | ||
309 | // Task with negative or zero period cannot sleep | ||
310 | if (get_rt_period(current) <= 0) { | ||
311 | retval = -EINVAL; | ||
312 | goto out; | ||
313 | } | ||
314 | /* Basically the plugin have to put the task into | ||
315 | * appropriate quantum queue and call schedule | ||
316 | */ | ||
317 | retval = curr_sched_plugin->sleep_next_period(); | ||
318 | out: | ||
319 | return retval; | ||
320 | } | ||
321 | |||
322 | /* Set scheduling options for all cpus. */ | ||
323 | void set_sched_options(int options) | ||
324 | { | ||
325 | sched_options = options; | ||
326 | } | ||
327 | |||
328 | |||
329 | /* Wrapper code for tick function - called by all schedulers before | ||
330 | entering their own code. | ||
331 | */ | ||
332 | |||
333 | int rt_scheduler_tick(void) | ||
334 | { | ||
335 | /* Check for mode change */ | ||
336 | if ((get_rt_mode() != atomic_read(&new_mode))) { | ||
337 | queue_lock(&mode_change_lock); | ||
338 | // If the mode is already changed, proceed | ||
339 | if (get_rt_mode() == atomic_read(&new_mode)) { | ||
340 | queue_unlock(&mode_change_lock); | ||
341 | goto proceed; | ||
342 | } | ||
343 | // change the mode | ||
344 | if ((atomic_read(&new_mode) == MODE_RT_RUN)) { | ||
345 | /* The deferral of entering real-time mode should be | ||
346 | * handled by deferring task releases in the plugin. | ||
347 | * The plugin interface does not really need to know | ||
348 | * about quanta, that is the plugin's job. | ||
349 | */ | ||
350 | |||
351 | /* update rt start time */ | ||
352 | rt_start_time = jiffies; | ||
353 | TRACE("Real-Time mode enabled\n"); | ||
354 | if (curr_sched_plugin->mode_change) | ||
355 | curr_sched_plugin-> | ||
356 | mode_change(atomic_read(&new_mode)); | ||
357 | } | ||
358 | set_rt_mode(atomic_read(&new_mode)); | ||
359 | queue_unlock(&mode_change_lock); | ||
360 | } | ||
361 | |||
362 | proceed: | ||
363 | /* Call plugin-defined tick handler | ||
364 | * | ||
365 | * It is the plugin's tick handler' job to detect quantum | ||
366 | * boundaries in pfair. | ||
367 | */ | ||
368 | return curr_sched_plugin->algo_scheduler_tick(); | ||
369 | } | ||
370 | |||
371 | inline int get_sched_options(void) | ||
372 | { | ||
373 | return sched_options; | ||
374 | } | ||
375 | |||
376 | /* This code must be non-preemptable */ | ||
377 | asmlinkage spolicy sys_sched_setpolicy(spolicy newpolicy) | ||
378 | { | ||
379 | /* Dynamic policy change is disabled at the moment */ | ||
380 | /* | ||
381 | spolicy cpolicy = sched_policy; | ||
382 | |||
383 | if (newpolicy >= SCHED_BEG && newpolicy <= SCHED_END) { | ||
384 | sched_policy = newpolicy; | ||
385 | switch (sched_policy) { | ||
386 | case SCHED_GLOBAL_EDF: | ||
387 | initialize_global_edf(); | ||
388 | break; | ||
389 | case SCHED_PART_EDF: | ||
390 | initialize_part_edf(); | ||
391 | break; | ||
392 | case SCHED_PFAIR: | ||
393 | initialize_scheduler_pfair(); | ||
394 | break; | ||
395 | case SCHED_PFAIR_STAGGER: | ||
396 | initialize_scheduler_pfair_stagger(); | ||
397 | break; | ||
398 | default: | ||
399 | initialize_scheduler_linux(); | ||
400 | break; | ||
401 | } | ||
402 | return cpolicy; | ||
403 | } else | ||
404 | */ | ||
405 | return SCHED_INVALID; | ||
406 | } | ||
407 | |||
408 | asmlinkage spolicy sys_sched_getpolicy(void) | ||
409 | { | ||
410 | return sched_policy; | ||
411 | } | ||
412 | |||
413 | |||
414 | asmlinkage int sys_scheduler_setup(int cmd, void __user *parameter) | ||
415 | { | ||
416 | return curr_sched_plugin->scheduler_setup(cmd, parameter); | ||
417 | } | ||
418 | |||
419 | |||
420 | #ifdef CONFIG_MAGIC_SYSRQ | ||
421 | /* We offer the possibility to change the real-time mode of the system | ||
422 | * with a magic sys request. This helps in debugging in case the system fails | ||
423 | * to perform its planned switch back to normal mode. This may happen if we have | ||
424 | * total system utilization and the task that is supposed to do the switch is | ||
425 | * always preempted (if it is not a real-time task). | ||
426 | */ | ||
427 | |||
428 | static void sysrq_handle_toGgle_rt_mode(int key, struct tty_struct *tty) | ||
429 | { | ||
430 | sys_set_rt_mode(get_rt_mode() == MODE_NON_RT); | ||
431 | } | ||
432 | |||
433 | static struct sysrq_key_op sysrq_toGgle_rt_mode_op = { | ||
434 | .handler = sysrq_handle_toGgle_rt_mode, | ||
435 | .help_msg = "toGgle-rt-mode", | ||
436 | .action_msg = "real-time mode changed", | ||
437 | }; | ||
438 | |||
439 | static void sysrq_handle_kill_rt_tasks(int key, struct tty_struct *tty) | ||
440 | { | ||
441 | struct task_struct *t; | ||
442 | read_lock(&tasklist_lock); | ||
443 | for_each_process(t) { | ||
444 | if (is_realtime(t)) { | ||
445 | sys_kill(t->pid, SIGKILL); | ||
446 | } | ||
447 | } | ||
448 | read_unlock(&tasklist_lock); | ||
449 | } | ||
450 | |||
451 | static struct sysrq_key_op sysrq_kill_rt_tasks_op = { | ||
452 | .handler = sysrq_handle_kill_rt_tasks, | ||
453 | .help_msg = "f:kill-rt-tasks", | ||
454 | .action_msg = "sent SIGKILL to all real-time tasks", | ||
455 | }; | ||
456 | #endif | ||
457 | |||
458 | /* | ||
459 | * Scheduler initialization so that customized scheduler is | ||
460 | * enabled at boot time | ||
461 | * by setting boot option "rtsched=plugin_name", e.g. "rtsched=pfair" | ||
462 | */ | ||
463 | |||
464 | /* All we need to know about other plugins is their initialization | ||
465 | * functions. These functions initialize internal data structures of a | ||
466 | * scheduler and return a pointer to initialized sched_plugin data | ||
467 | * structure with pointers to scheduling function implementations. | ||
468 | * If called repeatedly these init functions just return an existing | ||
469 | * plugin pointer. | ||
470 | */ | ||
471 | /* | ||
472 | CLEANUP: Add init function when the plugin has been ported. | ||
473 | sched_plugin_t *init_pfair_plugin(void); | ||
474 | sched_plugin_t *init_global_edf_plugin(void); | ||
475 | sched_plugin_t *init_part_edf_plugin(void); | ||
476 | sched_plugin_t *init_desync_pfair_plugin(void); | ||
477 | sched_plugin_t *init_global_edf_np_plugin(void); | ||
478 | sched_plugin_t *init_edf_hsb_plugin(void); | ||
479 | */ | ||
480 | |||
481 | |||
482 | |||
483 | |||
484 | /* keep everything needed to setup plugins in one place */ | ||
485 | |||
486 | /* we are lazy, so we use a convention for function naming to fill | ||
487 | * a table | ||
488 | */ | ||
489 | #define PLUGIN(caps, small) \ | ||
490 | {PLUGIN_ ## caps, SCHED_ ## caps, init_ ## small ## _plugin} | ||
491 | |||
492 | #define init_nosetup_plugin 0 | ||
493 | |||
494 | static struct { | ||
495 | const char *name; | ||
496 | const spolicy policy_id; | ||
497 | sched_plugin_t *(*init) (void); | ||
498 | } available_plugins[] = { | ||
499 | PLUGIN(LINUX, nosetup), | ||
500 | /* CLEANUP: Add when ported. | ||
501 | PLUGIN(PFAIR, pfair), | ||
502 | PLUGIN(PART_EDF, part_edf), | ||
503 | PLUGIN(GLOBAL_EDF, global_edf), | ||
504 | PLUGIN(PFAIR_DESYNC, desync_pfair), | ||
505 | PLUGIN(GLOBAL_EDF_NP, global_edf_np), | ||
506 | PLUGIN(GLOBAL_EDF, global_edf), | ||
507 | PLUGIN(EDF_HSB, edf_hsb) | ||
508 | */ | ||
509 | |||
510 | /********************************************* | ||
511 | * Add your custom plugin here | ||
512 | **********************************************/ | ||
513 | }; | ||
514 | |||
515 | /* Some plugins may leave important functions unused. We define dummies | ||
516 | * so that we don't have to check for null pointers all over the place. | ||
517 | */ | ||
518 | void litmus_dummy_finish_switch(struct task_struct * prev); | ||
519 | int litmus_dummy_schedule(struct task_struct * prev, struct task_struct** next, | ||
520 | runqueue_t* q); | ||
521 | reschedule_check_t litmus_dummy_scheduler_tick(void); | ||
522 | long litmus_dummy_prepare_task(struct task_struct *t); | ||
523 | void litmus_dummy_wake_up_task(struct task_struct *task); | ||
524 | void litmus_dummy_task_blocks(struct task_struct *task); | ||
525 | long litmus_dummy_tear_down(struct task_struct *task); | ||
526 | int litmus_dummy_scheduler_setup(int cmd, void __user *parameter); | ||
527 | |||
528 | #define CHECK(func) {\ | ||
529 | if (!curr_sched_plugin->func) \ | ||
530 | curr_sched_plugin->func = litmus_dummy_ ## func;} | ||
531 | |||
532 | static int boot_sched_setup(char *plugin_name) | ||
533 | { | ||
534 | int i = 0; | ||
535 | |||
536 | /* Common initializers, | ||
537 | * mode change lock is used to enforce single mode change | ||
538 | * operation. | ||
539 | */ | ||
540 | queue_lock_init(&mode_change_lock, NR_CPUS); | ||
541 | |||
542 | printk("Starting LITMUS kernel\n"); | ||
543 | |||
544 | /* Look for a matching plugin. | ||
545 | */ | ||
546 | for (i = 0; i < ARRAY_SIZE(available_plugins); i++) { | ||
547 | if (!strcmp(plugin_name, available_plugins[i].name)) { | ||
548 | printk("Using %s scheduler plugin\n", plugin_name); | ||
549 | sched_policy = available_plugins[i].policy_id; | ||
550 | if (available_plugins[i].init) | ||
551 | curr_sched_plugin = available_plugins[i].init(); | ||
552 | goto out; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | |||
557 | /* Otherwise we have default linux scheduler */ | ||
558 | printk("Plugin name %s is unknown, using default %s\n", plugin_name, | ||
559 | curr_sched_plugin->plugin_name); | ||
560 | |||
561 | out: | ||
562 | /* make sure we don't trip over null pointers later */ | ||
563 | CHECK(finish_switch); | ||
564 | CHECK(schedule); | ||
565 | CHECK(scheduler_tick); | ||
566 | CHECK(wake_up_task); | ||
567 | CHECK(tear_down); | ||
568 | CHECK(task_blocks); | ||
569 | CHECK(prepare_task); | ||
570 | CHECK(scheduler_setup); | ||
571 | |||
572 | #ifdef CONFIG_MAGIC_SYSRQ | ||
573 | /* offer some debugging help */ | ||
574 | if (!register_sysrq_key('g', &sysrq_toGgle_rt_mode_op)) | ||
575 | printk("Registered eXit real-time mode magic sysrq.\n"); | ||
576 | else | ||
577 | printk("Could not register eXit real-time mode magic sysrq.\n"); | ||
578 | if (!register_sysrq_key('f', &sysrq_kill_rt_tasks_op)) | ||
579 | printk("Registered kill rt tasks magic sysrq.\n"); | ||
580 | else | ||
581 | printk("Could not register kill rt tasks magic sysrq.\n"); | ||
582 | #endif | ||
583 | printk("Litmus setup complete."); | ||
584 | return 1; | ||
585 | } | ||
586 | |||
587 | /* Register for boot option */ | ||
588 | __setup("rtsched=", boot_sched_setup); | ||