diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /kernel/time.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'kernel/time.c')
-rw-r--r-- | kernel/time.c | 599 |
1 files changed, 599 insertions, 0 deletions
diff --git a/kernel/time.c b/kernel/time.c new file mode 100644 index 000000000000..96fd0f499631 --- /dev/null +++ b/kernel/time.c | |||
@@ -0,0 +1,599 @@ | |||
1 | /* | ||
2 | * linux/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
5 | * | ||
6 | * This file contains the interface functions for the various | ||
7 | * time related system calls: time, stime, gettimeofday, settimeofday, | ||
8 | * adjtime | ||
9 | */ | ||
10 | /* | ||
11 | * Modification history kernel/time.c | ||
12 | * | ||
13 | * 1993-09-02 Philip Gladstone | ||
14 | * Created file with time related functions from sched.c and adjtimex() | ||
15 | * 1993-10-08 Torsten Duwe | ||
16 | * adjtime interface update and CMOS clock write code | ||
17 | * 1995-08-13 Torsten Duwe | ||
18 | * kernel PLL updated to 1994-12-13 specs (rfc-1589) | ||
19 | * 1999-01-16 Ulrich Windl | ||
20 | * Introduced error checking for many cases in adjtimex(). | ||
21 | * Updated NTP code according to technical memorandum Jan '96 | ||
22 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
23 | * Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10) | ||
24 | * (Even though the technical memorandum forbids it) | ||
25 | * 2004-07-14 Christoph Lameter | ||
26 | * Added getnstimeofday to allow the posix timer functions to return | ||
27 | * with nanosecond accuracy | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/timex.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/smp_lock.h> | ||
34 | #include <linux/syscalls.h> | ||
35 | #include <linux/security.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/module.h> | ||
38 | |||
39 | #include <asm/uaccess.h> | ||
40 | #include <asm/unistd.h> | ||
41 | |||
42 | /* | ||
43 | * The timezone where the local system is located. Used as a default by some | ||
44 | * programs who obtain this value by using gettimeofday. | ||
45 | */ | ||
46 | struct timezone sys_tz; | ||
47 | |||
48 | EXPORT_SYMBOL(sys_tz); | ||
49 | |||
50 | #ifdef __ARCH_WANT_SYS_TIME | ||
51 | |||
52 | /* | ||
53 | * sys_time() can be implemented in user-level using | ||
54 | * sys_gettimeofday(). Is this for backwards compatibility? If so, | ||
55 | * why not move it into the appropriate arch directory (for those | ||
56 | * architectures that need it). | ||
57 | */ | ||
58 | asmlinkage long sys_time(time_t __user * tloc) | ||
59 | { | ||
60 | time_t i; | ||
61 | struct timeval tv; | ||
62 | |||
63 | do_gettimeofday(&tv); | ||
64 | i = tv.tv_sec; | ||
65 | |||
66 | if (tloc) { | ||
67 | if (put_user(i,tloc)) | ||
68 | i = -EFAULT; | ||
69 | } | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * sys_stime() can be implemented in user-level using | ||
75 | * sys_settimeofday(). Is this for backwards compatibility? If so, | ||
76 | * why not move it into the appropriate arch directory (for those | ||
77 | * architectures that need it). | ||
78 | */ | ||
79 | |||
80 | asmlinkage long sys_stime(time_t __user *tptr) | ||
81 | { | ||
82 | struct timespec tv; | ||
83 | int err; | ||
84 | |||
85 | if (get_user(tv.tv_sec, tptr)) | ||
86 | return -EFAULT; | ||
87 | |||
88 | tv.tv_nsec = 0; | ||
89 | |||
90 | err = security_settime(&tv, NULL); | ||
91 | if (err) | ||
92 | return err; | ||
93 | |||
94 | do_settimeofday(&tv); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | #endif /* __ARCH_WANT_SYS_TIME */ | ||
99 | |||
100 | asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz) | ||
101 | { | ||
102 | if (likely(tv != NULL)) { | ||
103 | struct timeval ktv; | ||
104 | do_gettimeofday(&ktv); | ||
105 | if (copy_to_user(tv, &ktv, sizeof(ktv))) | ||
106 | return -EFAULT; | ||
107 | } | ||
108 | if (unlikely(tz != NULL)) { | ||
109 | if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) | ||
110 | return -EFAULT; | ||
111 | } | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Adjust the time obtained from the CMOS to be UTC time instead of | ||
117 | * local time. | ||
118 | * | ||
119 | * This is ugly, but preferable to the alternatives. Otherwise we | ||
120 | * would either need to write a program to do it in /etc/rc (and risk | ||
121 | * confusion if the program gets run more than once; it would also be | ||
122 | * hard to make the program warp the clock precisely n hours) or | ||
123 | * compile in the timezone information into the kernel. Bad, bad.... | ||
124 | * | ||
125 | * - TYT, 1992-01-01 | ||
126 | * | ||
127 | * The best thing to do is to keep the CMOS clock in universal time (UTC) | ||
128 | * as real UNIX machines always do it. This avoids all headaches about | ||
129 | * daylight saving times and warping kernel clocks. | ||
130 | */ | ||
131 | inline static void warp_clock(void) | ||
132 | { | ||
133 | write_seqlock_irq(&xtime_lock); | ||
134 | wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; | ||
135 | xtime.tv_sec += sys_tz.tz_minuteswest * 60; | ||
136 | time_interpolator_reset(); | ||
137 | write_sequnlock_irq(&xtime_lock); | ||
138 | clock_was_set(); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * In case for some reason the CMOS clock has not already been running | ||
143 | * in UTC, but in some local time: The first time we set the timezone, | ||
144 | * we will warp the clock so that it is ticking UTC time instead of | ||
145 | * local time. Presumably, if someone is setting the timezone then we | ||
146 | * are running in an environment where the programs understand about | ||
147 | * timezones. This should be done at boot time in the /etc/rc script, | ||
148 | * as soon as possible, so that the clock can be set right. Otherwise, | ||
149 | * various programs will get confused when the clock gets warped. | ||
150 | */ | ||
151 | |||
152 | int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) | ||
153 | { | ||
154 | static int firsttime = 1; | ||
155 | int error = 0; | ||
156 | |||
157 | error = security_settime(tv, tz); | ||
158 | if (error) | ||
159 | return error; | ||
160 | |||
161 | if (tz) { | ||
162 | /* SMP safe, global irq locking makes it work. */ | ||
163 | sys_tz = *tz; | ||
164 | if (firsttime) { | ||
165 | firsttime = 0; | ||
166 | if (!tv) | ||
167 | warp_clock(); | ||
168 | } | ||
169 | } | ||
170 | if (tv) | ||
171 | { | ||
172 | /* SMP safe, again the code in arch/foo/time.c should | ||
173 | * globally block out interrupts when it runs. | ||
174 | */ | ||
175 | return do_settimeofday(tv); | ||
176 | } | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | asmlinkage long sys_settimeofday(struct timeval __user *tv, | ||
181 | struct timezone __user *tz) | ||
182 | { | ||
183 | struct timeval user_tv; | ||
184 | struct timespec new_ts; | ||
185 | struct timezone new_tz; | ||
186 | |||
187 | if (tv) { | ||
188 | if (copy_from_user(&user_tv, tv, sizeof(*tv))) | ||
189 | return -EFAULT; | ||
190 | new_ts.tv_sec = user_tv.tv_sec; | ||
191 | new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; | ||
192 | } | ||
193 | if (tz) { | ||
194 | if (copy_from_user(&new_tz, tz, sizeof(*tz))) | ||
195 | return -EFAULT; | ||
196 | } | ||
197 | |||
198 | return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); | ||
199 | } | ||
200 | |||
201 | long pps_offset; /* pps time offset (us) */ | ||
202 | long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */ | ||
203 | |||
204 | long pps_freq; /* frequency offset (scaled ppm) */ | ||
205 | long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */ | ||
206 | |||
207 | long pps_valid = PPS_VALID; /* pps signal watchdog counter */ | ||
208 | |||
209 | int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */ | ||
210 | |||
211 | long pps_jitcnt; /* jitter limit exceeded */ | ||
212 | long pps_calcnt; /* calibration intervals */ | ||
213 | long pps_errcnt; /* calibration errors */ | ||
214 | long pps_stbcnt; /* stability limit exceeded */ | ||
215 | |||
216 | /* hook for a loadable hardpps kernel module */ | ||
217 | void (*hardpps_ptr)(struct timeval *); | ||
218 | |||
219 | /* we call this to notify the arch when the clock is being | ||
220 | * controlled. If no such arch routine, do nothing. | ||
221 | */ | ||
222 | void __attribute__ ((weak)) notify_arch_cmos_timer(void) | ||
223 | { | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | /* adjtimex mainly allows reading (and writing, if superuser) of | ||
228 | * kernel time-keeping variables. used by xntpd. | ||
229 | */ | ||
230 | int do_adjtimex(struct timex *txc) | ||
231 | { | ||
232 | long ltemp, mtemp, save_adjust; | ||
233 | int result; | ||
234 | |||
235 | /* In order to modify anything, you gotta be super-user! */ | ||
236 | if (txc->modes && !capable(CAP_SYS_TIME)) | ||
237 | return -EPERM; | ||
238 | |||
239 | /* Now we validate the data before disabling interrupts */ | ||
240 | |||
241 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | ||
242 | /* singleshot must not be used with any other mode bits */ | ||
243 | if (txc->modes != ADJ_OFFSET_SINGLESHOT) | ||
244 | return -EINVAL; | ||
245 | |||
246 | if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET)) | ||
247 | /* adjustment Offset limited to +- .512 seconds */ | ||
248 | if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE ) | ||
249 | return -EINVAL; | ||
250 | |||
251 | /* if the quartz is off by more than 10% something is VERY wrong ! */ | ||
252 | if (txc->modes & ADJ_TICK) | ||
253 | if (txc->tick < 900000/USER_HZ || | ||
254 | txc->tick > 1100000/USER_HZ) | ||
255 | return -EINVAL; | ||
256 | |||
257 | write_seqlock_irq(&xtime_lock); | ||
258 | result = time_state; /* mostly `TIME_OK' */ | ||
259 | |||
260 | /* Save for later - semantics of adjtime is to return old value */ | ||
261 | save_adjust = time_next_adjust ? time_next_adjust : time_adjust; | ||
262 | |||
263 | #if 0 /* STA_CLOCKERR is never set yet */ | ||
264 | time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */ | ||
265 | #endif | ||
266 | /* If there are input parameters, then process them */ | ||
267 | if (txc->modes) | ||
268 | { | ||
269 | if (txc->modes & ADJ_STATUS) /* only set allowed bits */ | ||
270 | time_status = (txc->status & ~STA_RONLY) | | ||
271 | (time_status & STA_RONLY); | ||
272 | |||
273 | if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */ | ||
274 | if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) { | ||
275 | result = -EINVAL; | ||
276 | goto leave; | ||
277 | } | ||
278 | time_freq = txc->freq - pps_freq; | ||
279 | } | ||
280 | |||
281 | if (txc->modes & ADJ_MAXERROR) { | ||
282 | if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) { | ||
283 | result = -EINVAL; | ||
284 | goto leave; | ||
285 | } | ||
286 | time_maxerror = txc->maxerror; | ||
287 | } | ||
288 | |||
289 | if (txc->modes & ADJ_ESTERROR) { | ||
290 | if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) { | ||
291 | result = -EINVAL; | ||
292 | goto leave; | ||
293 | } | ||
294 | time_esterror = txc->esterror; | ||
295 | } | ||
296 | |||
297 | if (txc->modes & ADJ_TIMECONST) { /* p. 24 */ | ||
298 | if (txc->constant < 0) { /* NTP v4 uses values > 6 */ | ||
299 | result = -EINVAL; | ||
300 | goto leave; | ||
301 | } | ||
302 | time_constant = txc->constant; | ||
303 | } | ||
304 | |||
305 | if (txc->modes & ADJ_OFFSET) { /* values checked earlier */ | ||
306 | if (txc->modes == ADJ_OFFSET_SINGLESHOT) { | ||
307 | /* adjtime() is independent from ntp_adjtime() */ | ||
308 | if ((time_next_adjust = txc->offset) == 0) | ||
309 | time_adjust = 0; | ||
310 | } | ||
311 | else if ( time_status & (STA_PLL | STA_PPSTIME) ) { | ||
312 | ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) == | ||
313 | (STA_PPSTIME | STA_PPSSIGNAL) ? | ||
314 | pps_offset : txc->offset; | ||
315 | |||
316 | /* | ||
317 | * Scale the phase adjustment and | ||
318 | * clamp to the operating range. | ||
319 | */ | ||
320 | if (ltemp > MAXPHASE) | ||
321 | time_offset = MAXPHASE << SHIFT_UPDATE; | ||
322 | else if (ltemp < -MAXPHASE) | ||
323 | time_offset = -(MAXPHASE << SHIFT_UPDATE); | ||
324 | else | ||
325 | time_offset = ltemp << SHIFT_UPDATE; | ||
326 | |||
327 | /* | ||
328 | * Select whether the frequency is to be controlled | ||
329 | * and in which mode (PLL or FLL). Clamp to the operating | ||
330 | * range. Ugly multiply/divide should be replaced someday. | ||
331 | */ | ||
332 | |||
333 | if (time_status & STA_FREQHOLD || time_reftime == 0) | ||
334 | time_reftime = xtime.tv_sec; | ||
335 | mtemp = xtime.tv_sec - time_reftime; | ||
336 | time_reftime = xtime.tv_sec; | ||
337 | if (time_status & STA_FLL) { | ||
338 | if (mtemp >= MINSEC) { | ||
339 | ltemp = (time_offset / mtemp) << (SHIFT_USEC - | ||
340 | SHIFT_UPDATE); | ||
341 | if (ltemp < 0) | ||
342 | time_freq -= -ltemp >> SHIFT_KH; | ||
343 | else | ||
344 | time_freq += ltemp >> SHIFT_KH; | ||
345 | } else /* calibration interval too short (p. 12) */ | ||
346 | result = TIME_ERROR; | ||
347 | } else { /* PLL mode */ | ||
348 | if (mtemp < MAXSEC) { | ||
349 | ltemp *= mtemp; | ||
350 | if (ltemp < 0) | ||
351 | time_freq -= -ltemp >> (time_constant + | ||
352 | time_constant + | ||
353 | SHIFT_KF - SHIFT_USEC); | ||
354 | else | ||
355 | time_freq += ltemp >> (time_constant + | ||
356 | time_constant + | ||
357 | SHIFT_KF - SHIFT_USEC); | ||
358 | } else /* calibration interval too long (p. 12) */ | ||
359 | result = TIME_ERROR; | ||
360 | } | ||
361 | if (time_freq > time_tolerance) | ||
362 | time_freq = time_tolerance; | ||
363 | else if (time_freq < -time_tolerance) | ||
364 | time_freq = -time_tolerance; | ||
365 | } /* STA_PLL || STA_PPSTIME */ | ||
366 | } /* txc->modes & ADJ_OFFSET */ | ||
367 | if (txc->modes & ADJ_TICK) { | ||
368 | tick_usec = txc->tick; | ||
369 | tick_nsec = TICK_USEC_TO_NSEC(tick_usec); | ||
370 | } | ||
371 | } /* txc->modes */ | ||
372 | leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 | ||
373 | || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0 | ||
374 | && (time_status & STA_PPSSIGNAL) == 0) | ||
375 | /* p. 24, (b) */ | ||
376 | || ((time_status & (STA_PPSTIME|STA_PPSJITTER)) | ||
377 | == (STA_PPSTIME|STA_PPSJITTER)) | ||
378 | /* p. 24, (c) */ | ||
379 | || ((time_status & STA_PPSFREQ) != 0 | ||
380 | && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0)) | ||
381 | /* p. 24, (d) */ | ||
382 | result = TIME_ERROR; | ||
383 | |||
384 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | ||
385 | txc->offset = save_adjust; | ||
386 | else { | ||
387 | if (time_offset < 0) | ||
388 | txc->offset = -(-time_offset >> SHIFT_UPDATE); | ||
389 | else | ||
390 | txc->offset = time_offset >> SHIFT_UPDATE; | ||
391 | } | ||
392 | txc->freq = time_freq + pps_freq; | ||
393 | txc->maxerror = time_maxerror; | ||
394 | txc->esterror = time_esterror; | ||
395 | txc->status = time_status; | ||
396 | txc->constant = time_constant; | ||
397 | txc->precision = time_precision; | ||
398 | txc->tolerance = time_tolerance; | ||
399 | txc->tick = tick_usec; | ||
400 | txc->ppsfreq = pps_freq; | ||
401 | txc->jitter = pps_jitter >> PPS_AVG; | ||
402 | txc->shift = pps_shift; | ||
403 | txc->stabil = pps_stabil; | ||
404 | txc->jitcnt = pps_jitcnt; | ||
405 | txc->calcnt = pps_calcnt; | ||
406 | txc->errcnt = pps_errcnt; | ||
407 | txc->stbcnt = pps_stbcnt; | ||
408 | write_sequnlock_irq(&xtime_lock); | ||
409 | do_gettimeofday(&txc->time); | ||
410 | notify_arch_cmos_timer(); | ||
411 | return(result); | ||
412 | } | ||
413 | |||
414 | asmlinkage long sys_adjtimex(struct timex __user *txc_p) | ||
415 | { | ||
416 | struct timex txc; /* Local copy of parameter */ | ||
417 | int ret; | ||
418 | |||
419 | /* Copy the user data space into the kernel copy | ||
420 | * structure. But bear in mind that the structures | ||
421 | * may change | ||
422 | */ | ||
423 | if(copy_from_user(&txc, txc_p, sizeof(struct timex))) | ||
424 | return -EFAULT; | ||
425 | ret = do_adjtimex(&txc); | ||
426 | return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret; | ||
427 | } | ||
428 | |||
429 | inline struct timespec current_kernel_time(void) | ||
430 | { | ||
431 | struct timespec now; | ||
432 | unsigned long seq; | ||
433 | |||
434 | do { | ||
435 | seq = read_seqbegin(&xtime_lock); | ||
436 | |||
437 | now = xtime; | ||
438 | } while (read_seqretry(&xtime_lock, seq)); | ||
439 | |||
440 | return now; | ||
441 | } | ||
442 | |||
443 | EXPORT_SYMBOL(current_kernel_time); | ||
444 | |||
445 | /** | ||
446 | * current_fs_time - Return FS time | ||
447 | * @sb: Superblock. | ||
448 | * | ||
449 | * Return the current time truncated to the time granuality supported by | ||
450 | * the fs. | ||
451 | */ | ||
452 | struct timespec current_fs_time(struct super_block *sb) | ||
453 | { | ||
454 | struct timespec now = current_kernel_time(); | ||
455 | return timespec_trunc(now, sb->s_time_gran); | ||
456 | } | ||
457 | EXPORT_SYMBOL(current_fs_time); | ||
458 | |||
459 | /** | ||
460 | * timespec_trunc - Truncate timespec to a granuality | ||
461 | * @t: Timespec | ||
462 | * @gran: Granuality in ns. | ||
463 | * | ||
464 | * Truncate a timespec to a granuality. gran must be smaller than a second. | ||
465 | * Always rounds down. | ||
466 | * | ||
467 | * This function should be only used for timestamps returned by | ||
468 | * current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because | ||
469 | * it doesn't handle the better resolution of the later. | ||
470 | */ | ||
471 | struct timespec timespec_trunc(struct timespec t, unsigned gran) | ||
472 | { | ||
473 | /* | ||
474 | * Division is pretty slow so avoid it for common cases. | ||
475 | * Currently current_kernel_time() never returns better than | ||
476 | * jiffies resolution. Exploit that. | ||
477 | */ | ||
478 | if (gran <= jiffies_to_usecs(1) * 1000) { | ||
479 | /* nothing */ | ||
480 | } else if (gran == 1000000000) { | ||
481 | t.tv_nsec = 0; | ||
482 | } else { | ||
483 | t.tv_nsec -= t.tv_nsec % gran; | ||
484 | } | ||
485 | return t; | ||
486 | } | ||
487 | EXPORT_SYMBOL(timespec_trunc); | ||
488 | |||
489 | #ifdef CONFIG_TIME_INTERPOLATION | ||
490 | void getnstimeofday (struct timespec *tv) | ||
491 | { | ||
492 | unsigned long seq,sec,nsec; | ||
493 | |||
494 | do { | ||
495 | seq = read_seqbegin(&xtime_lock); | ||
496 | sec = xtime.tv_sec; | ||
497 | nsec = xtime.tv_nsec+time_interpolator_get_offset(); | ||
498 | } while (unlikely(read_seqretry(&xtime_lock, seq))); | ||
499 | |||
500 | while (unlikely(nsec >= NSEC_PER_SEC)) { | ||
501 | nsec -= NSEC_PER_SEC; | ||
502 | ++sec; | ||
503 | } | ||
504 | tv->tv_sec = sec; | ||
505 | tv->tv_nsec = nsec; | ||
506 | } | ||
507 | EXPORT_SYMBOL_GPL(getnstimeofday); | ||
508 | |||
509 | int do_settimeofday (struct timespec *tv) | ||
510 | { | ||
511 | time_t wtm_sec, sec = tv->tv_sec; | ||
512 | long wtm_nsec, nsec = tv->tv_nsec; | ||
513 | |||
514 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
515 | return -EINVAL; | ||
516 | |||
517 | write_seqlock_irq(&xtime_lock); | ||
518 | { | ||
519 | /* | ||
520 | * This is revolting. We need to set "xtime" correctly. However, the value | ||
521 | * in this location is the value at the most recent update of wall time. | ||
522 | * Discover what correction gettimeofday would have done, and then undo | ||
523 | * it! | ||
524 | */ | ||
525 | nsec -= time_interpolator_get_offset(); | ||
526 | |||
527 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | ||
528 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | ||
529 | |||
530 | set_normalized_timespec(&xtime, sec, nsec); | ||
531 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | ||
532 | |||
533 | time_adjust = 0; /* stop active adjtime() */ | ||
534 | time_status |= STA_UNSYNC; | ||
535 | time_maxerror = NTP_PHASE_LIMIT; | ||
536 | time_esterror = NTP_PHASE_LIMIT; | ||
537 | time_interpolator_reset(); | ||
538 | } | ||
539 | write_sequnlock_irq(&xtime_lock); | ||
540 | clock_was_set(); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | void do_gettimeofday (struct timeval *tv) | ||
545 | { | ||
546 | unsigned long seq, nsec, usec, sec, offset; | ||
547 | do { | ||
548 | seq = read_seqbegin(&xtime_lock); | ||
549 | offset = time_interpolator_get_offset(); | ||
550 | sec = xtime.tv_sec; | ||
551 | nsec = xtime.tv_nsec; | ||
552 | } while (unlikely(read_seqretry(&xtime_lock, seq))); | ||
553 | |||
554 | usec = (nsec + offset) / 1000; | ||
555 | |||
556 | while (unlikely(usec >= USEC_PER_SEC)) { | ||
557 | usec -= USEC_PER_SEC; | ||
558 | ++sec; | ||
559 | } | ||
560 | |||
561 | tv->tv_sec = sec; | ||
562 | tv->tv_usec = usec; | ||
563 | } | ||
564 | |||
565 | EXPORT_SYMBOL(do_gettimeofday); | ||
566 | |||
567 | |||
568 | #else | ||
569 | /* | ||
570 | * Simulate gettimeofday using do_gettimeofday which only allows a timeval | ||
571 | * and therefore only yields usec accuracy | ||
572 | */ | ||
573 | void getnstimeofday(struct timespec *tv) | ||
574 | { | ||
575 | struct timeval x; | ||
576 | |||
577 | do_gettimeofday(&x); | ||
578 | tv->tv_sec = x.tv_sec; | ||
579 | tv->tv_nsec = x.tv_usec * NSEC_PER_USEC; | ||
580 | } | ||
581 | #endif | ||
582 | |||
583 | #if (BITS_PER_LONG < 64) | ||
584 | u64 get_jiffies_64(void) | ||
585 | { | ||
586 | unsigned long seq; | ||
587 | u64 ret; | ||
588 | |||
589 | do { | ||
590 | seq = read_seqbegin(&xtime_lock); | ||
591 | ret = jiffies_64; | ||
592 | } while (read_seqretry(&xtime_lock, seq)); | ||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | EXPORT_SYMBOL(get_jiffies_64); | ||
597 | #endif | ||
598 | |||
599 | EXPORT_SYMBOL(jiffies); | ||