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 | } |
