time.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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.  */
  26. #include <linux/mm.h>
  27. #include <linux/timex.h>
  28. #include <linux/smp_lock.h>
  29. #include <asm/uaccess.h>
  30. /* 
  31.  * The timezone where the local system is located.  Used as a default by some
  32.  * programs who obtain this value by using gettimeofday.
  33.  */
  34. struct timezone sys_tz;
  35. /* The xtime_lock is not only serializing the xtime read/writes but it's also
  36.    serializing all accesses to the global NTP variables now. */
  37. extern rwlock_t xtime_lock;
  38. #if !defined(__alpha__) && !defined(__ia64__)
  39. /*
  40.  * sys_time() can be implemented in user-level using
  41.  * sys_gettimeofday().  Is this for backwards compatibility?  If so,
  42.  * why not move it into the appropriate arch directory (for those
  43.  * architectures that need it).
  44.  *
  45.  * XXX This function is NOT 64-bit clean!
  46.  */
  47. asmlinkage long sys_time(int * tloc)
  48. {
  49. struct timeval now; 
  50. int i; 
  51. do_gettimeofday(&now);
  52. i = now.tv_sec;
  53. if (tloc) {
  54. if (put_user(i,tloc))
  55. i = -EFAULT;
  56. }
  57. return i;
  58. }
  59. /*
  60.  * sys_stime() can be implemented in user-level using
  61.  * sys_settimeofday().  Is this for backwards compatibility?  If so,
  62.  * why not move it into the appropriate arch directory (for those
  63.  * architectures that need it).
  64.  */
  65.  
  66. asmlinkage long sys_stime(int * tptr)
  67. {
  68. int value;
  69. if (!capable(CAP_SYS_TIME))
  70. return -EPERM;
  71. if (get_user(value, tptr))
  72. return -EFAULT;
  73. write_lock_irq(&xtime_lock);
  74. xtime.tv_sec = value;
  75. xtime.tv_usec = 0;
  76. time_adjust = 0; /* stop active adjtime() */
  77. time_status |= STA_UNSYNC;
  78. time_maxerror = NTP_PHASE_LIMIT;
  79. time_esterror = NTP_PHASE_LIMIT;
  80. write_unlock_irq(&xtime_lock);
  81. return 0;
  82. }
  83. #endif
  84. asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz)
  85. {
  86. if (tv) {
  87. struct timeval ktv;
  88. do_gettimeofday(&ktv);
  89. if (copy_to_user(tv, &ktv, sizeof(ktv)))
  90. return -EFAULT;
  91. }
  92. if (tz) {
  93. if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
  94. return -EFAULT;
  95. }
  96. return 0;
  97. }
  98. /*
  99.  * Adjust the time obtained from the CMOS to be UTC time instead of
  100.  * local time.
  101.  * 
  102.  * This is ugly, but preferable to the alternatives.  Otherwise we
  103.  * would either need to write a program to do it in /etc/rc (and risk
  104.  * confusion if the program gets run more than once; it would also be 
  105.  * hard to make the program warp the clock precisely n hours)  or
  106.  * compile in the timezone information into the kernel.  Bad, bad....
  107.  *
  108.  *               - TYT, 1992-01-01
  109.  *
  110.  * The best thing to do is to keep the CMOS clock in universal time (UTC)
  111.  * as real UNIX machines always do it. This avoids all headaches about
  112.  * daylight saving times and warping kernel clocks.
  113.  */
  114. inline static void warp_clock(void)
  115. {
  116. write_lock_irq(&xtime_lock);
  117. xtime.tv_sec += sys_tz.tz_minuteswest * 60;
  118. write_unlock_irq(&xtime_lock);
  119. }
  120. /*
  121.  * In case for some reason the CMOS clock has not already been running
  122.  * in UTC, but in some local time: The first time we set the timezone,
  123.  * we will warp the clock so that it is ticking UTC time instead of
  124.  * local time. Presumably, if someone is setting the timezone then we
  125.  * are running in an environment where the programs understand about
  126.  * timezones. This should be done at boot time in the /etc/rc script,
  127.  * as soon as possible, so that the clock can be set right. Otherwise,
  128.  * various programs will get confused when the clock gets warped.
  129.  */
  130. int do_sys_settimeofday(struct timeval *tv, struct timezone *tz)
  131. {
  132. static int firsttime = 1;
  133. if (!capable(CAP_SYS_TIME))
  134. return -EPERM;
  135. if (tz) {
  136. /* SMP safe, global irq locking makes it work. */
  137. sys_tz = *tz;
  138. if (firsttime) {
  139. firsttime = 0;
  140. if (!tv)
  141. warp_clock();
  142. }
  143. }
  144. if (tv)
  145. {
  146. /* SMP safe, again the code in arch/foo/time.c should
  147.  * globally block out interrupts when it runs.
  148.  */
  149. do_settimeofday(tv);
  150. }
  151. return 0;
  152. }
  153. asmlinkage long sys_settimeofday(struct timeval *tv, struct timezone *tz)
  154. {
  155. struct timeval new_tv;
  156. struct timezone new_tz;
  157. if (tv) {
  158. if (copy_from_user(&new_tv, tv, sizeof(*tv)))
  159. return -EFAULT;
  160. }
  161. if (tz) {
  162. if (copy_from_user(&new_tz, tz, sizeof(*tz)))
  163. return -EFAULT;
  164. }
  165. return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
  166. }
  167. long pps_offset; /* pps time offset (us) */
  168. long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
  169. long pps_freq; /* frequency offset (scaled ppm) */
  170. long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
  171. long pps_valid = PPS_VALID; /* pps signal watchdog counter */
  172. int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
  173. long pps_jitcnt; /* jitter limit exceeded */
  174. long pps_calcnt; /* calibration intervals */
  175. long pps_errcnt; /* calibration errors */
  176. long pps_stbcnt; /* stability limit exceeded */
  177. /* hook for a loadable hardpps kernel module */
  178. void (*hardpps_ptr)(struct timeval *);
  179. /* adjtimex mainly allows reading (and writing, if superuser) of
  180.  * kernel time-keeping variables. used by xntpd.
  181.  */
  182. int do_adjtimex(struct timex *txc)
  183. {
  184.         long ltemp, mtemp, save_adjust;
  185. int result;
  186. /* In order to modify anything, you gotta be super-user! */
  187. if (txc->modes && !capable(CAP_SYS_TIME))
  188. return -EPERM;
  189. /* Now we validate the data before disabling interrupts */
  190. if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
  191.   /* adjustment Offset limited to +- .512 seconds */
  192. if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
  193. return -EINVAL;
  194. /* if the quartz is off by more than 10% something is VERY wrong ! */
  195. if (txc->modes & ADJ_TICK)
  196. if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ)
  197. return -EINVAL;
  198. write_lock_irq(&xtime_lock);
  199. result = time_state; /* mostly `TIME_OK' */
  200. /* Save for later - semantics of adjtime is to return old value */
  201. save_adjust = time_adjust;
  202. #if 0 /* STA_CLOCKERR is never set yet */
  203. time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */
  204. #endif
  205. /* If there are input parameters, then process them */
  206. if (txc->modes)
  207. {
  208.     if (txc->modes & ADJ_STATUS) /* only set allowed bits */
  209. time_status =  (txc->status & ~STA_RONLY) |
  210.       (time_status & STA_RONLY);
  211.     if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */
  212. if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
  213.     result = -EINVAL;
  214.     goto leave;
  215. }
  216. time_freq = txc->freq - pps_freq;
  217.     }
  218.     if (txc->modes & ADJ_MAXERROR) {
  219. if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
  220.     result = -EINVAL;
  221.     goto leave;
  222. }
  223. time_maxerror = txc->maxerror;
  224.     }
  225.     if (txc->modes & ADJ_ESTERROR) {
  226. if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
  227.     result = -EINVAL;
  228.     goto leave;
  229. }
  230. time_esterror = txc->esterror;
  231.     }
  232.     if (txc->modes & ADJ_TIMECONST) { /* p. 24 */
  233. if (txc->constant < 0) { /* NTP v4 uses values > 6 */
  234.     result = -EINVAL;
  235.     goto leave;
  236. }
  237. time_constant = txc->constant;
  238.     }
  239.     if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
  240. if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
  241.     /* adjtime() is independent from ntp_adjtime() */
  242.     time_adjust = txc->offset;
  243. }
  244. else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
  245.     ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
  246.             (STA_PPSTIME | STA_PPSSIGNAL) ?
  247.             pps_offset : txc->offset;
  248.     /*
  249.      * Scale the phase adjustment and
  250.      * clamp to the operating range.
  251.      */
  252.     if (ltemp > MAXPHASE)
  253.         time_offset = MAXPHASE << SHIFT_UPDATE;
  254.     else if (ltemp < -MAXPHASE)
  255. time_offset = -(MAXPHASE << SHIFT_UPDATE);
  256.     else
  257.         time_offset = ltemp << SHIFT_UPDATE;
  258.     /*
  259.      * Select whether the frequency is to be controlled
  260.      * and in which mode (PLL or FLL). Clamp to the operating
  261.      * range. Ugly multiply/divide should be replaced someday.
  262.      */
  263.     if (time_status & STA_FREQHOLD || time_reftime == 0)
  264.         time_reftime = xtime.tv_sec;
  265.     mtemp = xtime.tv_sec - time_reftime;
  266.     time_reftime = xtime.tv_sec;
  267.     if (time_status & STA_FLL) {
  268.         if (mtemp >= MINSEC) {
  269.     ltemp = (time_offset / mtemp) << (SHIFT_USEC -
  270.       SHIFT_UPDATE);
  271.     if (ltemp < 0)
  272.         time_freq -= -ltemp >> SHIFT_KH;
  273.     else
  274.         time_freq += ltemp >> SHIFT_KH;
  275. } else /* calibration interval too short (p. 12) */
  276. result = TIME_ERROR;
  277.     } else { /* PLL mode */
  278.         if (mtemp < MAXSEC) {
  279.     ltemp *= mtemp;
  280.     if (ltemp < 0)
  281.         time_freq -= -ltemp >> (time_constant +
  282. time_constant +
  283. SHIFT_KF - SHIFT_USEC);
  284.     else
  285.         time_freq += ltemp >> (time_constant +
  286.        time_constant +
  287.        SHIFT_KF - SHIFT_USEC);
  288. } else /* calibration interval too long (p. 12) */
  289. result = TIME_ERROR;
  290.     }
  291.     if (time_freq > time_tolerance)
  292.         time_freq = time_tolerance;
  293.     else if (time_freq < -time_tolerance)
  294.         time_freq = -time_tolerance;
  295. } /* STA_PLL || STA_PPSTIME */
  296.     } /* txc->modes & ADJ_OFFSET */
  297.     if (txc->modes & ADJ_TICK) {
  298. /* if the quartz is off by more than 10% something is
  299.    VERY wrong ! */
  300. if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) {
  301.     result = -EINVAL;
  302.     goto leave;
  303. }
  304. tick = txc->tick;
  305.     }
  306. } /* txc->modes */
  307. leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
  308.     || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
  309. && (time_status & STA_PPSSIGNAL) == 0)
  310.     /* p. 24, (b) */
  311.     || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
  312. == (STA_PPSTIME|STA_PPSJITTER))
  313.     /* p. 24, (c) */
  314.     || ((time_status & STA_PPSFREQ) != 0
  315. && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
  316.     /* p. 24, (d) */
  317. result = TIME_ERROR;
  318. if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
  319.     txc->offset    = save_adjust;
  320. else {
  321.     if (time_offset < 0)
  322. txc->offset = -(-time_offset >> SHIFT_UPDATE);
  323.     else
  324. txc->offset = time_offset >> SHIFT_UPDATE;
  325. }
  326. txc->freq    = time_freq + pps_freq;
  327. txc->maxerror    = time_maxerror;
  328. txc->esterror    = time_esterror;
  329. txc->status    = time_status;
  330. txc->constant    = time_constant;
  331. txc->precision    = time_precision;
  332. txc->tolerance    = time_tolerance;
  333. txc->tick    = tick;
  334. txc->ppsfreq    = pps_freq;
  335. txc->jitter    = pps_jitter >> PPS_AVG;
  336. txc->shift    = pps_shift;
  337. txc->stabil    = pps_stabil;
  338. txc->jitcnt    = pps_jitcnt;
  339. txc->calcnt    = pps_calcnt;
  340. txc->errcnt    = pps_errcnt;
  341. txc->stbcnt    = pps_stbcnt;
  342. write_unlock_irq(&xtime_lock);
  343. do_gettimeofday(&txc->time);
  344. return(result);
  345. }
  346. asmlinkage long sys_adjtimex(struct timex *txc_p)
  347. {
  348. struct timex txc; /* Local copy of parameter */
  349. int ret;
  350. /* Copy the user data space into the kernel copy
  351.  * structure. But bear in mind that the structures
  352.  * may change
  353.  */
  354. if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
  355. return -EFAULT;
  356. ret = do_adjtimex(&txc);
  357. return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
  358. }