Skip to content

Commit ed4fb6d

Browse files
fmoessbauerKAGA-KOKO
authored andcommitted
hrtimer: Use and report correct timerslack values for realtime tasks
The timerslack_ns setting is used to specify how much the hardware timers should be delayed, to potentially dispatch multiple timers in a single interrupt. This is a performance optimization. Timers of realtime tasks (having a realtime scheduling policy) should not be delayed. This logic was inconsitently applied to the hrtimers, leading to delays of realtime tasks which used timed waits for events (e.g. condition variables). Due to the downstream override of the slack for rt tasks, the procfs reported incorrect (non-zero) timerslack_ns values. This is changed by setting the timer_slack_ns task attribute to 0 for all tasks with a rt policy. By that, downstream users do not need to specially handle rt tasks (w.r.t. the slack), and the procfs entry shows the correct value of "0". Setting non-zero slack values (either via procfs or PR_SET_TIMERSLACK) on tasks with a rt policy is ignored, as stated in "man 2 PR_SET_TIMERSLACK": Timer slack is not applied to threads that are scheduled under a real-time scheduling policy (see sched_setscheduler(2)). The special handling of timerslack on rt tasks in downstream users is removed as well. Signed-off-by: Felix Moessbauer <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 330dd6d commit ed4fb6d

File tree

5 files changed

+22
-26
lines changed

5 files changed

+22
-26
lines changed

fs/proc/base.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2569,10 +2569,11 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
25692569
}
25702570

25712571
task_lock(p);
2572-
if (slack_ns == 0)
2573-
p->timer_slack_ns = p->default_timer_slack_ns;
2574-
else
2575-
p->timer_slack_ns = slack_ns;
2572+
if (task_is_realtime(p))
2573+
slack_ns = 0;
2574+
else if (slack_ns == 0)
2575+
slack_ns = p->default_timer_slack_ns;
2576+
p->timer_slack_ns = slack_ns;
25762577
task_unlock(p);
25772578

25782579
out:

fs/select.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,16 @@ u64 select_estimate_accuracy(struct timespec64 *tv)
7777
{
7878
u64 ret;
7979
struct timespec64 now;
80+
u64 slack = current->timer_slack_ns;
8081

81-
/*
82-
* Realtime tasks get a slack of 0 for obvious reasons.
83-
*/
84-
85-
if (rt_task(current))
82+
if (slack == 0)
8683
return 0;
8784

8885
ktime_get_ts64(&now);
8986
now = timespec64_sub(*tv, now);
9087
ret = __estimate_accuracy(&now);
91-
if (ret < current->timer_slack_ns)
92-
return current->timer_slack_ns;
88+
if (ret < slack)
89+
return slack;
9390
return ret;
9491
}
9592

kernel/sched/syscalls.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,14 @@ static void __setscheduler_params(struct task_struct *p,
406406
else if (fair_policy(policy))
407407
p->static_prio = NICE_TO_PRIO(attr->sched_nice);
408408

409+
/* rt-policy tasks do not have a timerslack */
410+
if (task_is_realtime(p)) {
411+
p->timer_slack_ns = 0;
412+
} else if (p->timer_slack_ns == 0) {
413+
/* when switching back to non-rt policy, restore timerslack */
414+
p->timer_slack_ns = p->default_timer_slack_ns;
415+
}
416+
409417
/*
410418
* __sched_setscheduler() ensures attr->sched_priority == 0 when
411419
* !rt_policy. Always setting this ensures that things like

kernel/sys.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,8 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
25572557
error = current->timer_slack_ns;
25582558
break;
25592559
case PR_SET_TIMERSLACK:
2560+
if (task_is_realtime(current))
2561+
break;
25602562
if (arg2 <= 0)
25612563
current->timer_slack_ns =
25622564
current->default_timer_slack_ns;

kernel/time/hrtimer.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,14 +2074,9 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
20742074
struct restart_block *restart;
20752075
struct hrtimer_sleeper t;
20762076
int ret = 0;
2077-
u64 slack;
2078-
2079-
slack = current->timer_slack_ns;
2080-
if (rt_task(current))
2081-
slack = 0;
20822077

20832078
hrtimer_init_sleeper_on_stack(&t, clockid, mode);
2084-
hrtimer_set_expires_range_ns(&t.timer, rqtp, slack);
2079+
hrtimer_set_expires_range_ns(&t.timer, rqtp, current->timer_slack_ns);
20852080
ret = do_nanosleep(&t, mode);
20862081
if (ret != -ERESTART_RESTARTBLOCK)
20872082
goto out;
@@ -2251,7 +2246,7 @@ void __init hrtimers_init(void)
22512246
/**
22522247
* schedule_hrtimeout_range_clock - sleep until timeout
22532248
* @expires: timeout value (ktime_t)
2254-
* @delta: slack in expires timeout (ktime_t) for SCHED_OTHER tasks
2249+
* @delta: slack in expires timeout (ktime_t)
22552250
* @mode: timer mode
22562251
* @clock_id: timer clock to be used
22572252
*/
@@ -2278,13 +2273,6 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
22782273
return -EINTR;
22792274
}
22802275

2281-
/*
2282-
* Override any slack passed by the user if under
2283-
* rt contraints.
2284-
*/
2285-
if (rt_task(current))
2286-
delta = 0;
2287-
22882276
hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
22892277
hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
22902278
hrtimer_sleeper_start_expires(&t, mode);
@@ -2304,7 +2292,7 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);
23042292
/**
23052293
* schedule_hrtimeout_range - sleep until timeout
23062294
* @expires: timeout value (ktime_t)
2307-
* @delta: slack in expires timeout (ktime_t) for SCHED_OTHER tasks
2295+
* @delta: slack in expires timeout (ktime_t)
23082296
* @mode: timer mode
23092297
*
23102298
* Make the current task sleep until the given expiry time has

0 commit comments

Comments
 (0)