aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2011-08-27 09:43:54 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2011-08-27 10:06:11 -0400
commit7b1bb388bc879ffcc6c69b567816d5c354afe42b (patch)
tree5a217fdfb0b5e5a327bdcd624506337c1ae1fe32 /kernel/time/tick-broadcast.c
parent7d754596756240fa918b94cd0c3011c77a638987 (diff)
parent02f8c6aee8df3cdc935e9bdd4f2d020306035dbe (diff)
Merge 'Linux v3.0' into Litmus
Some notes: * Litmus^RT scheduling class is the topmost scheduling class (above stop_sched_class). * scheduler_ipi() function (e.g., in smp_reschedule_interrupt()) may increase IPI latencies. * Added path into schedule() to quickly re-evaluate scheduling decision without becoming preemptive again. This used to be a standard path before the removal of BKL. Conflicts: Makefile arch/arm/kernel/calls.S arch/arm/kernel/smp.c arch/x86/include/asm/unistd_32.h arch/x86/kernel/smp.c arch/x86/kernel/syscall_table_32.S include/linux/hrtimer.h kernel/printk.c kernel/sched.c kernel/sched_fair.c
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 48b2761b5668..c7218d132738 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -18,7 +18,6 @@
18#include <linux/percpu.h> 18#include <linux/percpu.h>
19#include <linux/profile.h> 19#include <linux/profile.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/tick.h>
22 21
23#include "tick-internal.h" 22#include "tick-internal.h"
24 23
@@ -457,23 +456,27 @@ void tick_broadcast_oneshot_control(unsigned long reason)
457 unsigned long flags; 456 unsigned long flags;
458 int cpu; 457 int cpu;
459 458
460 raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
461
462 /* 459 /*
463 * Periodic mode does not care about the enter/exit of power 460 * Periodic mode does not care about the enter/exit of power
464 * states 461 * states
465 */ 462 */
466 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 463 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
467 goto out; 464 return;
468 465
469 bc = tick_broadcast_device.evtdev; 466 /*
467 * We are called with preemtion disabled from the depth of the
468 * idle code, so we can't be moved away.
469 */
470 cpu = smp_processor_id(); 470 cpu = smp_processor_id();
471 td = &per_cpu(tick_cpu_device, cpu); 471 td = &per_cpu(tick_cpu_device, cpu);
472 dev = td->evtdev; 472 dev = td->evtdev;
473 473
474 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) 474 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
475 goto out; 475 return;
476
477 bc = tick_broadcast_device.evtdev;
476 478
479 raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
477 if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) { 480 if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
478 if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) { 481 if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
479 cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask()); 482 cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask());
@@ -490,8 +493,6 @@ void tick_broadcast_oneshot_control(unsigned long reason)
490 tick_program_event(dev->next_event, 1); 493 tick_program_event(dev->next_event, 1);
491 } 494 }
492 } 495 }
493
494out:
495 raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); 496 raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
496} 497}
497 498
@@ -523,10 +524,11 @@ static void tick_broadcast_init_next_event(struct cpumask *mask,
523 */ 524 */
524void tick_broadcast_setup_oneshot(struct clock_event_device *bc) 525void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
525{ 526{
527 int cpu = smp_processor_id();
528
526 /* Set it up only once ! */ 529 /* Set it up only once ! */
527 if (bc->event_handler != tick_handle_oneshot_broadcast) { 530 if (bc->event_handler != tick_handle_oneshot_broadcast) {
528 int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC; 531 int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
529 int cpu = smp_processor_id();
530 532
531 bc->event_handler = tick_handle_oneshot_broadcast; 533 bc->event_handler = tick_handle_oneshot_broadcast;
532 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); 534 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
@@ -552,6 +554,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
552 tick_broadcast_set_event(tick_next_period, 1); 554 tick_broadcast_set_event(tick_next_period, 1);
553 } else 555 } else
554 bc->next_event.tv64 = KTIME_MAX; 556 bc->next_event.tv64 = KTIME_MAX;
557 } else {
558 /*
559 * The first cpu which switches to oneshot mode sets
560 * the bit for all other cpus which are in the general
561 * (periodic) broadcast mask. So the bit is set and
562 * would prevent the first broadcast enter after this
563 * to program the bc device.
564 */
565 tick_broadcast_clear_oneshot(cpu);
555 } 566 }
556} 567}
557 568
@@ -600,4 +611,14 @@ int tick_broadcast_oneshot_active(void)
600 return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT; 611 return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT;
601} 612}
602 613
614/*
615 * Check whether the broadcast device supports oneshot.
616 */
617bool tick_broadcast_oneshot_available(void)
618{
619 struct clock_event_device *bc = tick_broadcast_device.evtdev;
620
621 return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false;
622}
623
603#endif 624#endif