Commit ff5a6a35 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

Merge branch 'timers/urgent' of...

Merge branch 'timers/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into timers/urgent

Pull dyntick fixes from Frederic Weisbecker:

  - Fix a rearm race in the posix cpu timer code
  - Handle get_next_timer_interrupt() correctly when no timers are pending

Link: https://lore.kernel.org/r/20210715104218.81276-1-frederic@kernel.org
parents 2734d6c1 aebacb7f
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -991,6 +991,11 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
	if (!p)
		goto out;

	/* Protect timer list r/w in arm_timer() */
	sighand = lock_task_sighand(p, &flags);
	if (unlikely(sighand == NULL))
		goto out;

	/*
	 * Fetch the current sample and update the timer's expiry time.
	 */
@@ -1001,11 +1006,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)

	bump_cpu_timer(timer, now);

	/* Protect timer list r/w in arm_timer() */
	sighand = lock_task_sighand(p, &flags);
	if (unlikely(sighand == NULL))
		goto out;

	/*
	 * Now re-arm for the new expiry time.
	 */
+5 −3
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ struct timer_base {
	unsigned int		cpu;
	bool			next_expiry_recalc;
	bool			is_idle;
	bool			timers_pending;
	DECLARE_BITMAP(pending_map, WHEEL_SIZE);
	struct hlist_head	vectors[WHEEL_SIZE];
} ____cacheline_aligned;
@@ -595,6 +596,7 @@ static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
		 * can reevaluate the wheel:
		 */
		base->next_expiry = bucket_expiry;
		base->timers_pending = true;
		base->next_expiry_recalc = false;
		trigger_dyntick_cpu(base, timer);
	}
@@ -1582,6 +1584,7 @@ static unsigned long __next_timer_interrupt(struct timer_base *base)
	}

	base->next_expiry_recalc = false;
	base->timers_pending = !(next == base->clk + NEXT_TIMER_MAX_DELTA);

	return next;
}
@@ -1633,7 +1636,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
	struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
	u64 expires = KTIME_MAX;
	unsigned long nextevt;
	bool is_max_delta;

	/*
	 * Pretend that there is no timer pending if the cpu is offline.
@@ -1646,7 +1648,6 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
	if (base->next_expiry_recalc)
		base->next_expiry = __next_timer_interrupt(base);
	nextevt = base->next_expiry;
	is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);

	/*
	 * We have a fresh next event. Check whether we can forward the
@@ -1664,7 +1665,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
		expires = basem;
		base->is_idle = false;
	} else {
		if (!is_max_delta)
		if (base->timers_pending)
			expires = basem + (u64)(nextevt - basej) * TICK_NSEC;
		/*
		 * If we expect to sleep more than a tick, mark the base idle.
@@ -1947,6 +1948,7 @@ int timers_prepare_cpu(unsigned int cpu)
		base = per_cpu_ptr(&timer_bases[b], cpu);
		base->clk = jiffies;
		base->next_expiry = base->clk + NEXT_TIMER_MAX_DELTA;
		base->timers_pending = false;
		base->is_idle = false;
	}
	return 0;