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.

hrtimer: Convert state and properties to boolean

All 'u8' flags are true booleans, so make it entirely clear that these can
only contain true or false.

This is especially true for hrtimer::state, which has a historical leftover
of using the state with bitwise operations. That was used in the early
hrtimer implementation with several bits, but then converted to a boolean
state. But that conversion missed to replace the bit OR and bit check
operations all over the place, which creates suboptimal code. As of today
'state' is a misnomer because it's only purpose is to reflect whether the
timer is enqueued into the RB-tree or not. Rename it to 'is_queued' and
make all operations on it boolean.

This reduces text size from 8926 to 8732 bytes.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260224163430.542427240@kernel.org

authored by

Thomas Gleixner and committed by
Peter Zijlstra
22f011be 7d27eafe

+49 -54
+2 -29
include/linux/hrtimer.h
··· 63 63 HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD, 64 64 }; 65 65 66 - /* 67 - * Values to track state of the timer 68 - * 69 - * Possible states: 70 - * 71 - * 0x00 inactive 72 - * 0x01 enqueued into rbtree 73 - * 74 - * The callback state is not part of the timer->state because clearing it would 75 - * mean touching the timer after the callback, this makes it impossible to free 76 - * the timer from the callback function. 77 - * 78 - * Therefore we track the callback state in: 79 - * 80 - * timer->base->cpu_base->running == timer 81 - * 82 - * On SMP it is possible to have a "callback function running and enqueued" 83 - * status. It happens for example when a posix timer expired and the callback 84 - * queued a signal. Between dropping the lock which protects the posix timer 85 - * and reacquiring the base lock of the hrtimer, another CPU can deliver the 86 - * signal and rearm the timer. 87 - * 88 - * All state transitions are protected by cpu_base->lock. 89 - */ 90 - #define HRTIMER_STATE_INACTIVE 0x00 91 - #define HRTIMER_STATE_ENQUEUED 0x01 92 - 93 66 /** 94 67 * struct hrtimer_sleeper - simple sleeper structure 95 68 * @timer: embedded timer structure ··· 273 300 */ 274 301 static inline bool hrtimer_is_queued(struct hrtimer *timer) 275 302 { 276 - /* The READ_ONCE pairs with the update functions of timer->state */ 277 - return !!(READ_ONCE(timer->state) & HRTIMER_STATE_ENQUEUED); 303 + /* The READ_ONCE pairs with the update functions of timer->is_queued */ 304 + return READ_ONCE(timer->is_queued); 278 305 } 279 306 280 307 /*
+6 -6
include/linux/hrtimer_types.h
··· 28 28 * was armed. 29 29 * @function: timer expiry callback function 30 30 * @base: pointer to the timer base (per cpu and per clock) 31 - * @state: state information (See bit values above) 31 + * @is_queued: Indicates whether a timer is enqueued or not 32 32 * @is_rel: Set if the timer was armed relative 33 33 * @is_soft: Set if hrtimer will be expired in soft interrupt context. 34 34 * @is_hard: Set if hrtimer will be expired in hard interrupt context ··· 43 43 ktime_t _softexpires; 44 44 enum hrtimer_restart (*__private function)(struct hrtimer *); 45 45 struct hrtimer_clock_base *base; 46 - u8 state; 47 - u8 is_rel; 48 - u8 is_soft; 49 - u8 is_hard; 50 - u8 is_lazy; 46 + bool is_queued; 47 + bool is_rel; 48 + bool is_soft; 49 + bool is_hard; 50 + bool is_lazy; 51 51 }; 52 52 53 53 #endif /* _LINUX_HRTIMER_TYPES_H */
+40 -18
kernel/time/hrtimer.c
··· 50 50 #include "tick-internal.h" 51 51 52 52 /* 53 + * Constants to set the queued state of the timer (INACTIVE, ENQUEUED) 54 + * 55 + * The callback state is kept separate in the CPU base because having it in 56 + * the timer would required touching the timer after the callback, which 57 + * makes it impossible to free the timer from the callback function. 58 + * 59 + * Therefore we track the callback state in: 60 + * 61 + * timer->base->cpu_base->running == timer 62 + * 63 + * On SMP it is possible to have a "callback function running and enqueued" 64 + * status. It happens for example when a posix timer expired and the callback 65 + * queued a signal. Between dropping the lock which protects the posix timer 66 + * and reacquiring the base lock of the hrtimer, another CPU can deliver the 67 + * signal and rearm the timer. 68 + * 69 + * All state transitions are protected by cpu_base->lock. 70 + */ 71 + #define HRTIMER_STATE_INACTIVE false 72 + #define HRTIMER_STATE_ENQUEUED true 73 + 74 + /* 53 75 * The resolution of the clocks. The resolution value is returned in 54 76 * the clock_getres() system call to give application programmers an 55 77 * idea of the (in)accuracy of timers. Timer values are rounded up to ··· 1060 1038 if (delta < 0) 1061 1039 return 0; 1062 1040 1063 - if (WARN_ON(timer->state & HRTIMER_STATE_ENQUEUED)) 1041 + if (WARN_ON(timer->is_queued)) 1064 1042 return 0; 1065 1043 1066 1044 if (interval < hrtimer_resolution) ··· 1104 1082 base->cpu_base->active_bases |= 1 << base->index; 1105 1083 1106 1084 /* Pairs with the lockless read in hrtimer_is_queued() */ 1107 - WRITE_ONCE(timer->state, HRTIMER_STATE_ENQUEUED); 1085 + WRITE_ONCE(timer->is_queued, HRTIMER_STATE_ENQUEUED); 1108 1086 1109 1087 return timerqueue_add(&base->active, &timer->node); 1110 1088 } ··· 1118 1096 * anyway (e.g. timer interrupt) 1119 1097 */ 1120 1098 static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, 1121 - u8 newstate, bool reprogram) 1099 + bool newstate, bool reprogram) 1122 1100 { 1123 1101 struct hrtimer_cpu_base *cpu_base = base->cpu_base; 1124 - u8 state = timer->state; 1125 1102 1126 1103 lockdep_assert_held(&cpu_base->lock); 1127 1104 1128 - /* Pairs with the lockless read in hrtimer_is_queued() */ 1129 - WRITE_ONCE(timer->state, newstate); 1130 - if (!(state & HRTIMER_STATE_ENQUEUED)) 1105 + if (!timer->is_queued) 1131 1106 return; 1107 + 1108 + /* Pairs with the lockless read in hrtimer_is_queued() */ 1109 + WRITE_ONCE(timer->is_queued, newstate); 1132 1110 1133 1111 if (!timerqueue_del(&base->active, &timer->node)) 1134 1112 cpu_base->active_bases &= ~(1 << base->index); ··· 1149 1127 static inline bool remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, 1150 1128 bool restart, bool keep_local) 1151 1129 { 1152 - u8 state = timer->state; 1130 + bool queued_state = timer->is_queued; 1153 1131 1154 1132 lockdep_assert_held(&base->cpu_base->lock); 1155 1133 1156 - if (state & HRTIMER_STATE_ENQUEUED) { 1134 + if (queued_state) { 1157 1135 bool reprogram; 1158 1136 1159 1137 debug_hrtimer_deactivate(timer); ··· 1175 1153 * and a moment later when it's requeued). 1176 1154 */ 1177 1155 if (!restart) 1178 - state = HRTIMER_STATE_INACTIVE; 1156 + queued_state = HRTIMER_STATE_INACTIVE; 1179 1157 else 1180 1158 reprogram &= !keep_local; 1181 1159 1182 - __remove_hrtimer(timer, base, state, reprogram); 1160 + __remove_hrtimer(timer, base, queued_state, reprogram); 1183 1161 return true; 1184 1162 } 1185 1163 return false; ··· 1726 1704 base = READ_ONCE(timer->base); 1727 1705 seq = raw_read_seqcount_begin(&base->seq); 1728 1706 1729 - if (timer->state != HRTIMER_STATE_INACTIVE || base->running == timer) 1707 + if (timer->is_queued || base->running == timer) 1730 1708 return true; 1731 1709 1732 1710 } while (read_seqcount_retry(&base->seq, seq) || base != READ_ONCE(timer->base)); ··· 1743 1721 * - callback: the timer is being ran 1744 1722 * - post: the timer is inactive or (re)queued 1745 1723 * 1746 - * On the read side we ensure we observe timer->state and cpu_base->running 1724 + * On the read side we ensure we observe timer->is_queued and cpu_base->running 1747 1725 * from the same section, if anything changed while we looked at it, we retry. 1748 1726 * This includes timer->base changing because sequence numbers alone are 1749 1727 * insufficient for that. ··· 1766 1744 base->running = timer; 1767 1745 1768 1746 /* 1769 - * Separate the ->running assignment from the ->state assignment. 1747 + * Separate the ->running assignment from the ->is_queued assignment. 1770 1748 * 1771 1749 * As with a regular write barrier, this ensures the read side in 1772 1750 * hrtimer_active() cannot observe base->running == NULL && 1773 - * timer->state == INACTIVE. 1751 + * timer->is_queued == INACTIVE. 1774 1752 */ 1775 1753 raw_write_seqcount_barrier(&base->seq); 1776 1754 ··· 1809 1787 * hrtimer_start_range_ns() can have popped in and enqueued the timer 1810 1788 * for us already. 1811 1789 */ 1812 - if (restart != HRTIMER_NORESTART && !(timer->state & HRTIMER_STATE_ENQUEUED)) 1790 + if (restart == HRTIMER_RESTART && !timer->is_queued) 1813 1791 enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS, false); 1814 1792 1815 1793 /* 1816 - * Separate the ->running assignment from the ->state assignment. 1794 + * Separate the ->running assignment from the ->is_queued assignment. 1817 1795 * 1818 1796 * As with a regular write barrier, this ensures the read side in 1819 1797 * hrtimer_active() cannot observe base->running.timer == NULL && 1820 - * timer->state == INACTIVE. 1798 + * timer->is_queued == INACTIVE. 1821 1799 */ 1822 1800 raw_write_seqcount_barrier(&base->seq); 1823 1801
+1 -1
kernel/time/timer_list.c
··· 47 47 int idx, u64 now) 48 48 { 49 49 SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, ACCESS_PRIVATE(timer, function)); 50 - SEQ_printf(m, ", S:%02x", timer->state); 50 + SEQ_printf(m, ", S:%02x", timer->is_queued); 51 51 SEQ_printf(m, "\n"); 52 52 SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n", 53 53 (unsigned long long)ktime_to_ns(hrtimer_get_softexpires(timer)),