aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohn stultz <johnstul@us.ibm.com>2006-06-26 03:25:06 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:20 -0400
commitad596171ed635c51a9eef829187af100cbf8dcf7 (patch)
tree24b19bec1b1abd8bd110064226569aa42dde0b3b
parent734efb467b31e56c2f9430590a9aa867ecf3eea1 (diff)
[PATCH] Time: Use clocksource infrastructure for update_wall_time
Modify the update_wall_time function so it increments time using the clocksource abstraction instead of jiffies. Since the only clocksource driver currently provided is the jiffies clocksource, this should result in no functional change. Additionally, a timekeeping_init and timekeeping_resume function has been added to initialize and maintain some of the new timekeping state. [hirofumi@mail.parknet.co.jp: fixlet] Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/time.h2
-rw-r--r--init/main.c1
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/time/clocksource.c4
-rw-r--r--kernel/timer.c93
5 files changed, 86 insertions, 15 deletions
diff --git a/include/linux/time.h b/include/linux/time.h
index 0cd696cee998..88d3b812841e 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -77,6 +77,8 @@ extern struct timespec xtime;
77extern struct timespec wall_to_monotonic; 77extern struct timespec wall_to_monotonic;
78extern seqlock_t xtime_lock; 78extern seqlock_t xtime_lock;
79 79
80void timekeeping_init(void);
81
80static inline unsigned long get_seconds(void) 82static inline unsigned long get_seconds(void)
81{ 83{
82 return xtime.tv_sec; 84 return xtime.tv_sec;
diff --git a/init/main.c b/init/main.c
index f715b9b89753..9a970d317ea5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -490,6 +490,7 @@ asmlinkage void __init start_kernel(void)
490 hrtimers_init(); 490 hrtimers_init();
491 softirq_init(); 491 softirq_init();
492 time_init(); 492 time_init();
493 timekeeping_init();
493 494
494 /* 495 /*
495 * HACK ALERT! This is early. We're enabling the console before 496 * HACK ALERT! This is early. We're enabling the console before
diff --git a/kernel/Makefile b/kernel/Makefile
index f6ef00f4f90f..bc4b8a7161ff 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ 10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
11 hrtimer.o 11 hrtimer.o
12 12
13obj-y += time/
13obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o 14obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
14obj-$(CONFIG_FUTEX) += futex.o 15obj-$(CONFIG_FUTEX) += futex.o
15ifeq ($(CONFIG_COMPAT),y) 16ifeq ($(CONFIG_COMPAT),y)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 95dd2200a109..4288bfa12c3f 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -56,7 +56,7 @@ static int finished_booting;
56 * 56 *
57 * Hack to avoid lots of clocksource churn at boot time 57 * Hack to avoid lots of clocksource churn at boot time
58 */ 58 */
59static int clocksource_done_booting(void) 59static int __init clocksource_done_booting(void)
60{ 60{
61 finished_booting = 1; 61 finished_booting = 1;
62 return 0; 62 return 0;
@@ -289,7 +289,7 @@ static struct sys_device device_clocksource = {
289 .cls = &clocksource_sysclass, 289 .cls = &clocksource_sysclass,
290}; 290};
291 291
292static int init_clocksource_sysfs(void) 292static int __init init_clocksource_sysfs(void)
293{ 293{
294 int error = sysdev_class_register(&clocksource_sysclass); 294 int error = sysdev_class_register(&clocksource_sysclass);
295 295
diff --git a/kernel/timer.c b/kernel/timer.c
index eb97371b87d8..524c7f638365 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -792,24 +792,93 @@ u64 current_tick_length(void)
792 return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj; 792 return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj;
793} 793}
794 794
795/* XXX - all of this timekeeping code should be later moved to time.c */
796#include <linux/clocksource.h>
797static struct clocksource *clock; /* pointer to current clocksource */
798static cycle_t last_clock_cycle; /* cycle value at last update_wall_time */
795/* 799/*
796 * Using a loop looks inefficient, but "ticks" is 800 * timekeeping_init - Initializes the clocksource and common timekeeping values
797 * usually just one (we shouldn't be losing ticks,
798 * we're doing this this way mainly for interrupt
799 * latency reasons, not because we think we'll
800 * have lots of lost timer ticks
801 */ 801 */
802static void update_wall_time(unsigned long ticks) 802void __init timekeeping_init(void)
803{ 803{
804 do { 804 unsigned long flags;
805 ticks--; 805
806 write_seqlock_irqsave(&xtime_lock, flags);
807 clock = get_next_clocksource();
808 calculate_clocksource_interval(clock, tick_nsec);
809 last_clock_cycle = read_clocksource(clock);
810 ntp_clear();
811 write_sequnlock_irqrestore(&xtime_lock, flags);
812}
813
814
815/*
816 * timekeeping_resume - Resumes the generic timekeeping subsystem.
817 * @dev: unused
818 *
819 * This is for the generic clocksource timekeeping.
820 * xtime/wall_to_monotonic/jiffies/wall_jiffies/etc are
821 * still managed by arch specific suspend/resume code.
822 */
823static int timekeeping_resume(struct sys_device *dev)
824{
825 unsigned long flags;
826
827 write_seqlock_irqsave(&xtime_lock, flags);
828 /* restart the last cycle value */
829 last_clock_cycle = read_clocksource(clock);
830 write_sequnlock_irqrestore(&xtime_lock, flags);
831 return 0;
832}
833
834/* sysfs resume/suspend bits for timekeeping */
835static struct sysdev_class timekeeping_sysclass = {
836 .resume = timekeeping_resume,
837 set_kset_name("timekeeping"),
838};
839
840static struct sys_device device_timer = {
841 .id = 0,
842 .cls = &timekeeping_sysclass,
843};
844
845static int __init timekeeping_init_device(void)
846{
847 int error = sysdev_class_register(&timekeeping_sysclass);
848 if (!error)
849 error = sysdev_register(&device_timer);
850 return error;
851}
852
853device_initcall(timekeeping_init_device);
854
855/*
856 * update_wall_time - Uses the current clocksource to increment the wall time
857 *
858 * Called from the timer interrupt, must hold a write on xtime_lock.
859 */
860static void update_wall_time(void)
861{
862 cycle_t now, offset;
863
864 now = read_clocksource(clock);
865 offset = (now - last_clock_cycle)&clock->mask;
866
867 /* normally this loop will run just once, however in the
868 * case of lost or late ticks, it will accumulate correctly.
869 */
870 while (offset > clock->interval_cycles) {
871 /* accumulate one interval */
872 last_clock_cycle += clock->interval_cycles;
873 offset -= clock->interval_cycles;
874
806 update_wall_time_one_tick(); 875 update_wall_time_one_tick();
807 if (xtime.tv_nsec >= 1000000000) { 876 if (xtime.tv_nsec >= 1000000000) {
808 xtime.tv_nsec -= 1000000000; 877 xtime.tv_nsec -= 1000000000;
809 xtime.tv_sec++; 878 xtime.tv_sec++;
810 second_overflow(); 879 second_overflow();
811 } 880 }
812 } while (ticks); 881 }
813} 882}
814 883
815/* 884/*
@@ -915,10 +984,8 @@ static inline void update_times(void)
915 unsigned long ticks; 984 unsigned long ticks;
916 985
917 ticks = jiffies - wall_jiffies; 986 ticks = jiffies - wall_jiffies;
918 if (ticks) { 987 wall_jiffies += ticks;
919 wall_jiffies += ticks; 988 update_wall_time();
920 update_wall_time(ticks);
921 }
922 calc_load(ticks); 989 calc_load(ticks);
923} 990}
924 991