Skip to content

Commit 2d44ae4

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
hrtimer: clean up cpu->base locking tricks
In order to more easily allow for the scheduler to use timers, clean up the locking a bit. Signed-off-by: Peter Zijlstra <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 48d5e25 commit 2d44ae4

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

kernel/hrtimer.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,9 @@ void hrtimer_interrupt(struct clock_event_device *dev)
10631063
basenow = ktime_add(now, base->offset);
10641064

10651065
while ((node = base->first)) {
1066+
enum hrtimer_restart (*fn)(struct hrtimer *);
10661067
struct hrtimer *timer;
1068+
int restart;
10671069

10681070
timer = rb_entry(node, struct hrtimer, node);
10691071

@@ -1091,13 +1093,29 @@ void hrtimer_interrupt(struct clock_event_device *dev)
10911093
HRTIMER_STATE_CALLBACK, 0);
10921094
timer_stats_account_hrtimer(timer);
10931095

1096+
fn = timer->function;
1097+
if (timer->cb_mode == HRTIMER_CB_IRQSAFE_NO_SOFTIRQ) {
1098+
/*
1099+
* Used for scheduler timers, avoid lock
1100+
* inversion with rq->lock and tasklist_lock.
1101+
*
1102+
* These timers are required to deal with
1103+
* enqueue expiry themselves and are not
1104+
* allowed to migrate.
1105+
*/
1106+
spin_unlock(&cpu_base->lock);
1107+
restart = fn(timer);
1108+
spin_lock(&cpu_base->lock);
1109+
} else
1110+
restart = fn(timer);
1111+
10941112
/*
10951113
* Note: We clear the CALLBACK bit after
10961114
* enqueue_hrtimer to avoid reprogramming of
10971115
* the event hardware. This happens at the end
10981116
* of this function anyway.
10991117
*/
1100-
if (timer->function(timer) != HRTIMER_NORESTART) {
1118+
if (restart != HRTIMER_NORESTART) {
11011119
BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
11021120
enqueue_hrtimer(timer, base, 0);
11031121
}

kernel/time/tick-sched.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
514514
{
515515
struct tick_sched *ts =
516516
container_of(timer, struct tick_sched, sched_timer);
517-
struct hrtimer_cpu_base *base = timer->base->cpu_base;
518517
struct pt_regs *regs = get_irq_regs();
519518
ktime_t now = ktime_get();
520519
int cpu = smp_processor_id();
@@ -552,15 +551,8 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
552551
touch_softlockup_watchdog();
553552
ts->idle_jiffies++;
554553
}
555-
/*
556-
* update_process_times() might take tasklist_lock, hence
557-
* drop the base lock. sched-tick hrtimers are per-CPU and
558-
* never accessible by userspace APIs, so this is safe to do.
559-
*/
560-
spin_unlock(&base->lock);
561554
update_process_times(user_mode(regs));
562555
profile_tick(CPU_PROFILING);
563-
spin_lock(&base->lock);
564556
}
565557

566558
/* Do not restart, when we are in the idle loop */

0 commit comments

Comments
 (0)