diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2014-03-13 16:28:07 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2014-03-13 16:28:07 -0400 |
commit | 1a747de02f4f13b4398940b32470ea0cac45074b (patch) | |
tree | e132c00db99c68b5cd275e25f41bebe07f16c46b | |
parent | 9f09e173b0414f9c80fce7dd9f5324eec1ecc5f1 (diff) |
C-EDF: Use sbinheap to track to top-m prio tasks.
This patch updates C-EDF to use sbinheap instead of
binheap to track the m-highest priority released jobs.
-rw-r--r-- | include/litmus/budget.h | 5 | ||||
-rw-r--r-- | litmus/budget.c | 3 | ||||
-rw-r--r-- | litmus/sched_cedf.c | 85 |
3 files changed, 59 insertions, 34 deletions
diff --git a/include/litmus/budget.h b/include/litmus/budget.h index aff48d9218fa..de38c01444a7 100644 --- a/include/litmus/budget.h +++ b/include/litmus/budget.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/semaphore.h> | 5 | #include <linux/semaphore.h> |
6 | 6 | ||
7 | #include <litmus/binheap.h> | 7 | #include <litmus/binheap.h> |
8 | #include <litmus/sbinheap.h> | ||
8 | 9 | ||
9 | struct enforcement_timer | 10 | struct enforcement_timer |
10 | { | 11 | { |
@@ -62,7 +63,9 @@ struct budget_tracker | |||
62 | const struct budget_tracker_ops* ops; | 63 | const struct budget_tracker_ops* ops; |
63 | unsigned long flags; | 64 | unsigned long flags; |
64 | 65 | ||
65 | struct binheap_node top_m_node; | 66 | sbinheap_node_t top_m_node; |
67 | binheap_node_t not_top_m_node; | ||
68 | |||
66 | lt_t suspend_timestamp; | 69 | lt_t suspend_timestamp; |
67 | }; | 70 | }; |
68 | 71 | ||
diff --git a/litmus/budget.c b/litmus/budget.c index 410112213cf0..65cc3bc263a8 100644 --- a/litmus/budget.c +++ b/litmus/budget.c | |||
@@ -456,5 +456,6 @@ void init_budget_tracker(struct budget_tracker* bt, | |||
456 | hrtimer_init(&bt->timer.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 456 | hrtimer_init(&bt->timer.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
457 | bt->timer.timer.function = __on_timeout; | 457 | bt->timer.timer.function = __on_timeout; |
458 | bt->ops = ops; | 458 | bt->ops = ops; |
459 | INIT_BINHEAP_NODE(&bt->top_m_node); | 459 | INIT_SBINHEAP_NODE(&bt->top_m_node); |
460 | INIT_BINHEAP_NODE(&bt->not_top_m_node); | ||
460 | } | 461 | } |
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c index a6b61926eda1..61fef55f38a5 100644 --- a/litmus/sched_cedf.c +++ b/litmus/sched_cedf.c | |||
@@ -133,8 +133,7 @@ typedef struct clusterdomain { | |||
133 | raw_spinlock_t dgl_lock; | 133 | raw_spinlock_t dgl_lock; |
134 | #endif | 134 | #endif |
135 | 135 | ||
136 | int top_m_size; | 136 | struct sbinheap top_m; |
137 | struct binheap top_m; | ||
138 | struct binheap not_top_m; | 137 | struct binheap not_top_m; |
139 | 138 | ||
140 | } cedf_domain_t; | 139 | } cedf_domain_t; |
@@ -163,7 +162,7 @@ static unsigned int gpu_cluster_size; | |||
163 | inline static const struct task_struct* binheap_node_to_task(const struct binheap_node *bn) | 162 | inline static const struct task_struct* binheap_node_to_task(const struct binheap_node *bn) |
164 | { | 163 | { |
165 | const struct budget_tracker *bt = | 164 | const struct budget_tracker *bt = |
166 | binheap_entry(bn, struct budget_tracker, top_m_node); | 165 | binheap_entry(bn, struct budget_tracker, not_top_m_node); |
167 | const struct task_struct *t = | 166 | const struct task_struct *t = |
168 | container_of( | 167 | container_of( |
169 | container_of(bt, struct rt_param, budget), | 168 | container_of(bt, struct rt_param, budget), |
@@ -180,11 +179,23 @@ static int cedf_max_heap_base_priority_order(const struct binheap_node *a, | |||
180 | return __edf_higher_prio(t_a, BASE, t_b, BASE); | 179 | return __edf_higher_prio(t_a, BASE, t_b, BASE); |
181 | } | 180 | } |
182 | 181 | ||
183 | static int cedf_min_heap_base_priority_order(const struct binheap_node *a, | 182 | inline static const struct task_struct* sbinheap_node_to_task(const struct sbinheap_node *bn) |
184 | const struct binheap_node *b) | ||
185 | { | 183 | { |
186 | const struct task_struct* t_a = binheap_node_to_task(a); | 184 | const struct budget_tracker *bt = |
187 | const struct task_struct* t_b = binheap_node_to_task(b); | 185 | sbinheap_entry(bn, struct budget_tracker, top_m_node); |
186 | const struct task_struct *t = | ||
187 | container_of( | ||
188 | container_of(bt, struct rt_param, budget), | ||
189 | struct task_struct, | ||
190 | rt_param); | ||
191 | return t; | ||
192 | } | ||
193 | |||
194 | static int cedf_min_heap_base_priority_order(const struct sbinheap_node *a, | ||
195 | const struct sbinheap_node *b) | ||
196 | { | ||
197 | const struct task_struct* t_a = sbinheap_node_to_task(a); | ||
198 | const struct task_struct* t_b = sbinheap_node_to_task(b); | ||
188 | return __edf_higher_prio(t_b, BASE, t_a, BASE); | 199 | return __edf_higher_prio(t_b, BASE, t_a, BASE); |
189 | } | 200 | } |
190 | 201 | ||
@@ -195,23 +206,23 @@ static void cedf_track_in_top_m(struct task_struct *t) | |||
195 | struct budget_tracker *bt; | 206 | struct budget_tracker *bt; |
196 | struct task_struct *mth_highest; | 207 | struct task_struct *mth_highest; |
197 | 208 | ||
198 | if (binheap_is_in_heap(&tsk_rt(t)->budget.top_m_node)) | 209 | if (sbinheap_is_in_heap(&tsk_rt(t)->budget.top_m_node) || |
210 | binheap_is_in_heap(&tsk_rt(t)->budget.not_top_m_node)) | ||
199 | return; | 211 | return; |
200 | 212 | ||
201 | /* TODO: do cluster_size-1 if release master is in this cluster */ | 213 | /* TODO: do cluster_size-1 if release master is in this cluster */ |
202 | if (cluster->top_m_size < cluster_size) { | 214 | if (cluster->top_m.size < cluster_size) { |
203 | binheap_add(&tsk_rt(t)->budget.top_m_node, &cluster->top_m, | 215 | sbinheap_add(&tsk_rt(t)->budget.top_m_node, &cluster->top_m, |
204 | struct budget_tracker, top_m_node); | 216 | struct budget_tracker, top_m_node); |
205 | ++cluster->top_m_size; | ||
206 | bt_flag_set(t, BTF_IS_TOP_M); | 217 | bt_flag_set(t, BTF_IS_TOP_M); |
207 | budget_state_machine(t,on_enter_top_m); | 218 | budget_state_machine(t,on_enter_top_m); |
208 | 219 | ||
209 | return; | 220 | return; |
210 | } | 221 | } |
211 | 222 | ||
212 | BUG_ON(binheap_empty(&cluster->top_m)); | 223 | BUG_ON(sbinheap_empty(&cluster->top_m)); |
213 | 224 | ||
214 | bt = binheap_top_entry(&cluster->top_m, struct budget_tracker, top_m_node); | 225 | bt = sbinheap_top_entry(&cluster->top_m, struct budget_tracker, top_m_node); |
215 | mth_highest = | 226 | mth_highest = |
216 | container_of( | 227 | container_of( |
217 | container_of(bt, struct rt_param, budget), | 228 | container_of(bt, struct rt_param, budget), |
@@ -219,23 +230,27 @@ static void cedf_track_in_top_m(struct task_struct *t) | |||
219 | rt_param); | 230 | rt_param); |
220 | 231 | ||
221 | if (__edf_higher_prio(t, BASE, mth_highest, BASE)) { | 232 | if (__edf_higher_prio(t, BASE, mth_highest, BASE)) { |
222 | binheap_delete_root(&cluster->top_m, struct budget_tracker, top_m_node); | 233 | /* remove m-th task from the top_m heap and add |
223 | INIT_BINHEAP_NODE(&tsk_rt(mth_highest)->budget.top_m_node); | 234 | it to the not-top-m heap */ |
224 | binheap_add(&tsk_rt(mth_highest)->budget.top_m_node, | 235 | sbinheap_delete_root(&cluster->top_m, struct budget_tracker, top_m_node); |
236 | INIT_SBINHEAP_NODE(&tsk_rt(mth_highest)->budget.top_m_node); | ||
237 | |||
238 | binheap_add(&tsk_rt(mth_highest)->budget.not_top_m_node, | ||
225 | &cluster->not_top_m, | 239 | &cluster->not_top_m, |
226 | struct budget_tracker, top_m_node); | 240 | struct budget_tracker, not_top_m_node); |
227 | budget_state_machine(mth_highest,on_exit_top_m); | 241 | budget_state_machine(mth_highest,on_exit_top_m); |
228 | bt_flag_clear(mth_highest, BTF_IS_TOP_M); | 242 | bt_flag_clear(mth_highest, BTF_IS_TOP_M); |
229 | 243 | ||
230 | binheap_add(&tsk_rt(t)->budget.top_m_node, &cluster->top_m, | 244 | /* add t to the top_m heap */ |
245 | sbinheap_add(&tsk_rt(t)->budget.top_m_node, &cluster->top_m, | ||
231 | struct budget_tracker, top_m_node); | 246 | struct budget_tracker, top_m_node); |
232 | bt_flag_set(t, BTF_IS_TOP_M); | 247 | bt_flag_set(t, BTF_IS_TOP_M); |
233 | budget_state_machine(t,on_enter_top_m); | 248 | budget_state_machine(t,on_enter_top_m); |
234 | } | 249 | } |
235 | else { | 250 | else { |
236 | binheap_add(&tsk_rt(t)->budget.top_m_node, | 251 | binheap_add(&tsk_rt(t)->budget.not_top_m_node, |
237 | &cluster->not_top_m, | 252 | &cluster->not_top_m, |
238 | struct budget_tracker, top_m_node); | 253 | struct budget_tracker, not_top_m_node); |
239 | } | 254 | } |
240 | } | 255 | } |
241 | 256 | ||
@@ -244,12 +259,14 @@ static void cedf_untrack_in_top_m(struct task_struct *t) | |||
244 | /* cluster lock must be held */ | 259 | /* cluster lock must be held */ |
245 | cedf_domain_t *cluster = task_cpu_cluster(t); | 260 | cedf_domain_t *cluster = task_cpu_cluster(t); |
246 | 261 | ||
247 | if (!binheap_is_in_heap(&tsk_rt(t)->budget.top_m_node)) | 262 | if (!sbinheap_is_in_heap(&tsk_rt(t)->budget.top_m_node) && |
263 | !binheap_is_in_heap(&tsk_rt(t)->budget.not_top_m_node)) | ||
248 | return; | 264 | return; |
249 | 265 | ||
250 | if (bt_flag_is_set(t, BTF_IS_TOP_M)) { | 266 | if (bt_flag_is_set(t, BTF_IS_TOP_M)) { |
251 | /* delete t's entry */ | 267 | /* delete t's entry */ |
252 | binheap_delete(&tsk_rt(t)->budget.top_m_node, &cluster->top_m); | 268 | sbinheap_delete(&tsk_rt(t)->budget.top_m_node, &cluster->top_m); |
269 | INIT_SBINHEAP_NODE(&tsk_rt(t)->budget.top_m_node); | ||
253 | budget_state_machine(t,on_exit_top_m); | 270 | budget_state_machine(t,on_exit_top_m); |
254 | bt_flag_clear(t, BTF_IS_TOP_M); | 271 | bt_flag_clear(t, BTF_IS_TOP_M); |
255 | 272 | ||
@@ -257,7 +274,7 @@ static void cedf_untrack_in_top_m(struct task_struct *t) | |||
257 | if(!binheap_empty(&cluster->not_top_m)) { | 274 | if(!binheap_empty(&cluster->not_top_m)) { |
258 | struct budget_tracker *bt = | 275 | struct budget_tracker *bt = |
259 | binheap_top_entry(&cluster->not_top_m, struct budget_tracker, | 276 | binheap_top_entry(&cluster->not_top_m, struct budget_tracker, |
260 | top_m_node); | 277 | not_top_m_node); |
261 | struct task_struct *to_move = | 278 | struct task_struct *to_move = |
262 | container_of( | 279 | container_of( |
263 | container_of(bt, struct rt_param, budget), | 280 | container_of(bt, struct rt_param, budget), |
@@ -265,21 +282,19 @@ static void cedf_untrack_in_top_m(struct task_struct *t) | |||
265 | rt_param); | 282 | rt_param); |
266 | 283 | ||
267 | binheap_delete_root(&cluster->not_top_m, struct budget_tracker, | 284 | binheap_delete_root(&cluster->not_top_m, struct budget_tracker, |
268 | top_m_node); | 285 | not_top_m_node); |
269 | INIT_BINHEAP_NODE(&tsk_rt(to_move)->budget.top_m_node); | 286 | INIT_BINHEAP_NODE(&tsk_rt(to_move)->budget.not_top_m_node); |
270 | 287 | ||
271 | binheap_add(&tsk_rt(to_move)->budget.top_m_node, | 288 | sbinheap_add(&tsk_rt(to_move)->budget.top_m_node, |
272 | &cluster->top_m, | 289 | &cluster->top_m, |
273 | struct budget_tracker, top_m_node); | 290 | struct budget_tracker, top_m_node); |
274 | bt_flag_set(to_move, BTF_IS_TOP_M); | 291 | bt_flag_set(to_move, BTF_IS_TOP_M); |
275 | budget_state_machine(to_move,on_enter_top_m); | 292 | budget_state_machine(to_move,on_enter_top_m); |
276 | } | 293 | } |
277 | else { | ||
278 | --cluster->top_m_size; | ||
279 | } | ||
280 | } | 294 | } |
281 | else { | 295 | else { |
282 | binheap_delete(&tsk_rt(t)->budget.top_m_node, &cluster->not_top_m); | 296 | binheap_delete(&tsk_rt(t)->budget.not_top_m_node, &cluster->not_top_m); |
297 | INIT_BINHEAP_NODE(&tsk_rt(t)->budget.not_top_m_node); | ||
283 | } | 298 | } |
284 | } | 299 | } |
285 | 300 | ||
@@ -2366,6 +2381,7 @@ static void cleanup_cedf(void) | |||
2366 | for (i = 0; i < num_clusters; i++) { | 2381 | for (i = 0; i < num_clusters; i++) { |
2367 | kfree(cedf[i].cpus); | 2382 | kfree(cedf[i].cpus); |
2368 | kfree(cedf[i].cpu_heap.buf); | 2383 | kfree(cedf[i].cpu_heap.buf); |
2384 | kfree(cedf[i].top_m.buf); | ||
2369 | free_cpumask_var(cedf[i].cpu_map); | 2385 | free_cpumask_var(cedf[i].cpu_map); |
2370 | } | 2386 | } |
2371 | 2387 | ||
@@ -2539,8 +2555,13 @@ static long cedf_activate_plugin(void) | |||
2539 | atomic_set(&cedf[i].owner_cpu, NO_CPU); | 2555 | atomic_set(&cedf[i].owner_cpu, NO_CPU); |
2540 | #endif | 2556 | #endif |
2541 | 2557 | ||
2542 | cedf[i].top_m_size = 0; | 2558 | cedf[i].top_m.compare = cedf_min_heap_base_priority_order; |
2543 | INIT_BINHEAP_HANDLE(&cedf[i].top_m, cedf_min_heap_base_priority_order); | 2559 | cedf[i].top_m.size = 0; |
2560 | cedf[i].top_m.max_size = cluster_size; | ||
2561 | cedf[i].top_m.buf = | ||
2562 | kmalloc(cluster_size * sizeof(struct sbinheap_node), GFP_ATOMIC); | ||
2563 | INIT_SBINHEAP(&(cedf[i].top_m)); | ||
2564 | |||
2544 | INIT_BINHEAP_HANDLE(&cedf[i].not_top_m, | 2565 | INIT_BINHEAP_HANDLE(&cedf[i].not_top_m, |
2545 | cedf_max_heap_base_priority_order); | 2566 | cedf_max_heap_base_priority_order); |
2546 | 2567 | ||