aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZelin Tong <ztong@ludwig.cs.unc.edu>2020-09-21 13:32:29 -0400
committerZelin Tong <ztong@ludwig.cs.unc.edu>2020-09-21 13:32:29 -0400
commitea90ac994afd39ec5899f663502502d47e060ae2 (patch)
tree2dd8f2ecfa7e99b45efbef858e80de18aa6034e5
parentb665fac6de1744ce6aeb4cfdd81a2cff528484dc (diff)
Backup Commit 2
-rw-r--r--include/litmus/reservations/ext_reservation.h24
-rw-r--r--include/litmus/reservations/gedf_reservation.h14
-rw-r--r--include/litmus/reservations/reservation.h44
-rw-r--r--include/litmus/reservations/table_driven_ext_reservation.h58
-rw-r--r--include/litmus/reservations/task_reservation.h10
-rw-r--r--include/litmus/rt_domain.h17
-rw-r--r--litmus/Makefile1
-rw-r--r--litmus/ext_reservation.c19
-rw-r--r--litmus/litmus.c2
-rw-r--r--litmus/reservations/Makefile4
-rw-r--r--litmus/reservations/ext_reservation.c410
-rw-r--r--litmus/reservations/gedf_reservation.c304
-rw-r--r--litmus/reservations/task_reservation.c18
-rw-r--r--litmus/rt_domain.c90
-rw-r--r--litmus/sched_ext_res.c467
15 files changed, 473 insertions, 1009 deletions
diff --git a/include/litmus/reservations/ext_reservation.h b/include/litmus/reservations/ext_reservation.h
index b5fedf46a2cc..7ec326bd14bd 100644
--- a/include/litmus/reservations/ext_reservation.h
+++ b/include/litmus/reservations/ext_reservation.h
@@ -2,11 +2,8 @@
2#define LITMUS_EXT_RESERVATION_H 2#define LITMUS_EXT_RESERVATION_H
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/hrtimer.h>
6 5
7#include <litmus/debug_trace.h> 6#include <litmus/debug_trace.h>
8#include <litmus/bheap.h>
9#include <litmus/rt_domain.h>
10#include <litmus/reservations/budget-notifier.h> 7#include <litmus/reservations/budget-notifier.h>
11 8
12struct reservation_environment; 9struct reservation_environment;
@@ -52,7 +49,6 @@ struct reservation_ops {
52 49
53struct reservation { 50struct reservation {
54 unsigned int id; 51 unsigned int id;
55 unsigned int kind;
56 52
57 /* exact meaning defined by impl. */ 53 /* exact meaning defined by impl. */
58 lt_t priority; 54 lt_t priority;
@@ -86,7 +82,7 @@ void init_ext_reservation(struct reservation* res);
86void clean_up_ext_reservation(struct reservation* res); 82void clean_up_ext_reservation(struct reservation* res);
87 83
88/* ************************************************************************** */ 84/* ************************************************************************** */
89typedef void (*env_advance_time_t) ( 85typedef void (*env_update_time_t) (
90 struct reservation_environment* env, 86 struct reservation_environment* env,
91 lt_t how_much, 87 lt_t how_much,
92 int cpu); 88 int cpu);
@@ -106,17 +102,14 @@ typedef void (*env_suspend_t) (
106 int cpu); 102 int cpu);
107 103
108typedef void (*env_add_res_t) (struct reservation_environment* env, 104typedef void (*env_add_res_t) (struct reservation_environment* env,
109 struct reservation* res, 105 struct reservation* res);
110 int cpu);
111 106
112typedef void (*env_remove_res_t) (struct reservation_environment* env, 107typedef void (*env_remove_res_t) (struct reservation_environment* env,
113 struct reservation* res, 108 struct reservation* res,
114 int complete, 109 int complete);
115 int cpu);
116 110
117typedef void (*env_shutdown_t) ( 111typedef void (*env_shutdown_t) (
118 struct reservation_environment* env, 112 struct reservation_environment* env);
119 int cpu);
120 113
121struct reservation_environment_ops { 114struct reservation_environment_ops {
122 env_update_time_t update_time; 115 env_update_time_t update_time;
@@ -130,6 +123,15 @@ struct reservation_environment_ops {
130 123
131struct reservation_environment { 124struct reservation_environment {
132 struct reservation_environment_ops* ops; 125 struct reservation_environment_ops* ops;
126 struct reservation* res;
133}; 127};
134 128
129static inline void env_to_res_couple(
130 struct reservation_environment* env,
131 struct reservation* res)
132{
133 res->env = env;
134 env->res = res;
135}
136
135#endif 137#endif
diff --git a/include/litmus/reservations/gedf_reservation.h b/include/litmus/reservations/gedf_reservation.h
index f00c21e37fac..235591a0897b 100644
--- a/include/litmus/reservations/gedf_reservation.h
+++ b/include/litmus/reservations/gedf_reservation.h
@@ -1,6 +1,10 @@
1#ifndef LITMUS_GEDF_RESERVATION_H 1#ifndef LITMUS_GEDF_RESERVATION_H
2#define LITMUS_GEDF_RESERVATION_H 2#define LITMUS_GEDF_RESERVATION_H
3 3
4#include <linux/hrtimer.h>
5
6#include <litmus/bheap.h>
7#include <litmus/rt_domain.h>
4#include <litmus/reservations/ext_reservation.h> 8#include <litmus/reservations/ext_reservation.h>
5 9
6/* ************************************************************************** */ 10/* ************************************************************************** */
@@ -14,8 +18,8 @@ struct cpu_entry {
14 18
15struct gedf_reservation { 19struct gedf_reservation {
16 struct reservation res; 20 struct reservation res;
17 struct cpu_entry linked_on; 21 struct cpu_entry* linked_on;
18 struct cpu_entry scheduled_on; 22 struct cpu_entry* scheduled_on;
19 int will_remove; 23 int will_remove;
20 int blocked; 24 int blocked;
21 lt_t period; 25 lt_t period;
@@ -24,7 +28,7 @@ struct gedf_reservation {
24}; 28};
25 29
26long alloc_gedf_reservation( 30long alloc_gedf_reservation(
27 struct reservation** _res, 31 struct gedf_reservation** _res,
28 int id, 32 int id,
29 lt_t exec_cost, 33 lt_t exec_cost,
30 lt_t period, 34 lt_t period,
@@ -34,6 +38,7 @@ long alloc_gedf_reservation(
34/* environment for scheduling reservations via gedf */ 38/* environment for scheduling reservations via gedf */
35struct gedf_reservation_environment { 39struct gedf_reservation_environment {
36 struct reservation_environment env; 40 struct reservation_environment env;
41 struct list_head all_reservations;
37 /* number of active cpus in reservation */ 42 /* number of active cpus in reservation */
38 int num_cpus; 43 int num_cpus;
39 /* array of gedf cpu entries */ 44 /* array of gedf cpu entries */
@@ -45,9 +50,6 @@ struct gedf_reservation_environment {
45 struct bheap cpu_heap; 50 struct bheap cpu_heap;
46 struct bheap_node cpu_node[NR_CPUS]; 51 struct bheap_node cpu_node[NR_CPUS];
47 52
48 /* operations */
49 struct reservation_environment_ops ops;
50
51 rt_domain_t domain; 53 rt_domain_t domain;
52}; 54};
53 55
diff --git a/include/litmus/reservations/reservation.h b/include/litmus/reservations/reservation.h
index 3dce3a47a2fa..1752dac4e698 100644
--- a/include/litmus/reservations/reservation.h
+++ b/include/litmus/reservations/reservation.h
@@ -202,8 +202,6 @@ struct sup_reservation_environment {
202 lt_t next_scheduler_update; 202 lt_t next_scheduler_update;
203 /* set to true if a call to sup_dispatch() is imminent */ 203 /* set to true if a call to sup_dispatch() is imminent */
204 bool will_schedule; 204 bool will_schedule;
205
206 struct res_env_ops ops;
207}; 205};
208 206
209/* Contract: 207/* Contract:
@@ -223,46 +221,4 @@ struct task_struct* sup_dispatch(struct sup_reservation_environment* sup_env);
223struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env, 221struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env,
224 unsigned int id); 222 unsigned int id);
225 223
226/* ************************************************************************* */
227/* cpu_entry struct */
228typedef struct {
229 int cpu;
230 struct task_struct* linked;
231 struct task_struct* scheduled;
232 struct bheap_node* hn;
233 struct list_node* ln;
234} cpu_entry_t;
235
236/* Hierarchical reservation environment */
237struct ext_reservation_environment {
238 struct reservation environment env;
239
240 /* only used for global reservation environments */
241 raw_spinlock_t lock;
242
243 /* ordered by priority */
244 struct list_head active_reservations;
245
246 /* ordered by next_replenishment */
247 struct list_head depleted_reservations;
248
249 /* unordered */
250 struct list_head inactive_reservations;
251
252 /* list of all reservations */
253 struct list_head all_reservations;
254
255 lt_t next_scheduler_update;
256 bool will_scheduled;
257}
258
259/* Hierarchical reservation */
260struct ext_reservation {
261 /* reservation data */
262 struct reservation res;
263
264 /* reservation environment for child reservations */
265 struct list_head child_envs;
266};
267
268#endif 224#endif
diff --git a/include/litmus/reservations/table_driven_ext_reservation.h b/include/litmus/reservations/table_driven_ext_reservation.h
new file mode 100644
index 000000000000..414791ee9261
--- /dev/null
+++ b/include/litmus/reservations/table_driven_ext_reservation.h
@@ -0,0 +1,58 @@
1#ifndef LITMUS_TD_RESERVATION_H
2#define LITMUS_TD_RESERVATION_H
3
4#include <litmus/reservations/ext_reservation.h>
5
6/* ************************************************************************** */
7struct cpu_entry {
8 int id;
9 struct hrtimer timer;
10 struct bheap_node* hn;
11 struct reservation* linked;
12 struct reservation* scheduled;
13};
14
15struct gedf_reservation {
16 struct reservation res;
17 struct cpu_entry linked_on;
18 struct cpu_entry scheduled_on;
19 int will_remove;
20 int blocked;
21 lt_t period;
22 lt_t relative_deadline;
23 lt_t exec_cost;
24};
25
26long alloc_gedf_reservation(
27 struct reservation** _res,
28 int id,
29 lt_t exec_cost,
30 lt_t period,
31 lt_t relative_deadline
32);
33
34/* environment for scheduling reservations via gedf */
35struct td_reservation_environment {
36 struct reservation_environment env;
37 /* number of active cpus in reservation */
38 int num_cpus;
39 /* array of gedf cpu entries */
40 struct cpu_entry cpu_entries[NR_CPUS];
41 /* smp_processor_id to environment cpu array offset mapping */
42 int cpu_mapping[NR_CPUS];
43
44 /* used to order cpus for gedf purposes */
45 struct bheap cpu_heap;
46 struct bheap_node cpu_node[NR_CPUS];
47
48 /* operations */
49 struct reservation_environment_ops ops;
50
51 rt_domain_t domain;
52};
53
54long alloc_td_reservation_environment(
55 struct td_reservation_environment** _env
56);
57
58#endif
diff --git a/include/litmus/reservations/task_reservation.h b/include/litmus/reservations/task_reservation.h
index d54a789ff3e2..0e0ef74591b6 100644
--- a/include/litmus/reservations/task_reservation.h
+++ b/include/litmus/reservations/task_reservation.h
@@ -1,15 +1,15 @@
1#ifndef LITMUS_GEDF_RESERVATION_H 1#ifndef LITMUS_TASK_RESERVATION_H
2#define LITMUS_GEDF_RESERVATION_H 2#define LITMUS_TASK_RESERVATION_H
3 3
4#include <litmus/reservations/ext_reservation.h> 4#include <litmus/reservations/ext_reservation.h>
5 5
6struct task_reservation_environment { 6struct task_reservation_environment {
7 struct reservation_environment res; 7 struct reservation_environment env;
8 struct task_struct* task; 8 struct task_struct* task;
9}; 9};
10 10
11void task_reservation_environment_init( 11long alloc_task_reservation_environment(
12 struct task_reservation_environment* task_env, 12 struct task_reservation_environment** _env,
13 struct task_struct* task 13 struct task_struct* task
14); 14);
15 15
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h
index 5a7fb59bd750..0fabd7e6ea55 100644
--- a/include/litmus/rt_domain.h
+++ b/include/litmus/rt_domain.h
@@ -5,8 +5,6 @@
5#ifndef __UNC_RT_DOMAIN_H__ 5#ifndef __UNC_RT_DOMAIN_H__
6#define __UNC_RT_DOMAIN_H__ 6#define __UNC_RT_DOMAIN_H__
7 7
8#include <linux/rbtree.h>
9
10#include <litmus/bheap.h> 8#include <litmus/bheap.h>
11#include <litmus/binheap.h> 9#include <litmus/binheap.h>
12#include <litmus/reservations/ext_reservation.h> 10#include <litmus/reservations/ext_reservation.h>
@@ -69,8 +67,8 @@ struct release_heap {
69 struct list_head list_head; 67 struct list_head list_head;
70}; 68};
71 69
72static void suspend_releases(rt_domain_t* rt); 70void suspend_releases(rt_domain_t* rt);
73static void resume_releases(rt_domain_t* rt); 71void resume_releases(rt_domain_t* rt);
74 72
75static inline struct task_struct* __next_ready(rt_domain_t* rt) 73static inline struct task_struct* __next_ready(rt_domain_t* rt)
76{ 74{
@@ -83,7 +81,7 @@ static inline struct task_struct* __next_ready(rt_domain_t* rt)
83 81
84static inline struct reservation* __next_ready_res(rt_domain_t* rt) 82static inline struct reservation* __next_ready_res(rt_domain_t* rt)
85{ 83{
86 struct bheap_node *n = bheap_peek(rt->order, &rt->ready_queue); 84 struct bheap_node *hn = bheap_peek(rt->order, &rt->ready_queue);
87 if (hn) 85 if (hn)
88 return bheap2res(hn); 86 return bheap2res(hn);
89 else 87 else
@@ -98,9 +96,10 @@ void __add_ready(rt_domain_t* rt, struct task_struct *new);
98void __merge_ready(rt_domain_t* rt, struct bheap *tasks); 96void __merge_ready(rt_domain_t* rt, struct bheap *tasks);
99void __add_release(rt_domain_t* rt, struct task_struct *task); 97void __add_release(rt_domain_t* rt, struct task_struct *task);
100 98
101void __add_ready_res(rt_domain* rt, struct reservation* new); 99void __add_ready_res(rt_domain_t* rt, struct reservation* new);
102void __merge_ready_res(rt_domain_t* rt, struct bheap *res); 100void __merge_ready_res(rt_domain_t* rt, struct bheap *res);
103void __add_release_res(rt_domain_t* rt, struct reservation* res); 101void __add_release_res(rt_domain_t* rt, struct reservation* res);
102void __add_release_res_no_timer(rt_domain_t* rt, struct reservation* res);
104 103
105static inline struct task_struct* __take_ready(rt_domain_t* rt) 104static inline struct task_struct* __take_ready(rt_domain_t* rt)
106{ 105{
@@ -146,7 +145,7 @@ static inline int is_queued(struct task_struct *t)
146 145
147static inline int is_queued_res(struct reservation* res) 146static inline int is_queued_res(struct reservation* res)
148{ 147{
149 BUG_ON(!cres->heap_node); 148 BUG_ON(!res->heap_node);
150 return bheap_node_in_heap(res->heap_node); 149 return bheap_node_in_heap(res->heap_node);
151} 150}
152 151
@@ -228,8 +227,8 @@ static inline void add_release_res(rt_domain_t* rt, struct reservation* res)
228{ 227{
229 unsigned long flags; 228 unsigned long flags;
230 raw_spin_lock_irqsave(&rt->tobe_lock, flags); 229 raw_spin_lock_irqsave(&rt->tobe_lock, flags);
231 __add_release_res(rt, task); 230 __add_release_res(rt, res);
232 raw_spin_unlock_irqstore(&rt->tobe_lock, flags); 231 raw_spin_unlock_irqrestore(&rt->tobe_lock, flags);
233} 232}
234 233
235#ifdef CONFIG_RELEASE_MASTER 234#ifdef CONFIG_RELEASE_MASTER
diff --git a/litmus/Makefile b/litmus/Makefile
index ecaa28dc68ad..a3c4a1db9b4e 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -32,5 +32,6 @@ obj-$(CONFIG_SCHED_DEBUG_TRACE) += sched_trace.o
32obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o 32obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o
33 33
34obj-y += sched_pres.o 34obj-y += sched_pres.o
35obj-y += sched_ext_res.o
35 36
36obj-y += reservations/ 37obj-y += reservations/
diff --git a/litmus/ext_reservation.c b/litmus/ext_reservation.c
deleted file mode 100644
index 89fe62d43c91..000000000000
--- a/litmus/ext_reservation.c
+++ /dev/null
@@ -1,19 +0,0 @@
1#include <litmus/ext_reservation.h>
2
3/* allocated in litmus.c */
4struct kmem_cache* bheap_node_cache;
5struct kmem_cache* release_heap_cache;
6
7void init_ext_reservation(struct reservation* res)
8{
9 memset(res, 0, sizeof(struct reservation));
10 res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC);
11 res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC);
12 INIT_LIST_HEAD(&res->ln);
13}
14
15void clean_up_ext_reservation(struct reservation* res)
16{
17 kmem_cache_free(bheap_node_cache, res->heap_node);
18 kmem_cache_free(release_heap_cache, res->rel_heap);
19}
diff --git a/litmus/litmus.c b/litmus/litmus.c
index 218109074fda..e1f9d99eaf7b 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -40,7 +40,7 @@ atomic_t rt_task_count = ATOMIC_INIT(0);
40atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); 40atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU);
41#endif 41#endif
42 42
43extern struct kmem_cache * bheap_node_cache; 43struct kmem_cache * bheap_node_cache;
44extern struct kmem_cache * release_heap_cache; 44extern struct kmem_cache * release_heap_cache;
45 45
46struct bheap_node* bheap_node_alloc(int gfp_flags) 46struct bheap_node* bheap_node_alloc(int gfp_flags)
diff --git a/litmus/reservations/Makefile b/litmus/reservations/Makefile
index 517fc2ff8a76..fcb3685ae72e 100644
--- a/litmus/reservations/Makefile
+++ b/litmus/reservations/Makefile
@@ -1,3 +1,7 @@
1obj-y += core.o budget-notifier.o alloc.o 1obj-y += core.o budget-notifier.o alloc.o
2obj-y += polling.o 2obj-y += polling.o
3obj-y += table-driven.o 3obj-y += table-driven.o
4
5obj-y += ext_reservation.o
6obj-y += gedf_reservation.o
7obj-y += task_reservation.o
diff --git a/litmus/reservations/ext_reservation.c b/litmus/reservations/ext_reservation.c
index 271c3abf5a3c..7d80491fd7b2 100644
--- a/litmus/reservations/ext_reservation.c
+++ b/litmus/reservations/ext_reservation.c
@@ -1,406 +1,20 @@
1#include <linux/sched.h> 1#include <linux/slab.h>
2#include <linux/smp.h>
3
4#include <litmus/litmus.h>
5#include <litmus/bheap.h>
6#include <litmus/edf_common.h>
7#include <litmus/jobs.h>
8#include <litmus/debug_trace.h>
9#include <litmus/reservations/ext_reservation.h> 2#include <litmus/reservations/ext_reservation.h>
10#include <litmus/rt_domain.h>
11
12/* ******************************************************************************* */
13static int higher_prio(struct reservation* first,
14 struct reservation* second)
15{
16 struct reservation *first_task = first;
17 struct reservation *second_task = second;
18
19 /* There is no point in comparing a reservation to itself. */
20 if (first && first == second) {
21 return 0;
22 }
23
24 /* check for NULL reservations */
25 if (!first || !second)
26 return first && !second;
27
28 if (first_task->priority > second_task->priority) {
29 return 1;
30 }
31 else if (first_task->priority == second_task->priority) {
32 /* Tie break by pid */
33 if (first_task->id < second_task->id) {
34 return 1;
35 }
36 }
37 return 0; /* fall-through. prio(second_task) > prio(first_task) */
38}
39
40/* returns 1 if res of a has earlier deadline than res of b */
41static int edf_ready_order(struct bheap_node* a, bheap_node* b)
42{
43 return higher_prio(bheap2res(b), bheap2res(a));
44}
45
46/* Functions used to maintain a heap of cpu entries in edf order
47 * cpu_lower_prio is the comparator function used to enforce edf order
48 *
49 * The next two functions must be called under domain.ready_lock of the reservation
50 * update_cpu_position is called when cpu->linked changes
51 * lowest_prio_cpu returns the lowest prio cpu
52 */
53static int cpu_lower_prio(struct bheap_node *_a, struct bheap_node *_b)
54{
55 struct cpu_entry *a, *b;
56 a = _a->value;
57 b = _b->value;
58 return higher_prio(b->linked, a->linked);
59}
60
61static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap)
62{
63 if (likely(bheap_node_in_heap(entry->hn)))
64 bheap_delete(cpu_lower_prio, cpu_heap, entry->hn);
65 bheap_insert(cpu_lower_prio, cpu_heap, entry->hn);
66}
67
68static struct cpu_entry* lowest_prio_cpu(struct bheap* cpu_heap)
69{
70 struct bheap_node* hn;
71 hn = bheap_peek(cpu_lower_prio, cpu_heap);
72 return hn->value;
73}
74
75/* ******************************************************************************* */
76
77static void gedf_on_preempt(
78 struct reservation *res,
79 int cpu)
80{
81 res->env->ops->suspend(res->env, cpu);
82}
83
84static void gedf_on_schedule(
85 struct reservation *res,
86 lt_t now,
87 int cpu)
88{
89 res->env->ops->resume(res->env, now, cpu);
90}
91
92static void replenish_budget(
93 struct reservation* res,
94 int cpu)
95{
96 struct gedf_reservation gedf_res =
97 container_of(res, struct gedf_reservation, res);
98 res->budget_consumed = 0;
99 res->cur_budget = gedf_res->exec_cost;
100 res->priority = res->next_replenishment + gedf_res->relative_deadline;
101 res->next_replenishment += gedf_res->period;
102}
103
104static void gedf_drain_budget(
105 struct reservation* res,
106 lt_t,
107 int cpu)
108{
109 if (how_much > cur_budget)
110 cur_budget = 0;
111 else
112 cur_budget -= how_much;
113 budget_consumed += how_much;
114 budget_consumed_total += how_much;
115
116 res->env->ops->advance_time(res->env, how_much, cpu);
117}
118
119static struct gedf_reservation_ops gedf_ops
120{
121 .drain_budget = gedf_drain_budget,
122 .replenish_budget = gedf_replenish_budget,
123 .on_schedule = gedf_on_schedule,
124 .on_preempt = gedf_on_preempt,
125 .shutdown = gedf_shutdown
126};
127
128/* ******************************************************************************** */
129static void preempt(struct cpu_entry* entry)
130{
131 if (entry->scheduled) {
132 if (smp_processor_id() == entry->id)
133 litmus_reschedule_local();
134 else
135 litmus_reschedule(entry->id);
136 }
137}
138
139static void timer_callback(hrtimer* timer)
140{
141 litmus_reschedule_local();
142}
143
144static void requeue(rt_domain_t* domain, struct reservation* res) {
145 BUG_ON(!res);
146 BUG_ON(is_queued_res(res));
147
148 if (lt_before_eq(res->next_replenishment, litmus_clock()))
149 __add_ready_res(domain, res);
150 else
151 __add_release_res(domain, res);
152
153}
154
155static void link_task_to_cpu(
156 struct gedf_reservation* linked,
157 struct cpu_entry* entry)
158{
159 struct cpu_entry* sched;
160 struct gedf_reservation* tmp;
161
162 if (entry->linked)
163 entry->linked->linked_on = NULL;
164
165 if (linked) {
166 sched = linked->scheduled_on;
167 if (on_cpu) {
168 BUG_ON(sched->linked == linked);
169 if (entry != sched) {
170 tmp = sched->linked;
171 linked->linked_on = sched;
172 sched->linked = linked;
173 update_cpu_position(sched);
174 linked = tmp
175 }
176 }
177 if (linked)
178 linked->linked_on = entry;
179 }
180 entry->linked = linked;
181 update_cpu_position(entry);
182}
183
184static void unlink(struct gedf_reservation* res)
185{
186 BUG_ON(!res->linked_on);
187 if (res->linked_on) {
188 link_task_to_cpu(NULL, res->linked_on);
189 }
190}
191
192static void check_for_preemptions(struct gedf_reservation_environment* env)
193{
194 struct gedf_reservation* res;
195 struct gedf_cpu_entry* last;
196
197 for (last = lowest_prio_cpu();
198 edf_preemption_needed(&env->domain, last->linked);
199 last = lowest_prio_cpu()) {
200 res = __take_ready_res(&env->domain);
201 if (last->linked->cur_budget)
202 requeue(last->linked);
203 link_task_to_cpu(task, last);
204 preempt(last);
205 }
206}
207/* ******************************************************************************** */
208/* not really called because liblitms doesn't support removing reservations
209 * the callback is here in case someone plans on adding it in the future
210 */
211static void gedf_env_shutdown(
212 struct reservation_environment* env,
213 int cpu)
214{
215 struct gedf_reservation_environment* gedf_env;
216 gedf_env = container_of(env, struct gedf_reservation_environment* gedf_env);
217 env->ops->suspend(env, cpu);
218}
219
220/* must be called when res is scheduled or from task_exit or task_block */
221static void gedf_env_remove_res(
222 struct reservation_environment* env,
223 struct reservation* res,
224 int complete,
225 int cpu)
226{
227 struct gedf_reservation_environment* gedf_env;
228 struct gedf_reservation gedf_res;
229 unsigned long flags;
230 gedf_env = container_of(env, struct gedf_reservation_environment, env);
231 gedf_res = container_of(res, struct gedf_reservation, res);
232 gedf_res->will_remove = complete;
233 gedf_res->blocked = !complete;
234 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
235 unlink(res);
236 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
237 preempt(gedf_res->scheduled_on);
238 /* After preempt is called, schedule will update budget tracking.
239 * In advance_time, the environment will detect that res(which is scheduled)
240 * wants to be removed.
241 * If the reservation is flagged for removal, the shutdown callback is called
242 * If the reservation is flagged as blocked, then it will not be requeued back
243 * into the domain, and will invoke on_preempt callback in env_dispatch.
244 * Because we unlinked it, after env_dispatch, res is essentially gone.
245 */
246}
247
248static void gedf_env_add_res(
249 struct reservation_environment* env,
250 struct reservation* res,
251 int cpu)
252{
253 struct gedf_reservation_environment* gedf_env;
254 struct gedf_reservation gedf_res;
255 gedf_env = container_of(env, struct gedf_reservation_environment, env);
256 gedf_res = container_of(res, struct gedf_reservation, res);
257 res->par_env = env;
258 gedf_res->will_remove = 0;
259 gedf_res->blocked = 0;
260 requeue(&gedf_env->domain, res);
261 check_for_preemptions(gedf_env);
262}
263
264static gedf_env_suspend(
265 struct reservation_environment* env,
266 int cpu)
267{
268 struct gedf_reservation_environment* gedf_env;
269 struct cpu_entry* entry;
270 int env_cpu;
271
272 gedf_env = container_of(env, struct gedf_reservation_environment, env);
273 env_cpu = gedf_env->cpu_mapping[cpu];
274 entry = gedf_env->cpu_entries[env_cpu];
275
276 if (res_cpu == 0)
277 suspend_releases(&gedf_env->domain);
278 hrtimer_try_to_cancel(&entry->timer);
279}
280
281static gedf_env_resume(
282 struct reservation_environment* env,
283 lt_t now,
284 int cpu)
285{
286 struct gedf_reservation_environment* gedf_env;
287 struct cpu_entry* entry;
288 int env_cpu;
289 3
290 gedf_env = container_of(env, struct gedf_reservation_environment, env); 4/* allocated in litmus.c */
291 env_cpu = gedf_env->cpu_mapping[cpu]; 5struct kmem_cache* bheap_node_cache;
292 entry = gedf_env->cpu_entries[env_cpu]; 6struct kmem_cache* release_heap_cache;
293 7
294 if (env_cpu == 0) 8void init_ext_reservation(struct reservation* res)
295 resume_releases(&gedf_env->domain);
296 if (entry->scheduled)
297 hrtimer_start(&entry->timer, ns_to_ktime(now + entry->scheduled->cur_budget));
298}
299
300static struct task_struct* gedf_env_dispatch(
301 struct reservation_environment* env,
302 lt_t now,
303 int cpu)
304{ 9{
305 struct gedf_reservation_environment* gedf_env; 10 memset(res, 0, sizeof(struct reservation));
306 struct cpu_entry* entry; 11 res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC);
307 int env_cpu; 12 res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC);
308 struct task_struct* next; 13 INIT_LIST_HEAD(&res->ln);
309 unsigned long flags;
310
311 gedf_env = container_of(env, struct gedf_reservation_environment, env);
312 env_cpu = gedf_env->cpu_mapping[cpu];
313 entry = &gedf_env->cpu_entries[env_cpu];
314
315 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
316
317 check_for_preemptions(gedf_env);
318 if (entry->scheduled != entry->linked) {
319 if (entry->scheduled)
320 entry->scheduled->op->on_preempt(entry->scheduled, env_cpu);
321 if (entry->linked)
322 entry->linked->op->on_schedule(entry->linked, now, env_cpu);
323 entry->scheduled = entry->linked;
324 }
325 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
326
327 next = entry->scheduled->env->op->dispatch(next, time_slice, cpu);
328
329 hrtimer_start(&entry->timer, ns_to_ktime(now + entry->scheduled->cur_budget);
330
331 return next;
332} 14}
333 15
334static void gedf_env_advance_time( 16void clean_up_ext_reservation(struct reservation* res)
335 struct reservation_environment* env, lt_t how_much, int cpu)
336{ 17{
337 struct gedf_reservation_environment* gedf_env; 18 kmem_cache_free(bheap_node_cache, res->heap_node);
338 struct gedf_reservation* gedf_res; 19 kmem_cache_free(release_heap_cache, res->rel_heap);
339 struct cpu_entry* entry;
340 int env_cpu;
341 unsigned long flags;
342
343 gedf_env = container_of(env, struct gedf_reservation_environment, env);
344 env_cpu = gedf_env->cpu_mapping[cpu];
345 entry = &gedf_env->cpu_entries[env_cpu];
346
347 BUG_ON(entry->id != cpu);
348 entry->scheduled->ops->drain_budget(entry->scheduled, how_much, env_cpu);
349 gedf_res = container_of(entry->scheduled, struct gedf_reservation, res);
350 /* if flagged for removal from environment, invoke shutdown callback */
351 if (gedf_res->will_remove) {
352 entry->scheduled->ops->shutdown(entry->scheduled);
353 entry->scheduled = NULL;
354 } else if (!entry->scheduled->cur_budget) {
355 entry->scheduled->ops->replenish(entry->scheduled, env_cpu);
356 /* unlink and requeue if not blocked */
357 if (!gedf_res->blocked) {
358 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
359 unlink(entry->scheduled);
360 requeue(&gedf_env->domain, entry->scheduled);
361 check_for_preemption();
362 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
363 }
364 }
365}
366
367static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res)
368{
369 unsigned long flags;
370 struct gedf_reservation_environment gedf_env
371 = container_of(rt, struct gedf_reservation_environment, domain);
372
373 raw_spin_lock_irqsave(&rt->ready_lock);
374 __merge_ready_res(rt, tasks);
375 check_for_preemptions(gedf_env);
376 raw_spin_unlock_irqrestore(&rt->ready_lock);
377}
378
379static struct gedf_reservation_environment_ops gedf_env_ops {
380 .advance_time = gedf_env_advance_time,
381 .dispatch = gedf_env_dispatch,
382 .resume = gedf_env_resume,
383 .suspend = gedf_env_suspend,
384 .add_res = gedf_env_add_res,
385 .remove_res = gedf_env_remove_res,
386 .shutdown = gedf_env_shutdown
387}
388
389void gedf_reservation_environment_init(
390 struct gedf_reservation_environment* gedf_env)
391{
392 int i;
393
394 gedf_env->env.ops = &gedf_env_ops;
395 res->num_cpus = 0;
396 memset(&res->cpu_entries, 0, sizeof(struct cpu_entry) * NR_CPUS);
397 memset(&res->cpu_mapping, 0, sizeof(int) * NR_CPUS);
398 bheap_init(&res->cpu_heap);
399 for_each_online_cpu(i) {
400 res->cpu_entries[i].hn = &res->cpu_node[i];
401 hrtimer_init(&res->cpu_entries[i].timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
402 res->cpu_entires[i].timer.function = timer_callback;
403 bheap_node_init(&res->cpu_entries[i].hn, &res->cpu_entries[i]);
404 }
405 rt_domain_init(&res->domain, edf_ready_order, NULL, gedf_env_release_jobs);
406} 20}
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c
index 8b20be315237..b813544cc1bf 100644
--- a/litmus/reservations/gedf_reservation.c
+++ b/litmus/reservations/gedf_reservation.c
@@ -1,8 +1,11 @@
1#include <linux/sched.h> 1#include <linux/sched.h>
2#include <linux/smp.h> 2#include <linux/smp.h>
3#include <linux/slab.h>
4#include <linux/hrtimer.h>
3 5
4#include <litmus/litmus.h> 6#include <litmus/litmus.h>
5#include <litmus/edf_common.h> 7#include <litmus/bheap.h>
8#include <litmus/rt_domain.h>
6#include <litmus/jobs.h> 9#include <litmus/jobs.h>
7#include <litmus/debug_trace.h> 10#include <litmus/debug_trace.h>
8#include <litmus/reservations/gedf_reservation.h> 11#include <litmus/reservations/gedf_reservation.h>
@@ -53,7 +56,8 @@ static int cpu_lower_prio(struct bheap_node *_a, struct bheap_node *_b)
53 struct cpu_entry *a, *b; 56 struct cpu_entry *a, *b;
54 a = _a->value; 57 a = _a->value;
55 b = _b->value; 58 b = _b->value;
56 return higher_prio(b->linked, a->linked); 59 /* use higher prio here because prio is deadline value */
60 return higher_prio(a->linked, b->linked);
57} 61}
58 62
59static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap) 63static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap)
@@ -70,99 +74,22 @@ static struct cpu_entry* lowest_prio_cpu(struct bheap* cpu_heap)
70 return hn->value; 74 return hn->value;
71} 75}
72 76
73/* ******************************************************************************* */ 77int edf_preemption_needed(rt_domain_t* rt, struct gedf_reservation* res)
74static void gedf_shutdown(
75 struct reservation *res,
76 int cpu)
77{
78 res->env->ops->shutdown(res->env, cpu);
79 clean_up_ext_reservation(res);
80 kfree(res);
81}
82
83static void gedf_on_preempt(
84 struct reservation *res,
85 int cpu)
86{
87 res->env->ops->suspend(res->env, cpu);
88}
89
90static void gedf_on_schedule(
91 struct reservation *res,
92 lt_t now,
93 int cpu)
94{
95 res->env->ops->resume(res->env, now, cpu);
96}
97
98static void replenish_budget(
99 struct reservation* res,
100 int cpu)
101{
102 struct gedf_reservation gedf_res =
103 container_of(res, struct gedf_reservation, res);
104 res->budget_consumed = 0;
105 res->cur_budget = gedf_res->exec_cost;
106 res->priority = res->next_replenishment + gedf_res->relative_deadline;
107 res->next_replenishment += gedf_res->period;
108}
109
110static void gedf_drain_budget(
111 struct reservation* res,
112 lt_t,
113 int cpu)
114{
115 if (how_much > cur_budget)
116 cur_budget = 0;
117 else
118 cur_budget -= how_much;
119 budget_consumed += how_much;
120 budget_consumed_total += how_much;
121
122 res->env->ops->advance_time(res->env, how_much, cpu);
123}
124
125static struct gedf_reservation_ops gedf_ops
126{ 78{
127 .drain_budget = gedf_drain_budget, 79 /* we need the read lock for edf_ready_queue */
128 .replenish_budget = gedf_replenish_budget, 80 /* no need to preempt if there is nothing pending */
129 .on_schedule = gedf_on_schedule, 81 if (bheap_empty(&rt->ready_queue))
130 .on_preempt = gedf_on_preempt, 82 return 0;
131 .shutdown = gedf_shutdown 83 /* we need to reschedule if res doesn't exist */
132}; 84 if (!res)
133 85 return 1;
134void gedf_reservation_init(
135 struct gedf_reservation* res,
136 lt_t period,
137 lt_t relative_deadline,
138 lt_t exec_cost)
139{
140 reservation_init(&res->res);
141 res->linked_on = NULL;
142 res->scheduled_on = NULL;
143 res->will_remove = 0;
144 res->blocked = 0;
145 res->period = period;
146 res->relative_deadline = relative_deadline;
147 res->exec_cost = exec_cost;
148}
149
150long alloc_gedf_reservation(
151 struct reservation** _res,
152 int id,
153 lt_t exec_cost,
154 lt_t period,
155 lt_t relative_deadline)
156{
157 struct gedf_reservation* gedf_res;
158 gedf_res = kzalloc(sizeof(*gedf_res), GFP_KERNEL);
159 if (!gedf_res)
160 return -ENOMEM;
161 86
162 init_ext_reservation(&gedf_res.res); 87 /* NOTE: We cannot check for non-preemptibility since we
163 gedf_res->res.id = id; 88 * don't know what address space we're currently in.
89 */
164 90
165 return 0; 91 /* reversed */
92 return higher_prio(&res->res, __next_ready_res(rt));
166} 93}
167 94
168/* ******************************************************************************** */ 95/* ******************************************************************************** */
@@ -176,7 +103,7 @@ static void preempt(struct cpu_entry* entry)
176 } 103 }
177} 104}
178 105
179static void timer_callback(hrtimer* timer) 106static void timer_callback(struct hrtimer* timer)
180{ 107{
181 litmus_reschedule_local(); 108 litmus_reschedule_local();
182} 109}
@@ -196,41 +123,43 @@ static void link_task_to_cpu(
196 struct gedf_reservation* linked, 123 struct gedf_reservation* linked,
197 struct cpu_entry* entry) 124 struct cpu_entry* entry)
198{ 125{
199 struct cpu_entry* sched; 126 struct cpu_entry* sched = NULL;
200 struct gedf_reservation* tmp; 127 struct reservation* tmp;
128 struct bheap* cpu_heap =
129 &((struct gedf_reservation_environment*)linked->res.par_env)->cpu_heap;
201 130
202 if (entry->linked) 131 if (entry->linked)
203 entry->linked->linked_on = NULL; 132 ((struct gedf_reservation*)entry->linked)->linked_on = NULL;
204 133
205 if (linked) { 134 if (linked) {
206 sched = linked->scheduled_on; 135 sched = linked->scheduled_on;
207 if (on_cpu) { 136 if (sched) {
208 BUG_ON(sched->linked == linked); 137 BUG_ON(sched->linked == linked);
209 if (entry != sched) { 138 if (entry != sched) {
210 tmp = sched->linked; 139 tmp = sched->linked;
211 linked->linked_on = sched; 140 linked->linked_on = sched;
212 sched->linked = linked; 141 sched->linked = &linked->res;
213 update_cpu_position(sched); 142 update_cpu_position(sched, cpu_heap);
214 linked = tmp 143 linked = (struct gedf_reservation*)tmp;
215 } 144 }
216 } 145 }
217 if (linked) 146 if (linked)
218 linked->linked_on = entry; 147 linked->linked_on = entry;
219 } 148 }
220 entry->linked = linked; 149 entry->linked = &linked->res;
221 update_cpu_position(entry); 150 update_cpu_position(entry, cpu_heap);
222} 151}
223 152
224static void unlink(struct gedf_reservation* res) 153static void unlink(struct gedf_reservation* res)
225{ 154{
226 struct gedf_reservation_environment gedf_env; 155 struct gedf_reservation_environment* gedf_env;
227 BUG_ON(!res->linked_on); 156 BUG_ON(!res->linked_on);
228 gedf_env = container_of(res->par_env, struct gedf_reservation_environment, env); 157 gedf_env = container_of(res->res.par_env, struct gedf_reservation_environment, env);
229 if (res->linked_on) { 158 if (res->linked_on) {
230 link_task_to_cpu(NULL, res->linked_on); 159 link_task_to_cpu(NULL, res->linked_on);
231 res->linked_on = NULL; 160 res->linked_on = NULL;
232 } else if (is_queue_res(res)) { 161 } else if (is_queued_res(res)) {
233 remove_res(&gedf_env, res); 162 remove_res(&gedf_env->domain, &res->res);
234 } 163 }
235} 164}
236 165
@@ -239,38 +168,134 @@ static void check_for_preemptions(struct gedf_reservation_environment* env)
239 struct gedf_reservation* res; 168 struct gedf_reservation* res;
240 struct cpu_entry* last; 169 struct cpu_entry* last;
241 170
242 for (last = lowest_prio_cpu(); 171 for (last = lowest_prio_cpu(&env->cpu_heap);
243 edf_preemption_needed(&env->domain, last->linked); 172 edf_preemption_needed(&env->domain, last->linked);
244 last = lowest_prio_cpu()) { 173 last = lowest_prio_cpu(&env->cpu_heap)) {
245 res = (gedf_reservation*)__take_ready_res(&env->domain); 174 res = (struct gedf_reservation*)__take_ready_res(&env->domain);
246 if (last->linked->cur_budget) 175 if (last->linked->cur_budget)
247 requeue(last->linked); 176 requeue(&env->domain, last->linked);
248 link_task_to_cpu(res, last); 177 link_task_to_cpu(res, last);
249 preempt(last); 178 preempt(last);
250 } 179 }
251} 180}
252 181
182/* ******************************************************************************* */
183static void gedf_shutdown(
184 struct reservation *res)
185{
186 res->env->ops->shutdown(res->env);
187 clean_up_ext_reservation(res);
188 kfree(res);
189}
190
191static void gedf_on_preempt(
192 struct reservation *res,
193 int cpu)
194{
195 res->env->ops->suspend(res->env, cpu);
196}
197
198static void gedf_on_schedule(
199 struct reservation *res,
200 lt_t now,
201 int cpu)
202{
203 res->env->ops->resume(res->env, now, cpu);
204}
205
206static void replenish_budget(
207 struct reservation* res,
208 int cpu)
209{
210 struct gedf_reservation* gedf_res =
211 container_of(res, struct gedf_reservation, res);
212 res->budget_consumed = 0;
213 res->cur_budget = gedf_res->exec_cost;
214 res->priority = res->next_replenishment + gedf_res->relative_deadline;
215 res->next_replenishment += gedf_res->period;
216}
217
218static void gedf_drain_budget(
219 struct reservation* res,
220 lt_t how_much,
221 int cpu)
222{
223 if (how_much > res->cur_budget)
224 res->cur_budget = 0;
225 else
226 res->cur_budget -= how_much;
227 res->budget_consumed += how_much;
228 res->budget_consumed_total += how_much;
229
230 res->env->ops->update_time(res->env, how_much, cpu);
231}
232
233static struct gedf_reservation_ops gedf_ops =
234{
235 .drain_budget = gedf_drain_budget,
236 .replenish_budget = gedf_replenish_budget,
237 .on_schedule = gedf_on_schedule,
238 .on_preempt = gedf_on_preempt,
239 .shutdown = gedf_shutdown
240};
241
242long alloc_gedf_reservation(
243 struct gedf_reservation** _res,
244 int id,
245 lt_t exec_cost,
246 lt_t period,
247 lt_t relative_deadline)
248{
249 struct gedf_reservation* gedf_res;
250 gedf_res = kzalloc(sizeof(*gedf_res), GFP_KERNEL);
251 if (!gedf_res)
252 return -ENOMEM;
253
254 init_ext_reservation(&gedf_res.res);
255 gedf_res->res.id = id;
256 *_res = gedf_res;
257
258 gedf_res->linked_on = NULL;
259 gedf_res->scheduled_on = NULL;
260 gedf_res->will_remove = 0;
261 gedf_res->blocked = 0;
262 gedf_res->exec_cost = exec_cost;
263 gedf_res->period = period;
264 gedf_res->relative_deadline = relative_deadline;
265
266 return 0;
267}
268
253/* ******************************************************************************** */ 269/* ******************************************************************************** */
254static void gedf_env_shutdown( 270static void gedf_env_shutdown(
255 struct reservation_environment* env, 271 struct reservation_environment* env)
256 int cpu)
257{ 272{
258 struct gedf_reservation_environment* gedf_env; 273 struct gedf_reservation_environment* gedf_env;
259 int i; 274 int i;
275 struct gedf_reservation gedf_res;
260 gedf_env = container_of(env, struct gedf_reservation_environment* gedf_env); 276 gedf_env = container_of(env, struct gedf_reservation_environment* gedf_env);
261 suspend_releases(&gedf_env->domain); 277 suspend_releases(&gedf_env->domain);
262 for (i = 0; i < gedf_env->num_cpus; i++) { 278 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
279 for_each_online_cpu(i) {
263 hrtimer_cancel(&cpu_entries[i]); 280 hrtimer_cancel(&cpu_entries[i]);
264 } 281 }
282 while (!list_empty(&gedf_env->all_reservations)) {
283 gedf_res = list_first_entry(&gedf_env->all_reservations,
284 struct gedf_reservation, all_list);
285 list_del(&gedf_res->res.all_list);
286 res->ops->shutdown(res);
287 }
288 raw_spin_unlock_irqsave(&gedf_env->domain.ready_lock, flags);
265 kfree(env); 289 kfree(env);
266} 290}
267 291
268/* must be called when res is scheduled or from task_exit or task_block */ 292/* can only be called when res is scheduled.
293 * this only marks for removal, actual removal is done in the subsequent schedule()
294 */
269static void gedf_env_remove_res( 295static void gedf_env_remove_res(
270 struct reservation_environment* env, 296 struct reservation_environment* env,
271 struct reservation* res, 297 struct reservation* res,
272 int complete, 298 int complete)
273 int cpu)
274{ 299{
275 struct gedf_reservation_environment* gedf_env; 300 struct gedf_reservation_environment* gedf_env;
276 struct gedf_reservation gedf_res; 301 struct gedf_reservation gedf_res;
@@ -280,11 +305,12 @@ static void gedf_env_remove_res(
280 gedf_res->will_remove = complete; 305 gedf_res->will_remove = complete;
281 gedf_res->blocked = !complete; 306 gedf_res->blocked = !complete;
282 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); 307 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
308 list_del_init(&gedf_res->res.all_list, &gedf_env->all_reservations);
283 unlink(res); 309 unlink(res);
284 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
285 preempt(gedf_res->scheduled_on); 310 preempt(gedf_res->scheduled_on);
311 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
286 /* After preempt is called, schedule will update budget tracking. 312 /* After preempt is called, schedule will update budget tracking.
287 * In advance_time, the environment will detect that res(which is scheduled) 313 * In update_time, the environment will detect that res(which is scheduled)
288 * wants to be removed. 314 * wants to be removed.
289 * If the reservation is flagged for removal, the shutdown callback is called 315 * If the reservation is flagged for removal, the shutdown callback is called
290 * If the reservation is flagged as blocked, then it will not be requeued back 316 * If the reservation is flagged as blocked, then it will not be requeued back
@@ -295,18 +321,22 @@ static void gedf_env_remove_res(
295 321
296static void gedf_env_add_res( 322static void gedf_env_add_res(
297 struct reservation_environment* env, 323 struct reservation_environment* env,
298 struct reservation* res, 324 struct reservation* res)
299 int cpu)
300{ 325{
301 struct gedf_reservation_environment* gedf_env; 326 struct gedf_reservation_environment* gedf_env;
302 struct gedf_reservation gedf_res; 327 struct gedf_reservation gedf_res;
328 unsigned long flags;
303 gedf_env = container_of(env, struct gedf_reservation_environment, env); 329 gedf_env = container_of(env, struct gedf_reservation_environment, env);
304 gedf_res = container_of(res, struct gedf_reservation, res); 330 gedf_res = container_of(res, struct gedf_reservation, res);
305 res->par_env = env; 331 res->par_env = env;
306 gedf_res->will_remove = 0; 332 gedf_res->will_remove = 0;
307 gedf_res->blocked = 0; 333 gedf_res->blocked = 0;
334
335 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
336 list_add(&gedf_res->res.all_list, &gedf_env->all_reservations);
308 requeue(&gedf_env->domain, res); 337 requeue(&gedf_env->domain, res);
309 check_for_preemptions(gedf_env); 338 check_for_preemptions(gedf_env);
339 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
310} 340}
311 341
312static gedf_env_suspend( 342static gedf_env_suspend(
@@ -316,6 +346,7 @@ static gedf_env_suspend(
316 struct gedf_reservation_environment* gedf_env; 346 struct gedf_reservation_environment* gedf_env;
317 struct cpu_entry* entry; 347 struct cpu_entry* entry;
318 int env_cpu; 348 int env_cpu;
349 unsigned long flags;
319 350
320 gedf_env = container_of(env, struct gedf_reservation_environment, env); 351 gedf_env = container_of(env, struct gedf_reservation_environment, env);
321 env_cpu = gedf_env->cpu_mapping[cpu]; 352 env_cpu = gedf_env->cpu_mapping[cpu];
@@ -323,6 +354,18 @@ static gedf_env_suspend(
323 354
324 if (res_cpu == 0) 355 if (res_cpu == 0)
325 suspend_releases(&gedf_env->domain); 356 suspend_releases(&gedf_env->domain);
357
358 /* this essentially removes the cpu from scheduling consideration */
359 /*
360 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
361 if (entry->linked) {
362 unlink(entry->linked);
363 requeue(entry->linked);
364 }
365 bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn);
366 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
367 */
368
326 hrtimer_try_to_cancel(&entry->timer); 369 hrtimer_try_to_cancel(&entry->timer);
327} 370}
328 371
@@ -334,6 +377,7 @@ static gedf_env_resume(
334 struct gedf_reservation_environment* gedf_env; 377 struct gedf_reservation_environment* gedf_env;
335 struct cpu_entry* entry; 378 struct cpu_entry* entry;
336 int env_cpu; 379 int env_cpu;
380 unsigned long flags;
337 381
338 gedf_env = container_of(env, struct gedf_reservation_environment, env); 382 gedf_env = container_of(env, struct gedf_reservation_environment, env);
339 env_cpu = gedf_env->cpu_mapping[cpu]; 383 env_cpu = gedf_env->cpu_mapping[cpu];
@@ -341,6 +385,14 @@ static gedf_env_resume(
341 385
342 if (env_cpu == 0) 386 if (env_cpu == 0)
343 resume_releases(&gedf_env->domain); 387 resume_releases(&gedf_env->domain);
388
389 /* adds cpu back to scheduling consideration */
390 /*
391 raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags);
392 bheap_insert(cpu_lower_prio, cpu_heap, entry->hn);
393 raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags);
394 */
395
344 if (entry->scheduled) 396 if (entry->scheduled)
345 hrtimer_start(&entry->timer, ns_to_ktime(now + entry->scheduled->cur_budget)); 397 hrtimer_start(&entry->timer, ns_to_ktime(now + entry->scheduled->cur_budget));
346} 398}
@@ -379,7 +431,7 @@ static struct task_struct* gedf_env_dispatch(
379 return next; 431 return next;
380} 432}
381 433
382static void gedf_env_advance_time( 434static void gedf_env_update_time(
383 struct reservation_environment* env, lt_t how_much, int cpu) 435 struct reservation_environment* env, lt_t how_much, int cpu)
384{ 436{
385 struct gedf_reservation_environment* gedf_env; 437 struct gedf_reservation_environment* gedf_env;
@@ -397,6 +449,7 @@ static void gedf_env_advance_time(
397 gedf_res = container_of(entry->scheduled, struct gedf_reservation, res); 449 gedf_res = container_of(entry->scheduled, struct gedf_reservation, res);
398 /* if flagged for removal from environment, invoke shutdown callback */ 450 /* if flagged for removal from environment, invoke shutdown callback */
399 if (gedf_res->will_remove) { 451 if (gedf_res->will_remove) {
452 /* assumed to already been unlinked by whatever set will_remove */
400 entry->scheduled->ops->shutdown(entry->scheduled); 453 entry->scheduled->ops->shutdown(entry->scheduled);
401 entry->scheduled = NULL; 454 entry->scheduled = NULL;
402 } else if (!entry->scheduled->cur_budget) { 455 } else if (!entry->scheduled->cur_budget) {
@@ -425,7 +478,7 @@ static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res)
425} 478}
426 479
427static struct gedf_reservation_environment_ops gedf_env_ops { 480static struct gedf_reservation_environment_ops gedf_env_ops {
428 .advance_time = gedf_env_advance_time, 481 .update_time = gedf_env_update_time,
429 .dispatch = gedf_env_dispatch, 482 .dispatch = gedf_env_dispatch,
430 .resume = gedf_env_resume, 483 .resume = gedf_env_resume,
431 .suspend = gedf_env_suspend, 484 .suspend = gedf_env_suspend,
@@ -435,15 +488,16 @@ static struct gedf_reservation_environment_ops gedf_env_ops {
435}; 488};
436 489
437long alloc_gedf_reservation_environment( 490long alloc_gedf_reservation_environment(
438 struct reservation_environment** _env) 491 struct gedf_reservation_environment** _env)
439{ 492{
440 struct gedf_reservation_environment* gedf_env; 493 struct gedf_reservation_environment* gedf_env;
441 gedf_env = kzalloc(sizeof(*gedf_env), GFP_KERNEL); 494 gedf_env = kzalloc(sizeof(struct gedf_reservation_environment), GFP_KERNEL);
442 if (!gedf_env) 495 if (!gedf_env)
443 return -ENOMEM; 496 return -ENOMEM;
444 497
445 memset(gedf_env, 0, sizeof(struct gedf_reservation_environment)); 498 memset(gedf_env, 0, sizeof(struct gedf_reservation_environment));
446 gedf_env->env.ops = &gedf_env_ops; 499 gedf_env->env.ops = &gedf_env_ops;
500 INIT_LIST_HEAD(&gedf_env->all_reservations);
447 gedf_env->num_cpus = 0; 501 gedf_env->num_cpus = 0;
448 bheap_init(&gedf_env->cpu_heap); 502 bheap_init(&gedf_env->cpu_heap);
449 for_each_online_cpu(i) { 503 for_each_online_cpu(i) {
@@ -454,6 +508,6 @@ long alloc_gedf_reservation_environment(
454 } 508 }
455 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs); 509 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs);
456 510
457 *_env = &gedf_env->env; 511 *_env = gedf_env;
458 return 0; 512 return 0;
459} 513}
diff --git a/litmus/reservations/task_reservation.c b/litmus/reservations/task_reservation.c
index 9422598cfd15..8a8fe4237882 100644
--- a/litmus/reservations/task_reservation.c
+++ b/litmus/reservations/task_reservation.c
@@ -1,9 +1,15 @@
1#include <linux/slab.h>
2#include <litmus/reservations/ext_reservation.h>
1#include <litmus/reservations/task_reservation.h> 3#include <litmus/reservations/task_reservation.h>
2 4
3static void task_env_shutdown( 5static void task_env_shutdown(
4 struct reservation_environment* env, 6 struct reservation_environment* env,
5 int cpu) 7 int cpu)
6{ 8{
9 struct task_reservation_environment* task_env =
10 container_of(env, struct task_reservation_environment, env);
11 tsk_rt(task_env->task)->plugin_state = NULL;
12 kfree(env);
7 return; 13 return;
8} 14}
9 15
@@ -65,9 +71,17 @@ static struct task_reservation_environment_ops task_env_ops {
65 .shutdown = gedf_env_shutdown 71 .shutdown = gedf_env_shutdown
66}; 72};
67 73
68void task_reservation_environment_init( 74long alloc_task_reservation_environment(
69 struct task_reservation_environment* task_env, 75 struct task_reservation_environment** _env,
70 struct task_struct* task) 76 struct task_struct* task)
71{ 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
72 task_env->task = task; 83 task_env->task = task;
84 tsk_rt(task)->plugin_state = task_env;
85
86 *_env = task_env;
73} 87}
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
index 044b3e64a2eb..62fac871a349 100644
--- a/litmus/rt_domain.c
+++ b/litmus/rt_domain.c
@@ -10,7 +10,6 @@
10#include <linux/sched.h> 10#include <linux/sched.h>
11#include <linux/list.h> 11#include <linux/list.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/rbtree.h>
14 13
15#include <litmus/litmus.h> 14#include <litmus/litmus.h>
16#include <litmus/sched_plugin.h> 15#include <litmus/sched_plugin.h>
@@ -34,6 +33,8 @@
34#define VTRACE(fmt, args...) /* be quiet already */ 33#define VTRACE(fmt, args...) /* be quiet already */
35#endif 34#endif
36 35
36#define NO_FUTURE_RELEASE ULLONG_MAX
37
37static int dummy_resched(rt_domain_t *rt) 38static int dummy_resched(rt_domain_t *rt)
38{ 39{
39 return 0; 40 return 0;
@@ -64,28 +65,31 @@ int release_order(struct binheap_node *a, struct binheap_node *b)
64static void release_jobs_before_now(rt_domain_t* rt) 65static void release_jobs_before_now(rt_domain_t* rt)
65{ 66{
66 unsigned long flags; 67 unsigned long flags;
67 struct rb_node *temp1, *temp2;
68 struct release_heap* rh; 68 struct release_heap* rh;
69 69
70 /* remove all heaps with release time earlier than now 70 /* remove all heaps with release time earlier than now
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->earliest_release)) { 74 lt_before_eq(litmus_clock(), rt->release_queue.earliest_release)) {
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
78 TS_RELEASE_LATENCY(rh->release_time);
79 TS_RELEASE_START;
80
81 /* O(1) operation */ 78 /* O(1) operation */
82 rh = binheap_top_entry(&rt->release_queue.queue, struct release_heap, node); 79 rh = binheap_top_entry(&rt->release_queue.queue, struct release_heap, node);
83 list_del_init(&rh->list); 80 list_del_init(&rh->list);
84 81
82 TS_RELEASE_LATENCY(rh->release_time);
83 TS_RELEASE_START;
84
85 binheap_delete_root(&rt->release_queue.queue, struct release_heap, node); 85 binheap_delete_root(&rt->release_queue.queue, struct release_heap, node);
86 rt->earliest_release = 86 if (binheap_empty(&rt->release_queue.queue)) {
87 binheap_top_entry(&rt->release_queue.queue, struct release_heap, node) 87 rt->release_queue.earliest_release = NO_FUTURE_RELEASE;
88 ->release_time; 88 } else {
89 rt->release_queue.earliest_release =
90 binheap_top_entry(&rt->release_queue.queue, struct release_heap, node)
91 ->release_time;
92 }
89 93
90 raw_spin_unlock_irqrestore(&rt->release_lock, flags); 94 raw_spin_unlock_irqrestore(&rt->release_lock, flags);
91 VTRACE("CB returned release_lock 0x%p\n", &rt->release_lock); 95 VTRACE("CB returned release_lock 0x%p\n", &rt->release_lock);
@@ -99,7 +103,6 @@ static void release_jobs_before_now(rt_domain_t* rt)
99static enum hrtimer_restart on_release_timer(struct hrtimer *timer) 103static enum hrtimer_restart on_release_timer(struct hrtimer *timer)
100{ 104{
101 rt_domain_t* rt; 105 rt_domain_t* rt;
102 struct release_heap* rh;
103 106
104 rt = container_of(timer, rt_domain_t, timer); 107 rt = container_of(timer, rt_domain_t, timer);
105 108
@@ -108,23 +111,25 @@ static enum hrtimer_restart on_release_timer(struct hrtimer *timer)
108 VTRACE("on_release_timer(0x%p) ends.\n", timer); 111 VTRACE("on_release_timer(0x%p) ends.\n", timer);
109 112
110 /* when there are no more jobs to release */ 113 /* when there are no more jobs to release */
111 if (!rt->first) 114 if (rt->release_queue.earliest_release == NO_FUTURE_RELEASE)
112 return HRTIMER_NORESTART; 115 return HRTIMER_NORESTART;
113 hrtimer_set_expires(timer, ns_to_ktime(rt->earliest_release)); 116 hrtimer_set_expires(timer, ns_to_ktime(rt->release_queue.earliest_release));
114 117
115 return HRTIMER_RESTART; 118 return HRTIMER_RESTART;
116} 119}
117 120
118static void suspend_releases(rt_domain_t* rt) 121void suspend_releases(rt_domain_t* rt)
119{ 122{
120 hrtimer_try_to_cancel(&rt->timer); 123 hrtimer_try_to_cancel(&rt->timer);
121} 124}
122 125
123static void resume_releases(rt_domain_t* rt) 126void resume_releases(rt_domain_t* rt)
124{ 127{
125 release_jobs_before_now(rt); 128 release_jobs_before_now(rt);
126 if (rt->first) { 129 if (rt->release_queue.earliest_release != NO_FUTURE_RELEASE) {
127 hrtimer_start(&rh->timer, ns_to_ktime(rt->earliest_release)); 130 hrtimer_start(&rt->timer,
131 ns_to_ktime(rt->release_queue.earliest_release),
132 HRTIMER_MODE_ABS_PINNED);
128 } 133 }
129 134
130} 135}
@@ -152,7 +157,7 @@ void release_heap_free(struct release_heap* rh)
152 */ 157 */
153static struct release_heap* __get_release_heap(rt_domain_t *rt, 158static struct release_heap* __get_release_heap(rt_domain_t *rt,
154 lt_t release_time, 159 lt_t release_time,
155 struct release_heap th, 160 struct release_heap* th,
156 int use_task_heap) 161 int use_task_heap)
157{ 162{
158 struct list_head* pos; 163 struct list_head* pos;
@@ -190,25 +195,25 @@ static struct release_heap* __get_release_heap(rt_domain_t *rt,
190 * if we want to be able to have 1 domain timer that we can disable 195 * if we want to be able to have 1 domain timer that we can disable
191 * easily upon domain preemption 196 * easily upon domain preemption
192 */ 197 */
193 binheap_add(&rh->node, ht->release_queue.queue, struct release_heap, node); 198 binheap_add(&rh->node, &rt->release_queue.queue, struct release_heap, node);
194 199
195 heap = rh; 200 heap = rh;
196 } 201 }
197 return heap; 202 return heap;
198} 203}
199 204
200static struct release_heap* get_release_heap(rt_domain_t *rt, 205static struct release_heap* get_release_heap_res(rt_domain_t *rt,
201 struct reservation* res, 206 struct reservation* res,
202 int use_task_heap) 207 int use_task_heap)
203{ 208{
204 __get_release_heap(rt, res->next_replenishment, res->rel_heap, use_task_heap); 209 return __get_release_heap(rt, res->next_replenishment, res->rel_heap, use_task_heap);
205} 210}
206 211
207static struct release_heap* get_release_heap(rt_domain_t *rt, 212static struct release_heap* get_release_heap(rt_domain_t *rt,
208 struct task_struct *t, 213 struct task_struct *t,
209 int use_task_heap) 214 int use_task_heap)
210{ 215{
211 __get_release_heap(rt, get_release(t), tsk_rt(t)->rel_heap, use_task_heap); 216 return __get_release_heap(rt, get_release(t), tsk_rt(t)->rel_heap, use_task_heap);
212} 217}
213 218
214static void reinit_release_heap(struct task_struct* t) 219static void reinit_release_heap(struct task_struct* t)
@@ -222,12 +227,12 @@ static void reinit_release_heap(struct task_struct* t)
222 bheap_init(&rh->heap); 227 bheap_init(&rh->heap);
223} 228}
224 229
225static void reinit_release_heap(struct reservation* t) 230static void reinit_release_heap_res(struct reservation* res)
226{ 231{
227 struct release_heap* rh; 232 struct release_heap* rh;
228 233
229 /* use pre-allocated release heap */ 234 /* use pre-allocated release heap */
230 rh = reservation->rel_heap; 235 rh = res->rel_heap;
231 INIT_LIST_HEAD(&rh->list_head); 236 INIT_LIST_HEAD(&rh->list_head);
232 /* initialize */ 237 /* initialize */
233 bheap_init(&rh->heap); 238 bheap_init(&rh->heap);
@@ -285,8 +290,8 @@ static void arm_release_timer(rt_domain_t *_rt)
285 bheap_insert(rt->order, &rh->heap, tsk_rt(t)->heap_node); 290 bheap_insert(rt->order, &rh->heap, tsk_rt(t)->heap_node);
286 VTRACE("arm_release_timer(): added to release heap\n"); 291 VTRACE("arm_release_timer(): added to release heap\n");
287 292
288 rh = binheap_top_entry(rt->release_queue.queue, struct release_heap, node); 293 rh = binheap_top_entry(&rt->release_queue.queue, struct release_heap, node);
289 rt->earliest_release = rh->release_time; 294 rt->release_queue.earliest_release = rh->release_time;
290 295
291 raw_spin_unlock(&rt->release_lock); 296 raw_spin_unlock(&rt->release_lock);
292 VTRACE("dropped the release_lock 0x%p\n", &rt->release_lock); 297 VTRACE("dropped the release_lock 0x%p\n", &rt->release_lock);
@@ -295,9 +300,9 @@ static void arm_release_timer(rt_domain_t *_rt)
295 * owner of the new earliest release heap do the arming. 300 * owner of the new earliest release heap do the arming.
296 */ 301 */
297 if (rh == tsk_rt(t)->rel_heap) { 302 if (rh == tsk_rt(t)->rel_heap) {
298 VTRACE("arming timer 0x%p\n", &rh->timer); 303 VTRACE("arming timer 0x%p\n", &rt->timer);
299 304
300 if (!hrtimer_is_hres_active(&rh->timer)) { 305 if (!hrtimer_is_hres_active(&rt->timer)) {
301 VTRACE("WARNING: no hires timer!!!\n"); 306 VTRACE("WARNING: no hires timer!!!\n");
302 } 307 }
303 308
@@ -339,7 +344,7 @@ static void arm_release_timer(rt_domain_t *_rt)
339 */ 344 */
340#ifdef CONFIG_RELEASE_MASTER 345#ifdef CONFIG_RELEASE_MASTER
341#define arm_release_timer_res(t) arm_release_timer_res_on((t), NO_CPU) 346#define arm_release_timer_res(t) arm_release_timer_res_on((t), NO_CPU)
342static void arm_release_timer_res_on(rt_domain_t *_rt , int interrupt_release, int target_cpu) 347static void arm_release_timer_res_on(rt_domain_t *_rt, int interrupt_release, int target_cpu)
343#else 348#else
344static void arm_release_timer_res(rt_domain_t *_rt, int interrupt_release) 349static void arm_release_timer_res(rt_domain_t *_rt, int interrupt_release)
345#endif 350#endif
@@ -363,28 +368,28 @@ static void arm_release_timer_res(rt_domain_t *_rt, int interrupt_release)
363 raw_spin_lock(&rt->release_lock); 368 raw_spin_lock(&rt->release_lock);
364 VTRACE("acquired the release_lock 0x%p\n", &rt->release_lock); 369 VTRACE("acquired the release_lock 0x%p\n", &rt->release_lock);
365 370
366 rh = get_release_heap(rt, res, 0); 371 rh = get_release_heap_res(rt, res, 0);
367 if (!rh) { 372 if (!rh) {
368 /* need to use our own, but drop lock first */ 373 /* need to use our own, but drop lock first */
369 raw_spin_unlock(&rt->release_lock); 374 raw_spin_unlock(&rt->release_lock);
370 VTRACE("dropped release_lock 0x%p\n", 375 VTRACE("dropped release_lock 0x%p\n",
371 &rt->release_lock); 376 &rt->release_lock);
372 377
373 reinit_release_heap(t); 378 reinit_release_heap_res(res);
374 VTRACE("release_heap ready\n"); 379 VTRACE("release_heap ready\n");
375 380
376 raw_spin_lock(&rt->release_lock); 381 raw_spin_lock(&rt->release_lock);
377 VTRACE("re-acquired release_lock 0x%p\n", 382 VTRACE("re-acquired release_lock 0x%p\n",
378 &rt->release_lock); 383 &rt->release_lock);
379 384
380 rh = get_release_heap(rt, res, 1); 385 rh = get_release_heap_res(rt, res, 1);
381 } 386 }
382 bheap_insert(rt->order, &rh->heap, res->heap_node); 387 bheap_insert(rt->order, &rh->heap, res->heap_node);
383 list_add_tail(&res->ln, &rh->list_head); 388 list_add_tail(&res->ln, &rh->list_head);
384 VTRACE("arm_release_timer(): added to release heap\n"); 389 VTRACE("arm_release_timer(): added to release heap\n");
385 390
386 rh = binheap_top_entry(rt->release_queue.queue, struct release_heap, node); 391 rh = binheap_top_entry(&rt->release_queue.queue, struct release_heap, node);
387 rt->earliest_release = rh->release_time; 392 rt->release_queue.earliest_release = rh->release_time;
388 393
389 raw_spin_unlock(&rt->release_lock); 394 raw_spin_unlock(&rt->release_lock);
390 VTRACE("dropped the release_lock 0x%p\n", &rt->release_lock); 395 VTRACE("dropped the release_lock 0x%p\n", &rt->release_lock);
@@ -393,9 +398,9 @@ static void arm_release_timer_res(rt_domain_t *_rt, int interrupt_release)
393 * owner of the new earliest release heap do the arming. 398 * owner of the new earliest release heap do the arming.
394 */ 399 */
395 if (rh == res->rel_heap && interrupt_release) { 400 if (rh == res->rel_heap && interrupt_release) {
396 VTRACE("arming timer 0x%p\n", &rh->timer); 401 VTRACE("arming timer 0x%p\n", &rt->timer);
397 402
398 if (!hrtimer_is_hres_active(&rh->timer)) { 403 if (!hrtimer_is_hres_active(&rt->timer)) {
399 VTRACE("WARNING: no hires timer!!!\n"); 404 VTRACE("WARNING: no hires timer!!!\n");
400 } 405 }
401 406
@@ -451,7 +456,7 @@ void rt_domain_init(rt_domain_t *rt,
451 for (i = 0; i < RELEASE_QUEUE_SLOTS; i++) 456 for (i = 0; i < RELEASE_QUEUE_SLOTS; i++)
452 INIT_LIST_HEAD(&rt->release_queue.slot[i]); 457 INIT_LIST_HEAD(&rt->release_queue.slot[i]);
453 INIT_BINHEAP_HANDLE(&rt->release_queue.queue, release_order); 458 INIT_BINHEAP_HANDLE(&rt->release_queue.queue, release_order);
454 rt->release_queue.earliest_release = 0; 459 rt->release_queue.earliest_release = NO_FUTURE_RELEASE;
455 460
456 raw_spin_lock_init(&rt->ready_lock); 461 raw_spin_lock_init(&rt->ready_lock);
457 raw_spin_lock_init(&rt->release_lock); 462 raw_spin_lock_init(&rt->release_lock);
@@ -500,7 +505,7 @@ void __merge_ready(rt_domain_t* rt, struct bheap* tasks)
500 505
501void __merge_ready_res(rt_domain_t* rt, struct bheap* res) 506void __merge_ready_res(rt_domain_t* rt, struct bheap* res)
502{ 507{
503 bheap_union(rt->order, &rt->ready_queue, tasks); 508 bheap_union(rt->order, &rt->ready_queue, res);
504 rt->check_resched(rt); 509 rt->check_resched(rt);
505} 510}
506 511
@@ -537,9 +542,16 @@ void __add_release(rt_domain_t* rt, struct task_struct *task)
537 arm_release_timer(rt); 542 arm_release_timer(rt);
538} 543}
539 544
540void __add_release_res(rt_domain_t* rt, struct reservation *reservation) 545void __add_release_res(rt_domain_t* rt, struct reservation *res)
546{
547 list_add(&res->ln, &rt->tobe_released);
548
549 arm_release_timer_res(rt, 1);
550}
551
552void __add_release_res_no_timer(rt_domain_t* rt, struct reservation* res)
541{ 553{
542 list_add(&res->ln, &rt->tobe_released); 554 list_add(&res->ln, &rt->tobe_released);
543 555
544 arm_release_timer_res(rt); 556 arm_release_timer_res(rt, 0);
545} 557}
diff --git a/litmus/sched_ext_res.c b/litmus/sched_ext_res.c
index bf4dc151a4d7..60f3c4bdd7df 100644
--- a/litmus/sched_ext_res.c
+++ b/litmus/sched_ext_res.c
@@ -14,125 +14,14 @@
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/alloc.h> 17#include <litmus/reservations/task_reservation.h>
18#include <litmus/reservations/gedf_reservation.h>
18 19
19struct pres_task_state { 20struct gedf_reservation_environment* gedf_env;
20 struct reservation_client *client;
21 int cpu;
22 struct task_client res_info;
23};
24
25struct pres_cpu_state {
26 raw_spinlock_t lock;
27
28 struct sup_reservation_environment sup_env;
29 struct hrtimer timer;
30
31 int cpu;
32 struct task_struct* scheduled;
33};
34 21
35struct gedf_reservation_environment gedf_env; 22static DEFINE_PER_CPU(lt_t, last_update_time);
36
37static DEFINE_PER_CPU(struct pres_cpu_state, pres_cpu_state);
38
39#define cpu_state_for(cpu_id) (&per_cpu(pres_cpu_state, cpu_id))
40#define local_cpu_state() (this_cpu_ptr(&pres_cpu_state))
41
42static struct pres_task_state* get_pres_state(struct task_struct *tsk)
43{
44 return (struct pres_task_state*) tsk_rt(tsk)->plugin_state;
45}
46
47static void task_departs(struct task_struct *tsk, int job_complete)
48{
49 struct pres_task_state* state = get_pres_state(tsk);
50 struct reservation* res;
51 struct reservation_client *client;
52
53 client = state->client;
54 res = client->reservation;
55
56 res->ops->client_departs(res, client, job_complete);
57 TRACE_TASK(tsk, "client_departs: removed from reservation R%d\n", res->id);
58}
59
60static void task_arrives(struct task_struct *tsk)
61{
62 struct pres_task_state* state = get_pres_state(tsk);
63 struct reservation* res;
64 struct reservation_client *client;
65
66 client = state->client;
67 res = client->reservation;
68
69 res->ops->client_arrives(res, client);
70 TRACE_TASK(tsk, "client_arrives: added to reservation R%d\n", res->id);
71}
72
73/* NOTE: drops state->lock */
74static void pres_update_timer_and_unlock(struct pres_cpu_state *state)
75{
76 int local;
77 lt_t update, now;
78
79 update = state->sup_env.next_scheduler_update;
80 now = state->sup_env.env.current_time;
81
82 /* Be sure we're actually running on the right core,
83 * as pres_update_timer() is also called from pres_task_resume(),
84 * which might be called on any CPU when a thread resumes.
85 */
86 local = local_cpu_state() == state;
87
88 /* Must drop state lock before calling into hrtimer_start(), which
89 * may raise a softirq, which in turn may wake ksoftirqd. */
90 raw_spin_unlock(&state->lock);
91
92 if (update <= now) {
93 litmus_reschedule(state->cpu);
94 } else if (likely(local && update != SUP_NO_SCHEDULER_UPDATE)) {
95 /* Reprogram only if not already set correctly. */
96 if (!hrtimer_active(&state->timer) ||
97 ktime_to_ns(hrtimer_get_expires(&state->timer)) != update) {
98 TRACE("canceling timer...\n");
99 hrtimer_cancel(&state->timer);
100 TRACE("setting scheduler timer for %llu\n", update);
101 hrtimer_start(&state->timer,
102 ns_to_ktime(update),
103 HRTIMER_MODE_ABS_PINNED);
104 if (update < litmus_clock()) {
105 /* uh oh, timer expired while trying to set it */
106 TRACE("timer expired during setting "
107 "update:%llu now:%llu actual:%llu\n",
108 update, now, litmus_clock());
109 /* The timer HW may not have been reprogrammed
110 * correctly; force rescheduling now. */
111 litmus_reschedule(state->cpu);
112 }
113 }
114 } else if (unlikely(!local && update != SUP_NO_SCHEDULER_UPDATE)) {
115 /* Poke remote core only if timer needs to be set earlier than
116 * it is currently set.
117 */
118 TRACE("pres_update_timer for remote CPU %d (update=%llu, "
119 "active:%d, set:%llu)\n",
120 state->cpu,
121 update,
122 hrtimer_active(&state->timer),
123 ktime_to_ns(hrtimer_get_expires(&state->timer)));
124 if (!hrtimer_active(&state->timer) ||
125 ktime_to_ns(hrtimer_get_expires(&state->timer)) > update) {
126 TRACE("poking CPU %d so that it can update its "
127 "scheduling timer (active:%d, set:%llu)\n",
128 state->cpu,
129 hrtimer_active(&state->timer),
130 ktime_to_ns(hrtimer_get_expires(&state->timer)));
131 litmus_reschedule(state->cpu);
132 }
133 }
134}
135 23
24/*
136static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) 25static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
137{ 26{
138 unsigned long flags; 27 unsigned long flags;
@@ -142,12 +31,12 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
142 31
143 state = container_of(timer, struct pres_cpu_state, timer); 32 state = container_of(timer, struct pres_cpu_state, timer);
144 33
145 /* The scheduling timer should only fire on the local CPU, because 34 // The scheduling timer should only fire on the local CPU, because
146 * otherwise deadlocks via timer_cancel() are possible. 35 // otherwise deadlocks via timer_cancel() are possible.
147 * Note: this does not interfere with dedicated interrupt handling, as 36 // Note: this does not interfere with dedicated interrupt handling, as
148 * even under dedicated interrupt handling scheduling timers for 37 // even under dedicated interrupt handling scheduling timers for
149 * budget enforcement must occur locally on each CPU. 38 // budget enforcement must occur locally on each CPU.
150 */ 39 //
151 BUG_ON(state->cpu != raw_smp_processor_id()); 40 BUG_ON(state->cpu != raw_smp_processor_id());
152 41
153 raw_spin_lock_irqsave(&state->lock, flags); 42 raw_spin_lock_irqsave(&state->lock, flags);
@@ -170,199 +59,105 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer)
170 59
171 return restart; 60 return restart;
172} 61}
62*/
173 63
174static struct task_struct* pres_schedule(struct task_struct * prev) 64static struct task_struct* ext_res_schedule(struct task_struct * prev)
175{ 65{
176 /* next == NULL means "schedule background work". */ 66 int cpu = smp_processor_id();
177 struct pres_cpu_state *state = local_cpu_state(); 67 lt_t now, delta;
178 68 struct task_struct* next;
179 raw_spin_lock(&state->lock);
180
181 BUG_ON(state->scheduled && state->scheduled != prev);
182 BUG_ON(state->scheduled && !is_realtime(prev));
183 69
184 /* update time */ 70 now = litmus_clock();
185 state->sup_env.will_schedule = true; 71 delta = now - *this_cpu_ptr(&last_update_time);
186 sup_update_time(&state->sup_env, litmus_clock()); 72 //TODO: implement per cpu lt_t to track time
187 73
188 /* figure out what to schedule next */ 74 gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu);
189 state->scheduled = sup_dispatch(&state->sup_env); 75 next = gedf_env->env.ops->dispatch(&gedf_env->env, now, cpu);
190 76
191 /* Notify LITMUS^RT core that we've arrived at a scheduling decision. */
192 sched_state_task_picked(); 77 sched_state_task_picked();
193 78
194 /* program scheduler timer */ 79 return next;
195 state->sup_env.will_schedule = false;
196 /* NOTE: drops state->lock */
197 pres_update_timer_and_unlock(state);
198
199 if (prev != state->scheduled && is_realtime(prev))
200 TRACE_TASK(prev, "descheduled.\n");
201 if (state->scheduled)
202 TRACE_TASK(state->scheduled, "scheduled.\n");
203
204 return state->scheduled;
205}
206
207static void resume_legacy_task_model_updates(struct task_struct *tsk)
208{
209 lt_t now;
210 if (is_sporadic(tsk)) {
211 /* If this sporadic task was gone for a "long" time and woke up past
212 * its deadline, then give it a new budget by triggering a job
213 * release. This is purely cosmetic and has no effect on the
214 * P-RES scheduler. */
215
216 now = litmus_clock();
217 if (is_tardy(tsk, now)) {
218 inferred_sporadic_job_release_at(tsk, now);
219 }
220 }
221} 80}
222 81
223
224/* Called when a task should be removed from the ready queue. 82/* Called when a task should be removed from the ready queue.
225 */ 83 */
226static void pres_task_block(struct task_struct *tsk) 84static void ext_res_task_block(struct task_struct *tsk)
227{ 85{
228 unsigned long flags; 86 struct task_reservation_environment* task_env;
229 struct pres_task_state* tinfo = get_pres_state(tsk); 87 struct reservation* res;
230 struct pres_cpu_state *state = cpu_state_for(tinfo->cpu);
231 88
232 TRACE_TASK(tsk, "thread suspends at %llu (state:%d, running:%d)\n", 89 TRACE_TASK(tsk, "thread suspends at %llu \n", litmus_clock());
233 litmus_clock(), tsk->state, is_current_running());
234 90
235 raw_spin_lock_irqsave(&state->lock, flags); 91 task_env = (struct task_reservation_environment*) tsk_rt(tsk)->plugin_state;
236 sup_update_time(&state->sup_env, litmus_clock()); 92 res = task_env->env.res;
237 task_departs(tsk, is_completed(tsk)); 93 res->par_env->ops->remove_res(res->par_env, res, 0);
238 raw_spin_unlock_irqrestore(&state->lock, flags);
239} 94}
240 95
241 96
242/* Called when the state of tsk changes back to TASK_RUNNING. 97/* Called when the state of tsk changes back to TASK_RUNNING.
243 * We need to requeue the task. 98 * We need to requeue the task.
244 */ 99 */
245static void pres_task_resume(struct task_struct *tsk) 100static void ext_res_task_resume(struct task_struct *tsk)
246{ 101{
247 unsigned long flags; 102 struct task_reservation_environment* task_env;
248 struct pres_task_state* tinfo = get_pres_state(tsk); 103 struct reservation* res;
249 struct pres_cpu_state *state = cpu_state_for(tinfo->cpu);
250 104
251 TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); 105 TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock());
252 106
253 raw_spin_lock_irqsave(&state->lock, flags); 107 task_env = (struct task_reservation_environment*) tsk_rt(tsk)->plugin_state;
254 /* Assumption: litmus_clock() is synchronized across cores, 108 res = task_env->env.res;
255 * since we might not actually be executing on tinfo->cpu 109 res->par_env->ops->add_res(res->par_env, res);
256 * at the moment. */
257 sup_update_time(&state->sup_env, litmus_clock());
258 task_arrives(tsk);
259 /* NOTE: drops state->lock */
260 pres_update_timer_and_unlock(state);
261 local_irq_restore(flags);
262
263 resume_legacy_task_model_updates(tsk);
264} 110}
265 111
266static long pres_admit_task(struct task_struct *tsk) 112static long ext_res_admit_task(struct task_struct *tsk)
267{ 113{
268 long err = -EINVAL; 114 long err;
269 unsigned long flags;
270 struct reservation *res;
271 struct pres_cpu_state *state;
272 struct pres_task_state *tinfo = kzalloc(sizeof(*tinfo), GFP_ATOMIC);
273
274 if (!tinfo)
275 return -ENOMEM;
276
277 preempt_disable();
278
279 /* NOTE: this is obviously racy w.r.t. affinity changes since
280 * we are not holding any runqueue locks. */
281 if (tsk->nr_cpus_allowed != 1) {
282 printk(KERN_WARNING "%s/%d: task does not have "
283 "singleton affinity mask\n",
284 tsk->comm, tsk->pid);
285 state = cpu_state_for(task_cpu(tsk));
286 } else {
287 state = cpu_state_for(cpumask_first(&tsk->cpus_allowed));
288 }
289
290 TRACE_TASK(tsk, "on CPU %d, valid?:%d\n",
291 task_cpu(tsk), cpumask_test_cpu(task_cpu(tsk), &tsk->cpus_allowed));
292
293 raw_spin_lock_irqsave(&state->lock, flags);
294
295 res = sup_find_by_id(&state->sup_env, tsk_rt(tsk)->task_params.cpu);
296
297 /* found the appropriate reservation (or vCPU) */
298 if (res) {
299 task_client_init(&tinfo->res_info, tsk, res);
300 tinfo->cpu = state->cpu;
301 tinfo->client = &tinfo->res_info.client;
302 tsk_rt(tsk)->plugin_state = tinfo;
303 err = 0;
304
305 /* disable LITMUS^RT's per-thread budget enforcement */
306 tsk_rt(tsk)->task_params.budget_policy = NO_ENFORCEMENT;
307 } else {
308 printk(KERN_WARNING "Could not find reservation %d on "
309 "core %d for task %s/%d\n",
310 tsk_rt(tsk)->task_params.cpu, state->cpu,
311 tsk->comm, tsk->pid);
312 }
313 115
314 raw_spin_unlock_irqrestore(&state->lock, flags); 116 struct gedf_reservation* gedf_res;
117 struct task_reservation_environment* task_env;
315 118
316 preempt_enable(); 119 err = alloc_gedf_reservation(
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;
317 128
129 err = alloc_task_reservation_environment(&task_env, tsk);
318 if (err) 130 if (err)
319 kfree(tinfo); 131 return err;
320 132
321 return err; 133 env_to_res_couple(&task_env->env, &gedf_res->res);
322}
323 134
324static void task_new_legacy_task_model_updates(struct task_struct *tsk) 135 //TODO: for checkpoint 2, need to find component and insert into it
325{
326 lt_t now = litmus_clock();
327 136
328 /* the first job exists starting as of right now */ 137 return 0;
329 release_at(tsk, now);
330 sched_trace_task_release(tsk);
331} 138}
332 139
333static void pres_task_new(struct task_struct *tsk, int on_runqueue, 140static void ext_res_task_new(struct task_struct *tsk, int on_runqueue,
334 int is_running) 141 int is_running)
335{ 142{
336 unsigned long flags; 143 struct task_reservation_environment* task_env;
337 struct pres_task_state* tinfo = get_pres_state(tsk); 144 struct reservation* res;
338 struct pres_cpu_state *state = cpu_state_for(tinfo->cpu); 145 lt_t now = litmus_clock();
339 146
340 TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n", 147 TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n",
341 litmus_clock(), on_runqueue, is_running); 148 now, on_runqueue, is_running);
342 149
343 /* acquire the lock protecting the state and disable interrupts */ 150 task_env = (struct task_reservation_environment*)tsk_rt(tsk)->plugin_state;
344 raw_spin_lock_irqsave(&state->lock, flags); 151 res = task_env->env.res;
152 res->next_replenishment = now;
345 153
346 if (is_running) { 154 res->par_env->ops->add_res(res->par_env, res);
347 state->scheduled = tsk;
348 /* make sure this task should actually be running */
349 litmus_reschedule_local();
350 }
351 155
352 if (on_runqueue || is_running) { 156 if (is_running)
353 /* Assumption: litmus_clock() is synchronized across cores 157 litmus_reschedule_local();
354 * [see comment in pres_task_resume()] */
355 sup_update_time(&state->sup_env, litmus_clock());
356 task_arrives(tsk);
357 /* NOTE: drops state->lock */
358 pres_update_timer_and_unlock(state);
359 local_irq_restore(flags);
360 } else
361 raw_spin_unlock_irqrestore(&state->lock, flags);
362
363 task_new_legacy_task_model_updates(tsk);
364} 158}
365 159
160/*
366static bool pres_fork_task(struct task_struct *tsk) 161static bool pres_fork_task(struct task_struct *tsk)
367{ 162{
368 TRACE_CUR("is forking\n"); 163 TRACE_CUR("is forking\n");
@@ -374,47 +169,38 @@ static bool pres_fork_task(struct task_struct *tsk)
374 tsk_rt(tsk)->task_params.exec_cost, 169 tsk_rt(tsk)->task_params.exec_cost,
375 tsk_rt(tsk)->task_params.period); 170 tsk_rt(tsk)->task_params.period);
376 171
377 /* We always allow forking. */ 172 // We always allow forking.
378 /* The newly forked task will be in the same reservation. */ 173 // The newly forked task will be in the same reservation.
379 return true; 174 return true;
380} 175}
176*/
381 177
382static void pres_task_exit(struct task_struct *tsk) 178static void ext_res_task_exit(struct task_struct *tsk)
383{ 179{
384 unsigned long flags; 180 struct task_reservation_environment* task_env;
385 struct pres_task_state* tinfo = get_pres_state(tsk); 181 struct reservation* res;
386 struct pres_cpu_state *state = cpu_state_for(tinfo->cpu); 182 struct reservation_environment* par_env;
387 183
388 raw_spin_lock_irqsave(&state->lock, flags); 184 task_env = (struct task_reservation_environment*)tsk_rt(tsk)->plugin_state;
185 res = task_env->env.res;
186 par_env = res->par_env;
389 187
390 TRACE_TASK(tsk, "task exits at %llu (present:%d sched:%d)\n", 188 par_env->ops->remove_res(par_env, res, 1);
391 litmus_clock(), is_present(tsk), state->scheduled == tsk); 189
392 190 TRACE_TASK(tsk, "task exits at %llu \n", litmus_clock());
393 if (state->scheduled == tsk)
394 state->scheduled = NULL;
395
396 /* remove from queues */
397 if (is_present(tsk)) {
398 /* Assumption: litmus_clock() is synchronized across cores
399 * [see comment in pres_task_resume()] */
400 sup_update_time(&state->sup_env, litmus_clock());
401 task_departs(tsk, 0);
402 /* NOTE: drops state->lock */
403 pres_update_timer_and_unlock(state);
404 local_irq_restore(flags);
405 } else
406 raw_spin_unlock_irqrestore(&state->lock, flags);
407
408 kfree(tsk_rt(tsk)->plugin_state);
409 tsk_rt(tsk)->plugin_state = NULL;
410} 191}
411 192
193/* used by task budget tracking in budget.c. Since we have tasks in containers that track
194 * budget, we don't need this. Furthermore, this scheme doesn't work efficiently with
195 * multicore reservations
196 */
197/*
412static void pres_current_budget(lt_t *used_so_far, lt_t *remaining) 198static void pres_current_budget(lt_t *used_so_far, lt_t *remaining)
413{ 199{
414 struct pres_task_state *tstate = get_pres_state(current); 200 struct pres_task_state *tstate = get_pres_state(current);
415 struct pres_cpu_state *state; 201 struct pres_cpu_state *state;
416 202
417 /* FIXME: protect against concurrent task_exit() */ 203 // FIXME: protect against concurrent task_exit()
418 204
419 local_irq_disable(); 205 local_irq_disable();
420 206
@@ -431,7 +217,9 @@ static void pres_current_budget(lt_t *used_so_far, lt_t *remaining)
431 217
432 local_irq_enable(); 218 local_irq_enable();
433} 219}
220*/
434 221
222/*
435static long do_pres_reservation_create( 223static long do_pres_reservation_create(
436 int res_type, 224 int res_type,
437 struct reservation_config *config) 225 struct reservation_config *config)
@@ -442,7 +230,7 @@ static long do_pres_reservation_create(
442 unsigned long flags; 230 unsigned long flags;
443 long err; 231 long err;
444 232
445 /* Allocate before we grab a spin lock. */ 233 // Allocate before we grab a spin lock.
446 switch (res_type) { 234 switch (res_type) {
447 case PERIODIC_POLLING: 235 case PERIODIC_POLLING:
448 case SPORADIC_POLLING: 236 case SPORADIC_POLLING:
@@ -479,7 +267,9 @@ static long do_pres_reservation_create(
479 267
480 return err; 268 return err;
481} 269}
270*/
482 271
272/*
483static long pres_reservation_create(int res_type, void* __user _config) 273static long pres_reservation_create(int res_type, void* __user _config)
484{ 274{
485 struct reservation_config config; 275 struct reservation_config config;
@@ -497,31 +287,32 @@ static long pres_reservation_create(int res_type, void* __user _config)
497 287
498 return do_pres_reservation_create(res_type, &config); 288 return do_pres_reservation_create(res_type, &config);
499} 289}
290*/
500 291
501static struct domain_proc_info pres_domain_proc_info; 292static struct domain_proc_info ext_res_domain_proc_info;
502 293
503static long pres_get_domain_proc_info(struct domain_proc_info **ret) 294static long ext_res_get_domain_proc_info(struct domain_proc_info **ret)
504{ 295{
505 *ret = &pres_domain_proc_info; 296 *ret = &ext_res_domain_proc_info;
506 return 0; 297 return 0;
507} 298}
508 299
509static void pres_setup_domain_proc(void) 300static void ext_res_setup_domain_proc(void)
510{ 301{
511 int i, cpu; 302 int i, cpu;
512 int num_rt_cpus = num_online_cpus(); 303 int num_rt_cpus = num_online_cpus();
513 304
514 struct cd_mapping *cpu_map, *domain_map; 305 struct cd_mapping *cpu_map, *domain_map;
515 306
516 memset(&pres_domain_proc_info, 0, sizeof(pres_domain_proc_info)); 307 memset(&ext_res_domain_proc_info, 0, sizeof(ext_res_domain_proc_info));
517 init_domain_proc_info(&pres_domain_proc_info, num_rt_cpus, num_rt_cpus); 308 init_domain_proc_info(&ext_res_domain_proc_info, num_rt_cpus, num_rt_cpus);
518 pres_domain_proc_info.num_cpus = num_rt_cpus; 309 ext_res_domain_proc_info.num_cpus = num_rt_cpus;
519 pres_domain_proc_info.num_domains = num_rt_cpus; 310 ext_res_domain_proc_info.num_domains = num_rt_cpus;
520 311
521 i = 0; 312 i = 0;
522 for_each_online_cpu(cpu) { 313 for_each_online_cpu(cpu) {
523 cpu_map = &pres_domain_proc_info.cpu_to_domains[i]; 314 cpu_map = &ext_res_domain_proc_info.cpu_to_domains[i];
524 domain_map = &pres_domain_proc_info.domain_to_cpus[i]; 315 domain_map = &ext_res_domain_proc_info.domain_to_cpus[i];
525 316
526 cpu_map->id = cpu; 317 cpu_map->id = cpu;
527 domain_map->id = i; 318 domain_map->id = i;
@@ -535,7 +326,7 @@ static long ext_res_activate_plugin(void)
535{ 326{
536 int cpu; 327 int cpu;
537 328
538 gedf_reservation_environment_init(&gedf_env); 329 alloc_gedf_reservation_environment(&gedf_env);
539 330
540 for_each_online_cpu(cpu) { 331 for_each_online_cpu(cpu) {
541 TRACE("Initializing CPU%d...\n", cpu); 332 TRACE("Initializing CPU%d...\n", cpu);
@@ -544,58 +335,34 @@ static long ext_res_activate_plugin(void)
544 } 335 }
545 gedf_env->num_cpus = cpu; 336 gedf_env->num_cpus = cpu;
546 337
547 pres_setup_domain_proc(); 338 ext_res_setup_domain_proc();
548 339
549 return 0; 340 return 0;
550} 341}
551 342
552static long pres_deactivate_plugin(void) 343static long ext_res_deactivate_plugin(void)
553{ 344{
554 int cpu; 345 gedf_env->env.ops->shutdown(&gedf_env->env);
555 struct pres_cpu_state *state;
556 struct reservation *res;
557
558 for_each_online_cpu(cpu) {
559 state = cpu_state_for(cpu);
560 raw_spin_lock(&state->lock);
561
562 hrtimer_cancel(&state->timer);
563
564 /* Delete all reservations --- assumes struct reservation
565 * is prefix of containing struct. */
566
567 while (!list_empty(&state->sup_env.all_reservations)) {
568 res = list_first_entry(
569 &state->sup_env.all_reservations,
570 struct reservation, all_list);
571 list_del(&res->all_list);
572 if (res->ops->shutdown)
573 res->ops->shutdown(res);
574 kfree(res);
575 }
576
577 raw_spin_unlock(&state->lock);
578 }
579 346
580 destroy_domain_proc_info(&pres_domain_proc_info); 347 destroy_domain_proc_info(&ext_res_domain_proc_info);
581 return 0; 348 return 0;
582} 349}
583 350
584static struct sched_plugin ext_res_plugin = { 351static struct sched_plugin ext_res_plugin = {
585 .plugin_name = "EXT-RES", 352 .plugin_name = "EXT-RES",
586 .schedule = pres_schedule, 353 .schedule = ext_res_schedule,
587 .task_block = pres_task_block, 354 .task_block = ext_res_task_block,
588 .task_wake_up = pres_task_resume, 355 .task_wake_up = ext_res_task_resume,
589 .admit_task = pres_admit_task, 356 .admit_task = ext_res_admit_task,
590 .task_new = pres_task_new, 357 .task_new = ext_res_task_new,
591 .fork_task = pres_fork_task, 358 //.fork_task = pres_fork_task,
592 .task_exit = pres_task_exit, 359 .task_exit = ext_res_task_exit,
593 .complete_job = complete_job_oneshot, 360 .complete_job = complete_job,
594 .get_domain_proc_info = pres_get_domain_proc_info, 361 .get_domain_proc_info = ext_res_get_domain_proc_info,
595 .activate_plugin = ext_res_activate_plugin, 362 .activate_plugin = ext_res_activate_plugin,
596 .deactivate_plugin = pres_deactivate_plugin, 363 .deactivate_plugin = ext_res_deactivate_plugin,
597 .reservation_create = pres_reservation_create, 364 //.reservation_create = pres_reservation_create,
598 .current_budget = pres_current_budget, 365 //.current_budget = pres_current_budget,
599}; 366};
600 367
601static int __init init_ext_res(void) 368static int __init init_ext_res(void)