diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-02-14 16:24:01 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-02-14 16:24:01 -0500 |
commit | 32e1c16c01276dceddf445a696b7e2c6ac4fb912 (patch) | |
tree | d7d0751ecd056b5be8374236421345cf6fa29f00 | |
parent | 83b11ea1c6ad113519c488853cf06e626c95a64d (diff) |
Added the dumbest plugin.
-rw-r--r-- | litmus/Makefile | 3 | ||||
-rw-r--r-- | litmus/sched_pdumb.c | 232 |
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 | ||
22 | obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o | 23 | obj-$(CONFIG_PLUGIN_CEDF) += sched_cedf.o |
23 | obj-$(CONFIG_PLUGIN_PFAIR) += sched_pfair.o | 24 | obj-$(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 */ | ||
16 | struct 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 | */ | ||
25 | DEFINE_PER_CPU(struct dumb_cpu, pdumb_cpus); | ||
26 | |||
27 | /** | ||
28 | * Called when litmus's active plugin is set to PDUMB. | ||
29 | */ | ||
30 | static 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 | */ | ||
55 | static 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 | */ | ||
88 | static 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 | */ | ||
115 | static 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 | */ | ||
132 | static 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 | */ | ||
166 | static 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 | */ | ||
183 | static 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 */ | ||
198 | static 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 | */ | ||
218 | static 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 | |||
232 | module_init(init_pdumb); | ||