diff --git a/src/rt-app.c b/src/rt-app.c index 7cd436e..085b5fc 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -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; @@ -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, @@ -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", @@ -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; @@ -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(); @@ -1099,30 +1138,37 @@ 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", @@ -1130,6 +1176,13 @@ static void set_thread_param(thread_data_t *data, sched_data_t *sched_data) 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; }