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

Commit 451bc6e4 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sched: Add a check for cpu unbound deferrable timers"

parents c55966ac 86a84d6b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -190,6 +190,9 @@ extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);

extern void set_timer_slack(struct timer_list *time, int slack_hz);
#ifdef CONFIG_SMP
extern bool check_pending_deferrable_timers(int cpu);
#endif

#define TIMER_NOT_PINNED	0
#define TIMER_PINNED		1
+6 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/irq_work.h>
#include <linux/posix-timers.h>
@@ -829,6 +830,11 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts)

	now = tick_nohz_start_idle(ts);

#ifdef CONFIG_SMP
	if (check_pending_deferrable_timers(cpu))
		raise_softirq_irqoff(TIMER_SOFTIRQ);
#endif

	if (can_stop_idle_tick(cpu, ts)) {
		int was_stopped = ts->tick_stopped;

+32 −3
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ EXPORT_SYMBOL(boot_tvec_bases);
static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
#ifdef CONFIG_SMP
struct tvec_base tvec_base_deferrable;
static atomic_t deferrable_pending;
#endif

static inline void __run_timers(struct tvec_base *base);
@@ -676,9 +677,13 @@ static inline bool is_deferrable_timer_base(struct tvec_base *base)

static inline void __run_deferrable_timers(void)
{
	if (smp_processor_id() == tick_do_timer_cpu &&
	    time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies))
	if (time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies)) {
		if ((atomic_cmpxchg(&deferrable_pending, 1, 0) &&
			tick_do_timer_cpu == TICK_DO_TIMER_NONE) ||
			tick_do_timer_cpu == smp_processor_id())
				__run_timers(&tvec_base_deferrable);

	}
}

static inline void init_deferrable_timer(void)
@@ -1402,6 +1407,30 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
	return expires;
}

#ifdef CONFIG_SMP
/*
 * check_pending_deferrable_timers - Check for unbound deferrable timer expiry.
 * @cpu - Current CPU
 *
 * The function checks whether any global deferrable pending timers
 * are exipired or not. This function does not check cpu bounded
 * diferrable pending timers expiry.
 *
 * The function returns true when a cpu unbounded deferrable timer is expired.
 */
bool check_pending_deferrable_timers(int cpu)
{
	if (cpu == tick_do_timer_cpu ||
		tick_do_timer_cpu == TICK_DO_TIMER_NONE) {
		if (time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies)
			&& !atomic_cmpxchg(&deferrable_pending, 0, 1)) {
				return true;
		}
	}
	return false;
}
#endif

/**
 * get_next_timer_interrupt - return the jiffy of the next pending timer
 * @now: current time (in jiffies)