Skip to content

Commit f286757

Browse files
committed
Merge tag 'timers-urgent-2025-02-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner: - Properly cast the input to secs_to_jiffies() to unsigned long as otherwise the result uses the data type of the input variable, which causes result range checks to fail if the input data type is signed and smaller than unsigned long. - Handle late armed hrtimers gracefully on CPU hotplug There are legitimate cases where a hrtimer is (re)armed on an outgoing CPU after the timers have been migrated away. This triggers warnings and caused people to implement horrible workarounds in RCU. But those workarounds are incomplete and do not cover e.g. the scheduler hrtimers. Stop this by force moving timer which are enqueued on the current CPU after timer migration to be queued on a remote online CPU. This allows to undo the workarounds in a seperate step. - Demote a warning level printk() to info level in the clocksource watchdog code as there is no point to emit a warning level message for a purely informational message. - Mark a helper function __always_inline and move it into the existing #ifdef block to avoid 'unused function' warnings from CLANG * tag 'timers-urgent-2025-02-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: jiffies: Cast to unsigned long in secs_to_jiffies() conversion clocksource: Use pr_info() for "Checking clocksource synchronization" message hrtimers: Force migrate away hrtimers queued after CPUHP_AP_HRTIMERS_DYING hrtimers: Mark is_migration_base() with __always_inline
2 parents a360f3f + bb2784d commit f286757

File tree

4 files changed

+98
-33
lines changed

4 files changed

+98
-33
lines changed

include/linux/hrtimer_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct hrtimer_cpu_base {
125125
ktime_t softirq_expires_next;
126126
struct hrtimer *softirq_next_timer;
127127
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
128+
call_single_data_t csd;
128129
} ____cacheline_aligned;
129130

130131

include/linux/jiffies.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ static __always_inline unsigned long msecs_to_jiffies(const unsigned int m)
537537
*
538538
* Return: jiffies value
539539
*/
540-
#define secs_to_jiffies(_secs) ((_secs) * HZ)
540+
#define secs_to_jiffies(_secs) (unsigned long)((_secs) * HZ)
541541

542542
extern unsigned long __usecs_to_jiffies(const unsigned int u);
543543
#if !(USEC_PER_SEC % HZ)

kernel/time/clocksource.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ void clocksource_verify_percpu(struct clocksource *cs)
382382
return;
383383
}
384384
testcpu = smp_processor_id();
385-
pr_warn("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n", cs->name, testcpu, cpumask_pr_args(&cpus_chosen));
385+
pr_info("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n",
386+
cs->name, testcpu, cpumask_pr_args(&cpus_chosen));
386387
for_each_cpu(cpu, &cpus_chosen) {
387388
if (cpu == testcpu)
388389
continue;

kernel/time/hrtimer.c

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
#define HRTIMER_ACTIVE_SOFT (HRTIMER_ACTIVE_HARD << MASK_SHIFT)
5959
#define HRTIMER_ACTIVE_ALL (HRTIMER_ACTIVE_SOFT | HRTIMER_ACTIVE_HARD)
6060

61+
static void retrigger_next_event(void *arg);
62+
6163
/*
6264
* The timer bases:
6365
*
@@ -111,7 +113,8 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
111113
.clockid = CLOCK_TAI,
112114
.get_time = &ktime_get_clocktai,
113115
},
114-
}
116+
},
117+
.csd = CSD_INIT(retrigger_next_event, NULL)
115118
};
116119

117120
static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
@@ -124,6 +127,14 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
124127
[CLOCK_TAI] = HRTIMER_BASE_TAI,
125128
};
126129

130+
static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base)
131+
{
132+
if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
133+
return true;
134+
else
135+
return likely(base->online);
136+
}
137+
127138
/*
128139
* Functions and macros which are different for UP/SMP systems are kept in a
129140
* single place
@@ -145,11 +156,6 @@ static struct hrtimer_cpu_base migration_cpu_base = {
145156

146157
#define migration_base migration_cpu_base.clock_base[0]
147158

148-
static inline bool is_migration_base(struct hrtimer_clock_base *base)
149-
{
150-
return base == &migration_base;
151-
}
152-
153159
/*
154160
* We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
155161
* means that all timers which are tied to this base via timer->base are
@@ -183,27 +189,54 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
183189
}
184190

185191
/*
186-
* We do not migrate the timer when it is expiring before the next
187-
* event on the target cpu. When high resolution is enabled, we cannot
188-
* reprogram the target cpu hardware and we would cause it to fire
189-
* late. To keep it simple, we handle the high resolution enabled and
190-
* disabled case similar.
192+
* Check if the elected target is suitable considering its next
193+
* event and the hotplug state of the current CPU.
194+
*
195+
* If the elected target is remote and its next event is after the timer
196+
* to queue, then a remote reprogram is necessary. However there is no
197+
* guarantee the IPI handling the operation would arrive in time to meet
198+
* the high resolution deadline. In this case the local CPU becomes a
199+
* preferred target, unless it is offline.
200+
*
201+
* High and low resolution modes are handled the same way for simplicity.
191202
*
192203
* Called with cpu_base->lock of target cpu held.
193204
*/
194-
static int
195-
hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
205+
static bool hrtimer_suitable_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base,
206+
struct hrtimer_cpu_base *new_cpu_base,
207+
struct hrtimer_cpu_base *this_cpu_base)
196208
{
197209
ktime_t expires;
198210

211+
/*
212+
* The local CPU clockevent can be reprogrammed. Also get_target_base()
213+
* guarantees it is online.
214+
*/
215+
if (new_cpu_base == this_cpu_base)
216+
return true;
217+
218+
/*
219+
* The offline local CPU can't be the default target if the
220+
* next remote target event is after this timer. Keep the
221+
* elected new base. An IPI will we issued to reprogram
222+
* it as a last resort.
223+
*/
224+
if (!hrtimer_base_is_online(this_cpu_base))
225+
return true;
226+
199227
expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
200-
return expires < new_base->cpu_base->expires_next;
228+
229+
return expires >= new_base->cpu_base->expires_next;
201230
}
202231

