diff options
author | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-09-23 13:28:33 -0400 |
---|---|---|
committer | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-09-23 13:28:33 -0400 |
commit | c98651d6dfdee7eba0134354583919dd9d2afbcf (patch) | |
tree | a0080396d20a4ae8ae5dc37172c5043270906885 | |
parent | 5eacf27747940e3a33f2b48f6335c6fa255598f5 (diff) |
Checkpoint1(Updated)
Encounters problem where task waits an extra period due to
sleep(unresolved)
-rw-r--r-- | arch/x86/boot/initrd.img | bin | 0 -> 41062876 bytes | |||
-rw-r--r-- | include/litmus/reservations/ext_reservation.h | 9 | ||||
-rw-r--r-- | include/litmus/reservations/gedf_reservation.h | 22 | ||||
-rw-r--r-- | include/litmus/reservations/task_reservation.h | 16 | ||||
-rw-r--r-- | litmus/reservations/ext_reservation.c | 2 | ||||
-rw-r--r-- | litmus/reservations/gedf_reservation.c | 197 | ||||
-rw-r--r-- | litmus/reservations/task_reservation.c | 89 | ||||
-rw-r--r-- | litmus/rt_domain.c | 4 | ||||
-rw-r--r-- | litmus/sched_ext_res.c | 45 |
9 files changed, 183 insertions, 201 deletions
diff --git a/arch/x86/boot/initrd.img b/arch/x86/boot/initrd.img new file mode 100644 index 000000000000..239454fce731 --- /dev/null +++ b/arch/x86/boot/initrd.img | |||
Binary files differ | |||
diff --git a/include/litmus/reservations/ext_reservation.h b/include/litmus/reservations/ext_reservation.h index 7ec326bd14bd..68784f71a268 100644 --- a/include/litmus/reservations/ext_reservation.h +++ b/include/litmus/reservations/ext_reservation.h | |||
@@ -23,6 +23,12 @@ typedef void (*drain_budget_t) ( | |||
23 | int cpu | 23 | int cpu |
24 | ); | 24 | ); |
25 | 25 | ||
26 | typedef struct task_struct* (*dispatch_client_t) ( | ||
27 | struct reservation *reservation, | ||
28 | lt_t now, | ||
29 | int cpu | ||
30 | ); | ||
31 | |||
26 | /* When reservation is scheduled. */ | 32 | /* When reservation is scheduled. */ |
27 | typedef void (*on_schedule_t) ( | 33 | typedef void (*on_schedule_t) ( |
28 | struct reservation *reservation, | 34 | struct reservation *reservation, |
@@ -42,6 +48,7 @@ typedef void (*shutdown_t)(struct reservation *reservation); | |||
42 | struct reservation_ops { | 48 | struct reservation_ops { |
43 | drain_budget_t drain_budget; | 49 | drain_budget_t drain_budget; |
44 | replenish_budget_t replenish_budget; | 50 | replenish_budget_t replenish_budget; |
51 | dispatch_client_t dispatch_client; | ||
45 | on_schedule_t on_schedule; | 52 | on_schedule_t on_schedule; |
46 | on_preempt_t on_preempt; | 53 | on_preempt_t on_preempt; |
47 | shutdown_t shutdown; | 54 | shutdown_t shutdown; |
@@ -53,7 +60,7 @@ struct reservation { | |||
53 | /* exact meaning defined by impl. */ | 60 | /* exact meaning defined by impl. */ |
54 | lt_t priority; | 61 | lt_t priority; |
55 | lt_t cur_budget; | 62 | lt_t cur_budget; |
56 | lt_t next_replenishment; | 63 | lt_t replenishment_time; |
57 | 64 | ||
58 | /* budget stats */ | 65 | /* budget stats */ |
59 | lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */ | 66 | lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */ |
diff --git a/include/litmus/reservations/gedf_reservation.h b/include/litmus/reservations/gedf_reservation.h index e2a4a3dc5968..57f2fa7f00fc 100644 --- a/include/litmus/reservations/gedf_reservation.h +++ b/include/litmus/reservations/gedf_reservation.h | |||
@@ -22,19 +22,33 @@ struct gedf_reservation { | |||
22 | struct cpu_entry* scheduled_on; | 22 | struct cpu_entry* scheduled_on; |
23 | int will_remove; | 23 | int will_remove; |
24 | int blocked; | 24 | int blocked; |
25 | }; | ||
26 | |||
27 | struct gedf_task_reservation { | ||
28 | struct gedf_reservation gedf_res; | ||
29 | struct task_struct* task; | ||
30 | }; | ||
31 | |||
32 | struct gedf_container_reservation { | ||
33 | struct gedf_reservation gedf_res; | ||
34 | lt_t max_budget; | ||
25 | lt_t period; | 35 | lt_t period; |
26 | lt_t relative_deadline; | 36 | lt_t relative_deadline; |
27 | lt_t exec_cost; | ||
28 | }; | 37 | }; |
29 | 38 | ||
30 | long alloc_gedf_reservation( | 39 | long alloc_gedf_container_reservation( |
31 | struct gedf_reservation** _res, | 40 | struct gedf_container_reservation** _res, |
32 | int id, | 41 | int id, |
33 | lt_t exec_cost, | 42 | lt_t max_budget, |
34 | lt_t period, | 43 | lt_t period, |
35 | lt_t relative_deadline | 44 | lt_t relative_deadline |
36 | ); | 45 | ); |
37 | 46 | ||
47 | long alloc_gedf_task_reservation( | ||
48 | struct gedf_task_reservation** _res, | ||
49 | struct task_struct* task | ||
50 | ); | ||
51 | |||
38 | /* environment for scheduling reservations via gedf */ | 52 | /* environment for scheduling reservations via gedf */ |
39 | struct gedf_reservation_environment { | 53 | struct gedf_reservation_environment { |
40 | struct reservation_environment env; | 54 | struct reservation_environment env; |
diff --git a/include/litmus/reservations/task_reservation.h b/include/litmus/reservations/task_reservation.h deleted file mode 100644 index 0e0ef74591b6..000000000000 --- a/include/litmus/reservations/task_reservation.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef LITMUS_TASK_RESERVATION_H | ||
2 | #define LITMUS_TASK_RESERVATION_H | ||
3 | |||
4 | #include <litmus/reservations/ext_reservation.h> | ||
5 | |||
6 | struct task_reservation_environment { | ||
7 | struct reservation_environment env; | ||
8 | struct task_struct* task; | ||
9 | }; | ||
10 | |||
11 | long alloc_task_reservation_environment( | ||
12 | struct task_reservation_environment** _env, | ||
13 | struct task_struct* task | ||
14 | ); | ||
15 | |||
16 | #endif | ||
diff --git a/litmus/reservations/ext_reservation.c b/litmus/reservations/ext_reservation.c index 9623ec520e98..9397241faf99 100644 --- a/litmus/reservations/ext_reservation.c +++ b/litmus/reservations/ext_reservation.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/slab.h> | 1 | #include <linux/slab.h> |
2 | #include <litmus/bheap.h> | ||
2 | #include <litmus/reservations/ext_reservation.h> | 3 | #include <litmus/reservations/ext_reservation.h> |
3 | 4 | ||
4 | /* allocated in litmus.c */ | 5 | /* allocated in litmus.c */ |
@@ -10,6 +11,7 @@ void init_ext_reservation(struct reservation* res) | |||
10 | memset(res, 0, sizeof(struct reservation)); | 11 | memset(res, 0, sizeof(struct reservation)); |
11 | res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC); | 12 | res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC); |
12 | res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC); | 13 | res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC); |
14 | bheap_node_init(&res->heap_node, res); | ||
13 | INIT_LIST_HEAD(&res->ln); | 15 | INIT_LIST_HEAD(&res->ln); |
14 | } | 16 | } |
15 | 17 | ||
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c index aa1878e208b8..95bc1bab28f4 100644 --- a/litmus/reservations/gedf_reservation.c +++ b/litmus/reservations/gedf_reservation.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <litmus/bheap.h> | 8 | #include <litmus/bheap.h> |
9 | #include <litmus/rt_domain.h> | 9 | #include <litmus/rt_domain.h> |
10 | #include <litmus/jobs.h> | 10 | #include <litmus/jobs.h> |
11 | #include <litmus/sched_trace.h> | ||
11 | #include <litmus/debug_trace.h> | 12 | #include <litmus/debug_trace.h> |
12 | #include <litmus/reservations/gedf_reservation.h> | 13 | #include <litmus/reservations/gedf_reservation.h> |
13 | 14 | ||
@@ -94,14 +95,10 @@ static int edf_preemption_needed(rt_domain_t* rt, struct reservation* res) | |||
94 | } | 95 | } |
95 | 96 | ||
96 | /* ******************************************************************************** */ | 97 | /* ******************************************************************************** */ |
98 | //TODO: add support for checking non-preemptivity | ||
97 | static void preempt(struct cpu_entry* entry) | 99 | static void preempt(struct cpu_entry* entry) |
98 | { | 100 | { |
99 | if (entry->scheduled) { | 101 | litmus_reschedule(entry->id); |
100 | if (smp_processor_id() == entry->id) | ||
101 | litmus_reschedule_local(); | ||
102 | else | ||
103 | litmus_reschedule(entry->id); | ||
104 | } | ||
105 | } | 102 | } |
106 | 103 | ||
107 | static enum hrtimer_restart timer_callback(struct hrtimer* timer) | 104 | static enum hrtimer_restart timer_callback(struct hrtimer* timer) |
@@ -114,7 +111,7 @@ static void requeue(rt_domain_t* domain, struct reservation* res) { | |||
114 | BUG_ON(!res); | 111 | BUG_ON(!res); |
115 | BUG_ON(is_queued_res(res)); | 112 | BUG_ON(is_queued_res(res)); |
116 | 113 | ||
117 | if (lt_before_eq(res->next_replenishment, litmus_clock())) | 114 | if (lt_before_eq(res->replenishment_time, litmus_clock())) |
118 | __add_ready_res(domain, res); | 115 | __add_ready_res(domain, res); |
119 | else | 116 | else |
120 | __add_release_res(domain, res); | 117 | __add_release_res(domain, res); |
@@ -123,42 +120,29 @@ static void requeue(rt_domain_t* domain, struct reservation* res) { | |||
123 | 120 | ||
124 | static void link_task_to_cpu( | 121 | static void link_task_to_cpu( |
125 | struct gedf_reservation* linked, | 122 | struct gedf_reservation* linked, |
126 | struct cpu_entry* entry) | 123 | struct cpu_entry* entry, |
124 | struct gedf_reservation_environment* gedf_env) | ||
127 | { | 125 | { |
128 | struct cpu_entry* sched = NULL; | 126 | struct cpu_entry* sched = NULL; |
129 | struct reservation* tmp; | 127 | struct reservation* tmp; |
130 | struct bheap* cpu_heap = | ||
131 | &((struct gedf_reservation_environment*)linked->res.par_env)->cpu_heap; | ||
132 | 128 | ||
133 | if (entry->linked) | 129 | if (entry->linked) |
134 | ((struct gedf_reservation*)entry->linked)->linked_on = NULL; | 130 | ((struct gedf_reservation*)entry->linked)->linked_on = NULL; |
135 | 131 | ||
136 | if (linked) { | 132 | if (linked) |
137 | sched = linked->scheduled_on; | 133 | linked->linked_on = entry; |
138 | if (sched) { | 134 | |
139 | BUG_ON(sched->linked == linked); | ||
140 | if (entry != sched) { | ||
141 | tmp = sched->linked; | ||
142 | linked->linked_on = sched; | ||
143 | sched->linked = &linked->res; | ||
144 | update_cpu_position(sched, cpu_heap); | ||
145 | linked = (struct gedf_reservation*)tmp; | ||
146 | } | ||
147 | } | ||
148 | if (linked) | ||
149 | linked->linked_on = entry; | ||
150 | } | ||
151 | entry->linked = &linked->res; | 135 | entry->linked = &linked->res; |
152 | update_cpu_position(entry, cpu_heap); | 136 | update_cpu_position(entry, &gedf_env->cpu_heap); |
153 | } | 137 | } |
154 | 138 | ||
155 | static void unlink(struct gedf_reservation* res) | 139 | static void unlink( |
140 | struct gedf_reservation* res, | ||
141 | struct gedf_reservation_environment* gedf_env) | ||
156 | { | 142 | { |
157 | struct gedf_reservation_environment* gedf_env; | ||
158 | BUG_ON(!res->linked_on); | 143 | BUG_ON(!res->linked_on); |
159 | gedf_env = container_of(res->res.par_env, struct gedf_reservation_environment, env); | ||
160 | if (res->linked_on) { | 144 | if (res->linked_on) { |
161 | link_task_to_cpu(NULL, res->linked_on); | 145 | link_task_to_cpu(NULL, res->linked_on, gedf_env); |
162 | res->linked_on = NULL; | 146 | res->linked_on = NULL; |
163 | } else if (is_queued_res(&res->res)) { | 147 | } else if (is_queued_res(&res->res)) { |
164 | remove_res(&gedf_env->domain, &res->res); | 148 | remove_res(&gedf_env->domain, &res->res); |
@@ -174,9 +158,9 @@ static void check_for_preemptions(struct gedf_reservation_environment* env) | |||
174 | edf_preemption_needed(&env->domain, last->linked); | 158 | edf_preemption_needed(&env->domain, last->linked); |
175 | last = lowest_prio_cpu(&env->cpu_heap)) { | 159 | last = lowest_prio_cpu(&env->cpu_heap)) { |
176 | res = (struct gedf_reservation*)__take_ready_res(&env->domain); | 160 | res = (struct gedf_reservation*)__take_ready_res(&env->domain); |
177 | if (last->linked->cur_budget) | 161 | if (last->linked && last->linked->cur_budget) |
178 | requeue(&env->domain, last->linked); | 162 | requeue(&env->domain, last->linked); |
179 | link_task_to_cpu(res, last); | 163 | link_task_to_cpu(res, last, env); |
180 | preempt(last); | 164 | preempt(last); |
181 | } | 165 | } |
182 | } | 166 | } |
@@ -190,6 +174,13 @@ static void gedf_shutdown( | |||
190 | kfree(res); | 174 | kfree(res); |
191 | } | 175 | } |
192 | 176 | ||
177 | static void gedf_task_shutdown( | ||
178 | struct reservation *res) | ||
179 | { | ||
180 | clean_up_ext_reservation(res); | ||
181 | kfree(res); | ||
182 | } | ||
183 | |||
193 | static void gedf_on_preempt( | 184 | static void gedf_on_preempt( |
194 | struct reservation *res, | 185 | struct reservation *res, |
195 | int cpu) | 186 | int cpu) |
@@ -205,16 +196,48 @@ static void gedf_on_schedule( | |||
205 | res->env->ops->resume(res->env, now, cpu); | 196 | res->env->ops->resume(res->env, now, cpu); |
206 | } | 197 | } |
207 | 198 | ||
199 | static struct task_struct* gedf_dispatch_client( | ||
200 | struct reservation* res, | ||
201 | lt_t now, | ||
202 | int cpu) | ||
203 | { | ||
204 | return res->env->ops->dispatch(res->env, now, cpu); | ||
205 | } | ||
206 | |||
207 | static struct task_struct* gedf_task_dispatch_client( | ||
208 | struct reservation* res, | ||
209 | lt_t now, | ||
210 | int cpu) | ||
211 | { | ||
212 | return ((struct gedf_task_reservation*)res)->task; | ||
213 | } | ||
214 | |||
208 | static void gedf_replenish_budget( | 215 | static void gedf_replenish_budget( |
209 | struct reservation* res, | 216 | struct reservation* res, |
210 | int cpu) | 217 | int cpu) |
211 | { | 218 | { |
212 | struct gedf_reservation* gedf_res = | 219 | struct gedf_container_reservation* gedf_cont_res = |
213 | container_of(res, struct gedf_reservation, res); | 220 | (struct gedf_container_reservation*)res; |
214 | res->budget_consumed = 0; | 221 | res->budget_consumed = 0; |
215 | res->cur_budget = gedf_res->exec_cost; | 222 | res->cur_budget = gedf_cont_res->max_budget; |
216 | res->priority = res->next_replenishment + gedf_res->relative_deadline; | 223 | res->priority = res->replenishment_time + gedf_cont_res->relative_deadline; |
217 | res->next_replenishment += gedf_res->period; | 224 | res->replenishment_time += gedf_cont_res->period; |
225 | } | ||
226 | |||
227 | static void gedf_task_replenish_budget( | ||
228 | struct reservation* res, | ||
229 | int cpu) | ||
230 | { | ||
231 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; | ||
232 | sched_trace_task_completion(t, !is_completed(t)); | ||
233 | BUG_ON(get_exec_time(t) > 110000000); | ||
234 | tsk_rt(t)->completed = 0; | ||
235 | prepare_for_next_period(t); | ||
236 | sched_trace_task_release(t); | ||
237 | res->budget_consumed = 0; | ||
238 | res->cur_budget = get_exec_cost(t); | ||
239 | res->priority = get_deadline(t); | ||
240 | res->replenishment_time = get_release(t); | ||
218 | } | 241 | } |
219 | 242 | ||
220 | static void gedf_drain_budget( | 243 | static void gedf_drain_budget( |
@@ -232,40 +255,93 @@ static void gedf_drain_budget( | |||
232 | res->env->ops->update_time(res->env, how_much, cpu); | 255 | res->env->ops->update_time(res->env, how_much, cpu); |
233 | } | 256 | } |
234 | 257 | ||
235 | static struct reservation_ops gedf_ops = | 258 | static void gedf_task_drain_budget( |
259 | struct reservation* res, | ||
260 | lt_t how_much, | ||
261 | int cpu) | ||
262 | { | ||
263 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; | ||
264 | if (how_much > res->cur_budget || is_completed(t)) | ||
265 | res->cur_budget = 0; | ||
266 | else | ||
267 | res->cur_budget -= how_much; | ||
268 | res->budget_consumed += how_much; | ||
269 | res->budget_consumed_total += how_much; | ||
270 | } | ||
271 | |||
272 | static struct reservation_ops gedf_cont_ops = | ||
236 | { | 273 | { |
237 | .drain_budget = gedf_drain_budget, | 274 | .drain_budget = gedf_drain_budget, |
238 | .replenish_budget = gedf_replenish_budget, | 275 | .replenish_budget = gedf_replenish_budget, |
276 | .dispatch_client = gedf_dispatch_client, | ||
239 | .on_schedule = gedf_on_schedule, | 277 | .on_schedule = gedf_on_schedule, |
240 | .on_preempt = gedf_on_preempt, | 278 | .on_preempt = gedf_on_preempt, |
241 | .shutdown = gedf_shutdown | 279 | .shutdown = gedf_shutdown |
242 | }; | 280 | }; |
243 | 281 | ||
244 | long alloc_gedf_reservation( | 282 | static struct reservation_ops gedf_task_ops = |
245 | struct gedf_reservation** _res, | 283 | { |
284 | .drain_budget = gedf_task_drain_budget, | ||
285 | .replenish_budget = gedf_task_replenish_budget, | ||
286 | .dispatch_client = gedf_task_dispatch_client, | ||
287 | .shutdown = gedf_task_shutdown | ||
288 | }; | ||
289 | |||
290 | long alloc_gedf_task_reservation( | ||
291 | struct gedf_task_reservation** _res, | ||
292 | struct task_struct* task) | ||
293 | { | ||
294 | struct gedf_task_reservation* gedf_task_res; | ||
295 | struct gedf_reservation* gedf_res; | ||
296 | gedf_task_res = kzalloc(sizeof(*gedf_task_res), GFP_KERNEL); | ||
297 | if (!gedf_task_res) | ||
298 | return -ENOMEM; | ||
299 | gedf_res = &gedf_task_res->gedf_res; | ||
300 | |||
301 | init_ext_reservation(&gedf_res->res); | ||
302 | gedf_res->res.id = task->pid; | ||
303 | gedf_res->res.ops = &gedf_task_ops; | ||
304 | |||
305 | gedf_res->linked_on = NULL; | ||
306 | gedf_res->scheduled_on = NULL; | ||
307 | gedf_res->will_remove = 0; | ||
308 | gedf_res->blocked = 0; | ||
309 | |||
310 | gedf_task_res->task = task; | ||
311 | tsk_rt(task)->plugin_state = gedf_task_res; | ||
312 | |||
313 | *_res = gedf_task_res; | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | long alloc_gedf_container_reservation( | ||
318 | struct gedf_container_reservation** _res, | ||
246 | int id, | 319 | int id, |
247 | lt_t exec_cost, | 320 | lt_t max_budget, |
248 | lt_t period, | 321 | lt_t period, |
249 | lt_t relative_deadline) | 322 | lt_t relative_deadline) |
250 | { | 323 | { |
324 | struct gedf_container_reservation* gedf_cont_res; | ||
251 | struct gedf_reservation* gedf_res; | 325 | struct gedf_reservation* gedf_res; |
252 | gedf_res = kzalloc(sizeof(*gedf_res), GFP_KERNEL); | 326 | gedf_cont_res = kzalloc(sizeof(*gedf_cont_res), GFP_KERNEL); |
253 | if (!gedf_res) | 327 | if (!gedf_cont_res) |
254 | return -ENOMEM; | 328 | return -ENOMEM; |
329 | gedf_res = &gedf_cont_res->gedf_res; | ||
255 | 330 | ||
256 | init_ext_reservation(&gedf_res->res); | 331 | init_ext_reservation(&gedf_res->res); |
257 | gedf_res->res.id = id; | 332 | gedf_res->res.id = id; |
258 | gedf_res->res.ops = &gedf_ops; | 333 | gedf_res->res.ops = &gedf_cont_ops; |
259 | *_res = gedf_res; | ||
260 | 334 | ||
261 | gedf_res->linked_on = NULL; | 335 | gedf_res->linked_on = NULL; |
262 | gedf_res->scheduled_on = NULL; | 336 | gedf_res->scheduled_on = NULL; |
263 | gedf_res->will_remove = 0; | 337 | gedf_res->will_remove = 0; |
264 | gedf_res->blocked = 0; | 338 | gedf_res->blocked = 0; |
265 | gedf_res->exec_cost = exec_cost; | ||
266 | gedf_res->period = period; | ||
267 | gedf_res->relative_deadline = relative_deadline; | ||
268 | 339 | ||
340 | gedf_cont_res->max_budget = max_budget; | ||
341 | gedf_cont_res->period = period; | ||
342 | gedf_cont_res->relative_deadline = relative_deadline; | ||
343 | |||
344 | *_res = gedf_cont_res; | ||
269 | return 0; | 345 | return 0; |
270 | } | 346 | } |
271 | 347 | ||
@@ -294,8 +370,7 @@ static void gedf_env_shutdown( | |||
294 | kfree(env); | 370 | kfree(env); |
295 | } | 371 | } |
296 | 372 | ||
297 | /* can only be called when res is scheduled. | 373 | /* This assumes that is is only called from res itself requesting to be removed |
298 | * this only marks for removal, actual removal is done in the subsequent schedule() | ||
299 | */ | 374 | */ |
300 | static void gedf_env_remove_res( | 375 | static void gedf_env_remove_res( |
301 | struct reservation_environment* env, | 376 | struct reservation_environment* env, |
@@ -312,8 +387,9 @@ static void gedf_env_remove_res( | |||
312 | gedf_res->blocked = !complete; | 387 | gedf_res->blocked = !complete; |
313 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 388 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
314 | list_del_init(&gedf_res->res.all_list); | 389 | list_del_init(&gedf_res->res.all_list); |
315 | unlink(gedf_res); | 390 | unlink(gedf_res, gedf_env); |
316 | preempt(gedf_res->scheduled_on); | 391 | if (gedf_res->scheduled_on) |
392 | preempt(gedf_res->scheduled_on); | ||
317 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 393 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
318 | /* After preempt is called, schedule will update budget tracking. | 394 | /* After preempt is called, schedule will update budget tracking. |
319 | * In update_time, the environment will detect that res(which is scheduled) | 395 | * In update_time, the environment will detect that res(which is scheduled) |
@@ -365,7 +441,7 @@ static void gedf_env_suspend( | |||
365 | /* | 441 | /* |
366 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 442 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
367 | if (entry->linked) { | 443 | if (entry->linked) { |
368 | unlink(entry->linked); | 444 | unlink(entry->linked, gedf_env); |
369 | requeue(entry->linked); | 445 | requeue(entry->linked); |
370 | } | 446 | } |
371 | bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); | 447 | bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); |
@@ -402,7 +478,7 @@ static void gedf_env_resume( | |||
402 | if (entry->scheduled) | 478 | if (entry->scheduled) |
403 | hrtimer_start( | 479 | hrtimer_start( |
404 | &entry->timer, | 480 | &entry->timer, |
405 | ns_to_ktime(now + entry->scheduled->cur_budget), | 481 | ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), |
406 | HRTIMER_MODE_ABS_PINNED); | 482 | HRTIMER_MODE_ABS_PINNED); |
407 | } | 483 | } |
408 | 484 | ||
@@ -425,9 +501,9 @@ static struct task_struct* gedf_env_dispatch( | |||
425 | 501 | ||
426 | check_for_preemptions(gedf_env); | 502 | check_for_preemptions(gedf_env); |
427 | if (entry->scheduled != entry->linked) { | 503 | if (entry->scheduled != entry->linked) { |
428 | if (entry->scheduled) | 504 | if (entry->scheduled && entry->scheduled->ops->on_preempt) |
429 | entry->scheduled->ops->on_preempt(entry->scheduled, cpu); | 505 | entry->scheduled->ops->on_preempt(entry->scheduled, cpu); |
430 | if (entry->linked) | 506 | if (entry->linked && entry->linked->ops->on_schedule) |
431 | entry->linked->ops->on_schedule(entry->linked, now, cpu); | 507 | entry->linked->ops->on_schedule(entry->linked, now, cpu); |
432 | entry->scheduled = entry->linked; | 508 | entry->scheduled = entry->linked; |
433 | } | 509 | } |
@@ -435,12 +511,13 @@ static struct task_struct* gedf_env_dispatch( | |||
435 | 511 | ||
436 | //TODO: Think about possible problems with entry->scheduled being changed | 512 | //TODO: Think about possible problems with entry->scheduled being changed |
437 | if (entry->scheduled) { | 513 | if (entry->scheduled) { |
438 | next = entry->scheduled->env->ops->dispatch(entry->scheduled->env, now, cpu); | 514 | next = entry->scheduled->ops->dispatch_client(entry->scheduled, now, cpu); |
439 | |||
440 | hrtimer_start(&entry->timer, | 515 | hrtimer_start(&entry->timer, |
441 | ns_to_ktime(now + entry->scheduled->cur_budget), | 516 | ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), |
442 | HRTIMER_MODE_ABS_PINNED); | 517 | HRTIMER_MODE_ABS_PINNED); |
443 | } | 518 | } |
519 | else | ||
520 | hrtimer_try_to_cancel(&entry->timer); | ||
444 | 521 | ||
445 | return next; | 522 | return next; |
446 | } | 523 | } |
@@ -475,7 +552,7 @@ static void gedf_env_update_time( | |||
475 | /* unlink and requeue if not blocked */ | 552 | /* unlink and requeue if not blocked */ |
476 | if (!gedf_res->blocked) { | 553 | if (!gedf_res->blocked) { |
477 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 554 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
478 | unlink((struct gedf_reservation*)entry->scheduled); | 555 | unlink((struct gedf_reservation*)entry->scheduled, gedf_env); |
479 | requeue(&gedf_env->domain, entry->scheduled); | 556 | requeue(&gedf_env->domain, entry->scheduled); |
480 | check_for_preemptions(gedf_env); | 557 | check_for_preemptions(gedf_env); |
481 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 558 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
diff --git a/litmus/reservations/task_reservation.c b/litmus/reservations/task_reservation.c deleted file mode 100644 index ee4bbbc5ed07..000000000000 --- a/litmus/reservations/task_reservation.c +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | #include <linux/slab.h> | ||
2 | |||
3 | #include <litmus/litmus.h> | ||
4 | #include <litmus/reservations/ext_reservation.h> | ||
5 | #include <litmus/reservations/task_reservation.h> | ||
6 | |||
7 | static void task_env_shutdown( | ||
8 | struct reservation_environment* env) | ||
9 | { | ||
10 | struct task_reservation_environment* task_env = | ||
11 | container_of(env, struct task_reservation_environment, env); | ||
12 | tsk_rt(task_env->task)->plugin_state = NULL; | ||
13 | kfree(env); | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | static void task_env_remove_res( | ||
18 | struct reservation_environment* env, | ||
19 | struct reservation* res, | ||
20 | int complete) | ||
21 | { | ||
22 | return; | ||
23 | } | ||
24 | |||
25 | static void task_env_add_res( | ||
26 | struct reservation_environment* env, | ||
27 | struct reservation* res) | ||
28 | { | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | static void task_env_suspend( | ||
33 | struct reservation_environment* env, | ||
34 | int cpu) | ||
35 | { | ||
36 | return; | ||
37 | } | ||
38 | |||
39 | static void task_env_resume( | ||
40 | struct reservation_environment* env, | ||
41 | lt_t now, int cpu) | ||
42 | { | ||
43 | return; | ||
44 | } | ||
45 | |||
46 | static struct task_struct* task_env_dispatch( | ||
47 | struct reservation_environment* env, | ||
48 | lt_t now, | ||
49 | int cpu) | ||
50 | { | ||
51 | struct task_reservation_environment* task_env = | ||
52 | container_of(env, struct task_reservation_environment, env); | ||
53 | return task_env->task; | ||
54 | } | ||
55 | |||
56 | static void task_env_update_time( | ||
57 | struct reservation_environment* env, | ||
58 | lt_t how_much, | ||
59 | int cpu) | ||
60 | { | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | static struct reservation_environment_ops task_env_ops = { | ||
65 | .update_time = task_env_update_time, | ||
66 | .dispatch = task_env_dispatch, | ||
67 | .resume = task_env_resume, | ||
68 | .suspend = task_env_suspend, | ||
69 | .add_res = task_env_add_res, | ||
70 | .remove_res = task_env_remove_res, | ||
71 | .shutdown = task_env_shutdown | ||
72 | }; | ||
73 | |||
74 | long alloc_task_reservation_environment( | ||
75 | struct task_reservation_environment** _env, | ||
76 | struct task_struct* task) | ||
77 | { | ||
78 | struct task_reservation_environment* task_env; | ||
79 | task_env = kzalloc(sizeof(struct task_reservation_environment), GFP_KERNEL); | ||
80 | if (!task_env) | ||
81 | return -ENOMEM; | ||
82 | |||
83 | task_env->task = task; | ||
84 | task_env->env.ops = &task_env_ops; | ||
85 | tsk_rt(task)->plugin_state = task_env; | ||
86 | |||
87 | *_env = task_env; | ||
88 | return 0; | ||
89 | } | ||
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index 62fac871a349..4c37341065f0 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c | |||
@@ -71,7 +71,7 @@ static void release_jobs_before_now(rt_domain_t* rt) | |||
71 | * from the release queue and call release callback | 71 | * from the release queue and call release callback |
72 | */ | 72 | */ |
73 | while(!binheap_empty(&rt->release_queue.queue) && | 73 | while(!binheap_empty(&rt->release_queue.queue) && |
74 | lt_before_eq(litmus_clock(), rt->release_queue.earliest_release)) { | 74 | lt_before_eq(rt->release_queue.earliest_release, litmus_clock())) { |
75 | raw_spin_lock_irqsave(&rt->release_lock, flags); | 75 | raw_spin_lock_irqsave(&rt->release_lock, flags); |
76 | VTRACE("CB has the release_lock 0x%p\n", &rt->release_lock); | 76 | VTRACE("CB has the release_lock 0x%p\n", &rt->release_lock); |
77 | 77 | ||
@@ -206,7 +206,7 @@ static struct release_heap* get_release_heap_res(rt_domain_t *rt, | |||
206 | struct reservation* res, | 206 | struct reservation* res, |
207 | int use_task_heap) | 207 | int use_task_heap) |
208 | { | 208 | { |
209 | return __get_release_heap(rt, res->next_replenishment, res->rel_heap, use_task_heap); | 209 | return __get_release_heap(rt, res->replenishment_time, res->rel_heap, use_task_heap); |
210 | } | 210 | } |
211 | 211 | ||
212 | static struct release_heap* get_release_heap(rt_domain_t *rt, | 212 | static struct release_heap* get_release_heap(rt_domain_t *rt, |
diff --git a/litmus/sched_ext_res.c b/litmus/sched_ext_res.c index 3c34985bba85..e79986a12b2c 100644 --- a/litmus/sched_ext_res.c +++ b/litmus/sched_ext_res.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <litmus/sched_trace.h> | 14 | #include <litmus/sched_trace.h> |
15 | 15 | ||
16 | #include <litmus/reservations/ext_reservation.h> | 16 | #include <litmus/reservations/ext_reservation.h> |
17 | #include <litmus/reservations/task_reservation.h> | ||
18 | #include <litmus/reservations/gedf_reservation.h> | 17 | #include <litmus/reservations/gedf_reservation.h> |
19 | 18 | ||
20 | struct gedf_reservation_environment* gedf_env; | 19 | struct gedf_reservation_environment* gedf_env; |
@@ -69,11 +68,14 @@ static struct task_struct* ext_res_schedule(struct task_struct * prev) | |||
69 | 68 | ||
70 | now = litmus_clock(); | 69 | now = litmus_clock(); |
71 | delta = now - *this_cpu_ptr(&last_update_time); | 70 | delta = now - *this_cpu_ptr(&last_update_time); |
71 | |||
72 | //TODO: implement per cpu lt_t to track time | 72 | //TODO: implement per cpu lt_t to track time |
73 | 73 | ||
74 | gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu); | 74 | gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu); |
75 | next = gedf_env->env.ops->dispatch(&gedf_env->env, now, cpu); | 75 | next = gedf_env->env.ops->dispatch(&gedf_env->env, now, cpu); |
76 | 76 | ||
77 | *this_cpu_ptr(&last_update_time) = litmus_clock(); | ||
78 | |||
77 | sched_state_task_picked(); | 79 | sched_state_task_picked(); |
78 | 80 | ||
79 | return next; | 81 | return next; |
@@ -83,13 +85,11 @@ static struct task_struct* ext_res_schedule(struct task_struct * prev) | |||
83 | */ | 85 | */ |
84 | static void ext_res_task_block(struct task_struct *tsk) | 86 | static void ext_res_task_block(struct task_struct *tsk) |
85 | { | 87 | { |
86 | struct task_reservation_environment* task_env; | ||
87 | struct reservation* res; | 88 | struct reservation* res; |
88 | 89 | ||
89 | TRACE_TASK(tsk, "thread suspends at %llu \n", litmus_clock()); | 90 | TRACE_TASK(tsk, "thread suspends at %llu \n", litmus_clock()); |
90 | 91 | ||
91 | task_env = (struct task_reservation_environment*) tsk_rt(tsk)->plugin_state; | 92 | res = (struct reservation*) tsk_rt(tsk)->plugin_state; |
92 | res = task_env->env.res; | ||
93 | res->par_env->ops->remove_res(res->par_env, res, 0); | 93 | res->par_env->ops->remove_res(res->par_env, res, 0); |
94 | } | 94 | } |
95 | 95 | ||
@@ -99,38 +99,25 @@ static void ext_res_task_block(struct task_struct *tsk) | |||
99 | */ | 99 | */ |
100 | static void ext_res_task_resume(struct task_struct *tsk) | 100 | static void ext_res_task_resume(struct task_struct *tsk) |
101 | { | 101 | { |
102 | struct task_reservation_environment* task_env; | ||
103 | struct reservation* res; | 102 | struct reservation* res; |
104 | 103 | ||
105 | TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); | 104 | TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); |
106 | 105 | ||
107 | task_env = (struct task_reservation_environment*) tsk_rt(tsk)->plugin_state; | 106 | res = (struct reservation*) tsk_rt(tsk)->plugin_state; |
108 | res = task_env->env.res; | ||
109 | res->par_env->ops->add_res(res->par_env, res); | 107 | res->par_env->ops->add_res(res->par_env, res); |
110 | } | 108 | } |
111 | 109 | ||
112 | static long ext_res_admit_task(struct task_struct *tsk) | 110 | static long ext_res_admit_task(struct task_struct *tsk) |
113 | { | 111 | { |
114 | long err; | 112 | long err = 0; |
115 | |||
116 | struct gedf_reservation* gedf_res; | ||
117 | struct task_reservation_environment* task_env; | ||
118 | 113 | ||
119 | err = alloc_gedf_reservation( | 114 | struct gedf_task_reservation* gedf_task_res; |
120 | &gedf_res, | ||
121 | tsk->pid, | ||
122 | get_exec_cost(tsk), | ||
123 | get_rt_period(tsk), | ||
124 | get_rt_relative_deadline(tsk) | ||
125 | ); | ||
126 | if (err) | ||
127 | return err; | ||
128 | 115 | ||
129 | err = alloc_task_reservation_environment(&task_env, tsk); | 116 | err = alloc_gedf_task_reservation(&gedf_task_res, tsk); |
130 | if (err) | 117 | if (err) |
131 | return err; | 118 | return err; |
132 | 119 | ||
133 | env_to_res_couple(&task_env->env, &gedf_res->res); | 120 | gedf_task_res->gedf_res.res.par_env = &gedf_env->env; |
134 | 121 | ||
135 | //TODO: for checkpoint 2, need to find component and insert into it | 122 | //TODO: for checkpoint 2, need to find component and insert into it |
136 | 123 | ||
@@ -140,16 +127,16 @@ static long ext_res_admit_task(struct task_struct *tsk) | |||
140 | static void ext_res_task_new(struct task_struct *tsk, int on_runqueue, | 127 | static void ext_res_task_new(struct task_struct *tsk, int on_runqueue, |
141 | int is_running) | 128 | int is_running) |
142 | { | 129 | { |
143 | struct task_reservation_environment* task_env; | ||
144 | struct reservation* res; | 130 | struct reservation* res; |
145 | lt_t now = litmus_clock(); | 131 | lt_t now = litmus_clock(); |
146 | 132 | ||
147 | TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n", | 133 | TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n", |
148 | now, on_runqueue, is_running); | 134 | now, on_runqueue, is_running); |
149 | 135 | ||
150 | task_env = (struct task_reservation_environment*)tsk_rt(tsk)->plugin_state; | 136 | res = (struct reservation*)tsk_rt(tsk)->plugin_state; |
151 | res = task_env->env.res; | 137 | |
152 | res->next_replenishment = now; | 138 | release_at(tsk, now); |
139 | res->replenishment_time = now; | ||
153 | 140 | ||
154 | res->par_env->ops->add_res(res->par_env, res); | 141 | res->par_env->ops->add_res(res->par_env, res); |
155 | 142 | ||
@@ -177,12 +164,10 @@ static bool pres_fork_task(struct task_struct *tsk) | |||
177 | 164 | ||
178 | static void ext_res_task_exit(struct task_struct *tsk) | 165 | static void ext_res_task_exit(struct task_struct *tsk) |
179 | { | 166 | { |
180 | struct task_reservation_environment* task_env; | ||
181 | struct reservation* res; | 167 | struct reservation* res; |
182 | struct reservation_environment* par_env; | 168 | struct reservation_environment* par_env; |
183 | 169 | ||
184 | task_env = (struct task_reservation_environment*)tsk_rt(tsk)->plugin_state; | 170 | res = (struct reservation*)tsk_rt(tsk)->plugin_state; |
185 | res = task_env->env.res; | ||
186 | par_env = res->par_env; | 171 | par_env = res->par_env; |
187 | 172 | ||
188 | par_env->ops->remove_res(par_env, res, 1); | 173 | par_env->ops->remove_res(par_env, res, 1); |
@@ -326,11 +311,13 @@ static long ext_res_activate_plugin(void) | |||
326 | { | 311 | { |
327 | int cpu; | 312 | int cpu; |
328 | int num_cpus = num_online_cpus(); | 313 | int num_cpus = num_online_cpus(); |
314 | lt_t now = litmus_clock(); | ||
329 | 315 | ||
330 | alloc_gedf_reservation_environment(&gedf_env, num_cpus); | 316 | alloc_gedf_reservation_environment(&gedf_env, num_cpus); |
331 | 317 | ||
332 | for_each_online_cpu(cpu) { | 318 | for_each_online_cpu(cpu) { |
333 | TRACE("Initializing CPU%d...\n", cpu); | 319 | TRACE("Initializing CPU%d...\n", cpu); |
320 | *this_cpu_ptr(&last_update_time) = now; | ||
334 | gedf_env->cpu_mapping[cpu] = cpu; | 321 | gedf_env->cpu_mapping[cpu] = cpu; |
335 | gedf_env->cpu_entries[cpu].id = cpu; | 322 | gedf_env->cpu_entries[cpu].id = cpu; |
336 | } | 323 | } |