Ядро Linux в комментариях

       

Kernel/time.c


31331 /* 31332 * linux/kernel/time.c 31333 * 31334 * Copyright (C) 1991, 1992 Linus Torvalds 31335 * 31336 * This file contains the interface functions for the 31337 * various time related system calls: time, stime, 31338 * gettimeofday, settimeofday, adjtime */ 31339 /* 31340 * Modification history kernel/time.c 31341 * 31342 * 1993-09-02 Philip Gladstone 31343 * Created file with time related functions from 31344 * sched.c and adjtimex() 31345 * 1993-10-08 Torsten Duwe 31346 * adjtime interface update and CMOS clock write 31347 * code 31348 * 1995-08-13 Torsten Duwe 31349 * kernel PLL updated to 1994-12-13 specs (rfc-1589) 31350 * 1999-01-16 Ulrich Windl 31351 * Introduced error checking for many cases in 31352 * adjtimex(). Updated NTP code according to 31353 * technical memorandum Jan '96 "A Kernel Model for 31354 * Precision Timekeeping" by Dave Mills Allow 31355 * time_constant larger than MAXTC(6) for NTP v4 31356 * (MAXTC == 10) (Even though the technical 31357 * memorandum forbids it) */ 31358 31359 #include <linux/mm.h> 31360 #include <linux/timex.h> 31361 #include <linux/smp_lock.h> 31362 31363 #include <asm/uaccess.h> 31364 31365 /* The timezone where the local system is located. Used 31366 * as a default by some programs who obtain this value by 31367 * using gettimeofday. */ 31368 struct timezone sys_tz = { 0, 0}; 31369 31370 static void do_normal_gettime(struct timeval * tm) 31371 { 31372 *tm=xtime; 31373 } 31374 31375 void (*do_get_fast_time)(struct timeval *) = 31376 do_normal_gettime; 31377 31378 /* Generic way to access 'xtime' (the current time of 31379 * day). This can be changed if the platform provides a 31380 * more accurate (and fast!) version. */ 31381 31382 void get_fast_time(struct timeval * t) 31383 { 31384 do_get_fast_time(t); 31385 } 31386 31387 #ifndef __alpha__ 31388 31389 /* sys_time() can be implemented in user-level using 31390 * sys_gettimeofday(). Is this for backwards 31391 * compatibility? If so, why not move it into the 31392 * appropriate arch directory (for those architectures 31393 * that need it). */