203-
static inline
204-
struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
205-
int pinned)
232+
static inline struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, int pinned)
206233
{
234+
if (!hrtimer_base_is_online(base)) {
235+
int cpu = cpumask_any_and(cpu_online_mask, housekeeping_cpumask(HK_TYPE_TIMER));
236+
237+
return &per_cpu(hrtimer_bases, cpu);
238+
}
239+
207240
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
208241
if (static_branch_likely(&timers_migration_enabled) && !pinned)
209242
return &per_cpu(hrtimer_bases, get_nohz_timer_target());
@@ -254,8 +287,8 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
254287
raw_spin_unlock(&base->cpu_base->lock);
255288
raw_spin_lock(&new_base->cpu_base->lock);
256289

257-
if (new_cpu_base != this_cpu_base &&
258-
hrtimer_check_target(timer, new_base)) {
290+
if (!hrtimer_suitable_target(timer, new_base, new_cpu_base,
291+
this_cpu_base)) {
259292
raw_spin_unlock(&new_base->cpu_base->lock);
260293
raw_spin_lock(&base->cpu_base->lock);
261294
new_cpu_base = this_cpu_base;
@@ -264,8 +297,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
264297
}
265298
WRITE_ONCE(timer->base, new_base);
266299
} else {
267-
if (new_cpu_base != this_cpu_base &&
268-
hrtimer_check_target(timer, new_base)) {
300+
if (!hrtimer_suitable_target(timer, new_base, new_cpu_base, this_cpu_base)) {
269301
new_cpu_base = this_cpu_base;
270302
goto again;
271303
}
@@ -275,11 +307,6 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
275307

276308
#else /* CONFIG_SMP */
277309

278-
static inline bool is_migration_base(struct hrtimer_clock_base *base)
279-
{
280-
return false;
281-
}
282-
283310
static inline struct hrtimer_clock_base *
284311
lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
285312
__acquires(&timer->base->cpu_base->lock)
@@ -716,8 +743,6 @@ static inline int hrtimer_is_hres_enabled(void)
716743
return hrtimer_hres_enabled;
717744
}
718745

719-
static void retrigger_next_event(void *arg);
720-
721746
/*
722747
* Switch to high resolution mode
723748
*/
@@ -1205,6 +1230,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12051230
u64 delta_ns, const enum hrtimer_mode mode,
12061231
struct hrtimer_clock_base *base)
12071232
{
1233+
struct hrtimer_cpu_base *this_cpu_base = this_cpu_ptr(&hrtimer_bases);
12081234
struct hrtimer_clock_base *new_base;
12091235
bool force_local, first;
12101236

@@ -1216,9 +1242,15 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12161242
* and enforce reprogramming after it is queued no matter whether
12171243
* it is the new first expiring timer again or not.
12181244
*/
1219-
force_local = base->cpu_base == this_cpu_ptr(&hrtimer_bases);
1245+
force_local = base->cpu_base == this_cpu_base;
12201246
force_local &= base->cpu_base->next_timer == timer;
12211247

1248+
/*
1249+
* Don't force local queuing if this enqueue happens on a unplugged
1250+
* CPU after hrtimer_cpu_dying() has been invoked.
1251+
*/
1252+
force_local &= this_cpu_base->online;
1253+
12221254
/*
12231255
* Remove an active timer from the queue. In case it is not queued
12241256
* on the current CPU, make sure that remove_hrtimer() updates the
@@ -1248,8 +1280,27 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12481280
}
12491281

12501282
first = enqueue_hrtimer(timer, new_base, mode);
1251-
if (!force_local)
1252-
return first;
1283+
if (!force_local) {
1284+
/*
1285+
* If the current CPU base is online, then the timer is
1286+
* never queued on a remote CPU if it would be the first
1287+
* expiring timer there.
1288+
*/
1289+
if (hrtimer_base_is_online(this_cpu_base))
1290+
return first;
1291+
1292+
/*
1293+
* Timer was enqueued remote because the current base is
1294+
* already offline. If the timer is the first to expire,
1295+
* kick the remote CPU to reprogram the clock event.
1296+
*/
1297+
if (first) {
1298+
struct hrtimer_cpu_base *new_cpu_base = new_base->cpu_base;
1299+
1300+
smp_call_function_single_async(new_cpu_base->cpu, &new_cpu_base->csd);
1301+
}
1302+
return 0;
1303+
}
12531304

12541305
/*
12551306
* Timer was forced to stay on the current CPU to avoid
@@ -1370,6 +1421,18 @@ static void hrtimer_sync_wait_running(struct hrtimer_cpu_base *cpu_base,
13701421
}
13711422
}
13721423

1424+
#ifdef CONFIG_SMP
1425+
static __always_inline bool is_migration_base(struct hrtimer_clock_base *base)
1426+
{
1427+
return base == &migration_base;
1428+
}
1429+
#else
1430+
static __always_inline bool is_migration_base(struct hrtimer_clock_base *base)
1431+
{
1432+
return false;
1433+
}
1434+
#endif
1435+
13731436
/*
13741437
* This function is called on PREEMPT_RT kernels when the fast path
13751438
* deletion of a timer failed because the timer callback function was

0 commit comments

Comments
 (0)