aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-12-06 20:37:20 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-12-06 20:37:20 -0500
commit983773f990053cb0ced72afb4b69594e5d32c779 (patch)
tree27767f1719926a3973a2d9effa943ea1437f9a1c
parent964297dd588ee6feab1aedecb2611bece2681973 (diff)
AUX_FUTURE and revised inh-based aux tie break
-rwxr-xr-x[-rw-r--r--]include/litmus/aux_tasks.h2
-rwxr-xr-x[-rw-r--r--]include/litmus/litmus.h1
-rwxr-xr-x[-rw-r--r--]include/litmus/rt_param.h7
-rw-r--r--kernel/fork.c6
-rwxr-xr-xlitmus/aux_tasks.c198
-rwxr-xr-xlitmus/edf_common.c78
-rwxr-xr-x[-rw-r--r--]litmus/litmus.c8
7 files changed, 192 insertions, 108 deletions
diff --git a/include/litmus/aux_tasks.h b/include/litmus/aux_tasks.h
index 3bb6b26fef09..87745c1c0df0 100644..100755
--- a/include/litmus/aux_tasks.h
+++ b/include/litmus/aux_tasks.h
@@ -6,6 +6,8 @@ struct task_struct;
6/* admit an aux task with default parameters */ 6/* admit an aux task with default parameters */
7//int admit_aux_task(struct task_struct *t); 7//int admit_aux_task(struct task_struct *t);
8 8
9int make_aux_task_if_required(struct task_struct *t);
10
9/* call on an aux task when it exits real-time */ 11/* call on an aux task when it exits real-time */
10int exit_aux_task(struct task_struct *t); 12int exit_aux_task(struct task_struct *t);
11 13
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index db2987a24686..711b88e2b3d1 100644..100755
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -32,6 +32,7 @@ struct task_struct* __waitqueue_remove_first(wait_queue_head_t *wq);
32#define NO_CPU 0xffffffff 32#define NO_CPU 0xffffffff
33 33
34void litmus_fork(struct task_struct *tsk); 34void litmus_fork(struct task_struct *tsk);
35void litmus_post_fork_thread(struct task_struct *tsk);
35void litmus_exec(void); 36void litmus_exec(void);
36/* clean up real-time state of a task */ 37/* clean up real-time state of a task */
37void exit_litmus(struct task_struct *dead_tsk); 38void exit_litmus(struct task_struct *dead_tsk);
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index cb7c3ac64339..aca78a835529 100644..100755
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -41,6 +41,12 @@ typedef enum {
41 PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */ 41 PRECISE_SIGNALS, /* budget signals are triggered with hrtimers */
42} budget_signal_policy_t; 42} budget_signal_policy_t;
43 43
44typedef enum {
45 AUX_ENABLE = 0x1,
46 AUX_CURRENT = (AUX_ENABLE<<1),
47 AUX_FUTURE = (AUX_CURRENT<<2)
48} aux_flags_t;
49
44/* We use the common priority interpretation "lower index == higher priority", 50/* We use the common priority interpretation "lower index == higher priority",
45 * which is commonly used in fixed-priority schedulability analysis papers. 51 * which is commonly used in fixed-priority schedulability analysis papers.
46 * So, a numerically lower priority value implies higher scheduling priority, 52 * So, a numerically lower priority value implies higher scheduling priority,
@@ -370,6 +376,7 @@ struct aux_data
370 struct list_head aux_tasks; 376 struct list_head aux_tasks;
371 struct binheap aux_task_owners; 377 struct binheap aux_task_owners;
372 unsigned int initialized:1; 378 unsigned int initialized:1;
379 unsigned int aux_future:1;
373}; 380};
374#endif 381#endif
375 382
diff --git a/kernel/fork.c b/kernel/fork.c
index 25c6111fe3a6..7491c4f5e78c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1370,8 +1370,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1370 write_unlock_irq(&tasklist_lock); 1370 write_unlock_irq(&tasklist_lock);
1371 proc_fork_connector(p); 1371 proc_fork_connector(p);
1372 cgroup_post_fork(p); 1372 cgroup_post_fork(p);
1373 if (clone_flags & CLONE_THREAD) 1373 if (clone_flags & CLONE_THREAD) {
1374 threadgroup_fork_read_unlock(current); 1374 threadgroup_fork_read_unlock(current);
1375#ifdef CONFIG_REALTIME_AUX_TASKS
1376 litmus_post_fork_thread(p);
1377#endif
1378 }
1375 perf_event_fork(p); 1379 perf_event_fork(p);
1376 return p; 1380 return p;
1377 1381
diff --git a/litmus/aux_tasks.c b/litmus/aux_tasks.c
index bd7bcbed58fe..e5f3c82d32e9 100755
--- a/litmus/aux_tasks.c
+++ b/litmus/aux_tasks.c
@@ -25,7 +25,7 @@ static int admit_aux_task(struct task_struct *t)
25 struct rt_task tp = { 25 struct rt_task tp = {
26 .period = 1000000, /* 1ms */ 26 .period = 1000000, /* 1ms */
27 .relative_deadline = 1000000, 27 .relative_deadline = 1000000,
28 .exec_cost = 1000000, /* allow full utilization */ 28 .exec_cost = 1000000, /* allow full utilization with buget tracking */
29 .phase = 0, 29 .phase = 0,
30 .cpu = task_cpu(leader), /* take CPU of group leader */ 30 .cpu = task_cpu(leader), /* take CPU of group leader */
31 .budget_policy = QUANTUM_ENFORCEMENT, 31 .budget_policy = QUANTUM_ENFORCEMENT,
@@ -44,17 +44,15 @@ static int admit_aux_task(struct task_struct *t)
44int exit_aux_task(struct task_struct *t) 44int exit_aux_task(struct task_struct *t)
45{ 45{
46 int retval = 0; 46 int retval = 0;
47 struct task_struct *leader = t->group_leader;
48 47
49 BUG_ON(!tsk_rt(t)->is_aux_task); 48 BUG_ON(!tsk_rt(t)->is_aux_task);
50 49
51 TRACE_CUR("Aux task %s/%d is exiting from %s/%d.\n", t->comm, t->pid, leader->comm, leader->pid); 50 TRACE_CUR("Aux task %s/%d is exiting from %s/%d.\n", t->comm, t->pid, t->group_leader->comm, t->group_leader->pid);
52 51
52 tsk_rt(t)->is_aux_task = 0;
53
53#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE 54#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE
54 list_del(&tsk_rt(t)->aux_task_node); 55 list_del(&tsk_rt(t)->aux_task_node);
55
56 tsk_rt(t)->is_aux_task = 0;
57
58 if (tsk_rt(t)->inh_task) { 56 if (tsk_rt(t)->inh_task) {
59 litmus->__decrease_prio(t, NULL); 57 litmus->__decrease_prio(t, NULL);
60 } 58 }
@@ -80,10 +78,14 @@ static int aux_tasks_increase_priority(struct task_struct *leader, struct task_s
80 if (!is_realtime(aux)) { 78 if (!is_realtime(aux)) {
81 TRACE_CUR("skipping non-real-time aux task %s/%d\n", aux->comm, aux->pid); 79 TRACE_CUR("skipping non-real-time aux task %s/%d\n", aux->comm, aux->pid);
82 } 80 }
83 81 else if(tsk_rt(aux)->inh_task == hp) {
84 // aux tasks don't touch rt locks, so no nested call needed. 82 TRACE_CUR("skipping real-time aux task %s/%d that already inherits from %s/%d\n", aux->comm, aux->pid, hp->comm, hp->pid);
85 TRACE_CUR("increasing %s/%d.\n", aux->comm, aux->pid); 83 }
86 retval = litmus->__increase_prio(aux, hp); 84 else {
85 // aux tasks don't touch rt locks, so no nested call needed.
86 TRACE_CUR("increasing %s/%d.\n", aux->comm, aux->pid);
87 retval = litmus->__increase_prio(aux, hp);
88 }
87 } 89 }
88#endif 90#endif
89 91
@@ -208,6 +210,54 @@ out:
208 return retval; 210 return retval;
209} 211}
210 212
213int make_aux_task_if_required(struct task_struct *t)
214{
215 struct task_struct *leader;
216 int retval = 0;
217
218 read_lock_irq(&tasklist_lock);
219
220 leader = t->group_leader;
221
222 if(!tsk_aux(leader)->initialized || !tsk_aux(leader)->aux_future) {
223 goto out;
224 }
225
226 TRACE_CUR("Making %s/%d in %s/%d an aux thread.\n", t->comm, t->pid, leader->comm, leader->pid);
227
228 INIT_LIST_HEAD(&tsk_rt(t)->aux_task_node);
229 INIT_BINHEAP_NODE(&tsk_rt(t)->aux_task_owner_node);
230
231 retval = admit_aux_task(t);
232 if (retval == 0) {
233 tsk_rt(t)->is_aux_task = 1;
234
235#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE
236 list_add_tail(&tsk_rt(t)->aux_task_node, &tsk_aux(leader)->aux_tasks);
237
238 if (!binheap_empty(&tsk_aux(leader)->aux_task_owners)) {
239 struct task_struct *hp =
240 container_of(binheap_top_entry(&tsk_aux(leader)->aux_task_owners, struct rt_param, aux_task_owner_node),
241 struct task_struct, rt_param);
242
243 TRACE_CUR("hp in group: %s/%d\n", hp->comm, hp->pid);
244
245 retval = litmus->__increase_prio(t, (tsk_rt(hp)->inh_task)? tsk_rt(hp)->inh_task : hp);
246
247 if (retval != 0) {
248 /* don't know how to recover from bugs with prio inheritance. better just crash. */
249 read_unlock_irq(&tasklist_lock);
250 BUG();
251 }
252 }
253#endif
254 }
255
256out:
257 read_unlock_irq(&tasklist_lock);
258
259 return retval;
260}
211 261
212 262
213long enable_aux_task_owner(struct task_struct *t) 263long enable_aux_task_owner(struct task_struct *t)
@@ -313,11 +363,12 @@ static int aux_task_owner_max_priority_order(struct binheap_node *a,
313} 363}
314 364
315 365
316static long __do_enable_aux_tasks(void) 366static long __do_enable_aux_tasks(int flags)
317{ 367{
318 long retval = 0; 368 long retval = 0;
319 struct task_struct *leader; 369 struct task_struct *leader;
320 struct task_struct *t; 370 struct task_struct *t;
371 int aux_tasks_added = 0;
321 372
322 leader = current->group_leader; 373 leader = current->group_leader;
323 374
@@ -327,34 +378,52 @@ static long __do_enable_aux_tasks(void)
327 tsk_aux(leader)->initialized = 1; 378 tsk_aux(leader)->initialized = 1;
328 } 379 }
329 380
381 if (flags & AUX_FUTURE) {
382 tsk_aux(leader)->aux_future = 1;
383 }
384
330 t = leader; 385 t = leader;
331 do { 386 do {
332 /* doesn't hurt to initialize them both */ 387 if (!tsk_rt(t)->has_aux_tasks && !tsk_rt(t)->is_aux_task) {
333 INIT_LIST_HEAD(&tsk_rt(t)->aux_task_node); 388 /* This may harmlessly reinit unused nodes. TODO: Don't reinit already init nodes. */
334 INIT_BINHEAP_NODE(&tsk_rt(t)->aux_task_owner_node); 389 /* doesn't hurt to initialize both nodes */
390 INIT_LIST_HEAD(&tsk_rt(t)->aux_task_node);
391 INIT_BINHEAP_NODE(&tsk_rt(t)->aux_task_owner_node);
392 }
335 393
336 TRACE_CUR("Checking task in %s/%d: %s/%d = (p = %llu):\n", 394 TRACE_CUR("Checking task in %s/%d: %s/%d = (p = %llu):\n",
337 leader->comm, leader->pid, t->comm, t->pid, 395 leader->comm, leader->pid, t->comm, t->pid,
338 tsk_rt(t)->task_params.period); 396 tsk_rt(t)->task_params.period);
339 397
340 /* inspect heap_node to see if it is an rt task */ 398 /* inspect period to see if it is an rt task */
341 if (tsk_rt(t)->task_params.period == 0) { 399 if (tsk_rt(t)->task_params.period == 0) {
342 if (!tsk_rt(t)->is_aux_task) { 400 if (flags && AUX_CURRENT) {
343 TRACE_CUR("AUX task in %s/%d: %s/%d:\n", leader->comm, leader->pid, t->comm, t->pid); 401 if (!tsk_rt(t)->is_aux_task) {
344 /* hasn't been aux_tasks_increase_priorityted into rt. make it a aux. */ 402 int admit_ret;
345 tsk_rt(t)->is_aux_task = 1; 403
346 404 TRACE_CUR("AUX task in %s/%d: %s/%d:\n", leader->comm, leader->pid, t->comm, t->pid);
405
406 admit_ret = admit_aux_task(t);
407
408 if (admit_ret == 0) {
409 /* hasn't been aux_tasks_increase_priorityted into rt. make it a aux. */
410 tsk_rt(t)->is_aux_task = 1;
411 aux_tasks_added = 1;
412
347#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE 413#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE
348 list_add_tail(&tsk_rt(t)->aux_task_node, &tsk_aux(leader)->aux_tasks); 414 list_add_tail(&tsk_rt(t)->aux_task_node, &tsk_aux(leader)->aux_tasks);
349#endif 415#endif
350 416 }
351 (void)admit_aux_task(t); 417 }
418 else {
419 TRACE_CUR("AUX task in %s/%d is already set up: %s/%d\n", leader->comm, leader->pid, t->comm, t->pid);
420 }
352 } 421 }
353 else { 422 else {
354 TRACE_CUR("AUX task in %s/%d is already set up: %s/%d\n", leader->comm, leader->pid, t->comm, t->pid); 423 TRACE_CUR("Not changing thread in %s/%d to AUX task: %s/%d\n", leader->comm, leader->pid, t->comm, t->pid);
355 } 424 }
356 } 425 }
357 else { 426 else if (!tsk_rt(t)->is_aux_task) { /* don't let aux tasks get aux tasks of their own */
358 if (!tsk_rt(t)->has_aux_tasks) { 427 if (!tsk_rt(t)->has_aux_tasks) {
359 TRACE_CUR("task in %s/%d: %s/%d:\n", leader->comm, leader->pid, t->comm, t->pid); 428 TRACE_CUR("task in %s/%d: %s/%d:\n", leader->comm, leader->pid, t->comm, t->pid);
360 tsk_rt(t)->has_aux_tasks = 1; 429 tsk_rt(t)->has_aux_tasks = 1;
@@ -369,19 +438,18 @@ static long __do_enable_aux_tasks(void)
369 438
370 439
371#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE 440#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE
372 if (!binheap_empty(&tsk_aux(leader)->aux_task_owners)) { 441 if (aux_tasks_added && !binheap_empty(&tsk_aux(leader)->aux_task_owners)) {
373 struct task_struct *hp = container_of(binheap_top_entry(&tsk_aux(leader)->aux_task_owners, struct rt_param, aux_task_owner_node), 442 struct task_struct *hp = container_of(binheap_top_entry(&tsk_aux(leader)->aux_task_owners, struct rt_param, aux_task_owner_node),
374 struct task_struct, rt_param); 443 struct task_struct, rt_param);
375 TRACE_CUR("found hp in group: %s/%d\n", hp->comm, hp->pid); 444 TRACE_CUR("hp in group: %s/%d\n", hp->comm, hp->pid);
376 retval = aux_tasks_increase_priority(leader, 445 retval = aux_tasks_increase_priority(leader, (tsk_rt(hp)->inh_task)? tsk_rt(hp)->inh_task : hp);
377 (tsk_rt(hp)->inh_task)? tsk_rt(hp)->inh_task : hp);
378 } 446 }
379#endif 447#endif
380 448
381 return retval; 449 return retval;
382} 450}
383 451
384static long __do_disable_aux_tasks(void) 452static long __do_disable_aux_tasks(int flags)
385{ 453{
386 long retval = 0; 454 long retval = 0;
387 struct task_struct *leader; 455 struct task_struct *leader;
@@ -389,50 +457,56 @@ static long __do_disable_aux_tasks(void)
389 457
390 leader = current->group_leader; 458 leader = current->group_leader;
391 459
392 t = leader; 460 if (flags & AUX_FUTURE) {
393 do { 461 tsk_aux(leader)->aux_future = 0;
394 if (tsk_rt(t)->is_aux_task) { 462 }
395 463
396 TRACE_CUR("%s/%d is an aux task.\n", t->comm, t->pid); 464 if (flags & AUX_CURRENT) {
397 465 t = leader;
398 if (is_realtime(t)) { 466 do {
399 long temp_retval; 467 if (tsk_rt(t)->is_aux_task) {
400 struct sched_param param = { .sched_priority = 0}; 468
401 469 TRACE_CUR("%s/%d is an aux task.\n", t->comm, t->pid);
402 TRACE_CUR("%s/%d is real-time. Changing policy to SCHED_NORMAL.\n", t->comm, t->pid); 470
403 471 if (is_realtime(t)) {
404 temp_retval = sched_setscheduler_nocheck(t, SCHED_NORMAL, &param); 472 long temp_retval;
405 473 struct sched_param param = { .sched_priority = 0};
406 if (temp_retval != 0) { 474
407 TRACE_CUR("error changing policy of %s/%d to SCHED_NORMAL\n", t->comm, t->pid); 475 TRACE_CUR("%s/%d is real-time. Changing policy to SCHED_NORMAL.\n", t->comm, t->pid);
408 if (retval == 0) { 476
409 retval = temp_retval; 477 temp_retval = sched_setscheduler_nocheck(t, SCHED_NORMAL, &param);
410 } 478
411 else { 479 if (temp_retval != 0) {
412 TRACE_CUR("prior error (%d) masks new error (%d)\n", retval, temp_retval); 480 TRACE_CUR("error changing policy of %s/%d to SCHED_NORMAL\n", t->comm, t->pid);
481 if (retval == 0) {
482 retval = temp_retval;
483 }
484 else {
485 TRACE_CUR("prior error (%d) masks new error (%d)\n", retval, temp_retval);
486 }
413 } 487 }
414 } 488 }
415 }
416 489
417 tsk_rt(t)->is_aux_task = 0; 490 tsk_rt(t)->is_aux_task = 0;
418 } 491 }
419 t = next_thread(t); 492 t = next_thread(t);
420 } while(t != leader); 493 } while(t != leader);
494 }
421 495
422 return retval; 496 return retval;
423} 497}
424 498
425asmlinkage long sys_set_aux_tasks(int enable) 499asmlinkage long sys_set_aux_tasks(int flags)
426{ 500{
427 long retval; 501 long retval;
428 502
429 read_lock_irq(&tasklist_lock); 503 read_lock_irq(&tasklist_lock);
430 504
431 if (enable) { 505 if (flags & AUX_ENABLE) {
432 retval = __do_enable_aux_tasks(); 506 retval = __do_enable_aux_tasks(flags);
433 } 507 }
434 else { 508 else {
435 retval = __do_disable_aux_tasks(); 509 retval = __do_disable_aux_tasks(flags);
436 } 510 }
437 511
438 read_unlock_irq(&tasklist_lock); 512 read_unlock_irq(&tasklist_lock);
@@ -442,7 +516,7 @@ asmlinkage long sys_set_aux_tasks(int enable)
442 516
443#else 517#else
444 518
445asmlinkage long sys_set_aux_tasks(int enable) 519asmlinkage long sys_set_aux_tasks(int flags)
446{ 520{
447 printk("Unsupported. Recompile with CONFIG_REALTIME_AUX_TASKS.\n"); 521 printk("Unsupported. Recompile with CONFIG_REALTIME_AUX_TASKS.\n");
448 return -EINVAL; 522 return -EINVAL;
diff --git a/litmus/edf_common.c b/litmus/edf_common.c
index 5a3f5b417f73..c279bf12a7f5 100755
--- a/litmus/edf_common.c
+++ b/litmus/edf_common.c
@@ -22,7 +22,7 @@
22#include <litmus/fpmath.h> 22#include <litmus/fpmath.h>
23#endif 23#endif
24 24
25#if defined(CONFIG_EDF_TIE_BREAK_HASH) || defined(CONFIG_REALTIME_AUX_TASKS) 25#if defined(CONFIG_EDF_TIE_BREAK_HASH)
26#include <linux/hash.h> 26#include <linux/hash.h>
27static inline long edf_hash(struct task_struct *t) 27static inline long edf_hash(struct task_struct *t)
28{ 28{
@@ -43,23 +43,6 @@ static inline long edf_hash(struct task_struct *t)
43} 43}
44#endif 44#endif
45 45
46#ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE
47int aux_tie_break(struct task_struct *first, struct task_struct *second)
48{
49 long fhash = edf_hash(first);
50 long shash = edf_hash(second);
51 if (fhash < shash) {
52 TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, 1);
53 return 1;
54 }
55 else if(fhash == shash) {
56 TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, (first->pid < second->pid));
57 return first->pid < second->pid;
58 }
59 return 0;
60}
61#endif
62
63 46
64/* edf_higher_prio - returns true if first has a higher EDF priority 47/* edf_higher_prio - returns true if first has a higher EDF priority
65 * than second. Deadline ties are broken by PID. 48 * than second. Deadline ties are broken by PID.
@@ -93,44 +76,47 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second)
93 76
94#if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_BOOSTED) 77#if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_BOOSTED)
95 /* run aux tasks at max priority */ 78 /* run aux tasks at max priority */
79 /* TODO: Actually use prio-boosting. */
96 if (first->rt_param.is_aux_task != second->rt_param.is_aux_task) 80 if (first->rt_param.is_aux_task != second->rt_param.is_aux_task)
97 { 81 {
98 return (first->rt_param.is_aux_task > second->rt_param.is_aux_task); 82 return (first->rt_param.is_aux_task > second->rt_param.is_aux_task);
99 } 83 }
100 else if(first->rt_param.is_aux_task && second->rt_param.is_aux_task) 84 else if(first->rt_param.is_aux_task && second->rt_param.is_aux_task)
101 { 85 {
86 if(first->group_leader == second->group_leader) {
87 TRACE_CUR("aux tie break!\n"); // tie-break by BASE priority of the aux tasks
88 goto aux_tie_break;
89 }
102 first = first->group_leader; 90 first = first->group_leader;
103 second = second->group_leader; 91 second = second->group_leader;
104 } 92 }
105#elif defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE) 93#elif defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE)
106 { 94 {
107 int first_lo_aux, second_lo_aux; 95 int first_lo_aux = first->rt_param.is_aux_task && !first->rt_param.inh_task;
108 int first_hi_aux, second_hi_aux; 96 int second_lo_aux = second->rt_param.is_aux_task && !second->rt_param.inh_task;
109 first_lo_aux = first->rt_param.is_aux_task && !first->rt_param.inh_task; 97
110 second_lo_aux = second->rt_param.is_aux_task && !second->rt_param.inh_task; 98 /* prioritize aux tasks without inheritance below real-time tasks */
111 99 if (first_lo_aux || second_lo_aux) {
112 if (first_lo_aux && !second_lo_aux) { 100 // one of these is an aux task without inheritance.
113 TRACE_CUR("%s/%d >> %s/%d --- 0\n", first->comm, first->pid, second->comm, second->pid); 101 if(first_lo_aux && second_lo_aux) {
114 return 0; 102 TRACE_CUR("aux tie break!\n"); // tie-break by BASE priority of the aux tasks
115 } 103 goto aux_tie_break;
116 else if (second_lo_aux && !first_lo_aux) { 104 }
117 TRACE_CUR("%s/%d >> %s/%d --- 1\n", first->comm, first->pid, second->comm, second->pid); 105 else {
118 return 1; 106 // make the aux thread lowest priority real-time task
119 } 107 int temp = (first_lo_aux) ? !is_realtime(second) : !is_realtime(first);
120 else if (first_lo_aux && second_lo_aux) { 108 TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, temp);
121 int aux_lo_tie_break = aux_tie_break(first, second); 109 return temp;
122 TRACE_CUR("low aux tie break: %s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, aux_lo_tie_break); 110 }
123 return aux_lo_tie_break; 111 }
124 } 112
125 113 if (first->rt_param.is_aux_task && second->rt_param.is_aux_task &&
126 first_hi_aux = first->rt_param.is_aux_task && first->rt_param.inh_task; 114 first->rt_param.inh_task == second->rt_param.inh_task) { // inh_task is !NULL for both tasks since neither was a lo_aux task
127 second_hi_aux = second->rt_param.is_aux_task && second->rt_param.inh_task; 115 // Both aux tasks inherit from the same task, so tie-break
128 116 // by base priority of the aux tasks.
129 if (first_hi_aux && second_hi_aux && first->rt_param.inh_task == second->rt_param.inh_task) { 117 TRACE_CUR("aux tie break!\n");
130 int aux_hi_tie_break = aux_tie_break(first, second); 118 goto aux_tie_break;
131 TRACE_CUR("hi aux tie break: %s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, aux_hi_tie_break); 119 }
132 return aux_hi_tie_break;
133 }
134 } 120 }
135#endif 121#endif
136 122
@@ -174,6 +160,8 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second)
174 160
175#endif 161#endif
176 162
163aux_tie_break:
164
177 if (!is_realtime(second_task)) { 165 if (!is_realtime(second_task)) {
178 return 1; 166 return 1;
179 } 167 }
diff --git a/litmus/litmus.c b/litmus/litmus.c
index cfd14852502b..8bc159b2fcce 100644..100755
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -634,6 +634,14 @@ void litmus_fork(struct task_struct* p)
634 p->od_table = NULL; 634 p->od_table = NULL;
635} 635}
636 636
637/* Called right before copy_process() returns a forked thread. */
638void litmus_post_fork_thread(struct task_struct* p)
639{
640#ifdef CONFIG_REALTIME_AUX_TASKS
641 make_aux_task_if_required(p);
642#endif
643}
644
637/* Called upon execve(). 645/* Called upon execve().
638 * current is doing the exec. 646 * current is doing the exec.
639 * Don't let address space specific stuff leak. 647 * Don't let address space specific stuff leak.