aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/reservations/ext_reservation.h13
-rw-r--r--include/litmus/reservations/gedf_reservation.h28
-rw-r--r--include/litmus/reservations/table_driven_ext_reservation.h26
-rw-r--r--include/litmus/rt_param.h21
-rw-r--r--litmus/reservations/ext_reservation.c8
-rw-r--r--litmus/reservations/gedf_reservation.c268
-rw-r--r--litmus/sched_ext_res.c7
7 files changed, 204 insertions, 167 deletions
diff --git a/include/litmus/reservations/ext_reservation.h b/include/litmus/reservations/ext_reservation.h
index 68784f71a268..40c9cd9e098e 100644
--- a/include/litmus/reservations/ext_reservation.h
+++ b/include/litmus/reservations/ext_reservation.h
@@ -25,14 +25,12 @@ typedef void (*drain_budget_t) (
25 25
26typedef struct task_struct* (*dispatch_client_t) ( 26typedef struct task_struct* (*dispatch_client_t) (
27 struct reservation *reservation, 27 struct reservation *reservation,
28 lt_t now,
29 int cpu 28 int cpu
30); 29);
31 30
32/* When reservation is scheduled. */ 31/* When reservation is scheduled. */
33typedef void (*on_schedule_t) ( 32typedef void (*on_schedule_t) (
34 struct reservation *reservation, 33 struct reservation *reservation,
35 lt_t now,
36 int cpu 34 int cpu
37); 35);
38 36
@@ -59,16 +57,12 @@ struct reservation {
59 57
60 /* exact meaning defined by impl. */ 58 /* exact meaning defined by impl. */
61 lt_t priority; 59 lt_t priority;
62 lt_t cur_budget;
63 lt_t replenishment_time; 60 lt_t replenishment_time;
64 61
65 /* budget stats */ 62 /* budget stats */
66 lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */ 63 lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */
67 lt_t budget_consumed_total; 64 lt_t budget_consumed_total;
68 65
69 /* list of registered budget callbacks */
70 struct budget_notifier_list budget_notifiers;
71
72 /* for memory reclamation purposes */ 66 /* for memory reclamation purposes */
73 struct list_head all_list; 67 struct list_head all_list;
74 68
@@ -84,7 +78,10 @@ struct reservation {
84 struct list_head ln; 78 struct list_head ln;
85}; 79};
86 80
87void init_ext_reservation(struct reservation* res); 81void init_ext_reservation(
82 struct reservation* res,
83 unsigned int id,
84 struct reservation_ops* ops);
88 85
89void clean_up_ext_reservation(struct reservation* res); 86void clean_up_ext_reservation(struct reservation* res);
90 87
@@ -96,12 +93,10 @@ typedef void (*env_update_time_t) (
96 93
97typedef struct task_struct* (*env_dispatch_t) ( 94typedef struct task_struct* (*env_dispatch_t) (
98 struct reservation_environment* env, 95 struct reservation_environment* env,
99 lt_t now,
100 int cpu); 96 int cpu);
101 97
102typedef void (*env_resume_t) ( 98typedef void (*env_resume_t) (
103 struct reservation_environment* env, 99 struct reservation_environment* env,
104 lt_t now,
105 int cpu); 100 int cpu);
106 101
107typedef void (*env_suspend_t) ( 102typedef void (*env_suspend_t) (
diff --git a/include/litmus/reservations/gedf_reservation.h b/include/litmus/reservations/gedf_reservation.h
index 57f2fa7f00fc..2adaaabbcaf4 100644
--- a/include/litmus/reservations/gedf_reservation.h
+++ b/include/litmus/reservations/gedf_reservation.h
@@ -8,22 +8,22 @@
8#include <litmus/reservations/ext_reservation.h> 8#include <litmus/reservations/ext_reservation.h>
9 9
10/* ************************************************************************** */ 10/* ************************************************************************** */
11struct cpu_entry {
12 int id;
13 struct hrtimer timer;
14 struct bheap_node* hn;
15 struct reservation* linked;
16 struct reservation* scheduled;
17};
18
19struct gedf_reservation { 11struct gedf_reservation {
20 struct reservation res; 12 struct reservation res;
21 struct cpu_entry* linked_on; 13 struct cpu_entry* linked_on;
22 struct cpu_entry* scheduled_on; 14 lt_t cur_budget;
23 int will_remove; 15 int will_remove;
24 int blocked; 16 int blocked;
25}; 17};
26 18
19struct cpu_entry {
20 int id;
21 struct hrtimer timer;
22 struct bheap_node* hn;
23 struct gedf_reservation* linked;
24 struct gedf_reservation* scheduled;
25};
26
27struct gedf_task_reservation { 27struct gedf_task_reservation {
28 struct gedf_reservation gedf_res; 28 struct gedf_reservation gedf_res;
29 struct task_struct* task; 29 struct task_struct* task;
@@ -52,13 +52,15 @@ long alloc_gedf_task_reservation(
52/* environment for scheduling reservations via gedf */ 52/* environment for scheduling reservations via gedf */
53struct gedf_reservation_environment { 53struct gedf_reservation_environment {
54 struct reservation_environment env; 54 struct reservation_environment env;
55
56 /* list of all reservations scheduled by environment */
55 struct list_head all_reservations; 57 struct list_head all_reservations;
58
56 /* number of active cpus in reservation */ 59 /* number of active cpus in reservation */
57 int num_cpus; 60 volatile int num_cpus;
61
58 /* array of gedf cpu entries */ 62 /* array of gedf cpu entries */
59 struct cpu_entry cpu_entries[NR_CPUS]; 63 struct cpu_entry cpu_entries[NR_CPUS];
60 /* smp_processor_id to environment cpu array offset mapping */
61 int cpu_mapping[NR_CPUS];
62 64
63 /* used to order cpus for gedf purposes */ 65 /* used to order cpus for gedf purposes */
64 struct bheap cpu_heap; 66 struct bheap cpu_heap;
@@ -69,7 +71,7 @@ struct gedf_reservation_environment {
69 71
70long alloc_gedf_reservation_environment( 72long alloc_gedf_reservation_environment(
71 struct gedf_reservation_environment** _env, 73 struct gedf_reservation_environment** _env,
72 int num_cpus 74 int max_cpus
73); 75);
74 76
75#endif 77#endif
diff --git a/include/litmus/reservations/table_driven_ext_reservation.h b/include/litmus/reservations/table_driven_ext_reservation.h
index 414791ee9261..51c32eadb419 100644
--- a/include/litmus/reservations/table_driven_ext_reservation.h
+++ b/include/litmus/reservations/table_driven_ext_reservation.h
@@ -12,23 +12,21 @@ struct cpu_entry {
12 struct reservation* scheduled; 12 struct reservation* scheduled;
13}; 13};
14 14
15struct gedf_reservation { 15struct mtd_reservation {
16 struct reservation res; 16 struct reservation res;
17 struct cpu_entry linked_on; 17 lt_t major_cycle;
18 struct cpu_entry scheduled_on; 18 unsigned int interval_index[NR_CPUS];
19 int will_remove; 19 unsigned int num_intervals[NR_CPUS];
20 int blocked; 20 struct lt_interval* intervals[NR_CPUS];
21 lt_t period; 21
22 lt_t relative_deadline; 22 int num_cur_intervals;
23 lt_t exec_cost; 23 struct lt_interval cur_interval[NR_CPUS];
24 lt_t major_cycle_start;
24}; 25};
25 26
26long alloc_gedf_reservation( 27long alloc_mtd_reservation(
27 struct reservation** _res, 28 struct reservation_config* config,
28 int id, 29 struct reservation** _res
29 lt_t exec_cost,
30 lt_t period,
31 lt_t relative_deadline
32); 30);
33 31
34/* environment for scheduling reservations via gedf */ 32/* environment for scheduling reservations via gedf */
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index 9b291343714f..29bf745b4497 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -110,6 +110,27 @@ struct reservation_config {
110 }; 110 };
111}; 111};
112 112
113struct ext_reservation_config {
114 unsigned int id;
115 lt_t priority;
116 int cpu;
117
118 union {
119 struct {
120 lt_t period;
121 lt_t budget;
122 lt_t relative_deadline;
123 lt_t offset;
124 } polling_params;
125
126 struct {
127 lt_t major_cycle_length;
128 unsigned int num_intervals;
129 struct lt_interval __user *intervals;
130 } table_driven_params;
131 };
132};
133
113/* regular sporadic task support */ 134/* regular sporadic task support */
114 135
115struct rt_task { 136struct rt_task {
diff --git a/litmus/reservations/ext_reservation.c b/litmus/reservations/ext_reservation.c
index 9397241faf99..c39bbae08513 100644
--- a/litmus/reservations/ext_reservation.c
+++ b/litmus/reservations/ext_reservation.c
@@ -6,9 +6,13 @@
6extern struct kmem_cache* bheap_node_cache; 6extern struct kmem_cache* bheap_node_cache;
7extern struct kmem_cache* release_heap_cache; 7extern struct kmem_cache* release_heap_cache;
8 8
9void init_ext_reservation(struct reservation* res) 9void init_ext_reservation(
10 struct reservation* res,
11 unsigned int id,
12 struct reservation_ops* ops)
10{ 13{
11 memset(res, 0, sizeof(struct reservation)); 14 res->id = id;
15 res->ops = ops;
12 res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC); 16 res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC);
13 res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC); 17 res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC);
14 bheap_node_init(&res->heap_node, res); 18 bheap_node_init(&res->heap_node, res);
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c
index 5951963e03ec..aa5eb9d4b821 100644
--- a/litmus/reservations/gedf_reservation.c
+++ b/litmus/reservations/gedf_reservation.c
@@ -59,7 +59,7 @@ static int cpu_lower_prio(struct bheap_node *_a, struct bheap_node *_b)
59 a = _a->value; 59 a = _a->value;
60 b = _b->value; 60 b = _b->value;
61 /* use higher prio here because prio is deadline value */ 61 /* use higher prio here because prio is deadline value */
62 return higher_prio(a->linked, b->linked); 62 return higher_prio(&a->linked->res, &b->linked->res);
63} 63}
64 64
65static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap) 65static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap)
@@ -76,14 +76,16 @@ static struct cpu_entry* lowest_prio_cpu(struct bheap* cpu_heap)
76 return hn->value; 76 return hn->value;
77} 77}
78 78
79static int edf_preemption_needed(rt_domain_t* rt, struct reservation* res) 79static int edf_preemption_needed(
80 struct gedf_reservation_environment* gedf_env,
81 struct gedf_reservation* gedf_res)
80{ 82{
81 /* we need the read lock for edf_ready_queue */ 83 /* we need the read lock for edf_ready_queue */
82 /* no need to preempt if there is nothing pending */ 84 /* no need to preempt if there is nothing pending */
83 if (bheap_empty(&rt->ready_queue)) 85 if (bheap_empty(&gedf_env->domain.ready_queue))
84 return 0; 86 return 0;
85 /* we need to reschedule if res doesn't exist */ 87 /* we need to reschedule if res doesn't exist */
86 if (!res) 88 if (!gedf_res)
87 return 1; 89 return 1;
88 90
89 /* NOTE: We cannot check for non-preemptibility since we 91 /* NOTE: We cannot check for non-preemptibility since we
@@ -91,7 +93,7 @@ static int edf_preemption_needed(rt_domain_t* rt, struct reservation* res)
91 */ 93 */
92 94
93 /* reversed */ 95 /* reversed */
94 return higher_prio(res, __next_ready_res(rt)); 96 return higher_prio(&gedf_res->res, __next_ready_res(&gedf_env->domain));
95} 97}
96 98
97/* ******************************************************************************** */ 99/* ******************************************************************************** */
@@ -107,60 +109,61 @@ static enum hrtimer_restart timer_callback(struct hrtimer* timer)
107 return HRTIMER_NORESTART; 109 return HRTIMER_NORESTART;
108} 110}
109 111
110static void requeue(rt_domain_t* domain, struct reservation* res) { 112static void requeue(
111 BUG_ON(!res); 113 struct gedf_reservation_environment* gedf_env,
112 BUG_ON(is_queued_res(res)); 114 struct gedf_reservation* gedf_res)
115{
116 BUG_ON(!gedf_res);
117 BUG_ON(is_queued_res(&gedf_res->res));
113 118
114 if (lt_before_eq(res->replenishment_time, litmus_clock())) 119 if (lt_before_eq(gedf_res->res.replenishment_time, litmus_clock()))
115 __add_ready_res(domain, res); 120 __add_ready_res(&gedf_env->domain, &gedf_res->res);
116 else 121 else
117 __add_release_res(domain, res); 122 __add_release_res(&gedf_env->domain, &gedf_res->res);
118 123
119} 124}
120 125
121static void link_task_to_cpu( 126static void link_task_to_cpu(
127 struct gedf_reservation_environment* gedf_env,
122 struct gedf_reservation* linked, 128 struct gedf_reservation* linked,
123 struct cpu_entry* entry, 129 struct cpu_entry* entry)
124 struct gedf_reservation_environment* gedf_env)
125{ 130{
126 struct cpu_entry* sched = NULL;
127 struct reservation* tmp;
128 131
129 if (entry->linked) 132 if (entry->linked)
130 ((struct gedf_reservation*)entry->linked)->linked_on = NULL; 133 entry->linked->linked_on = NULL;
131 134
132 if (linked) 135 if (linked)
133 linked->linked_on = entry; 136 linked->linked_on = entry;
134 137
135 entry->linked = &linked->res; 138 entry->linked = linked;
136 update_cpu_position(entry, &gedf_env->cpu_heap); 139 update_cpu_position(entry, &gedf_env->cpu_heap);
137} 140}
138 141
139static void unlink( 142static void unlink(
140 struct gedf_reservation* res, 143 struct gedf_reservation_environment* gedf_env,
141 struct gedf_reservation_environment* gedf_env) 144 struct gedf_reservation* gedf_res)
142{ 145{
143 BUG_ON(!res->linked_on); 146 BUG_ON(!gedf_res->linked_on);
144 if (res->linked_on) { 147 if (gedf_res->linked_on) {
145 link_task_to_cpu(NULL, res->linked_on, gedf_env); 148 link_task_to_cpu(gedf_env, NULL, gedf_res->linked_on);
146 res->linked_on = NULL; 149 gedf_res->linked_on = NULL;
147 } else if (is_queued_res(&res->res)) { 150 } else if (is_queued_res(&gedf_res->res)) {
148 remove_res(&gedf_env->domain, &res->res); 151 remove_res(&gedf_env->domain, &gedf_res->res);
149 } 152 }
150} 153}
151 154
152static void check_for_preemptions(struct gedf_reservation_environment* env) 155static void check_for_preemptions(struct gedf_reservation_environment* gedf_env)
153{ 156{
154 struct gedf_reservation* res; 157 struct gedf_reservation* gedf_res;
155 struct cpu_entry* last; 158 struct cpu_entry* last;
156 159
157 for (last = lowest_prio_cpu(&env->cpu_heap); 160 for (last = lowest_prio_cpu(&gedf_env->cpu_heap);
158 edf_preemption_needed(&env->domain, last->linked); 161 edf_preemption_needed(gedf_env, last->linked);
159 last = lowest_prio_cpu(&env->cpu_heap)) { 162 last = lowest_prio_cpu(&gedf_env->cpu_heap)) {
160 res = (struct gedf_reservation*)__take_ready_res(&env->domain); 163 gedf_res = (struct gedf_reservation*)__take_ready_res(&gedf_env->domain);
161 if (last->linked && last->linked->cur_budget) 164 if (last->linked && last->linked->cur_budget)
162 requeue(&env->domain, last->linked); 165 requeue(gedf_env, last->linked);
163 link_task_to_cpu(res, last, env); 166 link_task_to_cpu(gedf_env, gedf_res, last);
164 preempt(last); 167 preempt(last);
165 } 168 }
166} 169}
@@ -190,23 +193,20 @@ static void gedf_on_preempt(
190 193
191static void gedf_on_schedule( 194static void gedf_on_schedule(
192 struct reservation *res, 195 struct reservation *res,
193 lt_t now,
194 int cpu) 196 int cpu)
195{ 197{
196 res->env->ops->resume(res->env, now, cpu); 198 res->env->ops->resume(res->env, cpu);
197} 199}
198 200
199static struct task_struct* gedf_dispatch_client( 201static struct task_struct* gedf_dispatch_client(
200 struct reservation* res, 202 struct reservation* res,
201 lt_t now,
202 int cpu) 203 int cpu)
203{ 204{
204 return res->env->ops->dispatch(res->env, now, cpu); 205 return res->env->ops->dispatch(res->env, cpu);
205} 206}
206 207
207static struct task_struct* gedf_task_dispatch_client( 208static struct task_struct* gedf_task_dispatch_client(
208 struct reservation* res, 209 struct reservation* res,
209 lt_t now,
210 int cpu) 210 int cpu)
211{ 211{
212 return ((struct gedf_task_reservation*)res)->task; 212 return ((struct gedf_task_reservation*)res)->task;
@@ -219,9 +219,9 @@ static void gedf_replenish_budget(
219 struct gedf_container_reservation* gedf_cont_res = 219 struct gedf_container_reservation* gedf_cont_res =
220 (struct gedf_container_reservation*)res; 220 (struct gedf_container_reservation*)res;
221 res->budget_consumed = 0; 221 res->budget_consumed = 0;
222 res->cur_budget = gedf_cont_res->max_budget; 222 gedf_cont_res->gedf_res.cur_budget = gedf_cont_res->max_budget;
223 res->priority = res->replenishment_time + gedf_cont_res->relative_deadline;
224 res->replenishment_time += gedf_cont_res->period; 223 res->replenishment_time += gedf_cont_res->period;
224 res->priority = res->replenishment_time + gedf_cont_res->relative_deadline;
225} 225}
226 226
227static void gedf_task_replenish_budget( 227static void gedf_task_replenish_budget(
@@ -229,6 +229,8 @@ static void gedf_task_replenish_budget(
229 int cpu) 229 int cpu)
230{ 230{
231 struct task_struct* t = ((struct gedf_task_reservation*)res)->task; 231 struct task_struct* t = ((struct gedf_task_reservation*)res)->task;
232 struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res);
233
232 if (is_completed(t)) { 234 if (is_completed(t)) {
233 sched_trace_task_completion(t, 0); 235 sched_trace_task_completion(t, 0);
234 prepare_for_next_period(t); 236 prepare_for_next_period(t);
@@ -243,7 +245,7 @@ static void gedf_task_replenish_budget(
243 TRACE_TASK(t, "overrun budget!\n"); 245 TRACE_TASK(t, "overrun budget!\n");
244 } 246 }
245 res->budget_consumed = 0; 247 res->budget_consumed = 0;
246 res->cur_budget = get_exec_cost(t); 248 gedf_res->cur_budget = get_exec_cost(t);
247} 249}
248 250
249static void gedf_drain_budget( 251static void gedf_drain_budget(
@@ -251,10 +253,12 @@ static void gedf_drain_budget(
251 lt_t how_much, 253 lt_t how_much,
252 int cpu) 254 int cpu)
253{ 255{
254 if (how_much > res->cur_budget) 256 struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res);
255 res->cur_budget = 0; 257
258 if (how_much > gedf_res->cur_budget)
259 gedf_res->cur_budget = 0;
256 else 260 else
257 res->cur_budget -= how_much; 261 gedf_res->cur_budget -= how_much;
258 res->budget_consumed += how_much; 262 res->budget_consumed += how_much;
259 res->budget_consumed_total += how_much; 263 res->budget_consumed_total += how_much;
260 264
@@ -267,10 +271,12 @@ static void gedf_task_drain_budget(
267 int cpu) 271 int cpu)
268{ 272{
269 struct task_struct* t = ((struct gedf_task_reservation*)res)->task; 273 struct task_struct* t = ((struct gedf_task_reservation*)res)->task;
270 if (how_much > res->cur_budget || is_completed(t)) 274 struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res);
271 res->cur_budget = 0; 275
276 if (how_much > gedf_res->cur_budget || is_completed(t))
277 gedf_res->cur_budget = 0;
272 else 278 else
273 res->cur_budget -= how_much; 279 gedf_res->cur_budget -= how_much;
274 res->budget_consumed += how_much; 280 res->budget_consumed += how_much;
275 res->budget_consumed_total += how_much; 281 res->budget_consumed_total += how_much;
276} 282}
@@ -298,20 +304,12 @@ long alloc_gedf_task_reservation(
298 struct task_struct* task) 304 struct task_struct* task)
299{ 305{
300 struct gedf_task_reservation* gedf_task_res; 306 struct gedf_task_reservation* gedf_task_res;
301 struct gedf_reservation* gedf_res;
302 gedf_task_res = kzalloc(sizeof(*gedf_task_res), GFP_KERNEL); 307 gedf_task_res = kzalloc(sizeof(*gedf_task_res), GFP_KERNEL);
303 if (!gedf_task_res) 308 if (!gedf_task_res)
304 return -ENOMEM; 309 return -ENOMEM;
305 gedf_res = &gedf_task_res->gedf_res;
306 310
307 init_ext_reservation(&gedf_res->res); 311 memset(gedf_task_res, 0, sizeof(struct gedf_task_reservation));
308 gedf_res->res.id = task->pid; 312 init_ext_reservation(&gedf_task_res->gedf_res.res, task->pid, &gedf_task_ops);
309 gedf_res->res.ops = &gedf_task_ops;
310
311 gedf_res->linked_on = NULL;
312 gedf_res->scheduled_on = NULL;
313 gedf_res->will_remove = 0;
314 gedf_res->blocked = 0;
315 313
316 gedf_task_res->task = task; 314 gedf_task_res->task = task;
317 tsk_rt(task)->plugin_state = gedf_task_res; 315 tsk_rt(task)->plugin_state = gedf_task_res;
@@ -328,20 +326,12 @@ long alloc_gedf_container_reservation(
328 lt_t relative_deadline) 326 lt_t relative_deadline)
329{ 327{
330 struct gedf_container_reservation* gedf_cont_res; 328 struct gedf_container_reservation* gedf_cont_res;
331 struct gedf_reservation* gedf_res;
332 gedf_cont_res = kzalloc(sizeof(*gedf_cont_res), GFP_KERNEL); 329 gedf_cont_res = kzalloc(sizeof(*gedf_cont_res), GFP_KERNEL);
333 if (!gedf_cont_res) 330 if (!gedf_cont_res)
334 return -ENOMEM; 331 return -ENOMEM;
335 gedf_res = &gedf_cont_res->gedf_res;
336 332
337 init_ext_reservation(&gedf_res->res); 333 memset(gedf_cont_res, 0, sizeof(struct gedf_container_reservation));
338 gedf_res->res.id = id; 334 init_ext_reservation(&gedf_cont_res->gedf_res.res, id, &gedf_cont_ops);
339 gedf_res->res.ops = &gedf_cont_ops;
340
341 gedf_res->linked_on = NULL;
342 gedf_res->scheduled_on = NULL;
343 gedf_res->will_remove = 0;
344 gedf_res->blocked = 0;
345 335
346 gedf_cont_res->max_budget = max_budget; 336 gedf_cont_res->max_budget = max_budget;
347 gedf_cont_res->period = period; 337 gedf_cont_res->period = period;
@@ -361,11 +351,15 @@ static void gedf_env_shutdown(
361 unsigned long flags; 351 unsigned long flags;
362 352
363 gedf_env = container_of(env, struct gedf_reservation_environment, env); 353 gedf_env = container_of(env, struct gedf_reservation_environment, env);
354
364 suspend_releases(&gedf_env->domain); 355 suspend_releases(&gedf_env->domain);
356
365 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 357 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
358 /* cancel all budget tracking hrtimers */
366 for_each_online_cpu(i) { 359 for_each_online_cpu(i) {
367 hrtimer_cancel(&gedf_env->cpu_entries[i].timer); 360 hrtimer_cancel(&gedf_env->cpu_entries[i].timer);
368 } 361 }
362 /* call shutdown on all scheduled reservations */
369 while (!list_empty(&gedf_env->all_reservations)) { 363 while (!list_empty(&gedf_env->all_reservations)) {
370 res = list_first_entry(&gedf_env->all_reservations, 364 res = list_first_entry(&gedf_env->all_reservations,
371 struct reservation, all_list); 365 struct reservation, all_list);
@@ -373,6 +367,8 @@ static void gedf_env_shutdown(
373 res->ops->shutdown(res); 367 res->ops->shutdown(res);
374 } 368 }
375 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 369 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
370
371 /* free memory */
376 kfree(env); 372 kfree(env);
377} 373}
378 374
@@ -389,13 +385,14 @@ static void gedf_env_remove_res(
389 385
390 gedf_env = container_of(env, struct gedf_reservation_environment, env); 386 gedf_env = container_of(env, struct gedf_reservation_environment, env);
391 gedf_res = container_of(res, struct gedf_reservation, res); 387 gedf_res = container_of(res, struct gedf_reservation, res);
388
392 gedf_res->will_remove = complete; 389 gedf_res->will_remove = complete;
393 gedf_res->blocked = !complete; 390 gedf_res->blocked = !complete;
391
394 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 392 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
395 list_del_init(&gedf_res->res.all_list); 393 list_del_init(&gedf_res->res.all_list);
396 unlink(gedf_res, gedf_env); 394 unlink(gedf_env, gedf_res);
397 if (gedf_res->scheduled_on) 395 check_for_preemptions(gedf_env);
398 preempt(gedf_res->scheduled_on);
399 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 396 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
400 /* After preempt is called, schedule will update budget tracking. 397 /* After preempt is called, schedule will update budget tracking.
401 * In update_time, the environment will detect that res(which is scheduled) 398 * In update_time, the environment will detect that res(which is scheduled)
@@ -414,114 +411,124 @@ static void gedf_env_add_res(
414 struct gedf_reservation_environment* gedf_env; 411 struct gedf_reservation_environment* gedf_env;
415 struct gedf_reservation* gedf_res; 412 struct gedf_reservation* gedf_res;
416 unsigned long flags; 413 unsigned long flags;
414
417 gedf_env = container_of(env, struct gedf_reservation_environment, env); 415 gedf_env = container_of(env, struct gedf_reservation_environment, env);
418 gedf_res = container_of(res, struct gedf_reservation, res); 416 gedf_res = container_of(res, struct gedf_reservation, res);
417
419 res->par_env = env; 418 res->par_env = env;
420 gedf_res->will_remove = 0; 419 gedf_res->will_remove = 0;
421 gedf_res->blocked = 0; 420 gedf_res->blocked = 0;
422 421
423 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 422 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
424 list_add(&gedf_res->res.all_list, &gedf_env->all_reservations); 423 list_add(&gedf_res->res.all_list, &gedf_env->all_reservations);
425 requeue(&gedf_env->domain, res); 424 requeue(gedf_env, gedf_res);
426 check_for_preemptions(gedf_env); 425 check_for_preemptions(gedf_env);
427 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 426 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
428} 427}
429 428
429/* TODO: currently does not fully support dynamic cores count in environment
430 * when a core is suspended, if the release timer is on that core, it will not be
431 * properly suspended. Only the last core to suspend stops the release timer
432 */
430static void gedf_env_suspend( 433static void gedf_env_suspend(
431 struct reservation_environment* env, 434 struct reservation_environment* env,
432 int cpu) 435 int cpu)
433{ 436{
434 struct gedf_reservation_environment* gedf_env; 437 struct gedf_reservation_environment* gedf_env;
435 struct cpu_entry* entry; 438 struct cpu_entry* entry;
436 int env_cpu;
437 unsigned long flags; 439 unsigned long flags;
438 440
439 gedf_env = container_of(env, struct gedf_reservation_environment, env); 441 gedf_env = container_of(env, struct gedf_reservation_environment, env);
440 env_cpu = gedf_env->cpu_mapping[cpu]; 442 entry = &gedf_env->cpu_entries[cpu];
441 entry = &gedf_env->cpu_entries[env_cpu];
442
443 if (env_cpu == 0)
444 suspend_releases(&gedf_env->domain);
445 443
446 /* this essentially removes the cpu from scheduling consideration */
447 /*
448 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 444 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
445
446 gedf_env->num_cpus--;
447 /* on env suspension, we need to preempt scheduled tasks, and unlink linked tasks */
449 if (entry->linked) { 448 if (entry->linked) {
450 unlink(entry->linked, gedf_env); 449 unlink(gedf_env, entry->linked);
451 requeue(entry->linked); 450 requeue(gedf_env, entry->linked);
452 } 451 }
452 if (entry->scheduled && entry->scheduled->res.ops->on_preempt)
453 entry->scheduled->res.ops->on_preempt(&entry->scheduled->res, cpu);
454
455 /* this essentially removes the cpu from scheduling consideration */
453 bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); 456 bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn);
457
454 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 458 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
455 */ 459
460 /* suspends rt_domain releases when the last core of env is preempted */
461 if (!gedf_env->num_cpus)
462 suspend_releases(&gedf_env->domain);
456 463
457 hrtimer_try_to_cancel(&entry->timer); 464 hrtimer_try_to_cancel(&entry->timer);
458} 465}
459 466
460static void gedf_env_resume( 467static void gedf_env_resume(
461 struct reservation_environment* env, 468 struct reservation_environment* env,
462 lt_t now,
463 int cpu) 469 int cpu)
464{ 470{
465 struct gedf_reservation_environment* gedf_env; 471 struct gedf_reservation_environment* gedf_env;
466 struct cpu_entry* entry; 472 struct cpu_entry* entry;
467 int env_cpu;
468 unsigned long flags; 473 unsigned long flags;
469 474
470 gedf_env = container_of(env, struct gedf_reservation_environment, env); 475 gedf_env = container_of(env, struct gedf_reservation_environment, env);
471 env_cpu = gedf_env->cpu_mapping[cpu]; 476 entry = &gedf_env->cpu_entries[cpu];
472 entry = &gedf_env->cpu_entries[env_cpu];
473 477
474 if (env_cpu == 0) 478 /* resumes rt_domain releases when the first core of env resumes execution */
479 if (!gedf_env->num_cpus)
475 resume_releases(&gedf_env->domain); 480 resume_releases(&gedf_env->domain);
476 481
477 /* adds cpu back to scheduling consideration */
478 /*
479 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 482 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
480 bheap_insert(cpu_lower_prio, cpu_heap, entry->hn);
481 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
482 */
483 483
484 if (entry->scheduled) 484 gedf_env->num_cpus++;
485 hrtimer_start( 485 /* adds cpu back to scheduling consideration */
486 &entry->timer, 486 bheap_insert(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn);
487 ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), 487
488 HRTIMER_MODE_ABS_PINNED); 488 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
489} 489}
490 490
491static struct task_struct* gedf_env_dispatch( 491static struct task_struct* gedf_env_dispatch(
492 struct reservation_environment* env, 492 struct reservation_environment* env,
493 lt_t now,
494 int cpu) 493 int cpu)
495{ 494{
496 struct gedf_reservation_environment* gedf_env; 495 struct gedf_reservation_environment* gedf_env;
497 struct cpu_entry* entry; 496 struct cpu_entry* entry;
498 int env_cpu;
499 struct task_struct* next = NULL; 497 struct task_struct* next = NULL;
500 unsigned long flags; 498 unsigned long flags;
501 499
502 gedf_env = container_of(env, struct gedf_reservation_environment, env); 500 gedf_env = container_of(env, struct gedf_reservation_environment, env);
503 env_cpu = gedf_env->cpu_mapping[cpu]; 501 entry = &gedf_env->cpu_entries[cpu];
504 entry = &gedf_env->cpu_entries[env_cpu]; 502
503 BUG_ON(!bheap_node_in_heap(entry->hn));
504 BUG_ON(entry->id != cpu);
505 505
506 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 506 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
507 507
508 check_for_preemptions(gedf_env); 508 /* update linked if linked for this cpu is empty */
509 if (!entry->linked)
510 check_for_preemptions(gedf_env);
511
512 /* if linked and scheduled differ, preempt and schedule accordingly */
509 if (entry->scheduled != entry->linked) { 513 if (entry->scheduled != entry->linked) {
510 if (entry->scheduled && entry->scheduled->ops->on_preempt) 514 if (entry->scheduled && entry->scheduled->res.ops->on_preempt)
511 entry->scheduled->ops->on_preempt(entry->scheduled, cpu); 515 entry->scheduled->res.ops->on_preempt(&entry->scheduled->res, cpu);
512 if (entry->linked && entry->linked->ops->on_schedule) 516 if (entry->linked && entry->linked->res.ops->on_schedule)
513 entry->linked->ops->on_schedule(entry->linked, now, cpu); 517 entry->linked->res.ops->on_schedule(&entry->linked->res, cpu);
514 entry->scheduled = entry->linked; 518 entry->scheduled = entry->linked;
515 } 519 }
516 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 520 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
517 521
518 //TODO: Think about possible problems with entry->scheduled being changed 522 //TODO: Think about possible problems with entry->scheduled being changed
519 if (entry->scheduled) { 523 if (entry->scheduled) {
520 next = entry->scheduled->ops->dispatch_client(entry->scheduled, now, cpu); 524 /* let scheduled reservation decide what runs next */
525 next = entry->scheduled->res.ops->dispatch_client(&entry->scheduled->res, cpu);
526 /* set timer for budget expiration */
521 hrtimer_start(&entry->timer, 527 hrtimer_start(&entry->timer,
522 ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), 528 ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget),
523 HRTIMER_MODE_ABS_PINNED); 529 HRTIMER_MODE_ABS_PINNED);
524 } 530 }
531 /* cancel budget timer when no reservation is set to be scheduled */
525 else 532 else
526 hrtimer_try_to_cancel(&entry->timer); 533 hrtimer_try_to_cancel(&entry->timer);
527 534
@@ -529,43 +536,45 @@ static struct task_struct* gedf_env_dispatch(
529} 536}
530 537
531static void gedf_env_update_time( 538static void gedf_env_update_time(
532 struct reservation_environment* env, lt_t how_much, int cpu) 539 struct reservation_environment* env,
540 lt_t how_much,
541 int cpu)
533{ 542{
534 struct gedf_reservation_environment* gedf_env; 543 struct gedf_reservation_environment* gedf_env;
535 struct gedf_reservation* gedf_res;
536 struct cpu_entry* entry; 544 struct cpu_entry* entry;
537 int env_cpu;
538 unsigned long flags; 545 unsigned long flags;
539 546
540 gedf_env = container_of(env, struct gedf_reservation_environment, env); 547 gedf_env = container_of(env, struct gedf_reservation_environment, env);
541 env_cpu = gedf_env->cpu_mapping[cpu]; 548 entry = &gedf_env->cpu_entries[cpu];
542 entry = &gedf_env->cpu_entries[env_cpu];
543 549
550 BUG_ON(!bheap_node_in_heap(entry->hn));
544 BUG_ON(entry->id != cpu); 551 BUG_ON(entry->id != cpu);
545 552
546 if (!entry->scheduled) 553 if (!entry->scheduled)
547 return; 554 return;
548 555
549 entry->scheduled->ops->drain_budget(entry->scheduled, how_much, cpu); 556 /* tells scheduled res to drain its budget */
550 gedf_res = container_of(entry->scheduled, struct gedf_reservation, res); 557 entry->scheduled->res.ops->drain_budget(&entry->scheduled->res, how_much, cpu);
558
551 /* if flagged for removal from environment, invoke shutdown callback */ 559 /* if flagged for removal from environment, invoke shutdown callback */
552 if (gedf_res->will_remove) { 560 if (entry->scheduled->will_remove) {
553 /* assumed to already been unlinked by whatever set will_remove */ 561 /* assumed to already been unlinked by whatever set will_remove */
554 entry->scheduled->ops->shutdown(entry->scheduled); 562 entry->scheduled->res.ops->shutdown(&entry->scheduled->res);
555 entry->scheduled = NULL; 563 entry->scheduled = NULL;
556 } else if (!entry->scheduled->cur_budget) { 564 } else if (!entry->scheduled->cur_budget) {
557 entry->scheduled->ops->replenish_budget(entry->scheduled, cpu); 565 entry->scheduled->res.ops->replenish_budget(&entry->scheduled->res, cpu);
558 /* unlink and requeue if not blocked */ 566 /* unlink and requeue if not blocked */
559 if (!gedf_res->blocked) { 567 if (!entry->scheduled->blocked) {
560 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 568 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
561 unlink((struct gedf_reservation*)entry->scheduled, gedf_env); 569 unlink(gedf_env, entry->scheduled);
562 requeue(&gedf_env->domain, entry->scheduled); 570 requeue(gedf_env, entry->scheduled);
563 check_for_preemptions(gedf_env); 571 check_for_preemptions(gedf_env);
564 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); 572 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
565 } 573 }
566 } 574 }
567} 575}
568 576
577/* callback for how the domain will release jobs */
569static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res) 578static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res)
570{ 579{
571 unsigned long flags; 580 unsigned long flags;
@@ -590,7 +599,7 @@ static struct reservation_environment_ops gedf_env_ops = {
590 599
591long alloc_gedf_reservation_environment( 600long alloc_gedf_reservation_environment(
592 struct gedf_reservation_environment** _env, 601 struct gedf_reservation_environment** _env,
593 int num_cpus) 602 int max_cpus)
594{ 603{
595 struct gedf_reservation_environment* gedf_env; 604 struct gedf_reservation_environment* gedf_env;
596 int i; 605 int i;
@@ -600,17 +609,26 @@ long alloc_gedf_reservation_environment(
600 return -ENOMEM; 609 return -ENOMEM;
601 610
602 memset(gedf_env, 0, sizeof(struct gedf_reservation_environment)); 611 memset(gedf_env, 0, sizeof(struct gedf_reservation_environment));
612
613 /* set environment callback actions */
603 gedf_env->env.ops = &gedf_env_ops; 614 gedf_env->env.ops = &gedf_env_ops;
615
604 INIT_LIST_HEAD(&gedf_env->all_reservations); 616 INIT_LIST_HEAD(&gedf_env->all_reservations);
605 gedf_env->num_cpus = 0; 617 gedf_env->num_cpus = 0;
606 bheap_init(&gedf_env->cpu_heap); 618 bheap_init(&gedf_env->cpu_heap);
607 for (i = 0; i < num_cpus; i++) { 619 for (i = 0; i < max_cpus; i++) {
608 gedf_env->cpu_entries[i].hn = &gedf_env->cpu_node[i]; 620 gedf_env->cpu_entries[i].id = i;
621
622 /* initialize cpu timer */
609 hrtimer_init(&gedf_env->cpu_entries[i].timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); 623 hrtimer_init(&gedf_env->cpu_entries[i].timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
610 gedf_env->cpu_entries[i].timer.function = timer_callback; 624 gedf_env->cpu_entries[i].timer.function = timer_callback;
625
626 /* initialize cpu heap node */
627 gedf_env->cpu_entries[i].hn = &gedf_env->cpu_node[i];
611 bheap_node_init(&gedf_env->cpu_entries[i].hn, &gedf_env->cpu_entries[i]); 628 bheap_node_init(&gedf_env->cpu_entries[i].hn, &gedf_env->cpu_entries[i]);
612 bheap_insert(cpu_lower_prio, &gedf_env->cpu_heap, gedf_env->cpu_entries[i].hn);
613 } 629 }
630
631 /* initialize environment domain */
614 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs); 632 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs);
615 633
616 *_env = gedf_env; 634 *_env = gedf_env;
diff --git a/litmus/sched_ext_res.c b/litmus/sched_ext_res.c
index e79986a12b2c..dd2ae0f02fb3 100644
--- a/litmus/sched_ext_res.c
+++ b/litmus/sched_ext_res.c
@@ -66,13 +66,12 @@ static struct task_struct* ext_res_schedule(struct task_struct * prev)
66 lt_t now, delta; 66 lt_t now, delta;
67 struct task_struct* next; 67 struct task_struct* next;
68 68
69 now = litmus_clock(); 69 delta = litmus_clock() - *this_cpu_ptr(&last_update_time);
70 delta = now - *this_cpu_ptr(&last_update_time);
71 70
72 //TODO: implement per cpu lt_t to track time 71 //TODO: implement per cpu lt_t to track time
73 72
74 gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu); 73 gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu);
75 next = gedf_env->env.ops->dispatch(&gedf_env->env, now, cpu); 74 next = gedf_env->env.ops->dispatch(&gedf_env->env, cpu);
76 75
77 *this_cpu_ptr(&last_update_time) = litmus_clock(); 76 *this_cpu_ptr(&last_update_time) = litmus_clock();
78 77
@@ -318,8 +317,8 @@ static long ext_res_activate_plugin(void)
318 for_each_online_cpu(cpu) { 317 for_each_online_cpu(cpu) {
319 TRACE("Initializing CPU%d...\n", cpu); 318 TRACE("Initializing CPU%d...\n", cpu);
320 *this_cpu_ptr(&last_update_time) = now; 319 *this_cpu_ptr(&last_update_time) = now;
321 gedf_env->cpu_mapping[cpu] = cpu;
322 gedf_env->cpu_entries[cpu].id = cpu; 320 gedf_env->cpu_entries[cpu].id = cpu;
321 gedf_env->env.ops->resume(&gedf_env->env, cpu);
323 } 322 }
324 gedf_env->num_cpus = num_cpus; 323 gedf_env->num_cpus = num_cpus;
325 324