mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
posix-timers: Clarify posix_timer_fn() comments
Make the issues vs. SIG_IGN understandable and remove the 15 years old promise that a proper solution is already on the horizon. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/874jnrdmrq.ffs@tglx
This commit is contained in:
parent
02972d7955
commit
84999b8bdb
@ -326,11 +326,11 @@ int posix_timer_event(struct k_itimer *timr, int si_private)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets called when a POSIX.1b interval timer expires. It
|
||||
* is used as a callback from the kernel internal timer. The
|
||||
* run_timer_list code ALWAYS calls with interrupts on.
|
||||
|
||||
* This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
|
||||
* This function gets called when a POSIX.1b interval timer expires from
|
||||
* the HRTIMER interrupt (soft interrupt on RT kernels).
|
||||
*
|
||||
* Handles CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_BOOTTIME and CLOCK_TAI
|
||||
* based timers.
|
||||
*/
|
||||
static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
|
||||
{
|
||||
@ -348,9 +348,10 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
|
||||
|
||||
if (posix_timer_event(timr, si_private)) {
|
||||
/*
|
||||
* signal was not sent because of sig_ignor
|
||||
* we will not get a call back to restart it AND
|
||||
* it should be restarted.
|
||||
* The signal was not queued due to SIG_IGN. As a
|
||||
* consequence the timer is not going to be rearmed from
|
||||
* the signal delivery path. But as a real signal handler
|
||||
* can be installed later the timer must be rearmed here.
|
||||
*/
|
||||
if (timr->it_interval != 0) {
|
||||
ktime_t now = hrtimer_cb_get_time(timer);
|
||||
@ -359,34 +360,35 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
|
||||
* FIXME: What we really want, is to stop this
|
||||
* timer completely and restart it in case the
|
||||
* SIG_IGN is removed. This is a non trivial
|
||||
* change which involves sighand locking
|
||||
* (sigh !), which we don't want to do late in
|
||||
* the release cycle.
|
||||
* change to the signal handling code.
|
||||
*
|
||||
* For now we just let timers with an interval
|
||||
* less than a jiffie expire every jiffie to
|
||||
* avoid softirq starvation in case of SIG_IGN
|
||||
* and a very small interval, which would put
|
||||
* the timer right back on the softirq pending
|
||||
* list. By moving now ahead of time we trick
|
||||
* hrtimer_forward() to expire the timer
|
||||
* later, while we still maintain the overrun
|
||||
* accuracy, but have some inconsistency in
|
||||
* the timer_gettime() case. This is at least
|
||||
* better than a starved softirq. A more
|
||||
* complex fix which solves also another related
|
||||
* inconsistency is already in the pipeline.
|
||||
* For now let timers with an interval less than a
|
||||
* jiffie expire every jiffie and recheck for a
|
||||
* valid signal handler.
|
||||
*
|
||||
* This avoids interrupt starvation in case of a
|
||||
* very small interval, which would expire the
|
||||
* timer immediately again.
|
||||
*
|
||||
* Moving now ahead of time by one jiffie tricks
|
||||
* hrtimer_forward() to expire the timer later,
|
||||
* while it still maintains the overrun accuracy
|
||||
* for the price of a slight inconsistency in the
|
||||
* timer_gettime() case. This is at least better
|
||||
* than a timer storm.
|
||||
*
|
||||
* Only required when high resolution timers are
|
||||
* enabled as the periodic tick based timers are
|
||||
* automatically aligned to the next tick.
|
||||
*/
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
{
|
||||
ktime_t kj = NSEC_PER_SEC / HZ;
|
||||
if (IS_ENABLED(CONFIG_HIGHRES_TIMERS)) {
|
||||
ktime_t kj = TICK_NSEC;
|
||||
|
||||
if (timr->it_interval < kj)
|
||||
now = ktime_add(now, kj);
|
||||
}
|
||||
#endif
|
||||
timr->it_overrun += hrtimer_forward(timer, now,
|
||||
timr->it_interval);
|
||||
|
||||
timr->it_overrun += hrtimer_forward(timer, now, timr->it_interval);
|
||||
ret = HRTIMER_RESTART;
|
||||
++timr->it_requeue_pending;
|
||||
timr->it_active = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user