diff options
author | Gennady Sharapov <Gennady.V.Sharapov@intel.com> | 2006-01-18 20:42:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-18 22:20:19 -0500 |
commit | cff65c4f0ea6662124bbb7bf3806e5df1c6d735d (patch) | |
tree | 5f19b3facdfa6a50ad1668b28d1ff74a92a90271 /arch/um/kernel/time_kern.c | |
parent | 4fef0c10fa174b57a10854b8b4b2b90d155706e0 (diff) |
[PATCH] uml: move libc-dependent time code
The serial UML OS-abstraction layer patch (um/kernel dir).
This moves all systemcalls from time.c file under os-Linux dir and joins
time.c and tine_kernel.c files
Signed-off-by: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/kernel/time_kern.c')
-rw-r--r-- | arch/um/kernel/time_kern.c | 124 |
1 files changed, 76 insertions, 48 deletions
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 020ca79b8d33..6712ffad0242 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -13,12 +13,12 @@ | |||
13 | #include "linux/interrupt.h" | 13 | #include "linux/interrupt.h" |
14 | #include "linux/init.h" | 14 | #include "linux/init.h" |
15 | #include "linux/delay.h" | 15 | #include "linux/delay.h" |
16 | #include "linux/hrtimer.h" | ||
16 | #include "asm/irq.h" | 17 | #include "asm/irq.h" |
17 | #include "asm/param.h" | 18 | #include "asm/param.h" |
18 | #include "asm/current.h" | 19 | #include "asm/current.h" |
19 | #include "kern_util.h" | 20 | #include "kern_util.h" |
20 | #include "user_util.h" | 21 | #include "user_util.h" |
21 | #include "time_user.h" | ||
22 | #include "mode.h" | 22 | #include "mode.h" |
23 | #include "os.h" | 23 | #include "os.h" |
24 | 24 | ||
@@ -39,7 +39,7 @@ unsigned long long sched_clock(void) | |||
39 | int timer_irq_inited = 0; | 39 | int timer_irq_inited = 0; |
40 | 40 | ||
41 | static int first_tick; | 41 | static int first_tick; |
42 | static unsigned long long prev_usecs; | 42 | static unsigned long long prev_nsecs; |
43 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 43 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
44 | static long long delta; /* Deviation per interval */ | 44 | static long long delta; /* Deviation per interval */ |
45 | #endif | 45 | #endif |
@@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs) | |||
58 | if(first_tick){ | 58 | if(first_tick){ |
59 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 59 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
60 | /* We've had 1 tick */ | 60 | /* We've had 1 tick */ |
61 | unsigned long long usecs = os_usecs(); | 61 | unsigned long long nsecs = os_nsecs(); |
62 | 62 | ||
63 | delta += usecs - prev_usecs; | 63 | delta += nsecs - prev_nsecs; |
64 | prev_usecs = usecs; | 64 | prev_nsecs = nsecs; |
65 | 65 | ||
66 | /* Protect against the host clock being set backwards */ | 66 | /* Protect against the host clock being set backwards */ |
67 | if(delta < 0) | 67 | if(delta < 0) |
68 | delta = 0; | 68 | delta = 0; |
69 | 69 | ||
70 | ticks += (delta * HZ) / MILLION; | 70 | ticks += (delta * HZ) / BILLION; |
71 | delta -= (ticks * MILLION) / HZ; | 71 | delta -= (ticks * BILLION) / HZ; |
72 | #else | 72 | #else |
73 | ticks = 1; | 73 | ticks = 1; |
74 | #endif | 74 | #endif |
75 | } | 75 | } |
76 | else { | 76 | else { |
77 | prev_usecs = os_usecs(); | 77 | prev_nsecs = os_nsecs(); |
78 | first_tick = 1; | 78 | first_tick = 1; |
79 | } | 79 | } |
80 | 80 | ||
@@ -88,45 +88,99 @@ void boot_timer_handler(int sig) | |||
88 | { | 88 | { |
89 | struct pt_regs regs; | 89 | struct pt_regs regs; |
90 | 90 | ||
91 | CHOOSE_MODE((void) | 91 | CHOOSE_MODE((void) |
92 | (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), | 92 | (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), |
93 | (void) (regs.regs.skas.is_user = 0)); | 93 | (void) (regs.regs.skas.is_user = 0)); |
94 | do_timer(®s); | 94 | do_timer(®s); |
95 | } | 95 | } |
96 | 96 | ||
97 | static DEFINE_SPINLOCK(timer_spinlock); | ||
98 | |||
99 | static unsigned long long local_offset = 0; | ||
100 | |||
101 | static inline unsigned long long get_time(void) | ||
102 | { | ||
103 | unsigned long long nsecs; | ||
104 | unsigned long flags; | ||
105 | |||
106 | spin_lock_irqsave(&timer_spinlock, flags); | ||
107 | nsecs = os_nsecs(); | ||
108 | nsecs += local_offset; | ||
109 | spin_unlock_irqrestore(&timer_spinlock, flags); | ||
110 | |||
111 | return nsecs; | ||
112 | } | ||
113 | |||
97 | irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) | 114 | irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) |
98 | { | 115 | { |
116 | unsigned long long nsecs; | ||
99 | unsigned long flags; | 117 | unsigned long flags; |
100 | 118 | ||
101 | do_timer(regs); | 119 | do_timer(regs); |
120 | |||
102 | write_seqlock_irqsave(&xtime_lock, flags); | 121 | write_seqlock_irqsave(&xtime_lock, flags); |
103 | timer(); | 122 | nsecs = get_time() + local_offset; |
123 | xtime.tv_sec = nsecs / NSEC_PER_SEC; | ||
124 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; | ||
104 | write_sequnlock_irqrestore(&xtime_lock, flags); | 125 | write_sequnlock_irqrestore(&xtime_lock, flags); |
126 | |||
105 | return(IRQ_HANDLED); | 127 | return(IRQ_HANDLED); |
106 | } | 128 | } |
107 | 129 | ||
108 | long um_time(int __user *tloc) | 130 | long um_time(int __user *tloc) |
109 | { | 131 | { |
110 | struct timeval now; | 132 | long ret = get_time() / NSEC_PER_SEC; |
111 | 133 | ||
112 | do_gettimeofday(&now); | 134 | if((tloc != NULL) && put_user(ret, tloc)) |
113 | if (tloc) { | 135 | return -EFAULT; |
114 | if (put_user(now.tv_sec, tloc)) | 136 | |
115 | now.tv_sec = -EFAULT; | 137 | return ret; |
116 | } | 138 | } |
117 | return now.tv_sec; | 139 | |
140 | void do_gettimeofday(struct timeval *tv) | ||
141 | { | ||
142 | unsigned long long nsecs = get_time(); | ||
143 | |||
144 | tv->tv_sec = nsecs / NSEC_PER_SEC; | ||
145 | /* Careful about calculations here - this was originally done as | ||
146 | * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC | ||
147 | * which gave bogus (> 1000000) values. Dunno why, suspect gcc | ||
148 | * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion | ||
149 | * problem that I missed. | ||
150 | */ | ||
151 | nsecs -= tv->tv_sec * NSEC_PER_SEC; | ||
152 | tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; | ||
153 | } | ||
154 | |||
155 | static inline void set_time(unsigned long long nsecs) | ||
156 | { | ||
157 | unsigned long long now; | ||
158 | unsigned long flags; | ||
159 | |||
160 | spin_lock_irqsave(&timer_spinlock, flags); | ||
161 | now = os_nsecs(); | ||
162 | local_offset = nsecs - now; | ||
163 | spin_unlock_irqrestore(&timer_spinlock, flags); | ||
164 | |||
165 | clock_was_set(); | ||
118 | } | 166 | } |
119 | 167 | ||
120 | long um_stime(int __user *tptr) | 168 | long um_stime(int __user *tptr) |
121 | { | 169 | { |
122 | int value; | 170 | int value; |
123 | struct timespec new; | ||
124 | 171 | ||
125 | if (get_user(value, tptr)) | 172 | if (get_user(value, tptr)) |
126 | return -EFAULT; | 173 | return -EFAULT; |
127 | new.tv_sec = value; | 174 | |
128 | new.tv_nsec = 0; | 175 | set_time((unsigned long long) value * NSEC_PER_SEC); |
129 | do_settimeofday(&new); | 176 | |
177 | return 0; | ||
178 | } | ||
179 | |||
180 | int do_settimeofday(struct timespec *tv) | ||
181 | { | ||
182 | set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); | ||
183 | |||
130 | return 0; | 184 | return 0; |
131 | } | 185 | } |
132 | 186 | ||
@@ -142,21 +196,6 @@ void timer_handler(int sig, union uml_pt_regs *regs) | |||
142 | timer_irq(regs); | 196 | timer_irq(regs); |
143 | } | 197 | } |
144 | 198 | ||
145 | static DEFINE_SPINLOCK(timer_spinlock); | ||
146 | |||
147 | unsigned long time_lock(void) | ||
148 | { | ||
149 | unsigned long flags; | ||
150 | |||
151 | spin_lock_irqsave(&timer_spinlock, flags); | ||
152 | return(flags); | ||
153 | } | ||
154 | |||
155 | void time_unlock(unsigned long flags) | ||
156 | { | ||
157 | spin_unlock_irqrestore(&timer_spinlock, flags); | ||
158 | } | ||
159 | |||
160 | int __init timer_init(void) | 199 | int __init timer_init(void) |
161 | { | 200 | { |
162 | int err; | 201 | int err; |
@@ -171,14 +210,3 @@ int __init timer_init(void) | |||
171 | } | 210 | } |
172 | 211 | ||
173 | __initcall(timer_init); | 212 | __initcall(timer_init); |
174 | |||
175 | /* | ||
176 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
177 | * Emacs will notice this stuff at the end of the file and automatically | ||
178 | * adjust the settings for this buffer only. This must remain at the end | ||
179 | * of the file. | ||
180 | * --------------------------------------------------------------------------- | ||
181 | * Local variables: | ||
182 | * c-file-style: "linux" | ||
183 | * End: | ||
184 | */ | ||