diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-02-11 22:48:51 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2013-02-11 22:48:51 -0500 |
commit | c063e088be8e1bcbb6a76b8cd087f8dc8b6923b2 (patch) | |
tree | 4450780888858cfbb0d042605035db689c3eedbe /litmus/sched_cedf.c | |
parent | 40d12009bd0c3515c5bfee5425bd80f58cdd7b73 (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.c | 40 |
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 | ||
1553 | static struct litmus_lock* cedf_new_fifo_mutex(void) | 1557 | static 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 | ||
1580 | static struct litmus_lock* cedf_new_prioq_mutex(void) | 1588 | static 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 | ||
1598 | static struct litmus_lock* cedf_new_ikglp(void* __user arg) | 1612 | static 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 | ||