diff options
-rw-r--r-- | include/linux/time.h | 2 | ||||
-rw-r--r-- | init/main.c | 1 | ||||
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/time/clocksource.c | 4 | ||||
-rw-r--r-- | kernel/timer.c | 93 |
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; | |||
77 | extern struct timespec wall_to_monotonic; | 77 | extern struct timespec wall_to_monotonic; |
78 | extern seqlock_t xtime_lock; | 78 | extern seqlock_t xtime_lock; |
79 | 79 | ||
80 | void timekeeping_init(void); | ||
81 | |||
80 | static inline unsigned long get_seconds(void) | 82 | static 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 | ||
13 | obj-y += time/ | ||
13 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o | 14 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o |
14 | obj-$(CONFIG_FUTEX) += futex.o | 15 | obj-$(CONFIG_FUTEX) += futex.o |
15 | ifeq ($(CONFIG_COMPAT),y) | 16 | ifeq ($(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 | */ |
59 | static int clocksource_done_booting(void) | 59 | static 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 | ||
292 | static int init_clocksource_sysfs(void) | 292 | static 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> | ||
797 | static struct clocksource *clock; /* pointer to current clocksource */ | ||
798 | static 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 | */ |
802 | static void update_wall_time(unsigned long ticks) | 802 | void __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 | */ | ||
823 | static 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 */ | ||
835 | static struct sysdev_class timekeeping_sysclass = { | ||
836 | .resume = timekeeping_resume, | ||
837 | set_kset_name("timekeeping"), | ||
838 | }; | ||
839 | |||
840 | static struct sys_device device_timer = { | ||
841 | .id = 0, | ||
842 | .cls = &timekeeping_sysclass, | ||
843 | }; | ||
844 | |||
845 | static 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 | |||
853 | device_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 | */ | ||
860 | static 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 | ||