31394 asmlinkage int sys_time(int * tloc) 31395 { 31396 int i; 31397 31398 /* SMP: This is fairly trivial. We grab CURRENT_TIME 31399 * and stuff it to user space. No side effects */ 31400 i = CURRENT_TIME; 31401 if (tloc) { 31402 if (put_user(i,tloc)) 31403 i = -EFAULT; 31404 } 31405 return i; 31406 } 31407 31408 /* sys_stime() can be implemented in user-level using 31409 * sys_settimeofday(). Is this for backwards 31410 * compatibility? If so, why not move it into the 31411 * appropriate arch directory (for those architectures 31412 * that need it). */ 31413 asmlinkage int sys_stime(int * tptr) 31414 { 31415 int value; 31416 31417 if (!capable(CAP_SYS_TIME)) 31418 return -EPERM; 31419 if (get_user(value, tptr)) 31420 return -EFAULT; 31421 cli(); 31422 xtime.tv_sec = value; 31423 xtime.tv_usec = 0; 31424 time_adjust = 0; /* stop active adjtime() */ 31425 time_status |= STA_UNSYNC; 31426 time_maxerror = NTP_PHASE_LIMIT; 31427 time_esterror = NTP_PHASE_LIMIT; 31428 sti(); 31429 return 0; 31430 } 31431 31432 #endif 31433 31434 asmlinkage int sys_gettimeofday(struct timeval *tv, 31435 struct timezone *tz) 31436 { 31437 if (tv) { 31438 struct timeval ktv; 31439 do_gettimeofday(&ktv); 31440 if (copy_to_user(tv, &ktv, sizeof(ktv))) 31441 return -EFAULT; 31442 } 31443 if (tz) { 31444 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 31445 return -EFAULT; 31446 } 31447 return 0; 31448 } 31449 31450 /* Adjust the time obtained from the CMOS to be UTC time 31451 * instead of local time. 31452 * 31453 * This is ugly, but preferable to the alternatives. 31454 * Otherwise we would either need to write a program to 31455 * do it in /etc/rc (and risk confusion if the program 31456 * gets run more than once; it would also be hard to make 31457 * the program warp the clock precisely n hours) or 31458 * compile in the timezone information into the kernel. 31459 * Bad, bad.... 31460 * 31461 * - TYT, 1992-01-01 31462 * 31463 * The best thing to do is to keep the CMOS clock in 31464 * universal time (UTC) as real UNIX machines always do 31465 * it. This avoids all headaches about daylight saving 31466 * times and warping kernel clocks. */ 31467 inline static void warp_clock(void) 31468 { 31469 cli(); 31470 xtime.tv_sec += sys_tz.tz_minuteswest * 60; 31471 sti(); 31472 } 31473 31474 /* In case for some reason the CMOS clock has not already 31475 * been running in UTC, but in some local time: The first 31476 * time we set the timezone, we will warp the clock so 31477 * that it is ticking UTC time instead of local 31478 * time. Presumably, if someone is setting the timezone 31479 * then we are running in an environment where the 31480 * programs understand about timezones. This should be 31481 * done at boot time in the /etc/rc script, as soon as 31482 * possible, so that the clock can be set 31483 * right. Otherwise, various programs will get confused 31484 * when the clock gets warped. */ 31485 int do_sys_settimeofday(struct timeval *tv, 31486 struct timezone *tz) 31487 { 31488 static int firsttime = 1; 31489 31490 if (!capable(CAP_SYS_TIME)) 31491 return -EPERM; 31492 31493 if (tz) { 31494 /* SMP safe, global irq locking makes it work. */ 31495 sys_tz = *tz; 31496 if (firsttime) { 31497 firsttime = 0; 31498 if (!tv) 31499 warp_clock(); 31500 } 31501 } 31502 if (tv) 31503 { 31504 /* SMP safe, again the code in arch/foo/time.c should 31505 * globally block out interrupts when it runs. 31506 */ 31507 do_settimeofday(tv); 31508 } 31509 return 0; 31510 } 31511 31512 asmlinkage int sys_settimeofday(struct timeval *tv, 31513 struct timezone *tz) 31514 { 31515 struct timeval new_tv; 31516 struct timezone new_tz; 31517 31518 if (tv) { 31519 if (copy_from_user(&new_tv, tv, sizeof(*tv))) 31520 return -EFAULT; 31521 } 31522 if (tz) { 31523 if (copy_from_user(&new_tz, tz, sizeof(*tz))) 31524 return -EFAULT; 31525 } 31526 31527 return do_sys_settimeofday(tv ? &new_tv : NULL, 31528 tz ? &new_tz : NULL); 31529 } 31530 31531 long pps_offset = 0; /* pps time offset (us) */ 31532 long pps_jitter = MAXTIME; /* time dispersion (jitter) 31533 (us) */ 31534 long pps_freq = 0; /* frequency offset (scaled 31535 ppm) */ 31536 long pps_stabil = MAXFREQ; /* frequency dispersion 31537 (scaled ppm) */ 31538 long pps_valid = PPS_VALID; /* pps signal watchdog 31539 counter */ 31540 int pps_shift = PPS_SHIFT; /* interval duration (s) 31541 (shift) */ 31542 long pps_jitcnt = 0; /* jitter limit exceeded */ 31543 long pps_calcnt = 0; /* calibration intervals */ 31544 long pps_errcnt = 0; /* calibration errors */ 31545 long pps_stbcnt = 0; /* stability limit exceeded*/ 31546 31547 /* hook for a loadable hardpps kernel module */ 31548 void (*hardpps_ptr)(struct timeval *) = 31549 (void (*)(struct timeval *))0; 31550 31551 /* adjtimex mainly allows reading (and writing, if 31552 * superuser) of kernel time-keeping variables. used by 31553 * xntpd. */ 31554 int do_adjtimex(struct timex *txc) 31555 { 31556 long ltemp, mtemp, save_adjust; 31557 int result = time_state; /* mostly `TIME_OK' */ 31558 31559 /* In order to modify anything, you gotta be 31560 * super-user! */ 31561 if (txc->modes && !capable(CAP_SYS_TIME)) 31562 return -EPERM; 31563 31564 /* Now we validate the data before disabling interrupts 31565 */ 31566 if (txc->modes != ADJ_OFFSET_SINGLESHOT && 31567 (txc->modes & ADJ_OFFSET)) 31568 /* adjustment Offset limited to +- .512 seconds */ 31569 if (txc->offset <= - MAXPHASE 31570 txc->offset >= MAXPHASE) 31571 return -EINVAL; 31572 31573 /* if the quartz is off by more than 10% something is 31574 * VERY wrong ! */ 31575 if (txc->modes & ADJ_TICK) 31576 if (txc->tick < 900000/HZ txc->tick > 1100000/HZ) 31577 return -EINVAL; 31578 31579 cli(); /* SMP: global cli() is enough protection. */ 31580 31581 /* Save for later - semantics of adjtime is to return 31582 * old value */ 31583 save_adjust = time_adjust; 31584 31585 #if 0 /* STA_CLOCKERR is never set yet */ 31586 time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */ 31587 #endif 31588 /* If there are input parameters, then process them */ 31589 if (txc->modes) 31590 { 31591 if (txc->modes & ADJ_STATUS) 31592 /* only set allowed bits */ 31593 time_status = (txc->status & ~STA_RONLY) | 31594 (time_status & STA_RONLY); 31595 31596 if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */ 31597 if (txc->freq > MAXFREQ txc->freq < -MAXFREQ){ 31598 result = -EINVAL; 31599 goto leave; 31600 } 31601 time_freq = txc->freq - pps_freq; 31602 } 31603 31604 if (txc->modes & ADJ_MAXERROR) { 31605 if (txc->maxerror < 0 31606 txc->maxerror >= NTP_PHASE_LIMIT) { 31607 result = -EINVAL; 31608 goto leave; 31609 } 31610 time_maxerror = txc->maxerror; 31611 } 31612 31613 if (txc->modes & ADJ_ESTERROR) { 31614 if (txc->esterror < 0 31615 txc->esterror >= NTP_PHASE_LIMIT) { 31616 result = -EINVAL; 31617 goto leave; 31618 } 31619 time_esterror = txc->esterror; 31620 } 31621 31622 if (txc->modes & ADJ_TIMECONST) { /* p. 24 */ 31623 if (txc->constant < 0) { /*NTP v4 uses values > 6*/ 31624 result = -EINVAL; 31625 goto leave; 31626 } 31627 time_constant = txc->constant; 31628 } 31629 31630 /* values checked earlier */ 31631 if (txc->modes & ADJ_OFFSET) { 31632 if (txc->modes == ADJ_OFFSET_SINGLESHOT) { 31633 /* adjtime() is independent from ntp_adjtime() */ 31634 time_adjust = txc->offset; 31635 } 31636 else if ( time_status & (STA_PLL | STA_PPSTIME) ) { 31637 ltemp = 31638 (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) 31639 == (STA_PPSTIME | STA_PPSSIGNAL) 31640 ? pps_offset : txc->offset; 31641 31642 /* Scale the phase adjustment and clamp to the 31643 * operating range. */ 31644 if (ltemp > MAXPHASE) 31645 time_offset = MAXPHASE << SHIFT_UPDATE; 31646 else if (ltemp < -MAXPHASE) 31647 time_offset = -(MAXPHASE << SHIFT_UPDATE); 31648 else 31649 time_offset = ltemp << SHIFT_UPDATE; 31650 31651 /* Select whether the frequency is to be 31652 * controlled and in which mode (PLL or 31653 * FLL). Clamp to the operating range. Ugly 31654 * multiply/divide should be replaced someday. 31655 */ 31656 31657 if (time_status & STA_FREQHOLD 31658 time_reftime == 0) 31659 time_reftime = xtime.tv_sec; 31660 mtemp = xtime.tv_sec - time_reftime; 31661 time_reftime = xtime.tv_sec; 31662 if (time_status & STA_FLL) { 31663 if (mtemp >= MINSEC) { 31664 ltemp = (time_offset / mtemp) << 31665 (SHIFT_USEC - SHIFT_UPDATE); 31666 if (ltemp < 0) 31667 time_freq -= -ltemp >> SHIFT_KH; 31668 else 31669 time_freq += ltemp >> SHIFT_KH; 31670 } else 31671 /* calibration interval too short (p. 12) */ 31672 result = TIME_ERROR; 31673 } else { /* PLL mode */ 31674 if (mtemp < MAXSEC) { 31675 ltemp *= mtemp; 31676 if (ltemp < 0) 31677 time_freq -= -ltemp >> 31678 (time_constant + 31679 time_constant + 31680 SHIFT_KF - SHIFT_USEC); 31681 else 31682 time_freq += ltemp >> 31683 (time_constant + 31684 time_constant + 31685 SHIFT_KF - SHIFT_USEC); 31686 } else 31687 /* calibration interval too long (p. 12) */ 31688 result = TIME_ERROR; 31689 } 31690 if (time_freq > time_tolerance) 31691 time_freq = time_tolerance; 31692 else if (time_freq < -time_tolerance) 31693 time_freq = -time_tolerance; 31694 } /* STA_PLL STA_PPSTIME */ 31695 } /* txc->modes & ADJ_OFFSET */ 31696 if (txc->modes & ADJ_TICK) { 31697 /* if the quartz is off by more than 10% something 31698 is VERY wrong ! */ 31699 if (txc->tick < 900000/HZ 31700 txc->tick > 1100000/HZ) { 31701 result = -EINVAL; 31702 goto leave; 31703 } 31704 tick = txc->tick; 31705 } 31706 } /* txc->modes */ 31707 leave: 31708 if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 31709 ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0 31710 && (time_status & STA_PPSSIGNAL) == 0) 31711 /* p. 24, (b) */ 31712 ((time_status & (STA_PPSTIME|STA_PPSJITTER)) 31713 == (STA_PPSTIME|STA_PPSJITTER)) 31714 /* p. 24, (c) */ 31715 ((time_status & STA_PPSFREQ) != 0 31716 && (time_status & 31717 (STA_PPSWANDER|STA_PPSERROR)) != 0)) 31718 /* p. 24, (d) */ 31719 result = TIME_ERROR; 31720 31721 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == 31722 ADJ_OFFSET_SINGLESHOT) 31723 txc->offset = save_adjust; 31724 else { 31725 if (time_offset < 0) 31726 txc->offset = -(-time_offset >> SHIFT_UPDATE); 31727 else 31728 txc->offset = time_offset >> SHIFT_UPDATE; 31729 } 31730 txc->freq = time_freq + pps_freq; 31731 txc->maxerror = time_maxerror; 31732 txc->esterror = time_esterror; 31733 txc->status = time_status; 31734 txc->constant = time_constant; 31735 txc->precision = time_precision; 31736 txc->tolerance = time_tolerance; 31737 do_gettimeofday(&txc->time); 31738 txc->tick = tick; 31739 txc->ppsfreq = pps_freq; 31740 txc->jitter = pps_jitter >> PPS_AVG; 31741 txc->shift = pps_shift; 31742 txc->stabil = pps_stabil; 31743 txc->jitcnt = pps_jitcnt; 31744 txc->calcnt = pps_calcnt; 31745 txc->errcnt = pps_errcnt; 31746 txc->stbcnt = pps_stbcnt; 31747 31748 sti(); 31749 return(result); 31750 } 31751 31752 asmlinkage int sys_adjtimex(struct timex *txc_p) 31753 { 31754 struct timex txc; /* Local copy of parameter */ 31755 int ret; 31756 31757 /* Copy the user data space into the kernel copy 31758 * structure. But bear in mind that the structures may 31759 * change */ 31760 if(copy_from_user(&txc, txc_p, sizeof(struct timex))) 31761 return -EFAULT; 31762 ret = do_adjtimex(&txc); 31763 return copy_to_user(txc_p, &txc, sizeof(struct timex)) 31764 ? -EFAULT : ret; 31765 }


Содержание раздела