/* * R : A Computer Language for Statistical Data Analysis * Copyright (C) 2000-2016 The R Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * https://www.R-project.org/Licenses/ * * * Interfaces to time functions. */ /* Notes on various time functions: =============================== The current (2008/13) POSIX recommendation to find the calendar time is to call clock_gettime(), defined in . This may also be used to find the time since some unspecified starting point (e.g. machine reboot), but is not currently so used in R. It returns in second and nanoseconds, although not necessarily to more than clock-tick accuracy. C11 adds 'struct timespec' to . And timespec_get() which can get the current time or interval after a base time. The previous POSIX recommendation was gettimeofday(), defined in . This returns in seconds and microseconds (with unspecified granularity). Many systems (including AIX, FreeBSD, Linux, Solaris) have clock_gettime(): it appeared in macOS 10.12. macOS and Cygwin have gettimeofday(). Function time() is C99 and defined in . C99 does not mandate the units, but POSIX does (as the number of seconds since the epoch: although not mandated, time_t seems always to be an integer type). Function clock() is C99 and defined in . It measures CPU time at CLOCKS_PER_SEC: there is a small danger of integer overflow. Function times() is POSIX and defined in . It returns the elapsed time in clock ticks, plus CPU times in a struct tms* argument (also in clock ticks). More precise information on CPU times may be available from the POSIX function getrusage() defined in . This returns the same time structure as gettimeofday() and on some systems offers millisecond resolution. It is available on Cygwin, FreeBSD, macOS, Linux and Solaris. currentTime() (in this file) uses clock_gettime(): AIX, FreeBSD, Linux, Solaris, macOS >= 10.12 gettimeofday(): macOS <= 10.11, Windows, Cygwin time() (as ultimate fallback, AFAIK unused). proc.time() uses currentTime() for elapsed time, and getrusage, then times for CPU times on a Unix-alike, GetProcessTimes on Windows. devPS.c uses time() and localtime() for timestamps. do_date (platform.c) uses ctime. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include /* clock_gettime, timespec_get time are in */ #ifdef HAVE_SYS_TIME_H /* gettimeoday, including on Windows */ # include #endif double currentTime(void) { double ans = NA_REAL; #ifdef HAVE_TIMESPEC_GET struct timespec tp; int res = timespec_get(&tp, TIME_UTC); if(res != 0) ans = (double) tp.tv_sec + 1e-9 * (double) tp.tv_nsec; #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) /* Has 2038 issue if time_t: tv.tv_sec is 32-bit. */ struct timespec tp; int res = clock_gettime(CLOCK_REALTIME, &tp); if(res == 0) ans = (double) tp.tv_sec + 1e-9 * (double) tp.tv_nsec; #elif defined(HAVE_GETTIMEOFDAY) /* macOS , mingw.org, used on mingw-w64. Has 2038 issue if time_t: tv.tv_sec is 32-bit. */ struct timeval tv; int res = gettimeofday(&tv, NULL); if(res == 0) ans = (double) tv.tv_sec + 1e-6 * (double) tv.tv_usec; #else /* No known current OSes */ time_t res = time(NULL); if(res != (time_t)(-1)) /* -1 must be an error as the real value -1 was ca 1969 */ ans = (double) res; #endif #ifndef HAVE_POSIX_LEAPSECONDS /* No known current OSes */ /* Disallowed by POSIX (1988-): http://www.mail-archive.com/leapsecs@rom.usno.navy.mil/msg00109.html https://en.wikipedia.org/wiki/Unix_time */ if (!ISNAN(ans)) { ans -= n_leapseconds; } #endif return ans; } SEXP attribute_hidden do_systime(SEXP call, SEXP op, SEXP args, SEXP env) { checkArity(op, args); return ScalarReal(currentTime()); } #ifdef HAVE_UNISTD_H #include /* for getpid */ #endif /* For RNG.c, main.c, mkdtemp.c */ attribute_hidden unsigned int TimeToSeed(void) { unsigned int seed, pid = getpid(); #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) { struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); seed = (unsigned int)(((uint_least64_t) tp.tv_nsec << 16) ^ tp.tv_sec); } #elif defined(HAVE_GETTIMEOFDAY) { struct timeval tv; gettimeofday (&tv, NULL); seed = (unsigned int)(((uint_least64_t) tv.tv_usec << 16) ^ tv.tv_sec); } #else /* C89, so must work */ seed = (Int32) time(NULL); #endif seed ^= (pid <<16); return seed; }