Skip to content

Commit

Permalink
uclamp: Fix sched_setattr call
Browse files Browse the repository at this point in the history
The struct sched_param passed to sched_setattr() for uclamp needs to
have a valid policy and priority set.

Currently, sched_data->prio is set to a special value
THREAD_PRIORITY_UNCHANGED when the phase does not declare a specific
priority, and sched_data->policy is set to "same". This is problematic
as the kernel expects a valid policy and priority.  We currently pass
the special values to the kernel, which makes the syscall fail.

Fix that by maintaining a valid policy and priority in
thread_data_t->curr_sched_data->{policy,prio} and using it where
appropriate.
  • Loading branch information
DouglasRaillard committed Feb 9, 2021
1 parent f100f45 commit d38b9e4
Showing 1 changed file with 69 additions and 16 deletions.
85 changes: 69 additions & 16 deletions src/rt-app.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,12 +914,17 @@ static void set_thread_membind(thread_data_t *data, numaset_data_t * numa_data)
* sched_priority is only meaningful for RT tasks. Otherwise, it must be
* set to 0 for the setattr syscall to succeed.
*/
static int __sched_priority(thread_data_t *data, sched_data_t *sched_data)
static int __sched_priority(thread_data_t *data, sched_data_t *sched_data, int curr_prio)
{
int prio = sched_data->prio;

if (prio == THREAD_PRIORITY_UNCHANGED)
prio = curr_prio;

switch (sched_data->policy) {
case rr:
case fifo:
return sched_data->prio;
return prio;
}

return 0;
Expand All @@ -945,7 +950,13 @@ static bool __set_thread_policy_priority(thread_data_t *data,
struct sched_param param;
int ret;

param.sched_priority = __sched_priority(data, sched_data);
if (sched_data->prio == THREAD_PRIORITY_UNCHANGED) {
log_error("Cannot resolve the priority of the thread %s",
data->name);
exit(EXIT_FAILURE);
}

param.sched_priority = __sched_priority(data, sched_data, sched_data->prio);

ret = pthread_setschedparam(pthread_self(),
sched_data->policy,
Expand Down Expand Up @@ -1013,12 +1024,20 @@ static void _set_thread_rt(thread_data_t *data, sched_data_t *sched_data)
}

/* deadline can't rely on the default __set_thread_policy_priority */
static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data)
static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data,
sched_data_t *curr_sched_data)
{
struct sched_attr sa_params = {0};
unsigned int flags = 0;
pid_t tid;
int ret;
int curr_prio;

if (curr_sched_data)
curr_prio = curr_sched_data->prio;
else
/* The value does not matter as it will not be used */
curr_prio = THREAD_PRIORITY_UNCHANGED;

log_debug("[%d] setting scheduler %s exec %lu, deadline %lu"
" period %lu",
Expand All @@ -1036,7 +1055,7 @@ static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data)
sa_params.size = sizeof(struct sched_attr);
sa_params.sched_flags = 0;
sa_params.sched_policy = SCHED_DEADLINE;
sa_params.sched_priority = __sched_priority(data, sched_data);
sa_params.sched_priority = __sched_priority(data, sched_data, curr_prio);
sa_params.sched_runtime = sched_data->runtime;
sa_params.sched_deadline = sched_data->deadline;
sa_params.sched_period = sched_data->period;
Expand All @@ -1051,19 +1070,39 @@ static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data)
}
}

static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data)
static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data, sched_data_t *curr_sched_data)
{
struct sched_attr sa_params = {0};
unsigned int flags = 0;
pid_t tid;
int ret;
policy_t policy;
int curr_prio;

if ((sched_data->util_min == -2 &&
sched_data->util_max == -2))
return;

sa_params.sched_policy = sched_data->policy;
sa_params.sched_priority = __sched_priority(data, sched_data);
if (curr_sched_data) {
if (sched_data->policy == same)
policy = curr_sched_data->policy;
else
policy = sched_data->policy;

curr_prio = curr_sched_data->prio;
} else {
curr_prio = THREAD_PRIORITY_UNCHANGED;
}


if (policy == same) {
log_error("Cannot resolve the policy of the thread %s",
data->name);
exit(EXIT_FAILURE);
}

sa_params.sched_policy = policy;
sa_params.sched_priority = __sched_priority(data, sched_data, curr_prio);
sa_params.size = sizeof(struct sched_attr);
sa_params.sched_flags = SCHED_FLAG_KEEP_ALL;
tid = gettid();
Expand Down Expand Up @@ -1099,37 +1138,51 @@ static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data)

static void set_thread_param(thread_data_t *data, sched_data_t *sched_data)
{
sched_data_t *curr_sched_data = data->curr_sched_data;

if (!sched_data)
return;

if (data->curr_sched_data == sched_data)
return;
if (curr_sched_data) {
if (curr_sched_data == sched_data)
return;

if (sched_data->prio == curr_sched_data->prio)
sched_data->prio = THREAD_PRIORITY_UNCHANGED;

/* if no policy is specified, reuse the previous one */
if ((sched_data->policy == same) && data->curr_sched_data)
sched_data->policy = data->curr_sched_data->policy;
/* if no policy is specified, reuse the previous one */
if (sched_data->policy == same)
sched_data->policy = curr_sched_data->policy;
}

switch (sched_data->policy) {
case rr:
case fifo:
_set_thread_rt(data, sched_data);
_set_thread_uclamp(data, sched_data);
_set_thread_uclamp(data, sched_data, curr_sched_data);
break;
case other:
case idle:
_set_thread_cfs(data, sched_data);
_set_thread_uclamp(data, sched_data);
_set_thread_uclamp(data, sched_data, curr_sched_data);
data->lock_pages = 0; /* forced off */
break;
case deadline:
_set_thread_deadline(data, sched_data);
_set_thread_deadline(data, sched_data, curr_sched_data);
break;
default:
log_error("Unknown scheduling policy %d",
sched_data->policy);
exit(EXIT_FAILURE);
}

/* Ensure we have an actual valid priority in curr_sched_data at all
* time, since it could be needed in a later phase for sched_setattr()
* syscall
*/
if (sched_data->prio == THREAD_PRIORITY_UNCHANGED)
sched_data->prio = curr_sched_data->prio;

data->curr_sched_data = sched_data;
}

Expand Down

0 comments on commit d38b9e4

Please sign in to comment.