Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe2ae32a authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Greg Kroah-Hartman
Browse files

nohz: Add TICK_DEP_BIT_RCU



[ Upstream commit 01b4c39901e087ceebae2733857248de81476bd8 ]

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: default avatarFrederic Weisbecker <frederic@kernel.org>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
Stable-dep-of: 58d766824264 ("tick/nohz: Fix cpu_is_hotpluggable() by checking with nohz subsystem")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent c6989314
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -102,7 +102,8 @@ enum tick_dep_bits {
	TICK_DEP_BIT_POSIX_TIMER	= 0,
	TICK_DEP_BIT_POSIX_TIMER	= 0,
	TICK_DEP_BIT_PERF_EVENTS	= 1,
	TICK_DEP_BIT_PERF_EVENTS	= 1,
	TICK_DEP_BIT_SCHED		= 2,
	TICK_DEP_BIT_SCHED		= 2,
	TICK_DEP_BIT_CLOCK_UNSTABLE	= 3
	TICK_DEP_BIT_CLOCK_UNSTABLE	= 3,
	TICK_DEP_BIT_RCU		= 4
};
};


#define TICK_DEP_MASK_NONE		0
#define TICK_DEP_MASK_NONE		0
@@ -110,6 +111,7 @@ enum tick_dep_bits {
#define TICK_DEP_MASK_PERF_EVENTS	(1 << TICK_DEP_BIT_PERF_EVENTS)
#define TICK_DEP_MASK_PERF_EVENTS	(1 << TICK_DEP_BIT_PERF_EVENTS)
#define TICK_DEP_MASK_SCHED		(1 << TICK_DEP_BIT_SCHED)
#define TICK_DEP_MASK_SCHED		(1 << TICK_DEP_BIT_SCHED)
#define TICK_DEP_MASK_CLOCK_UNSTABLE	(1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
#define TICK_DEP_MASK_CLOCK_UNSTABLE	(1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
#define TICK_DEP_MASK_RCU		(1 << TICK_DEP_BIT_RCU)


#ifdef CONFIG_NO_HZ_COMMON
#ifdef CONFIG_NO_HZ_COMMON
extern bool tick_nohz_enabled;
extern bool tick_nohz_enabled;
@@ -257,6 +259,9 @@ static inline bool tick_nohz_full_enabled(void) { return false; }
static inline bool tick_nohz_full_cpu(int cpu) { return false; }
static inline bool tick_nohz_full_cpu(int cpu) { return false; }
static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }


static inline void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
static inline void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }

static inline void tick_dep_set(enum tick_dep_bits bit) { }
static inline void tick_dep_set(enum tick_dep_bits bit) { }
static inline void tick_dep_clear(enum tick_dep_bits bit) { }
static inline void tick_dep_clear(enum tick_dep_bits bit) { }
static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
+2 −1
Original line number Original line Diff line number Diff line
@@ -362,7 +362,8 @@ TRACE_EVENT(itimer_expire,
		tick_dep_name(POSIX_TIMER)		\
		tick_dep_name(POSIX_TIMER)		\
		tick_dep_name(PERF_EVENTS)		\
		tick_dep_name(PERF_EVENTS)		\
		tick_dep_name(SCHED)			\
		tick_dep_name(SCHED)			\
		tick_dep_name_end(CLOCK_UNSTABLE)
		tick_dep_name(CLOCK_UNSTABLE)		\
		tick_dep_name_end(RCU)


#undef tick_dep_name
#undef tick_dep_name
#undef tick_dep_mask_name
#undef tick_dep_mask_name
+7 −0
Original line number Original line Diff line number Diff line
@@ -199,6 +199,11 @@ static bool check_tick_dependency(atomic_t *dep)
		return true;
		return true;
	}
	}


	if (val & TICK_DEP_MASK_RCU) {
		trace_tick_stop(0, TICK_DEP_MASK_RCU);
		return true;
	}

	return false;
	return false;
}
}


@@ -325,6 +330,7 @@ void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit)
		preempt_enable();
		preempt_enable();
	}
	}
}
}
EXPORT_SYMBOL_GPL(tick_nohz_dep_set_cpu);


void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
{
{
@@ -332,6 +338,7 @@ void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)


	atomic_andnot(BIT(bit), &ts->tick_dep_mask);
	atomic_andnot(BIT(bit), &ts->tick_dep_mask);
}
}
EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu);


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