aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-05 21:01:45 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-09-06 01:21:17 -0400
commit7300711e8c6824fcfbd42a126980ff50439d8dd0 (patch)
tree20183d1ce4fa8237042644b2a79fbf01471da18d /kernel/time/tick-broadcast.c
parent7cfb0435330364f90f274a26ecdc5f47f738498c (diff)
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 <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 2bc1f046151c..2f5a38294bf9 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -491,6 +491,18 @@ static void tick_broadcast_clear_oneshot(int cpu)
491 cpu_clear(cpu, tick_broadcast_oneshot_mask); 491 cpu_clear(cpu, tick_broadcast_oneshot_mask);
492} 492}
493 493
494static 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
494/** 506/**
495 * tick_broadcast_setup_oneshot - setup the broadcast device 507 * tick_broadcast_setup_oneshot - setup the broadcast device
496 */ 508 */
@@ -498,9 +510,32 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
498{ 510{
499 /* Set it up only once ! */ 511 /* Set it up only once ! */
500 if (bc->event_handler != tick_handle_oneshot_broadcast) { 512 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
501 bc->event_handler = tick_handle_oneshot_broadcast; 517 bc->event_handler = tick_handle_oneshot_broadcast;
502 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); 518 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;
504 } 539 }
505} 540}
506 541