Skip to content

Commit 82b4b47

Browse files
uclamp: Fix sched_setattr call
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.
1 parent 76ba113 commit 82b4b47

File tree

1 file changed

+69
-16
lines changed

1 file changed

+69
-16
lines changed

src/rt-app.c

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -914,12 +914,17 @@ static void set_thread_membind(thread_data_t *data, numaset_data_t * numa_data)
914914
* sched_priority is only meaningful for RT tasks. Otherwise, it must be
915915
* set to 0 for the setattr syscall to succeed.
916916
*/
917-
static int __sched_priority(thread_data_t *data, sched_data_t *sched_data)
917+
static int __sched_priority(thread_data_t *data, sched_data_t *sched_data, int curr_prio)
918918
{
919+
int prio = sched_data->prio;
920+
921+
if (prio == THREAD_PRIORITY_UNCHANGED)
922+
prio = curr_prio;
923+
919924
switch (sched_data->policy) {
920925
case rr:
921926
case fifo:
922-
return sched_data->prio;
927+
return prio;
923928
}
924929

925930
return 0;
@@ -945,7 +950,13 @@ static bool __set_thread_policy_priority(thread_data_t *data,
945950
struct sched_param param;
946951
int ret;
947952

948-
param.sched_priority = __sched_priority(data, sched_data);
953+
if (sched_data->prio == THREAD_PRIORITY_UNCHANGED) {
954+
log_error("Cannot resolve the priority of the thread %s",
955+
data->name);
956+
exit(EXIT_FAILURE);
957+
}
958+
959+
param.sched_priority = __sched_priority(data, sched_data, sched_data->prio);
949960

950961
ret = pthread_setschedparam(pthread_self(),
951962
sched_data->policy,
@@ -1013,12 +1024,20 @@ static void _set_thread_rt(thread_data_t *data, sched_data_t *sched_data)
10131024
}
10141025

10151026
/* deadline can't rely on the default __set_thread_policy_priority */
1016-
static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data)
1027+
static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data,
1028+
sched_data_t *curr_sched_data)
10171029
{
10181030
struct sched_attr sa_params = {0};
10191031
unsigned int flags = 0;
10201032
pid_t tid;
10211033
int ret;
1034+
int curr_prio;
1035+
1036+
if (curr_sched_data)
1037+
curr_prio = curr_sched_data->prio;
1038+
else
1039+
/* The value does not matter as it will not be used */
1040+
curr_prio = THREAD_PRIORITY_UNCHANGED;
10221041

10231042
log_debug("[%d] setting scheduler %s exec %lu, deadline %lu"
10241043
" period %lu",
@@ -1036,7 +1055,7 @@ static void _set_thread_deadline(thread_data_t *data, sched_data_t *sched_data)
10361055
sa_params.size = sizeof(struct sched_attr);
10371056
sa_params.sched_flags = 0;
10381057
sa_params.sched_policy = SCHED_DEADLINE;
1039-
sa_params.sched_priority = __sched_priority(data, sched_data);
1058+
sa_params.sched_priority = __sched_priority(data, sched_data, curr_prio);
10401059
sa_params.sched_runtime = sched_data->runtime;
10411060
sa_params.sched_deadline = sched_data->deadline;
10421061
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)
10511070
}
10521071
}
10531072

1054-
static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data)
1073+
static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data, sched_data_t *curr_sched_data)
10551074
{
10561075
struct sched_attr sa_params = {0};
10571076
unsigned int flags = 0;
10581077
pid_t tid;
10591078
int ret;
1079+
policy_t policy;
1080+
int curr_prio;
10601081

10611082
if ((sched_data->util_min == -2 &&
10621083
sched_data->util_max == -2))
10631084
return;
10641085

1065-
sa_params.sched_policy = sched_data->policy;
1066-
sa_params.sched_priority = __sched_priority(data, sched_data);
1086+
if (curr_sched_data) {
1087+
if (sched_data->policy == same)
1088+
policy = curr_sched_data->policy;
1089+
else
1090+
policy = sched_data->policy;
1091+
1092+
curr_prio = curr_sched_data->prio;
1093+
} else {
1094+
curr_prio = THREAD_PRIORITY_UNCHANGED;
1095+
}
1096+
1097+
1098+
if (policy == same) {
1099+
log_error("Cannot resolve the policy of the thread %s",
1100+
data->name);
1101+
exit(EXIT_FAILURE);
1102+
}
1103+
1104+
sa_params.sched_policy = policy;
1105+
sa_params.sched_priority = __sched_priority(data, sched_data, curr_prio);
10671106
sa_params.size = sizeof(struct sched_attr);
10681107
sa_params.sched_flags = SCHED_FLAG_KEEP_ALL;
10691108
tid = gettid();
@@ -1099,37 +1138,51 @@ static void _set_thread_uclamp(thread_data_t *data, sched_data_t *sched_data)
10991138

11001139
static void set_thread_param(thread_data_t *data, sched_data_t *sched_data)
11011140
{
1141+
sched_data_t *curr_sched_data = data->curr_sched_data;
1142+
11021143
if (!sched_data)
11031144
return;
11041145

1105-
if (data->curr_sched_data == sched_data)
1106-
return;
1146+
if (curr_sched_data) {
1147+
if (curr_sched_data == sched_data)
1148+
return;
1149+
1150+
if (sched_data->prio == curr_sched_data->prio)
1151+
sched_data->prio = THREAD_PRIORITY_UNCHANGED;
11071152

1108-
/* if no policy is specified, reuse the previous one */
1109-
if ((sched_data->policy == same) && data->curr_sched_data)
1110-
sched_data->policy = data->curr_sched_data->policy;
1153+
/* if no policy is specified, reuse the previous one */
1154+
if (sched_data->policy == same)
1155+
sched_data->policy = curr_sched_data->policy;
1156+
}
11111157

11121158
switch (sched_data->policy) {
11131159
case rr:
11141160
case fifo:
11151161
_set_thread_rt(data, sched_data);
1116-
_set_thread_uclamp(data, sched_data);
1162+
_set_thread_uclamp(data, sched_data, curr_sched_data);
11171163
break;
11181164
case other:
11191165
case idle:
11201166
_set_thread_cfs(data, sched_data);
1121-
_set_thread_uclamp(data, sched_data);
1167+
_set_thread_uclamp(data, sched_data, curr_sched_data);
11221168
data->lock_pages = 0; /* forced off */
11231169
break;
11241170
case deadline:
1125-
_set_thread_deadline(data, sched_data);
1171+
_set_thread_deadline(data, sched_data, curr_sched_data);
11261172
break;
11271173
default:
11281174
log_error("Unknown scheduling policy %d",
11291175
sched_data->policy);
11301176
exit(EXIT_FAILURE);
11311177
}
11321178

1179+
/* Ensure we have an actual valid priority in curr_sched_data at all
1180+
* time, since it could be needed in a later phase for sched_setattr()
1181+
* syscall
1182+
*/
1183+
if (sched_data->prio == THREAD_PRIORITY_UNCHANGED)
1184+
sched_data->prio = curr_sched_data->prio;
1185+
11331186
data->curr_sched_data = sched_data;
11341187
}
11351188

0 commit comments

Comments
 (0)