Skip to content

Commit 7300711

Browse files
committed
clockevents: broadcast fixup possible waiters
Until the C1E patches arrived there where no users of periodic broadcast before switching to oneshot mode. Now we need to trigger a possible waiter for a periodic broadcast when switching to oneshot mode. Otherwise we can starve them for ever. Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 7cfb043 commit 7300711

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

kernel/time/tick-broadcast.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,16 +491,51 @@ static void tick_broadcast_clear_oneshot(int cpu)
491491
cpu_clear(cpu, tick_broadcast_oneshot_mask);
492492
}
493493

494+
static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
495+
{
496+
struct tick_device *td;
497+
int cpu;
498+
499+
for_each_cpu_mask_nr(cpu, *mask) {
500+
td = &per_cpu(tick_cpu_device, cpu);
501+
if (td->evtdev)
502+
td->evtdev->next_event = expires;
503+
}
504+
}
505+
494506
/**
495507
* tick_broadcast_setup_oneshot - setup the broadcast device
496508
*/
497509
void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
498510
{
499511
/* Set it up only once ! */
500512
if (bc->event_handler != tick_handle_oneshot_broadcast) {
513+
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
514+
int cpu = smp_processor_id();
515+
cpumask_t mask;
516+
501517
bc->event_handler = tick_handle_oneshot_broadcast;
502518
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
503-
bc->next_event.tv64 = KTIME_MAX;
519+
520+
/* Take the do_timer update */
521+
tick_do_timer_cpu = cpu;
522+
523+
/*
524+
* We must be careful here. There might be other CPUs
525+
* waiting for periodic broadcast. We need to set the
526+
* oneshot_mask bits for those and program the
527+
* broadcast device to fire.
528+
*/
529+
mask = tick_broadcast_mask;
530+
cpu_clear(cpu, mask);
531+
cpus_or(tick_broadcast_oneshot_mask,
532+
tick_broadcast_oneshot_mask, mask);
533+
534+
if (was_periodic && !cpus_empty(mask)) {
535+
tick_broadcast_init_next_event(&mask, tick_next_period);
536+
tick_broadcast_set_event(tick_next_period, 1);
537+
} else
538+
bc->next_event.tv64 = KTIME_MAX;
504539
}
505540
}
506541

0 commit comments

Comments
 (0)