diff options
author | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-09-21 13:32:29 -0400 |
---|---|---|
committer | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-09-21 13:32:29 -0400 |
commit | ea90ac994afd39ec5899f663502502d47e060ae2 (patch) | |
tree | 2dd8f2ecfa7e99b45efbef858e80de18aa6034e5 | |
parent | b665fac6de1744ce6aeb4cfdd81a2cff528484dc (diff) |
Backup Commit 2
-rw-r--r-- | include/litmus/reservations/ext_reservation.h | 24 | ||||
-rw-r--r-- | include/litmus/reservations/gedf_reservation.h | 14 | ||||
-rw-r--r-- | include/litmus/reservations/reservation.h | 44 | ||||
-rw-r--r-- | include/litmus/reservations/table_driven_ext_reservation.h | 58 | ||||
-rw-r--r-- | include/litmus/reservations/task_reservation.h | 10 | ||||
-rw-r--r-- | include/litmus/rt_domain.h | 17 | ||||
-rw-r--r-- | litmus/Makefile | 1 | ||||
-rw-r--r-- | litmus/ext_reservation.c | 19 | ||||
-rw-r--r-- | litmus/litmus.c | 2 | ||||
-rw-r--r-- | litmus/reservations/Makefile | 4 | ||||
-rw-r--r-- | litmus/reservations/ext_reservation.c | 410 | ||||
-rw-r--r-- | litmus/reservations/gedf_reservation.c | 304 | ||||
-rw-r--r-- | litmus/reservations/task_reservation.c | 18 | ||||
-rw-r--r-- | litmus/rt_domain.c | 90 | ||||
-rw-r--r-- | litmus/sched_ext_res.c | 467 |
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 | ||
12 | struct reservation_environment; | 9 | struct reservation_environment; |
@@ -52,7 +49,6 @@ struct reservation_ops { | |||
52 | 49 | ||
53 | struct reservation { | 50 | struct 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); | |||
86 | void clean_up_ext_reservation(struct reservation* res); | 82 | void clean_up_ext_reservation(struct reservation* res); |
87 | 83 | ||
88 | /* ************************************************************************** */ | 84 | /* ************************************************************************** */ |
89 | typedef void (*env_advance_time_t) ( | 85 | typedef 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 | ||
108 | typedef void (*env_add_res_t) (struct reservation_environment* env, | 104 | typedef void (*env_add_res_t) (struct reservation_environment* env, |
109 | struct reservation* res, | 105 | struct reservation* res); |
110 | int cpu); | ||
111 | 106 | ||
112 | typedef void (*env_remove_res_t) (struct reservation_environment* env, | 107 | typedef 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 | ||
117 | typedef void (*env_shutdown_t) ( | 111 | typedef void (*env_shutdown_t) ( |
118 | struct reservation_environment* env, | 112 | struct reservation_environment* env); |
119 | int cpu); | ||
120 | 113 | ||
121 | struct reservation_environment_ops { | 114 | struct 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 | ||
131 | struct reservation_environment { | 124 | struct reservation_environment { |
132 | struct reservation_environment_ops* ops; | 125 | struct reservation_environment_ops* ops; |
126 | struct reservation* res; | ||
133 | }; | 127 | }; |
134 | 128 | ||
129 | static 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 | ||
15 | struct gedf_reservation { | 19 | struct 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 | ||
26 | long alloc_gedf_reservation( | 30 | long 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 */ |
35 | struct gedf_reservation_environment { | 39 | struct 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); | |||
223 | struct reservation* sup_find_by_id(struct sup_reservation_environment* sup_env, | 221 | struct 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 */ | ||
228 | typedef 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 */ | ||
237 | struct 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 */ | ||
260 | struct 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 | /* ************************************************************************** */ | ||
7 | struct cpu_entry { | ||
8 | int id; | ||
9 | struct hrtimer timer; | ||
10 | struct bheap_node* hn; | ||
11 | struct reservation* linked; | ||
12 | struct reservation* scheduled; | ||
13 | }; | ||
14 | |||
15 | struct 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 | |||
26 | long 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 */ | ||
35 | struct 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 | |||
54 | long 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 | ||
6 | struct task_reservation_environment { | 6 | struct 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 | ||
11 | void task_reservation_environment_init( | 11 | long 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 | ||
72 | static void suspend_releases(rt_domain_t* rt); | 70 | void suspend_releases(rt_domain_t* rt); |
73 | static void resume_releases(rt_domain_t* rt); | 71 | void resume_releases(rt_domain_t* rt); |
74 | 72 | ||
75 | static inline struct task_struct* __next_ready(rt_domain_t* rt) | 73 | static 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 | ||
84 | static inline struct reservation* __next_ready_res(rt_domain_t* rt) | 82 | static 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); | |||
98 | void __merge_ready(rt_domain_t* rt, struct bheap *tasks); | 96 | void __merge_ready(rt_domain_t* rt, struct bheap *tasks); |
99 | void __add_release(rt_domain_t* rt, struct task_struct *task); | 97 | void __add_release(rt_domain_t* rt, struct task_struct *task); |
100 | 98 | ||
101 | void __add_ready_res(rt_domain* rt, struct reservation* new); | 99 | void __add_ready_res(rt_domain_t* rt, struct reservation* new); |
102 | void __merge_ready_res(rt_domain_t* rt, struct bheap *res); | 100 | void __merge_ready_res(rt_domain_t* rt, struct bheap *res); |
103 | void __add_release_res(rt_domain_t* rt, struct reservation* res); | 101 | void __add_release_res(rt_domain_t* rt, struct reservation* res); |
102 | void __add_release_res_no_timer(rt_domain_t* rt, struct reservation* res); | ||
104 | 103 | ||
105 | static inline struct task_struct* __take_ready(rt_domain_t* rt) | 104 | static 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 | ||
147 | static inline int is_queued_res(struct reservation* res) | 146 | static 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 | |||
32 | obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o | 32 | obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o |
33 | 33 | ||
34 | obj-y += sched_pres.o | 34 | obj-y += sched_pres.o |
35 | obj-y += sched_ext_res.o | ||
35 | 36 | ||
36 | obj-y += reservations/ | 37 | obj-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 */ | ||
4 | struct kmem_cache* bheap_node_cache; | ||
5 | struct kmem_cache* release_heap_cache; | ||
6 | |||
7 | void 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 | |||
15 | void 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); | |||
40 | atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); | 40 | atomic_t release_master_cpu = ATOMIC_INIT(NO_CPU); |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | extern struct kmem_cache * bheap_node_cache; | 43 | struct kmem_cache * bheap_node_cache; |
44 | extern struct kmem_cache * release_heap_cache; | 44 | extern struct kmem_cache * release_heap_cache; |
45 | 45 | ||
46 | struct bheap_node* bheap_node_alloc(int gfp_flags) | 46 | struct 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 @@ | |||
1 | obj-y += core.o budget-notifier.o alloc.o | 1 | obj-y += core.o budget-notifier.o alloc.o |
2 | obj-y += polling.o | 2 | obj-y += polling.o |
3 | obj-y += table-driven.o | 3 | obj-y += table-driven.o |
4 | |||
5 | obj-y += ext_reservation.o | ||
6 | obj-y += gedf_reservation.o | ||
7 | obj-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 | /* ******************************************************************************* */ | ||
13 | static 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 */ | ||
41 | static 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 | */ | ||
53 | static 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 | |||
61 | static 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 | |||
68 | static 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 | |||
77 | static void gedf_on_preempt( | ||
78 | struct reservation *res, | ||
79 | int cpu) | ||
80 | { | ||
81 | res->env->ops->suspend(res->env, cpu); | ||
82 | } | ||
83 | |||
84 | static 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 | |||
92 | static 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 | |||
104 | static 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 | |||
119 | static 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 | /* ******************************************************************************** */ | ||
129 | static 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 | |||
139 | static void timer_callback(hrtimer* timer) | ||
140 | { | ||
141 | litmus_reschedule_local(); | ||
142 | } | ||
143 | |||
144 | static 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 | |||
155 | static 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 | |||
184 | static 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 | |||
192 | static 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 | */ | ||
211 | static 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 */ | ||
221 | static 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 | |||
248 | static 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 | |||
264 | static 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 | |||
281 | static 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]; | 5 | struct kmem_cache* bheap_node_cache; |
292 | entry = gedf_env->cpu_entries[env_cpu]; | 6 | struct kmem_cache* release_heap_cache; |
293 | 7 | ||
294 | if (env_cpu == 0) | 8 | void 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 | |||
300 | static 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 | ||
334 | static void gedf_env_advance_time( | 16 | void 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 | |||
367 | static 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 | |||
379 | static 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 | |||
389 | void 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 | ||
59 | static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap) | 63 | static 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 | /* ******************************************************************************* */ | 77 | int edf_preemption_needed(rt_domain_t* rt, struct gedf_reservation* res) |
74 | static 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 | |||
83 | static void gedf_on_preempt( | ||
84 | struct reservation *res, | ||
85 | int cpu) | ||
86 | { | ||
87 | res->env->ops->suspend(res->env, cpu); | ||
88 | } | ||
89 | |||
90 | static 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 | |||
98 | static 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 | |||
110 | static 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 | |||
125 | static 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; | |
134 | void 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 | |||
150 | long 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 | ||
179 | static void timer_callback(hrtimer* timer) | 106 | static 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 | ||
224 | static void unlink(struct gedf_reservation* res) | 153 | static 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 | /* ******************************************************************************* */ | ||
183 | static 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 | |||
191 | static void gedf_on_preempt( | ||
192 | struct reservation *res, | ||
193 | int cpu) | ||
194 | { | ||
195 | res->env->ops->suspend(res->env, cpu); | ||
196 | } | ||
197 | |||
198 | static 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 | |||
206 | static 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 | |||
218 | static 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 | |||
233 | static 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 | |||
242 | long 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 | /* ******************************************************************************** */ |
254 | static void gedf_env_shutdown( | 270 | static 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 | */ | ||
269 | static void gedf_env_remove_res( | 295 | static 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 | ||
296 | static void gedf_env_add_res( | 322 | static 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 | ||
312 | static gedf_env_suspend( | 342 | static 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 | ||
382 | static void gedf_env_advance_time( | 434 | static 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 | ||
427 | static struct gedf_reservation_environment_ops gedf_env_ops { | 480 | static 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 | ||
437 | long alloc_gedf_reservation_environment( | 490 | long 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 | ||
3 | static void task_env_shutdown( | 5 | static 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 | ||
68 | void task_reservation_environment_init( | 74 | long 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 | |||
37 | static int dummy_resched(rt_domain_t *rt) | 38 | static 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) | |||
64 | static void release_jobs_before_now(rt_domain_t* rt) | 65 | static 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) | |||
99 | static enum hrtimer_restart on_release_timer(struct hrtimer *timer) | 103 | static 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 | ||
118 | static void suspend_releases(rt_domain_t* rt) | 121 | void 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 | ||
123 | static void resume_releases(rt_domain_t* rt) | 126 | void 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 | */ |
153 | static struct release_heap* __get_release_heap(rt_domain_t *rt, | 158 | static 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 | ||
200 | static struct release_heap* get_release_heap(rt_domain_t *rt, | 205 | static 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 | ||
207 | static struct release_heap* get_release_heap(rt_domain_t *rt, | 212 | static 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 | ||
214 | static void reinit_release_heap(struct task_struct* t) | 219 | static 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 | ||
225 | static void reinit_release_heap(struct reservation* t) | 230 | static 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) |
342 | static void arm_release_timer_res_on(rt_domain_t *_rt , int interrupt_release, int target_cpu) | 347 | static void arm_release_timer_res_on(rt_domain_t *_rt, int interrupt_release, int target_cpu) |
343 | #else | 348 | #else |
344 | static void arm_release_timer_res(rt_domain_t *_rt, int interrupt_release) | 349 | static 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 | ||
501 | void __merge_ready_res(rt_domain_t* rt, struct bheap* res) | 506 | void __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 | ||
540 | void __add_release_res(rt_domain_t* rt, struct reservation *reservation) | 545 | void __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 | |||
552 | void __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 | ||
19 | struct pres_task_state { | 20 | struct gedf_reservation_environment* gedf_env; |
20 | struct reservation_client *client; | ||
21 | int cpu; | ||
22 | struct task_client res_info; | ||
23 | }; | ||
24 | |||
25 | struct 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 | ||
35 | struct gedf_reservation_environment gedf_env; | 22 | static DEFINE_PER_CPU(lt_t, last_update_time); |
36 | |||
37 | static 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 | |||
42 | static 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 | |||
47 | static 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 | |||
60 | static 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 */ | ||
74 | static 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 | /* | ||
136 | static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | 25 | static 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 | ||
174 | static struct task_struct* pres_schedule(struct task_struct * prev) | 64 | static 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 | |||
207 | static 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 | */ |
226 | static void pres_task_block(struct task_struct *tsk) | 84 | static 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 | */ |
245 | static void pres_task_resume(struct task_struct *tsk) | 100 | static 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 | ||
266 | static long pres_admit_task(struct task_struct *tsk) | 112 | static 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 | ||
324 | static 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 | ||
333 | static void pres_task_new(struct task_struct *tsk, int on_runqueue, | 140 | static 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 | /* | ||
366 | static bool pres_fork_task(struct task_struct *tsk) | 161 | static 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 | ||
382 | static void pres_task_exit(struct task_struct *tsk) | 178 | static 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 | /* | ||
412 | static void pres_current_budget(lt_t *used_so_far, lt_t *remaining) | 198 | static 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 | /* | ||
435 | static long do_pres_reservation_create( | 223 | static 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 | /* | ||
483 | static long pres_reservation_create(int res_type, void* __user _config) | 273 | static 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 | ||
501 | static struct domain_proc_info pres_domain_proc_info; | 292 | static struct domain_proc_info ext_res_domain_proc_info; |
502 | 293 | ||
503 | static long pres_get_domain_proc_info(struct domain_proc_info **ret) | 294 | static 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 | ||
509 | static void pres_setup_domain_proc(void) | 300 | static 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 | ||
552 | static long pres_deactivate_plugin(void) | 343 | static 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 | ||
584 | static struct sched_plugin ext_res_plugin = { | 351 | static 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 | ||
601 | static int __init init_ext_res(void) | 368 | static int __init init_ext_res(void) |