diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-02-16 01:28:03 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 08:13:59 -0800 |
commit | 79bf2bb335b85db25d27421c798595a2fa2a0e82 (patch) | |
tree | 550ec2654ae1dd65b871de7fe9c890108c6e86d8 /kernel/time/tick-common.c | |
parent | f8381cba04ba8173fd5a2b8e5cd8b3290ee13a98 (diff) | |
download | lwn-79bf2bb335b85db25d27421c798595a2fa2a0e82.tar.gz lwn-79bf2bb335b85db25d27421c798595a2fa2a0e82.zip |
[PATCH] tick-management: dyntick / highres functionality
With Ingo Molnar <mingo@elte.hu>
Add functions to provide dynamic ticks and high resolution timers. The code
which keeps track of jiffies and handles the long idle periods is shared
between tick based and high resolution timer based dynticks. The dyntick
functionality can be disabled on the kernel commandline. Provide also the
infrastructure to support high resolution timers.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/time/tick-common.c')
-rw-r--r-- | kernel/time/tick-common.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 48167a6ae55c..c35d449be031 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -34,6 +34,16 @@ ktime_t tick_period; static int tick_do_timer_cpu = -1; DEFINE_SPINLOCK(tick_device_lock); +/** + * tick_is_oneshot_available - check for a oneshot capable event device + */ +int tick_is_oneshot_available(void) +{ + struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; + + return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT); +} + /* * Periodic tick */ @@ -162,6 +172,8 @@ static void tick_setup_device(struct tick_device *td, if (td->mode == TICKDEV_MODE_PERIODIC) tick_setup_periodic(newdev, 0); + else + tick_setup_oneshot(newdev, handler, next_event); } /* @@ -209,6 +221,12 @@ static int tick_check_new_device(struct clock_event_device *newdev) */ if (curdev) { /* + * Prefer one shot capable devices ! + */ + if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) && + !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) + goto out_bc; + /* * Check the rating */ if (curdev->rating >= newdev->rating) @@ -226,6 +244,8 @@ static int tick_check_new_device(struct clock_event_device *newdev) } clockevents_exchange_device(curdev, newdev); tick_setup_device(td, newdev, cpu, cpumask); + if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) + tick_oneshot_notify(); spin_unlock_irqrestore(&tick_device_lock, flags); return NOTIFY_STOP; @@ -285,7 +305,13 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason, tick_broadcast_on_off(reason, dev); break; + case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: + case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: + tick_broadcast_oneshot_control(reason); + break; + case CLOCK_EVT_NOTIFY_CPU_DEAD: + tick_shutdown_broadcast_oneshot(dev); tick_shutdown_broadcast(dev); tick_shutdown(dev); break; |