= 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 LITMUS^RT^ 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`): {{{#!highlight c #include #include static struct task_struct* demo_schedule(struct task_struct * prev) { /* This mandatory. It triggers a transition in the LITMUS^RT remote * preemption state machine. Call this AFTER the plugin has made a local * scheduling decision. */ sched_state_task_picked(); /* We don't schedule anything for now. NULL means "schedule background work". */ return NULL; } static long demo_admit_task(struct task_struct *tsk) { /* Reject every task. */ return -EINVAL; } static struct sched_plugin demo_plugin = { .plugin_name = "DEMO", .schedule = demo_schedule, .admit_task = demo_admit_task, }; static int __init init_demo(void) { return register_sched_plugin(&demo_plugin); } 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 LITMUS^RT^ 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 LITMUS^RT^ 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 LITMUS^RT^ 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 [[../Step3|next step]], we are going to add tracing to observe the plugin in action.