aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_cedf.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-02-11 22:48:51 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2013-02-11 22:48:51 -0500
commitc063e088be8e1bcbb6a76b8cd087f8dc8b6923b2 (patch)
tree4450780888858cfbb0d042605035db689c3eedbe /litmus/sched_cedf.c
parent40d12009bd0c3515c5bfee5425bd80f58cdd7b73 (diff)
BUG FIX: Support DGLs with PRIOQ_MUTEXwip-prioq-dgl
First 'working' implementation of DGLs with PRIOQ_MUTEX. (All other code prior was work-in-progress.) General approach: Because of priority queue order, PRIOQ_MUTEX DGLs must be *acquired* atomically. This means that a task cannot acquire an available PRIOQ_MUTEX if another PRIOQ_MUTEX is not available at the same time. Requests are buffered in PRIOQ_MUTEX and the resource 'idles'-- that is, the mutex owner is NULL, but there are waiting tasks for the resource. Several notes/side-effects: 1) A high-priority task that idles a resource can effectively block lower-priority tasks from acquiring that resource. This is because the low-prio task cannot skip ahead of the high-prio task in the priority queue. 2) Priority inheritance from nesting can cause the low-prioity task in #1 to jump over the high-priority task and acquire the resource. This means that any task blocked on a DGL that receives an increase in priority while blocked on the DGL must trigger a re-eval of the locks it can take. If the resources can be acquired, then the task needs to be woken up! <<<<< Lock acquisition via inheritance is entirely new and weird! >>>>> 3) A similar case for #2 exists for priorty decreases (example: this can happen when a task loses a donor) while it is blocked on a PRIOQ_MUTEX. The high-priority task described in #1 can change and become a lower- priority task. Every idle lock (mutex owner is NULL) on which the task losing priority must be revaluated--- it is possible that the (possible) new head on the priority queue can take the lock. Note: This affects BOTH singular and DGL resource requests, while the case described in #2 only affects DGL requests (because a singular request at the head of the priority queue will never idle a resource).
Diffstat (limited to 'litmus/sched_cedf.c')
-rw-r--r--litmus/sched_cedf.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c
index 40daf8e16d74..69f30188f3ba 100644
--- a/litmus/sched_cedf.c
+++ b/litmus/sched_cedf.c
@@ -1316,6 +1316,14 @@ static int __decrease_priority_inheritance(struct task_struct* t,
1316{ 1316{
1317 int success = 1; 1317 int success = 1;
1318 1318
1319 if (prio_inh == tsk_rt(t)->inh_task) {
1320 /* relationship already established. */
1321 TRACE_TASK(t, "already inherits priority from %s/%d\n",
1322 (prio_inh) ? prio_inh->comm : "(null)",
1323 (prio_inh) ? prio_inh->pid : 0);
1324 goto out;
1325 }
1326
1319 if (prio_inh && (effective_priority(prio_inh) != prio_inh)) { 1327 if (prio_inh && (effective_priority(prio_inh) != prio_inh)) {
1320 TRACE_TASK(t, "Inheriting from %s/%d instead of the eff_prio = %s/%d!\n", 1328 TRACE_TASK(t, "Inheriting from %s/%d instead of the eff_prio = %s/%d!\n",
1321 prio_inh->comm, prio_inh->pid, 1329 prio_inh->comm, prio_inh->pid,
@@ -1337,14 +1345,6 @@ static int __decrease_priority_inheritance(struct task_struct* t,
1337#endif 1345#endif
1338 } 1346 }
1339 1347
1340 if (prio_inh == tsk_rt(t)->inh_task) {
1341 /* relationship already established. */
1342 TRACE_TASK(t, "already inherits priority from %s/%d\n",
1343 (prio_inh) ? prio_inh->comm : "(null)",
1344 (prio_inh) ? prio_inh->pid : 0);
1345 goto out;
1346 }
1347
1348#ifdef CONFIG_LITMUS_NESTED_LOCKING 1348#ifdef CONFIG_LITMUS_NESTED_LOCKING
1349 if(__edf_higher_prio(t, EFFECTIVE, prio_inh, BASE)) { 1349 if(__edf_higher_prio(t, EFFECTIVE, prio_inh, BASE)) {
1350#endif 1350#endif
@@ -1469,7 +1469,7 @@ static void nested_increase_priority_inheritance(struct task_struct* t,
1469 1469
1470 1470
1471 if(blocked_lock) { 1471 if(blocked_lock) {
1472 if(blocked_lock->ops->propagate_increase_inheritance) { 1472 if(blocked_lock->ops->supports_nesting) {
1473 TRACE_TASK(t, "Inheritor is blocked (...perhaps). Checking lock %d.\n", 1473 TRACE_TASK(t, "Inheritor is blocked (...perhaps). Checking lock %d.\n",
1474 blocked_lock->ident); 1474 blocked_lock->ident);
1475 1475
@@ -1506,7 +1506,7 @@ static void nested_decrease_priority_inheritance(struct task_struct* t,
1506 raw_spin_unlock(&tsk_rt(t)->hp_blocked_tasks_lock); // unlock the t's heap. 1506 raw_spin_unlock(&tsk_rt(t)->hp_blocked_tasks_lock); // unlock the t's heap.
1507 1507
1508 if(blocked_lock) { 1508 if(blocked_lock) {
1509 if(blocked_lock->ops->propagate_decrease_inheritance) { 1509 if(blocked_lock->ops->supports_nesting) {
1510 TRACE_TASK(t, "Inheritor is blocked (...perhaps). Checking lock %d.\n", 1510 TRACE_TASK(t, "Inheritor is blocked (...perhaps). Checking lock %d.\n",
1511 blocked_lock->ident); 1511 blocked_lock->ident);
1512 1512
@@ -1547,7 +1547,11 @@ static struct litmus_lock_ops cedf_fifo_mutex_lock_ops = {
1547 1547
1548 .dgl_can_quick_lock = NULL, 1548 .dgl_can_quick_lock = NULL,
1549 .dgl_quick_lock = NULL, 1549 .dgl_quick_lock = NULL,
1550
1551 .supports_dgl = 1,
1552 .requires_atomic_dgl = 0,
1550#endif 1553#endif
1554 .supports_nesting = 1,
1551}; 1555};
1552 1556
1553static struct litmus_lock* cedf_new_fifo_mutex(void) 1557static struct litmus_lock* cedf_new_fifo_mutex(void)
@@ -1574,7 +1578,11 @@ static struct litmus_lock_ops cedf_prioq_mutex_lock_ops = {
1574 1578
1575 .dgl_can_quick_lock = prioq_mutex_dgl_can_quick_lock, 1579 .dgl_can_quick_lock = prioq_mutex_dgl_can_quick_lock,
1576 .dgl_quick_lock = prioq_mutex_dgl_quick_lock, 1580 .dgl_quick_lock = prioq_mutex_dgl_quick_lock,
1581
1582 .supports_dgl = 1,
1583 .requires_atomic_dgl = 1,
1577#endif 1584#endif
1585 .supports_nesting = 1,
1578}; 1586};
1579 1587
1580static struct litmus_lock* cedf_new_prioq_mutex(void) 1588static struct litmus_lock* cedf_new_prioq_mutex(void)
@@ -1593,6 +1601,12 @@ static struct litmus_lock_ops cedf_ikglp_lock_ops = {
1593 // ikglp can only be an outer-most lock. 1601 // ikglp can only be an outer-most lock.
1594 .propagate_increase_inheritance = NULL, 1602 .propagate_increase_inheritance = NULL,
1595 .propagate_decrease_inheritance = NULL, 1603 .propagate_decrease_inheritance = NULL,
1604
1605#ifdef CONFIG_LITMUS_DGL_SUPPORT
1606 .supports_dgl = 0,
1607 .requires_atomic_dgl = 0,
1608#endif
1609 .supports_nesting = 0,
1596}; 1610};
1597 1611
1598static struct litmus_lock* cedf_new_ikglp(void* __user arg) 1612static struct litmus_lock* cedf_new_ikglp(void* __user arg)
@@ -1617,6 +1631,12 @@ static struct litmus_lock_ops cedf_kfmlp_lock_ops = {
1617 // kfmlp can only be an outer-most lock. 1631 // kfmlp can only be an outer-most lock.
1618 .propagate_increase_inheritance = NULL, 1632 .propagate_increase_inheritance = NULL,
1619 .propagate_decrease_inheritance = NULL, 1633 .propagate_decrease_inheritance = NULL,
1634
1635#ifdef CONFIG_LITMUS_DGL_SUPPORT
1636 .supports_dgl = 0,
1637 .requires_atomic_dgl = 0,
1638#endif
1639 .supports_nesting = 0,
1620}; 1640};
1621 1641
1622 1642