Skip to content

Commit 01b4c39

Browse files
Frederic Weisbeckerpaulmckrcu
authored andcommitted
nohz: Add TICK_DEP_BIT_RCU
If a nohz_full CPU is looping in the kernel, the scheduling-clock tick might nevertheless remain disabled. In !PREEMPT kernels, this can prevent RCU's attempts to enlist the aid of that CPU's executions of cond_resched(), which can in turn result in an arbitrarily delayed grace period and thus an OOM. RCU therefore needs a way to enable a holdout nohz_full CPU's scheduler-clock interrupt. This commit therefore provides a new TICK_DEP_BIT_RCU value which RCU can pass to tick_dep_set_cpu() and friends to force on the scheduler-clock interrupt for a specified CPU or task. In some cases, rcutorture needs to turn on the scheduler-clock tick, so this commit also exports the relevant symbols to GPL-licensed modules. Signed-off-by: Frederic Weisbecker <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 54ecb8f commit 01b4c39

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

include/linux/tick.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,16 @@ enum tick_dep_bits {
108108
TICK_DEP_BIT_POSIX_TIMER = 0,
109109
TICK_DEP_BIT_PERF_EVENTS = 1,
110110
TICK_DEP_BIT_SCHED = 2,
111-
TICK_DEP_BIT_CLOCK_UNSTABLE = 3
111+
TICK_DEP_BIT_CLOCK_UNSTABLE = 3,
112+
TICK_DEP_BIT_RCU = 4
112113
};
113114

114115
#define TICK_DEP_MASK_NONE 0
115116
#define TICK_DEP_MASK_POSIX_TIMER (1 << TICK_DEP_BIT_POSIX_TIMER)
116117
#define TICK_DEP_MASK_PERF_EVENTS (1 << TICK_DEP_BIT_PERF_EVENTS)
117118
#define TICK_DEP_MASK_SCHED (1 << TICK_DEP_BIT_SCHED)
118119
#define TICK_DEP_MASK_CLOCK_UNSTABLE (1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
120+
#define TICK_DEP_MASK_RCU (1 << TICK_DEP_BIT_RCU)
119121

120122
#ifdef CONFIG_NO_HZ_COMMON
121123
extern bool tick_nohz_enabled;
@@ -268,6 +270,9 @@ static inline bool tick_nohz_full_enabled(void) { return false; }
268270
static inline bool tick_nohz_full_cpu(int cpu) { return false; }
269271
static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
270272

273+
static inline void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
274+
static inline void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }
275+
271276
static inline void tick_dep_set(enum tick_dep_bits bit) { }
272277
static inline void tick_dep_clear(enum tick_dep_bits bit) { }
273278
static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }

include/trace/events/timer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ TRACE_EVENT(itimer_expire,
367367
tick_dep_name(POSIX_TIMER) \
368368
tick_dep_name(PERF_EVENTS) \
369369
tick_dep_name(SCHED) \
370-
tick_dep_name_end(CLOCK_UNSTABLE)
370+
tick_dep_name(CLOCK_UNSTABLE) \
371+
tick_dep_name_end(RCU)
371372

372373
#undef tick_dep_name
373374
#undef tick_dep_mask_name

kernel/time/tick-sched.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ static bool check_tick_dependency(atomic_t *dep)
198198
return true;
199199
}
200200

201+
if (val & TICK_DEP_MASK_RCU) {
202+
trace_tick_stop(0, TICK_DEP_MASK_RCU);
203+
return true;
204+
}
205+
201206
return false;
202207
}
203208

@@ -324,13 +329,15 @@ void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit)
324329
preempt_enable();
325330
}
326331
}
332+
EXPORT_SYMBOL_GPL(tick_nohz_dep_set_cpu);
327333

328334
void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
329335
{
330336
struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
331337

332338
atomic_andnot(BIT(bit), &ts->tick_dep_mask);
333339
}
340+
EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu);
334341

335342
/*
336343
* Set a per-task tick dependency. Posix CPU timers need this in order to elapse

0 commit comments

Comments
 (0)