Back to index

glibc  2.9
gettimeofday.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991,92,94,95,96,97,2001,2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #include <time.h>
00021 #include <sys/time.h>
00022 
00023 #ifndef HAVE_GNU_LD
00024 # define __daylight  daylight
00025 # define __timezone  timezone
00026 # define __tzname    tzname
00027 #endif
00028 
00029 #undef __gettimeofday
00030 
00031 extern int rtc_upper (void);
00032 extern int rtc_lower (void);
00033 
00034 /* Assembler Routines to access the timer registers */
00035 asm("\n\
00036 .rtc_upper: mfspr   3,4         # copy RTCU to return register\n\
00037             blr\n\
00038 \n\
00039 .rtc_lower: mfspr   3,5         # copy RTCL to return register\n\
00040             blr\n\
00041 ");
00042 
00043 /* Get the current time of day and timezone information,
00044    putting it into *TV and *TZ.  If TZ is NULL, *TZ is not filled.
00045    Returns 0 on success, -1 on errors.  */
00046 int
00047 __gettimeofday (tv, tz)
00048      struct timeval  *tv;
00049      struct timezone *tz;
00050 {
00051   int ts, tl, tu;
00052 
00053   if (tv == NULL)
00054     {
00055       __set_errno (EINVAL);
00056       return -1;
00057     }
00058 
00059   ts = rtc_upper ();        /* Seconds.  */
00060   tl = rtc_lower ();        /* Nanoseconds.  */
00061   tu = rtc_upper ();        /* Check for a carry from.  */
00062   if (ts != tu)                    /* The lower reg to the upper.  */
00063       tl  = rtc_lower ();   /* Recover from the race condition.  */
00064 
00065   tv->tv_sec  = (long int) (tu + (double) tl / 1000000000);
00066   tv->tv_usec = (long int) ((double) tl / 1000);
00067 
00068   if (tz != NULL)
00069     {
00070       const  time_t timer = tv->tv_sec;
00071       struct tm tm;
00072       const  struct tm *tmp;
00073 
00074       const long int save_timezone = __timezone;
00075       const long int save_daylight = __daylight;
00076       char *save_tzname[2];
00077       save_tzname[0] = __tzname[0];
00078       save_tzname[1] = __tzname[1];
00079 
00080       tmp = localtime_r (&timer, &tm);
00081 
00082       tz->tz_minuteswest = __timezone / 60;
00083       tz->tz_dsttime     = __daylight;
00084 
00085       __timezone  = save_timezone;
00086       __daylight  = save_daylight;
00087       __tzname[0] = save_tzname[0];
00088       __tzname[1] = save_tzname[1];
00089 
00090       if (tmp == NULL)
00091        return -1;
00092     }
00093 
00094   return 0;
00095 }
00096 
00097 INTDEF(__gettimeofday)
00098 weak_alias (__gettimeofday, gettimeofday)