uint64_t uv__hrtime(void) { uint64_t G = 1000000000; timebasestruct_t t; read_wall_time(&t, TIMEBASE_SZ); time_base_to_time(&t, TIMEBASE_SZ); return (uint64_t) t.tb_high * G + t.tb_low; }
/* * Get an arbitrary timer value of the highest possible resolution * * The timer value is added as random noise to the additional data, * which is not considered a trusted entropy sourec, so any result * is acceptable. */ static uint64_t get_timer_bits(void) { uint64_t res = OPENSSL_rdtsc(); if (res != 0) return res; # if defined(__sun) || defined(__hpux) return gethrtime(); # elif defined(_AIX) { timebasestruct_t t; read_wall_time(&t, TIMEBASE_SZ); return TWO32TO64(t.tb_high, t.tb_low); } # elif defined(OSSL_POSIX_TIMER_OKAY) { struct timespec ts; # ifdef CLOCK_BOOTTIME # define CLOCK_TYPE CLOCK_BOOTTIME # elif defined(_POSIX_MONOTONIC_CLOCK) # define CLOCK_TYPE CLOCK_MONOTONIC # else # define CLOCK_TYPE CLOCK_REALTIME # endif if (clock_gettime(CLOCK_TYPE, &ts) == 0) return TWO32TO64(ts.tv_sec, ts.tv_nsec); } # endif # if defined(__unix__) \ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) { struct timeval tv; if (gettimeofday(&tv, NULL) == 0) return TWO32TO64(tv.tv_sec, tv.tv_usec); } # endif return time(NULL); }
/* * Find a suitable source of time. Start with the highest resolution source * and work down to the slower ones. This is added as additional data and * isn't counted as randomness, so any result is acceptable. * * Returns 0 when we weren't able to find any time source */ static uint64_t get_timer_bits(void) { uint64_t res = OPENSSL_rdtsc(); if (res != 0) return res; #if defined(_WIN32) { LARGE_INTEGER t; FILETIME ft; if (QueryPerformanceCounter(&t) != 0) return t.QuadPart; GetSystemTimeAsFileTime(&ft); return TWO32TO64(ft.dwHighDateTime, ft.dwLowDateTime); } #elif defined(__sun) || defined(__hpux) return gethrtime(); #elif defined(_AIX) { timebasestruct_t t; read_wall_time(&t, TIMEBASE_SZ); return TWO32TO64(t.tb_high, t.tb_low); } #else # if defined(OSSL_POSIX_TIMER_OKAY) { struct timespec ts; clockid_t cid; # ifdef CLOCK_BOOTTIME cid = CLOCK_BOOTTIME; # elif defined(_POSIX_MONOTONIC_CLOCK) cid = CLOCK_MONOTONIC; # else cid = CLOCK_REALTIME; # endif if (clock_gettime(cid, &ts) == 0) return TWO32TO64(ts.tv_sec, ts.tv_nsec); } # endif # if defined(__unix__) \ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) { struct timeval tv; if (gettimeofday(&tv, NULL) == 0) return TWO32TO64(tv.tv_sec, tv.tv_usec); } # endif { time_t t = time(NULL); if (t == (time_t)-1) return 0; return t; } #endif }
static zend_always_inline php_hrtime_t _timer_current(void) {/*{{{*/ #if PHP_HRTIME_PLATFORM_WINDOWS LARGE_INTEGER lt = {0}; QueryPerformanceCounter(<); return (php_hrtime_t)((php_hrtime_t)lt.QuadPart * _timer_scale); #elif PHP_HRTIME_PLATFORM_APPLE return (php_hrtime_t)mach_absolute_time() * _timerlib_info.numer / _timerlib_info.denom; #elif PHP_HRTIME_PLATFORM_POSIX struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) { return ((php_hrtime_t) ts.tv_sec * (php_hrtime_t)NANO_IN_SEC) + ts.tv_nsec; } return 0; #elif PHP_HRTIME_PLATFORM_HPUX return (php_hrtime_t) gethrtime(); #elif PHP_HRTIME_PLATFORM_AIX timebasestruct_t t; read_wall_time(&t, TIMEBASE_SZ); time_base_to_time(&t, TIMEBASE_SZ); return (php_hrtime_t) t.tb_high * (php_hrtime_t)NANO_IN_SEC + t.tb_low; #else return 0; #endif }/*}}}*/ #if ZEND_ENABLE_ZVAL_LONG64 #define PHP_RETURN_HRTIME(t) RETURN_LONG((zend_long)t) #else #ifdef _WIN32 # define HRTIME_U64A(i, s, len) _ui64toa_s(i, s, len, 10) #else # define HRTIME_U64A(i, s, len) \ do { \ int st = snprintf(s, len, "%llu", i); \ s[st] = '\0'; \ } while (0) #endif #define PHP_RETURN_HRTIME(t) do { \ char _a[ZEND_LTOA_BUF_LEN]; \ double _d; \ HRTIME_U64A(t, _a, ZEND_LTOA_BUF_LEN); \ _d = zend_strtod(_a, NULL); \ RETURN_DOUBLE(_d); \ } while (0) #endif /* {{{ proto mixed hrtime([bool get_as_number = false]) Returns an array of integers in form [seconds, nanoseconds] counted from an arbitrary point in time. If an optional boolean argument is passed, returns an integer on 64-bit platforms or float on 32-bit containing the current high-resolution time in nanoseconds. The delivered timestamp is monotonic and can not be adjusted. */ PHP_FUNCTION(hrtime) { #if HRTIME_AVAILABLE zend_bool get_as_num = 0; php_hrtime_t t = _timer_current(); ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_BOOL(get_as_num) ZEND_PARSE_PARAMETERS_END(); if (UNEXPECTED(get_as_num)) { PHP_RETURN_HRTIME(t); } else { array_init_size(return_value, 2); zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); add_next_index_long(return_value, (zend_long)(t / (php_hrtime_t)NANO_IN_SEC)); add_next_index_long(return_value, (zend_long)(t % (php_hrtime_t)NANO_IN_SEC)); } #else RETURN_FALSE #endif } /* }}} */ PHPAPI php_hrtime_t php_hrtime_current(void) {/*{{{*/ return _timer_current(); }/*}}}*/