aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-02-14 16:24:01 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2012-02-14 16:24:01 -0500
commit32e1c16c01276dceddf445a696b7e2c6ac4fb912 (patch)
treed7d0751ecd056b5be8374236421345cf6fa29f00
parent83b11ea1c6ad113519c488853cf06e626c95a64d (diff)
Added the dumbest plugin.
-rw-r--r--litmus/Makefile3
-rw-r--r--litmus/sched_pdumb.c232
2 files changed, 234 insertions, 1 deletions
diff --git a/litmus/Makefile b/litmus/Makefile
index 7338180f196f..c23c5122931e 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -17,7 +17,8 @@ obj-y = sched_plugin.o litmus.o \
17 bheap.o \ 17 bheap.o \
18 ctrldev.o \ 18 ctrldev.o \
19 sched_gsn_edf.o \ 19 sched_gsn_edf.o \
20 sched_psn_edf.o 20 sched_psn_edf.o \
21 sched_pdumb.o
21 22
22obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o 23obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o
23obj-$(CONFIG_PLUGIN_PFAIR) += sched_pfair.o 24obj-$(CONFIG_PLUGIN_PFAIR) += sched_pfair.o
diff --git a/litmus/sched_pdumb.c b/litmus/sched_pdumb.c
new file mode 100644
index 000000000000..c4a123475160
--- /dev/null
+++ b/litmus/sched_pdumb.c
@@ -0,0 +1,232 @@
1#include <linux/percpu.h>
2#include <linux/sched.h>
3#include <linux/list.h>
4#include <linux/spinlock.h>
5#include <linux/module.h>
6
7#include <litmus/litmus.h>
8#include <litmus/jobs.h>
9#include <litmus/preempt.h>
10#include <litmus/sched_plugin.h>
11#include <litmus/edf_common.h>
12#include <litmus/sched_trace.h>
13#include <litmus/trace.h>
14
15/* This is the per-cpu state of the plugin */
16struct dumb_cpu {
17 struct task_struct* dumb_task;
18 int scheduled;
19 int blocked;
20 raw_spinlock_t lock;
21};
22/* Define AND initialize one dumb_cpu per CPU.
23 * Use of this macro is good for safety and performance reasons.
24 */
25DEFINE_PER_CPU(struct dumb_cpu, pdumb_cpus);
26
27/**
28 * Called when litmus's active plugin is set to PDUMB.
29 */
30static long pdumb_activate_plugin(void)
31{
32 int i;
33 struct dumb_cpu* cpu;
34
35 /* Reset per-cpu state. Always assume you have to wipe the
36 * slate clean in this method. Someone evil may have been
37 * tampering with your data structures.
38 */
39 for (i = 0; i < num_online_cpus(); i++) {
40 cpu = &per_cpu(pdumb_cpus, i);
41 cpu->dumb_task = NULL;
42 cpu->scheduled = 0;
43 cpu->blocked = 0;
44 }
45
46 printk(KERN_ERR "Activated a dumb plugin!\n");
47 return 0;
48}
49
50
51/**
52 * Returns 0 if the plugin will admit the task.
53 * In this case, we only allow one task per CPU.
54 */
55static long pdumb_admit_task(struct task_struct *t)
56{
57 long ret;
58 int cpu_num = get_partition(t);
59
60 /* Per CPU variables have to be accessed wierd.
61 * The macro per_cpu accesses based on an integer index.
62 */
63 struct dumb_cpu *cpu = &per_cpu(pdumb_cpus, cpu_num);
64
65 raw_spin_lock(&cpu->lock);
66
67 if (cpu->dumb_task) {
68 printk(KERN_ERR "Already have a dumb task on %d!\n",
69 cpu_num);
70 ret = -EINVAL;
71 } else {
72 printk(KERN_ERR "Taking your dumb task on %d!\n",
73 cpu_num);
74
75 /* Assign our dumb task! */
76 cpu->dumb_task = t;
77 ret = 0;
78 }
79
80 raw_spin_unlock(&cpu->lock);
81 return ret;
82}
83
84
85/**
86 * Called when an ADMITTED task joins the real-time world.
87 */
88static void pdumb_task_new(struct task_struct *t, int on_rq, int running)
89{
90 /* Needed to disable interrupts */
91 unsigned long flags;
92 /* The macro __get_cpu_var() returns the local cpu variable */
93 struct dumb_cpu *cpu = &per_cpu(pdumb_cpus, get_partition(t));
94
95 /* We are accessing state atomically, we need a lock and to
96 * disable irqs.
97 */
98 raw_spin_lock_irqsave(&cpu->lock, flags);
99
100 /* The task could already be running in Linux.
101 * Lets just say its running here too.
102 */
103 if (running) {
104 cpu->scheduled = 1;
105 }
106
107 /* Re-enable irqs and unlock */
108 raw_spin_unlock_irqrestore(&cpu->lock, flags);
109}
110
111
112/**
113 * Called when a task leaves the real-time world.
114 */
115static void pdumb_task_exit(struct task_struct *t)
116{
117 unsigned long flags;
118 struct dumb_cpu *cpu = &__get_cpu_var(pdumb_cpus);
119
120 raw_spin_lock_irqsave(&cpu->lock, flags);
121 cpu->dumb_task = NULL;
122 cpu->scheduled = 0;
123 raw_spin_unlock_irqrestore(&cpu->lock, flags);
124}
125
126
127/**
128 * Called when Litmus needs to figure out what to run.
129 * This plugin just swaps between nothing and the dumb task.
130 * If there is no dumb task, returns nothing.
131 */
132static struct task_struct* pdumb_schedule(struct task_struct *prev)
133{
134 struct dumb_cpu *cpu = &__get_cpu_var(pdumb_cpus);
135 struct task_struct *sched;
136
137 /* Accessing state, need lock. We don't need to disable irqs
138 * because they are already disabled when this method is
139 * called.
140 */
141 raw_spin_lock(&cpu->lock);
142
143 if (cpu->scheduled || cpu->blocked || !cpu->dumb_task) {
144 cpu->scheduled = 0;
145 sched = NULL;
146 TRACE("Nothing scheduled!\n");
147 } else {
148 cpu->scheduled = 1;
149 sched = cpu->dumb_task;
150 TRACE_TASK(cpu->dumb_task, "Scheduled!\n");
151 }
152
153 sched_state_task_picked();
154
155 raw_spin_unlock(&cpu->lock);
156 return sched;
157}
158
159
160/**
161 * Called when a task sleeps.
162 * This method MUST remove the task from all plugin data structures,
163 * or insanity ensues. There can be no chance that this task is ever
164 * returned in the _schedule method until it wakes up.
165 */
166static void pdumb_task_block(struct task_struct *t)
167{
168 unsigned long flags;
169 struct dumb_cpu *cpu = &per_cpu(pdumb_cpus, get_partition(t));
170
171 TRACE_TASK(t, "Blocked!\n");
172
173 raw_spin_lock_irqsave(&cpu->lock, flags);
174 cpu->blocked = 1;
175 cpu->scheduled = 0;
176 raw_spin_unlock_irqrestore(&cpu->lock, flags);
177}
178
179
180/**
181 * Called when a sleeping task resumes.
182 */
183static void pdumb_task_wake_up(struct task_struct *t)
184{
185 unsigned long flags;
186 struct dumb_cpu *cpu = &per_cpu(pdumb_cpus, get_partition(t));
187
188 TRACE_TASK(t, "Awoken!\n");
189
190 raw_spin_lock_irqsave(&cpu->lock, flags);
191 cpu->blocked = 0;
192 cpu->scheduled = 0;
193 raw_spin_unlock_irqrestore(&cpu->lock, flags);
194}
195
196
197/* The actual plugin structure */
198static struct sched_plugin pdumb_plugin __cacheline_aligned_in_smp = {
199 .plugin_name = "PDUMB",
200
201 /* Initialization (when someone switches to this plugin) */
202 .activate_plugin = pdumb_activate_plugin,
203
204 /* Scheduling methods */
205 .schedule = pdumb_schedule,
206 .task_wake_up = pdumb_task_wake_up,
207 .task_block = pdumb_task_block,
208
209 /* Task management methods */
210 .admit_task = pdumb_admit_task,
211 .task_new = pdumb_task_new,
212 .task_exit = pdumb_task_exit,
213};
214
215/**
216 * Called when the system boots up.
217 */
218static int __init init_pdumb(void)
219{
220 int i;
221 struct dumb_cpu* cpu;
222
223 /* Initialize CPU state. */
224 for (i = 0; i < num_online_cpus(); i++) {
225 cpu = &per_cpu(pdumb_cpus, i);
226 raw_spin_lock_init(&cpu->lock);
227 }
228
229 return register_sched_plugin(&pdumb_plugin);
230}
231
232module_init(init_pdumb);