time.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

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