sched/deadline: Add SCHED_DEADLINE inheritance logic
Some method to deal with rt-mutexes and make sched_dl interact with the current PI-coded is needed, raising all but trivial issues, that needs (according to us) to be solved with some restructuring of the pi-code (i.e., going toward a proxy execution-ish implementation). This is under development, in the meanwhile, as a temporary solution, what this commits does is: - ensure a pi-lock owner with waiters is never throttled down. Instead, when it runs out of runtime, it immediately gets replenished and it's deadline is postponed; - the scheduling parameters (relative deadline and default runtime) used for that replenishments --during the whole period it holds the pi-lock-- are the ones of the waiting task with earliest deadline. Acting this way, we provide some kind of boosting to the lock-owner, still by using the existing (actually, slightly modified by the previous commit) pi-architecture. We would stress the fact that this is only a surely needed, all but clean solution to the problem. In the end it's only a way to re-start discussion within the community. So, as always, comments, ideas, rants, etc.. are welcome! :-) Signed-off-by: Dario Faggioli <raistlin@linux.it> Signed-off-by: Juri Lelli <juri.lelli@gmail.com> [ Added !RT_MUTEXES build fix. ] Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1383831828-15501-11-git-send-email-juri.lelli@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
fb00aca474
commit
2d3d891d33
@@ -96,13 +96,16 @@ static inline int
|
||||
rt_mutex_waiter_less(struct rt_mutex_waiter *left,
|
||||
struct rt_mutex_waiter *right)
|
||||
{
|
||||
if (left->task->prio < right->task->prio)
|
||||
if (left->prio < right->prio)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* If both tasks are dl_task(), we check their deadlines.
|
||||
* If both waiters have dl_prio(), we check the deadlines of the
|
||||
* associated tasks.
|
||||
* If left waiter has a dl_prio(), and we didn't return 1 above,
|
||||
* then right waiter has a dl_prio() too.
|
||||
*/
|
||||
if (dl_prio(left->task->prio) && dl_prio(right->task->prio))
|
||||
if (dl_prio(left->prio))
|
||||
return (left->task->dl.deadline < right->task->dl.deadline);
|
||||
|
||||
return 0;
|
||||
@@ -197,10 +200,18 @@ int rt_mutex_getprio(struct task_struct *task)
|
||||
if (likely(!task_has_pi_waiters(task)))
|
||||
return task->normal_prio;
|
||||
|
||||
return min(task_top_pi_waiter(task)->task->prio,
|
||||
return min(task_top_pi_waiter(task)->prio,
|
||||
task->normal_prio);
|
||||
}
|
||||
|
||||
struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
|
||||
{
|
||||
if (likely(!task_has_pi_waiters(task)))
|
||||
return NULL;
|
||||
|
||||
return task_top_pi_waiter(task)->task;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the priority of a task, after its pi_waiters got modified.
|
||||
*
|
||||
@@ -210,7 +221,7 @@ static void __rt_mutex_adjust_prio(struct task_struct *task)
|
||||
{
|
||||
int prio = rt_mutex_getprio(task);
|
||||
|
||||
if (task->prio != prio)
|
||||
if (task->prio != prio || dl_prio(prio))
|
||||
rt_mutex_setprio(task, prio);
|
||||
}
|
||||
|
||||
@@ -328,7 +339,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
||||
* When deadlock detection is off then we check, if further
|
||||
* priority adjustment is necessary.
|
||||
*/
|
||||
if (!detect_deadlock && waiter->task->prio == task->prio)
|
||||
if (!detect_deadlock && waiter->prio == task->prio)
|
||||
goto out_unlock_pi;
|
||||
|
||||
lock = waiter->lock;
|
||||
@@ -350,7 +361,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
||||
|
||||
/* Requeue the waiter */
|
||||
rt_mutex_dequeue(lock, waiter);
|
||||
waiter->task->prio = task->prio;
|
||||
waiter->prio = task->prio;
|
||||
rt_mutex_enqueue(lock, waiter);
|
||||
|
||||
/* Release the task */
|
||||
@@ -448,7 +459,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
|
||||
* 3) it is top waiter
|
||||
*/
|
||||
if (rt_mutex_has_waiters(lock)) {
|
||||
if (task->prio >= rt_mutex_top_waiter(lock)->task->prio) {
|
||||
if (task->prio >= rt_mutex_top_waiter(lock)->prio) {
|
||||
if (!waiter || waiter != rt_mutex_top_waiter(lock))
|
||||
return 0;
|
||||
}
|
||||
@@ -508,6 +519,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
|
||||
__rt_mutex_adjust_prio(task);
|
||||
waiter->task = task;
|
||||
waiter->lock = lock;
|
||||
waiter->prio = task->prio;
|
||||
|
||||
/* Get the top priority waiter on the lock */
|
||||
if (rt_mutex_has_waiters(lock))
|
||||
@@ -653,7 +665,8 @@ void rt_mutex_adjust_pi(struct task_struct *task)
|
||||
raw_spin_lock_irqsave(&task->pi_lock, flags);
|
||||
|
||||
waiter = task->pi_blocked_on;
|
||||
if (!waiter || waiter->task->prio == task->prio) {
|
||||
if (!waiter || (waiter->prio == task->prio &&
|
||||
!dl_prio(task->prio))) {
|
||||
raw_spin_unlock_irqrestore(&task->pi_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ struct rt_mutex_waiter {
|
||||
struct pid *deadlock_task_pid;
|
||||
struct rt_mutex *deadlock_lock;
|
||||
#endif
|
||||
int prio;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user