Step 2: Register a Dummy Plugin
In this step, we are going to declare a dummy plugin object (that implements no particular policy and that rejects all tasks) and register it with the LITMUSRT core.
The Code
Edit the file litmus/sched_demo.c to declare a dummy plugin.
The required code looks like this (litmus/sched_demo.c):
1 #include <litmus/sched_plugin.h>
2 #include <litmus/preempt.h>
3
4 static struct task_struct* demo_schedule(struct task_struct * prev)
5 {
6 /* This mandatory. It triggers a transition in the LITMUS^RT remote
7 * preemption state machine. Call this AFTER the plugin has made a local
8 * scheduling decision.
9 */
10 sched_state_task_picked();
11
12 /* We don't schedule anything for now. NULL means "schedule background work". */
13 return NULL;
14 }
15
16 static long demo_admit_task(struct task_struct *tsk)
17 {
18 /* Reject every task. */
19 return -EINVAL;
20 }
21
22 static struct sched_plugin demo_plugin = {
23 .plugin_name = "DEMO",
24 .schedule = demo_schedule,
25 .admit_task = demo_admit_task,
26 };
27
28 static int __init init_demo(void)
29 {
30 return register_sched_plugin(&demo_plugin);
31 }
32
33 module_init(init_demo);
Plugin Declaration
Lines 22--26 declare a new plugin object (of type struct sched_plugin, defined in litmus/sched_plugin.h). Line 23 defines the plugin's name, which will be used to refer to it from userspace with setsched.
We define two plugin callbacks, demo_schedule() and demo_admit_task(), and hook them up with the plugin in Lines 24 and 25. See litmus/sched_plugin.h for a list of all plugin callbacks.
Plugin Initialization
To make the DEMO plugin known to the LITMUSRT core, it must be registered with the core at boot time. This is accomplished in lines 28-33.
The Linux API module_init() allows specifying a function that will be executed once during boot to carry out initialization tasks. Here, we specify the local initialization function init_demo(), which invokes register_sched_plugin() to make the plugin object known to the LITMUSRT core.
Callback Functions
Lines 4--14 define the scheduling callback of the DEMO plugin.
The schedule() method of plugin objects is invoked on each core whenever a scheduling decision has to be made. It is given a pointer to the currently scheduled task, which is customarily called prev, and returns a pointer to the next task to be scheduled. If the schedule() method returns NULL, then this is interpreted to mean that no real-time workload is present (or eligible to execute) and background best-effort tasks will be scheduled by Linux instead (or the idle task, if no ready tasks are pending).
Here, we simply return NULL because no scheduling policy is implemented yet. Nonetheless, the schedule() method needs to inform the LITMUSRT core when it has decided which task to schedule to trigger a transition in the (cross-processor) preemption state machine. This is done in Line 10 with the sched_state_task_picked() macro.
Finally, since no policy is implemented yet, we provide a dummy admission callback demo_admit_task(), which simply rejects any new real-time task by returning an error code (see linux/errno.h and asm/errno.h for a list of possible error codes).
Testing the Plugin
With the dummy plugin in place, it should be possible to boot the kernel and select the DEMO plugin with setsched.
To test if it rejects tasks as expected, run rtspin, which is part of liblitmus, inside the VM:
[root@litmus-rt ~]# setsched DEMO [root@litmus-rt ~]# showsched DEMO [root@litmus-rt ~]# liblitmus/rtspin 10 100 10 could not become RT task: Invalid argument
The plugin did indeed reject the task, as expected.
Commit your changes once everything works.
In the next step, we are going to add tracing to observe the plugin in action.