Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+10 -8
+5 -5
kernel/time/posix-cpu-timers.c
··· 991 991 if (!p) 992 992 goto out; 993 993 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 + 994 999 /* 995 1000 * Fetch the current sample and update the timer's expiry time. 996 1001 */ ··· 1005 1000 now = cpu_clock_sample_group(clkid, p, true); 1006 1001 1007 1002 bump_cpu_timer(timer, now); 1008 - 1009 - /* Protect timer list r/w in arm_timer() */ 1010 - sighand = lock_task_sighand(p, &flags); 1011 - if (unlikely(sighand == NULL)) 1012 - goto out; 1013 1003 1014 1004 /* 1015 1005 * Now re-arm for the new expiry time.
+5 -3
kernel/time/timer.c
··· 207 207 unsigned int cpu; 208 208 bool next_expiry_recalc; 209 209 bool is_idle; 210 + bool timers_pending; 210 211 DECLARE_BITMAP(pending_map, WHEEL_SIZE); 211 212 struct hlist_head vectors[WHEEL_SIZE]; 212 213 } ____cacheline_aligned; ··· 596 595 * can reevaluate the wheel: 597 596 */ 598 597 base->next_expiry = bucket_expiry; 598 + base->timers_pending = true; 599 599 base->next_expiry_recalc = false; 600 600 trigger_dyntick_cpu(base, timer); 601 601 } ··· 1584 1582 } 1585 1583 1586 1584 base->next_expiry_recalc = false; 1585 + base->timers_pending = !(next == base->clk + NEXT_TIMER_MAX_DELTA); 1587 1586 1588 1587 return next; 1589 1588 } ··· 1636 1633 struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); 1637 1634 u64 expires = KTIME_MAX; 1638 1635 unsigned long nextevt; 1639 - bool is_max_delta; 1640 1636 1641 1637 /* 1642 1638 * Pretend that there is no timer pending if the cpu is offline. ··· 1648 1646 if (base->next_expiry_recalc) 1649 1647 base->next_expiry = __next_timer_interrupt(base); 1650 1648 nextevt = base->next_expiry; 1651 - is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA); 1652 1649 1653 1650 /* 1654 1651 * We have a fresh next event. Check whether we can forward the ··· 1665 1664 expires = basem; 1666 1665 base->is_idle = false; 1667 1666 } else { 1668 - if (!is_max_delta) 1667 + if (base->timers_pending) 1669 1668 expires = basem + (u64)(nextevt - basej) * TICK_NSEC; 1670 1669 /* 1671 1670 * If we expect to sleep more than a tick, mark the base idle. ··· 1948 1947 base = per_cpu_ptr(&timer_bases[b], cpu); 1949 1948 base->clk = jiffies; 1950 1949 base->next_expiry = base->clk + NEXT_TIMER_MAX_DELTA; 1950 + base->timers_pending = false; 1951 1951 base->is_idle = false; 1952 1952 } 1953 1953 return 0;