Skip to content

Commit 12e9bd1

Browse files
committed
Merge tag 'timers-urgent-2021-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner: "A small set of timer related fixes: - Plug a race between rearm and process tick in the posix CPU timers code - Make the optimization to avoid recalculation of the next timer interrupt work correctly when there are no timers pending" * tag 'timers-urgent-2021-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: timers: Fix get_next_timer_interrupt() with no timers pending posix-cpu-timers: Fix rearm racing against process tick
2 parents d1b1782 + ff5a6a3 commit 12e9bd1

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

kernel/time/posix-cpu-timers.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,11 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
991991
if (!p)
992992
goto out;
993993

994+
/* Protect timer list r/w in arm_timer() */
995+
sighand = lock_task_sighand(p, &flags);
996+
if (unlikely(sighand == NULL))
997+
goto out;
998+
994999
/*
9951000
* Fetch the current sample and update the timer's expiry time.
9961001
*/
@@ -1001,11 +1006,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
10011006

10021007
bump_cpu_timer(timer, now);
10031008

1004-
/* Protect timer list r/w in arm_timer() */
1005-
sighand = lock_task_sighand(p, &flags);
1006-
if (unlikely(sighand == NULL))
1007-
goto out;
1008-
10091009
/*
10101010
* Now re-arm for the new expiry time.
10111011
*/

kernel/time/timer.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ struct timer_base {
207207
unsigned int cpu;
208208
bool next_expiry_recalc;
209209
bool is_idle;
210+
bool timers_pending;
210211
DECLARE_BITMAP(pending_map, WHEEL_SIZE);
211212
struct hlist_head vectors[WHEEL_SIZE];
212213
} ____cacheline_aligned;
@@ -595,6 +596,7 @@ static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
595596
* can reevaluate the wheel:
596597
*/
597598
base->next_expiry = bucket_expiry;
599+
base->timers_pending = true;
598600
base->next_expiry_recalc = false;
599601
trigger_dyntick_cpu(base, timer);
600602
}
@@ -1582,6 +1584,7 @@ static unsigned long __next_timer_interrupt(struct timer_base *base)
15821584
}
15831585

15841586
base->next_expiry_recalc = false;
1587+
base->timers_pending = !(next == base->clk + NEXT_TIMER_MAX_DELTA);
15851588

15861589
return next;
15871590
}
@@ -1633,7 +1636,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
16331636
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
16341637
u64 expires = KTIME_MAX;
16351638
unsigned long nextevt;
1636-
bool is_max_delta;
16371639

16381640
/*
16391641
* Pretend that there is no timer pending if the cpu is offline.
@@ -1646,7 +1648,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
16461648
if (base->next_expiry_recalc)
16471649
base->next_expiry = __next_timer_interrupt(base);
16481650
nextevt = base->next_expiry;
1649-
is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);
16501651

16511652
/*
16521653
* We have a fresh next event. Check whether we can forward the
@@ -1664,7 +1665,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
16641665
expires = basem;
16651666
base->is_idle = false;
16661667
} else {
1667-
if (!is_max_delta)
1668+
if (base->timers_pending)
16681669
expires = basem + (u64)(nextevt - basej) * TICK_NSEC;
16691670
/*
16701671
* If we expect to sleep more than a tick, mark the base idle.
@@ -1947,6 +1948,7 @@ int timers_prepare_cpu(unsigned int cpu)
19471948
base = per_cpu_ptr(&timer_bases[b], cpu);
19481949
base->clk = jiffies;
19491950
base->next_expiry = base->clk + NEXT_TIMER_MAX_DELTA;
1951+
base->timers_pending = false;
19501952
base->is_idle = false;
19511953
}
19521954
return 0;

0 commit comments

Comments
 (0)