diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 5313a85d7a6c0..87e57bc86dc2d 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -559,10 +559,8 @@ static const func_info_t func_infos[] = { F1("dechex", MAY_BE_STRING), F1("base_convert", MAY_BE_STRING), F1("number_format", MAY_BE_STRING), -#if defined(HAVE_GETTIMEOFDAY) F1("microtime", MAY_BE_STRING|MAY_BE_DOUBLE), F1("gettimeofday", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_DOUBLE), -#endif #if defined(HAVE_GETRUSAGE) F1("getrusage", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_FALSE), #endif @@ -597,9 +595,7 @@ static const func_info_t func_infos[] = { F1("stream_resolve_include_path", MAY_BE_STRING|MAY_BE_FALSE), F1("stream_get_wrappers", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("stream_get_transports", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), -#if defined(HAVE_GETTIMEOFDAY) F1("uniqid", MAY_BE_STRING), -#endif F1("parse_url", MAY_BE_LONG|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_NULL|MAY_BE_FALSE), F1("urlencode", MAY_BE_STRING), F1("urldecode", MAY_BE_STRING), diff --git a/Zend/zend_time.c b/Zend/zend_time.c new file mode 100644 index 0000000000000..3fb117690da95 --- /dev/null +++ b/Zend/zend_time.c @@ -0,0 +1,78 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marc Bennewitz | + +----------------------------------------------------------------------+ +*/ + +#include "zend_time.h" + +ZEND_API time_t zend_realtime_get(time_t *sec, long *nsec) { + if (!nsec) { + return time(sec); + } + +#if defined(HAVE_CLOCK_GETTIME) + + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + if (sec) *sec = ts.tv_sec; + *nsec = ts.tv_nsec; + return ts.tv_sec; + +#elif defined(HAVE_TIMESPEC_GET) + + struct timespec ts; + timespec_get(&ts, TIME_UTC); + if (sec) *sec = ts.tv_sec; + *nsec = ts.tv_nsec; + return ts.tv_sec; + +#elif defined(HAVE_GETTIMEOFDAY) + + struct timeval tv; + gettimeofday(&tv, NULL); + + if (sec) *sec = tv.tv_sec; + *nsec = tv.tv_usec * 1000; + return tv.tv_sec; + +#else + + *nsec = 0; + return time(sec); + +#endif +} + +ZEND_API void zend_realtime_spec(struct timespec *ts) { +#if defined(HAVE_CLOCK_GETTIME) + + clock_gettime(CLOCK_REALTIME, ts); + +#elif defined(HAVE_TIMESPEC_GET) + + timespec_get(ts, TIME_UTC); + +#elif defined(HAVE_GETTIMEOFDAY) + + struct timeval tv; + gettimeofday(&tv, NULL); + zend_time_val2spec(tv, ts); + +#else + + ts->tv_sec = time(NULL); + ts->tv_nsec = 0; + +#endif +} diff --git a/Zend/zend_time.h b/Zend/zend_time.h new file mode 100644 index 0000000000000..bf129f4cefa90 --- /dev/null +++ b/Zend/zend_time.h @@ -0,0 +1,95 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marc Bennewitz | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_TIME_H +#define ZEND_TIME_H + +#include "zend_portability.h" + +#ifdef PHP_WIN32 +# include "win32/time.h" +#endif +#ifdef HAVE_SYS_TIME_H +# include +#endif +#include + +#include "zend_hrtime.h" + +#define ZEND_MILLI_IN_SEC 1000U +#define ZEND_MICRO_IN_SEC 1000000U + +#ifndef PHP_WIN32 + +/* Helper macro to assign seconds to timeval */ +# define zend_time_sec2val(s, tv) \ + (tv).tv_sec = (time_t) (s); \ + (tv).tv_usec = 0; + +/* Helper macro to assign microseconds to timeval */ +# define zend_time_usec2val(usec, tv) \ + (tv).tv_sec = (time_t) ((usec) / ZEND_MICRO_IN_SEC); \ + (tv).tv_usec = (suseconds_t) ((usec) % ZEND_MICRO_IN_SEC); + +/* Helper macro to assign double (seconds) to timeval */ +# define zend_time_dbl2val(d, tv) \ + (tv).tv_sec = (time_t) (d); \ + (tv).tv_usec = (suseconds_t) (((d) - (tv).tv_sec) * ZEND_MICRO_IN_SEC); + +#else + +# define zend_time_sec2val(s, tv) \ + (tv).tv_sec = (long) (s); \ + (tv).tv_usec = 0; + +# define zend_time_usec2val(usec, tv) \ + (tv).tv_sec = (long) ((usec) / ZEND_MICRO_IN_SEC); \ + (tv).tv_usec = (long) ((usec) % ZEND_MICRO_IN_SEC); + +# define zend_time_dbl2val(d, tv) \ + (tv).tv_sec = (long) (d); \ + (tv).tv_usec = (long) (((d) - (tv).tv_sec) * ZEND_MICRO_IN_SEC); + +#endif + +/* Helper macro to copy timeval to timespec */ +#define zend_time_val2spec(tv, ts) \ + (ts).tv_sec = (time_t) (tv).tv_sec; \ + (ts).tv_nsec = (long) ((tv).tv_usec * 1000); + +BEGIN_EXTERN_C() + +/* Like time() but with up to nanosecond */ +ZEND_API time_t zend_realtime_get(time_t *sec, long *nsec); + +/* wrapper around clock_gettime/timestamp_get/gettimeofday/time */ +ZEND_API void zend_realtime_spec(struct timespec *ts); + +/* Monotonic time in nanoseconds with a fallback to real/wall-time + if no monotonic timer is available */ +#if ZEND_HRTIME_AVAILABLE +# define zend_monotime_fallback() (uint64_t)zend_hrtime() +#else +ZEND_API zend_always_inline uint64_t zend_monotime_fallback(void) { + struct timespec ts; + zend_realtime_spec(&ts); + return ((uint64_t) ts.tv_sec * ZEND_NANO_IN_SEC) + ts.tv_nsec; +} +#endif + +END_EXTERN_C() + +#endif // ZEND_TIME_H diff --git a/configure.ac b/configure.ac index 2bd6ae26ce625..6249ae7783603 100644 --- a/configure.ac +++ b/configure.ac @@ -529,6 +529,8 @@ AC_CHECK_FUNCS(m4_normalize([ asctime_r asprintf chroot + clock_gettime + clock_getres ctime_r explicit_memset fdatasync @@ -580,6 +582,8 @@ AC_CHECK_FUNCS(m4_normalize([ strptime strtok_r symlink + timespec_get + timespec_getres tzset unsetenv usleep @@ -1748,6 +1752,7 @@ PHP_ADD_SOURCES([Zend], m4_normalize([ zend_generators.c zend_hash.c zend_highlight.c + zend_time.c zend_hrtime.c zend_inheritance.c zend_ini_parser.c diff --git a/docs-old/streams.md b/docs-old/streams.md index 8220f9db78fc6..7652d0a4aac8c 100644 --- a/docs-old/streams.md +++ b/docs-old/streams.md @@ -90,7 +90,7 @@ PHPAPI php_stream *php_stream_sock_open_from_socket(int socket, int persistent); /* Convert a socket into a stream. */ PHPAPI php_stream *php_stream_sock_open_host(const char *host, unsigned short port, - int socktype, int timeout, int persistent); + int socktype, struct timeval *timeout, const char *persistent_id); /* Open a connection to a host and return a stream. */ PHPAPI php_stream *php_stream_sock_open_unix(const char *path, int persistent, diff --git a/ext/date/php_date.c b/ext/date/php_date.c index ae7f62fb8f734..0473933071d4b 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -23,13 +23,9 @@ #include "zend_attributes.h" #include "zend_interfaces.h" #include "zend_exceptions.h" +#include "zend_time.h" #include "lib/timelib.h" #include "lib/timelib_private.h" -#ifndef PHP_WIN32 -#include -#else -#include "win32/time.h" -#endif #ifdef PHP_WIN32 static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; } @@ -55,18 +51,7 @@ static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; PHPAPI time_t php_time(void) { -#ifdef HAVE_GETTIMEOFDAY - struct timeval tm; - - if (UNEXPECTED(gettimeofday(&tm, NULL) != SUCCESS)) { - /* fallback, can't reasonably happen */ - return time(NULL); - } - - return tm.tv_sec; -#else return time(NULL); -#endif } /* @@ -2353,16 +2338,9 @@ static void php_date_set_time_fraction(timelib_time *time, int microsecond) static void php_date_get_current_time_with_fraction(time_t *sec, suseconds_t *usec) { -#ifdef HAVE_GETTIMEOFDAY - struct timeval tp = {0}; /* For setting microsecond */ - - gettimeofday(&tp, NULL); - *sec = tp.tv_sec; - *usec = tp.tv_usec; -#else - *sec = time(NULL); - *usec = 0; -#endif + long nsec; + zend_realtime_get(sec, &nsec); + *usec = nsec / 1000; } PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, size_t time_str_len, const char *format, zval *timezone_object, int flags) /* {{{ */ diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index ceb3ee2509035..d4a60d2dcd0ef 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -20,6 +20,7 @@ #endif #include "php.h" +#include "zend_time.h" #include #include @@ -29,7 +30,6 @@ #endif #include #include -#include #ifdef PHP_WIN32 #include #else @@ -43,10 +43,6 @@ #endif #include -#ifdef HAVE_SYS_TIME_H -#include -#endif - #ifdef HAVE_SYS_SELECT_H #include #endif @@ -1374,22 +1370,21 @@ static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) { static int my_poll(php_socket_t fd, int events, int timeout) { int n; - zend_hrtime_t timeout_hr = (zend_hrtime_t) timeout * 1000000; + uint64_t timeout_ns = (uint64_t) timeout * 1000000; while (true) { - zend_hrtime_t start_ns = zend_hrtime(); - n = php_pollfd_for_ms(fd, events, (int) (timeout_hr / 1000000)); + uint64_t start_ns = zend_monotime_fallback(); + n = php_pollfd_for_ms(fd, events, (int) (timeout_ns / 1000000)); if (n == -1 && php_socket_errno() == EINTR) { - zend_hrtime_t delta_ns = zend_hrtime() - start_ns; - /* delta_ns == 0 is only possible with a platform that does not support a high-res timer. */ - if (delta_ns > timeout_hr || UNEXPECTED(delta_ns == 0)) { + uint64_t delta_ns = zend_monotime_fallback() - start_ns; + if (delta_ns > timeout_ns) { #ifndef PHP_WIN32 errno = ETIMEDOUT; #endif break; } - timeout_hr -= delta_ns; + timeout_ns -= delta_ns; } else { break; } @@ -1609,8 +1604,7 @@ static databuf_t* ftp_getdata(ftpbuf_t *ftp) /* connect */ /* Win 95/98 seems not to like size > sizeof(sockaddr_in) */ size = php_sockaddr_size(&ftp->pasvaddr); - tv.tv_sec = ftp->timeout_sec; - tv.tv_usec = 0; + zend_time_sec2val(ftp->timeout_sec, tv); if (php_connect_nonb(fd, (struct sockaddr*) &ftp->pasvaddr, size, &tv) == -1) { php_error_docref(NULL, E_WARNING, "php_connect_nonb() failed: %s (%d)", strerror(errno), errno); goto bail; diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c index ff80c620bee14..54f6f7aa9f74e 100644 --- a/ext/mysqlnd/mysqlnd_debug.c +++ b/ext/mysqlnd/mysqlnd_debug.c @@ -16,6 +16,7 @@ */ #include "php.h" +#include "zend_time.h" #include "mysqlnd.h" #include "mysqlnd_priv.h" #include "mysqlnd_debug.h" @@ -76,21 +77,19 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self, } if (flags & MYSQLND_DEBUG_DUMP_TIME) { /* The following from FF's DBUG library, which is in the public domain */ - struct timeval tv; + struct timespec ts; struct tm *tm_p; - if (gettimeofday(&tv, NULL) != -1) { - const time_t sec = tv.tv_sec; - if ((tm_p = localtime((const time_t *)&sec))) { - snprintf(time_buffer, sizeof(time_buffer) - 1, - /* "%04d-%02d-%02d " */ - "%02d:%02d:%02d.%06d ", - /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ - tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec, - (int) (tv.tv_usec)); - time_buffer[sizeof(time_buffer) - 1 ] = '\0'; - } else { - time_buffer[0] = '\0'; - } + zend_realtime_spec(&ts); + if ((tm_p = localtime((const time_t *)&ts.tv_sec))) { + snprintf(time_buffer, sizeof(time_buffer) - 1, + /* "%04d-%02d-%02d " */ + "%02d:%02d:%02d.%06d ", + /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ + tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec, + (int) (ts.tv_nsec / 1000)); + time_buffer[sizeof(time_buffer) - 1 ] = '\0'; + } else { + time_buffer[0] = '\0'; } } if (flags & MYSQLND_DEBUG_DUMP_FILE) { @@ -163,21 +162,19 @@ MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self, } if (flags & MYSQLND_DEBUG_DUMP_TIME) { /* The following from FF's DBUG library, which is in the public domain */ - struct timeval tv; + struct timespec ts; struct tm *tm_p; - if (gettimeofday(&tv, NULL) != -1) { - const time_t sec = tv.tv_sec; - if ((tm_p = localtime((const time_t *)&sec))) { - snprintf(time_buffer, sizeof(time_buffer) - 1, - /* "%04d-%02d-%02d " */ - "%02d:%02d:%02d.%06d ", - /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ - tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec, - (int) (tv.tv_usec)); - time_buffer[sizeof(time_buffer) - 1 ] = '\0'; - } else { - time_buffer[0] = '\0'; - } + zend_realtime_spec(&ts); + if ((tm_p = localtime((const time_t *)&ts.tv_sec))) { + snprintf(time_buffer, sizeof(time_buffer) - 1, + /* "%04d-%02d-%02d " */ + "%02d:%02d:%02d.%06d ", + /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ + tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec, + (int)(ts.tv_nsec / 1000)); + time_buffer[sizeof(time_buffer) - 1 ] = '\0'; + } else { + time_buffer[0] = '\0'; } } if (flags & MYSQLND_DEBUG_DUMP_FILE) { @@ -329,8 +326,8 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin uint64_t own_time = call_time - mine_non_own_time; uint32_t func_name_len = strlen(*func_name); - self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s (total=%u own=%u in_calls=%u)", - *func_name, (unsigned int) call_time, (unsigned int) own_time, (unsigned int) mine_non_own_time + self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s (total=%"PRIu64" own=%"PRIu64" in_calls=%"PRIu64")", + *func_name, call_time, own_time, mine_non_own_time ); if ((f_profile = zend_hash_str_find_ptr(&self->function_profiles, *func_name, func_name_len)) != NULL) { diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h index 24eb67ca1a744..056bc12a8b8d3 100644 --- a/ext/mysqlnd/mysqlnd_debug.h +++ b/ext/mysqlnd/mysqlnd_debug.h @@ -80,18 +80,14 @@ PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[]); #if defined(__GNUC__) || defined(PHP_WIN32) -#ifdef PHP_WIN32 -#include "win32/time.h" -#else -#include -#endif +#include "zend_time.h" #ifndef MYSQLND_PROFILING_DISABLED -#define DBG_PROFILE_TIMEVAL_TO_DOUBLE(tp) ((tp.tv_sec * 1000000LL)+ tp.tv_usec) -#define DBG_PROFILE_START_TIME() gettimeofday(&__dbg_prof_tp, NULL); __dbg_prof_start = DBG_PROFILE_TIMEVAL_TO_DOUBLE(__dbg_prof_tp); -#define DBG_PROFILE_END_TIME(duration) gettimeofday(&__dbg_prof_tp, NULL); (duration) = (DBG_PROFILE_TIMEVAL_TO_DOUBLE(__dbg_prof_tp) - __dbg_prof_start); +#define DBG_PROFILE_START_TIME() \ + __dbg_prof_start = zend_monotime_fallback(); +#define DBG_PROFILE_END_TIME(duration) \ + (duration) = zend_monotime_fallback() - __dbg_prof_start; #else -#define DBG_PROFILE_TIMEVAL_TO_DOUBLE(tp) #define DBG_PROFILE_START_TIME() #define DBG_PROFILE_END_TIME(duration) #endif @@ -117,7 +113,6 @@ PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[]); #define DBG_LEAVE_EX(dbg_obj, leave) DBG_LEAVE_EX2((dbg_obj), (MYSQLND_DEBUG *) NULL, leave) #define DBG_ENTER_EX2(dbg_obj1, dbg_obj2, func_name) \ - struct timeval __dbg_prof_tp = {0}; \ uint64_t __dbg_prof_start = 0; /* initialization is needed */ \ bool dbg_skip_trace = TRUE; \ ((void)__dbg_prof_start); \ diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c index 3a3f7b207214a..47a835acbd141 100644 --- a/ext/mysqlnd/mysqlnd_vio.c +++ b/ext/mysqlnd/mysqlnd_vio.c @@ -204,8 +204,7 @@ MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix)(MYSQLND_VIO * const vio, const MYS } if (vio->data->options.timeout_connect) { - tv.tv_sec = vio->data->options.timeout_connect; - tv.tv_usec = 0; + zend_time_sec2val(vio->data->options.timeout_connect, tv); } DBG_INF_FMT("calling php_stream_xport_create"); diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index d53e55aa15547..e800cf2fc33c5 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -26,8 +26,10 @@ #include "ext/standard/url.h" #include "streams/php_streams_int.h" #include "zend_smart_str.h" +#include "zend_time.h" #include "php_openssl.h" #include "php_network.h" + #include #include #include @@ -38,7 +40,6 @@ #ifdef PHP_WIN32 #include "win32/winutil.h" -#include "win32/time.h" #include #include /* These are from Wincrypt.h, they conflict with OpenSSL */ @@ -151,8 +152,8 @@ extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl); extern zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool raw); extern int php_openssl_get_ssl_stream_data_index(void); -static struct timeval php_openssl_subtract_timeval(struct timeval a, struct timeval b); -static int php_openssl_compare_timeval(struct timeval a, struct timeval b); +static zend_always_inline int zend_time_cmp_usec2val(uint64_t usec, struct timeval val); +static zend_always_inline struct timeval php_openssl_subtract_timeval(struct timeval tv, uint64_t usec); static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count); static const php_stream_ops php_openssl_socket_ops; @@ -1071,21 +1072,21 @@ static void php_openssl_limit_handshake_reneg(const SSL *ssl) /* {{{ */ { php_stream *stream; php_openssl_netstream_data_t *sslsock; - struct timeval now; + zend_long now; zend_long elapsed_time; stream = php_openssl_get_stream_from_ssl_handle(ssl); sslsock = (php_openssl_netstream_data_t*)stream->abstract; - gettimeofday(&now, NULL); + now = (zend_long)zend_realtime_get(NULL, NULL); /* The initial handshake is never rate-limited */ if (sslsock->reneg->prev_handshake == 0) { - sslsock->reneg->prev_handshake = now.tv_sec; + sslsock->reneg->prev_handshake = now; return; } - elapsed_time = (now.tv_sec - sslsock->reneg->prev_handshake); - sslsock->reneg->prev_handshake = now.tv_sec; + elapsed_time = (now - sslsock->reneg->prev_handshake); + sslsock->reneg->prev_handshake = now; sslsock->reneg->tokens -= (elapsed_time * (sslsock->reneg->limit / sslsock->reneg->window)); if (sslsock->reneg->tokens < 0) { @@ -1805,7 +1806,8 @@ static int php_openssl_enable_crypto(php_stream *stream, X509 *peer_cert; if (cparam->inputs.activate && !sslsock->ssl_active) { - struct timeval start_time, *timeout; + uint64_t start_usec = 0, elapsed_usec = 0; + struct timeval *timeout; int blocked = sslsock->s.is_blocked, has_timeout = 0; #ifdef HAVE_TLS_SNI @@ -1831,14 +1833,11 @@ static int php_openssl_enable_crypto(php_stream *stream, timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout; has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec)); - /* gettimeofday is not monotonic; using it here is not strictly correct */ if (has_timeout) { - gettimeofday(&start_time, NULL); + start_usec = zend_monotime_fallback() / 1000; } do { - struct timeval cur_time, elapsed_time; - ERR_clear_error(); if (sslsock->is_client) { n = SSL_connect(sslsock->ssl_handle); @@ -1847,10 +1846,8 @@ static int php_openssl_enable_crypto(php_stream *stream, } if (has_timeout) { - gettimeofday(&cur_time, NULL); - elapsed_time = php_openssl_subtract_timeval(cur_time, start_time); - - if (php_openssl_compare_timeval( elapsed_time, *timeout) > 0) { + elapsed_usec = (zend_monotime_fallback() / 1000) - start_usec; + if (zend_time_cmp_usec2val(elapsed_usec, *timeout) > 0) { php_error_docref(NULL, E_WARNING, "SSL: Handshake timed out"); return -1; } @@ -1866,7 +1863,7 @@ static int php_openssl_enable_crypto(php_stream *stream, struct timeval left_time; if (has_timeout) { - left_time = php_openssl_subtract_timeval(*timeout, elapsed_time); + left_time = php_openssl_subtract_timeval(*timeout, elapsed_usec); } php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL); @@ -1944,7 +1941,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si /* Only do this if SSL is active. */ if (sslsock->ssl_active) { int retry = 1; - struct timeval start_time; + uint64_t start_usec = 0, elapsed_usec = 0; struct timeval *timeout = NULL; int began_blocked = sslsock->s.is_blocked; int has_timeout = 0; @@ -1966,23 +1963,20 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) { has_timeout = 1; - /* gettimeofday is not monotonic; using it here is not strictly correct */ - gettimeofday(&start_time, NULL); + start_usec = zend_monotime_fallback() / 1000; } /* Main IO loop. */ do { - struct timeval cur_time, elapsed_time, left_time; + struct timeval left_time; /* If we have a timeout to check, figure out how much time has elapsed since we started. */ if (has_timeout) { - gettimeofday(&cur_time, NULL); - /* Determine how much time we've taken so far. */ - elapsed_time = php_openssl_subtract_timeval(cur_time, start_time); + elapsed_usec = (zend_monotime_fallback() / 1000) - start_usec; /* and return an error if we've taken too long. */ - if (php_openssl_compare_timeval(elapsed_time, *timeout) > 0 ) { + if (zend_time_cmp_usec2val(elapsed_usec, *timeout) > 0) { /* If the socket was originally blocking, set it back. */ if (began_blocked) { php_openssl_set_blocking(sslsock, 1); @@ -2010,7 +2004,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si /* Now, how much time until we time out? */ if (has_timeout) { - left_time = php_openssl_subtract_timeval( *timeout, elapsed_time ); + left_time = php_openssl_subtract_timeval(*timeout, elapsed_usec); } /* If we didn't do anything on the last loop (or an error) check to see if we should retry or exit. */ @@ -2100,32 +2094,37 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si } /* }}} */ -static struct timeval php_openssl_subtract_timeval(struct timeval a, struct timeval b) /* {{{ */ +static zend_always_inline int zend_time_cmp_usec2val(uint64_t usec, struct timeval val) /* {{{ */ { - struct timeval difference; + uint64_t tv_sec = usec / ZEND_MICRO_IN_SEC; + uint64_t tv_usec; - difference.tv_sec = a.tv_sec - b.tv_sec; - difference.tv_usec = a.tv_usec - b.tv_usec; + if (tv_sec > val.tv_sec) return 1; + if (tv_sec < val.tv_sec) return -1; - if (a.tv_usec < b.tv_usec) { - difference.tv_sec -= 1L; - difference.tv_usec += 1000000L; - } + tv_usec = usec % ZEND_MICRO_IN_SEC; + if (tv_usec > val.tv_usec) return 1; + if (tv_usec < val.tv_usec) return -1; - return difference; + return 0; } /* }}} */ -static int php_openssl_compare_timeval( struct timeval a, struct timeval b ) +static struct timeval php_openssl_subtract_timeval(struct timeval tv, uint64_t usec) /* {{{ */ { - if (a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec) ) { - return 1; - } else if( a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec ) { - return 0; - } else { - return -1; + struct timeval difference; + + difference.tv_sec = tv.tv_sec - (time_t) (usec / ZEND_MICRO_IN_SEC); + difference.tv_usec = tv.tv_usec - (long) (usec % ZEND_MICRO_IN_SEC); + + if (difference.tv_usec < 0) { + difference.tv_sec -= 1; + difference.tv_usec += 1000000; } + + return difference; } +/* }}} */ static int php_openssl_sockop_close(php_stream *stream, int close_handle) /* {{{ */ { @@ -2348,18 +2347,12 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val if (value == -1) { if (sslsock->s.timeout.tv_sec == -1) { -#ifdef _WIN32 - tv.tv_sec = (long)FG(default_socket_timeout); -#else - tv.tv_sec = (time_t)FG(default_socket_timeout); -#endif - tv.tv_usec = 0; + zend_time_sec2val(FG(default_socket_timeout), tv); } else { tv = sslsock->connect_timeout; } } else { - tv.tv_sec = value; - tv.tv_usec = 0; + zend_time_sec2val(value, tv); } if (sslsock->s.socket == -1) { @@ -2377,8 +2370,9 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val /* additionally, we don't use this optimization if SSL is active because in that case, we're not using MSG_DONTWAIT */ if (sslsock->ssl_active) { int retry = 1; - struct timeval start_time; + uint64_t start_usec = 0, elapsed_usec = 0; struct timeval *timeout = NULL; + struct timeval left_time; int began_blocked = sslsock->s.is_blocked; int has_timeout = 0; @@ -2393,23 +2387,18 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) { has_timeout = 1; - /* gettimeofday is not monotonic; using it here is not strictly correct */ - gettimeofday(&start_time, NULL); + start_usec = zend_monotime_fallback() / 1000; } /* Main IO loop. */ do { - struct timeval cur_time, elapsed_time, left_time; - /* If we have a timeout to check, figure out how much time has elapsed since we started. */ if (has_timeout) { - gettimeofday(&cur_time, NULL); - /* Determine how much time we've taken so far. */ - elapsed_time = php_openssl_subtract_timeval(cur_time, start_time); + elapsed_usec = (zend_monotime_fallback() / 1000) - start_usec; /* and return an error if we've taken too long. */ - if (php_openssl_compare_timeval(elapsed_time, *timeout) > 0 ) { + if (zend_time_cmp_usec2val(elapsed_usec, *timeout) > 0 ) { /* If the socket was originally blocking, set it back. */ if (began_blocked) { php_openssl_set_blocking(sslsock, 1); @@ -2448,7 +2437,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val */ if (retry) { /* Now, how much time until we time out? */ - left_time = php_openssl_subtract_timeval(*timeout, elapsed_time); + left_time = php_openssl_subtract_timeval(*timeout, elapsed_usec); if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI|POLLOUT, has_timeout ? &left_time : NULL) <= 0) { retry = 0; alive = 0; @@ -2670,15 +2659,10 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, sslsock->s.is_blocked = 1; /* this timeout is used by standard stream funcs, therefore it should use the default value */ -#ifdef _WIN32 - sslsock->s.timeout.tv_sec = (long)FG(default_socket_timeout); -#else - sslsock->s.timeout.tv_sec = (time_t)FG(default_socket_timeout); -#endif - sslsock->s.timeout.tv_usec = 0; + zend_time_sec2val(FG(default_socket_timeout), sslsock->s.timeout); /* use separate timeout for our private funcs */ - sslsock->connect_timeout.tv_sec = timeout->tv_sec; + sslsock->connect_timeout.tv_sec = timeout->tv_sec; sslsock->connect_timeout.tv_usec = timeout->tv_usec; /* we don't know the socket until we have determined if we are binding or diff --git a/ext/random/random.c b/ext/random/random.c index 46a6c4fd44f2c..b4d37ed4dbc57 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -30,6 +30,7 @@ #include "Zend/zend_attributes.h" #include "Zend/zend_enum.h" #include "Zend/zend_exceptions.h" +#include "Zend/zend_time.h" #include "php_random.h" #include "php_random_csprng.h" @@ -40,11 +41,8 @@ #endif #ifdef PHP_WIN32 -# include "win32/time.h" # include "win32/winutil.h" # include -#else -# include #endif #ifdef HAVE_SYS_PARAM_H @@ -650,7 +648,7 @@ PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_st * being cryptographically safe. */ PHP_SHA1_CTX c; - struct timeval tv; + struct timespec ts; void *pointer; pid_t pid; #ifdef ZTS @@ -661,8 +659,8 @@ PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_st PHP_SHA1Init(&c); if (!state->initialized) { /* Current time. */ - gettimeofday(&tv, NULL); - fallback_seed_add(&c, &tv, sizeof(tv)); + zend_realtime_spec(&ts); + fallback_seed_add(&c, &ts, sizeof(ts)); /* Various PIDs. */ pid = getpid(); fallback_seed_add(&c, &pid, sizeof(pid)); @@ -680,8 +678,8 @@ PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_st pointer = &c; fallback_seed_add(&c, &pointer, sizeof(pointer)); /* Updated time. */ - gettimeofday(&tv, NULL); - fallback_seed_add(&c, &tv, sizeof(tv)); + zend_realtime_spec(&ts); + fallback_seed_add(&c, &ts, sizeof(ts)); /* Hostname. */ memset(buf, 0, sizeof(buf)); if (gethostname(buf, sizeof(buf) - 1) == 0) { @@ -692,12 +690,12 @@ PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_st fallback_seed_add(&c, buf, 16); } /* Updated time. */ - gettimeofday(&tv, NULL); - fallback_seed_add(&c, &tv, sizeof(tv)); + zend_realtime_spec(&ts); + fallback_seed_add(&c, &ts, sizeof(ts)); } else { /* Current time. */ - gettimeofday(&tv, NULL); - fallback_seed_add(&c, &tv, sizeof(tv)); + zend_realtime_spec(&ts); + fallback_seed_add(&c, &ts, sizeof(ts)); /* Previous state. */ fallback_seed_add(&c, state->seed, 20); } diff --git a/ext/session/session.c b/ext/session/session.c index edcfe9c433607..fcc68755a405b 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -23,9 +23,6 @@ #ifdef PHP_WIN32 # include "win32/winutil.h" -# include "win32/time.h" -#else -# include #endif #include @@ -41,6 +38,7 @@ #include "ext/standard/url_scanner_ex.h" #include "ext/standard/info.h" #include "zend_smart_str.h" +#include "zend_time.h" #include "ext/standard/url.h" #include "ext/standard/basic_functions.h" #include "ext/standard/head.h" @@ -1256,13 +1254,12 @@ static inline void last_modified(void) CACHE_LIMITER_FUNC(public) { char buf[MAX_STR + 1]; - struct timeval tv; - time_t now; + time_t expire_at; + - gettimeofday(&tv, NULL); - now = tv.tv_sec + PS(cache_expire) * 60; + expire_at = zend_realtime_get(NULL, NULL) + PS(cache_expire) * 60; memcpy(buf, EXPIRES, sizeof(EXPIRES) - 1); - strcpy_gmt(buf + sizeof(EXPIRES) - 1, &now); + strcpy_gmt(buf + sizeof(EXPIRES) - 1, &expire_at); ADD_HEADER(buf); snprintf(buf, sizeof(buf) , "Cache-Control: public, max-age=" ZEND_LONG_FMT, PS(cache_expire) * 60); /* SAFE */ @@ -1401,11 +1398,9 @@ static zend_result php_session_send_cookie(void) zend_string_release_ex(e_id, 0); if (PS(cookie_lifetime) > 0) { - struct timeval tv; time_t t; - gettimeofday(&tv, NULL); - t = tv.tv_sec + PS(cookie_lifetime); + t = zend_realtime_get(NULL, NULL) + PS(cookie_lifetime); if (t > 0) { date_fmt = php_format_date(ZEND_STRL("D, d M Y H:i:s \\G\\M\\T"), t, false); @@ -3062,18 +3057,18 @@ static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, b if (Z_LVAL_P(progress->post_bytes_processed) < progress->next_update) { return; } -#ifdef HAVE_GETTIMEOFDAY + if (PS(rfc1867_min_freq) > 0.0) { - struct timeval tv = {0}; + struct timespec ts; double dtv; - gettimeofday(&tv, NULL); - dtv = (double) tv.tv_sec + tv.tv_usec / 1000000.0; + zend_realtime_spec(&ts); + dtv = (double)(ts.tv_sec + ts.tv_nsec / 1000000000.0); if (dtv < progress->next_update_time) { return; } progress->next_update_time = dtv + PS(rfc1867_min_freq); } -#endif + progress->next_update = Z_LVAL_P(progress->post_bytes_processed) + progress->update_step; } diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 71f32d4b9d107..7fc5a0a787ca2 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +#include "Zend/zend_time.h" + #include "php_soap.h" #include "ext/hash/php_hash.h" /* For php_hash_bin2hex() */ @@ -188,8 +190,7 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph tmp = Z_CLIENT_CONNECTION_TIMEOUT_P(this_ptr); if (Z_TYPE_P(tmp) == IS_LONG && Z_LVAL_P(tmp) > 0) { - tv.tv_sec = Z_LVAL_P(tmp); - tv.tv_usec = 0; + zend_time_sec2val(Z_LVAL_P(tmp), tv); timeout = &tv; } diff --git a/ext/standard/array.c b/ext/standard/array.c index 5f2e34fdd545e..560407169a147 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "zend_globals.h" #include "zend_interfaces.h" diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 24f7f9267209c..1c903aef8ad9b 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -37,13 +37,13 @@ #include "zend_enum.h" #include "zend_ini.h" #include "zend_operators.h" +#include "zend_time.h" #include "ext/standard/php_dns.h" #include "ext/standard/php_uuencode.h" #include "ext/standard/crc32_x86.h" #ifdef PHP_WIN32 #include "win32/php_win32_globals.h" -#include "win32/time.h" #include "win32/ioutil.h" #endif @@ -59,7 +59,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; #include #include #include -#include #include #ifndef PHP_WIN32 @@ -1185,7 +1184,7 @@ PHP_FUNCTION(time_nanosleep) PHP_FUNCTION(time_sleep_until) { double target_secs; - struct timeval tm; + struct timespec ts; struct timespec php_req, php_rem; uint64_t current_ns, target_ns, diff_ns; const uint64_t ns_per_sec = 1000000000; @@ -1195,17 +1194,15 @@ PHP_FUNCTION(time_sleep_until) Z_PARAM_DOUBLE(target_secs) ZEND_PARSE_PARAMETERS_END(); - if (gettimeofday((struct timeval *) &tm, NULL) != 0) { - RETURN_FALSE; - } - if (UNEXPECTED(!(target_secs >= 0 && target_secs <= top_target_sec))) { zend_argument_value_error(1, "must be between 0 and %" PRIu64, (uint64_t)top_target_sec); RETURN_THROWS(); } + zend_realtime_spec(&ts); + target_ns = (uint64_t) (target_secs * ns_per_sec); - current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000; + current_ns = ((uint64_t) ts.tv_sec) * ns_per_sec + ((uint64_t) ts.tv_nsec); if (target_ns < current_ns) { php_error_docref(NULL, E_WARNING, "Argument #1 ($timestamp) must be greater than or equal to the current time"); RETURN_FALSE; diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 2d4798a14db78..77af212fab9f4 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -3285,7 +3285,6 @@ function fpow(float $num, float $exponent): float {} /* microtime.c */ -#ifdef HAVE_GETTIMEOFDAY /** @refcount 1 */ function microtime(bool $as_float = false): string|float {} @@ -3294,7 +3293,6 @@ function microtime(bool $as_float = false): string|float {} * @refcount 1 */ function gettimeofday(bool $as_float = false): array|float {} -#endif #ifdef HAVE_GETRUSAGE /** @@ -3702,10 +3700,8 @@ function is_countable(mixed $value): bool {} /* uniqid.c */ -#ifdef HAVE_GETTIMEOFDAY /** @refcount 1 */ function uniqid(string $prefix = "", bool $more_entropy = false): string {} -#endif /* url.c */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 6bfef392f21d1..bd2af91d1cc5d 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: dcc4e6865dac52b23534b6ef61c0d6be766af6b9 */ + * Stub hash: fdd4cd2914ebb4e773fb7159ca0a2a2edaa8364b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -1733,7 +1733,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fpow, 0, 2, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, exponent, IS_DOUBLE, 0) ZEND_END_ARG_INFO() -#if defined(HAVE_GETTIMEOFDAY) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_microtime, 0, 0, MAY_BE_STRING|MAY_BE_DOUBLE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, as_float, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() @@ -1741,7 +1740,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_gettimeofday, 0, 0, MAY_BE_ARRAY|MAY_BE_DOUBLE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, as_float, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() -#endif #if defined(HAVE_GETRUSAGE) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_getrusage, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) @@ -2069,12 +2067,10 @@ ZEND_END_ARG_INFO() #define arginfo_is_countable arginfo_boolval -#if defined(HAVE_GETTIMEOFDAY) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_uniqid, 0, 0, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, prefix, IS_STRING, 0, "\"\"") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, more_entropy, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_parse_url, 0, 1, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_NULL|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, url, IS_STRING, 0) @@ -2757,10 +2753,8 @@ ZEND_FUNCTION(number_format); ZEND_FUNCTION(fmod); ZEND_FUNCTION(fdiv); ZEND_FUNCTION(fpow); -#if defined(HAVE_GETTIMEOFDAY) ZEND_FUNCTION(microtime); ZEND_FUNCTION(gettimeofday); -#endif #if defined(HAVE_GETRUSAGE) ZEND_FUNCTION(getrusage); #endif @@ -2845,9 +2839,7 @@ ZEND_FUNCTION(is_scalar); ZEND_FUNCTION(is_callable); ZEND_FUNCTION(is_iterable); ZEND_FUNCTION(is_countable); -#if defined(HAVE_GETTIMEOFDAY) ZEND_FUNCTION(uniqid); -#endif ZEND_FUNCTION(parse_url); ZEND_FUNCTION(urlencode); ZEND_FUNCTION(urldecode); @@ -3361,10 +3353,8 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("fmod", zif_fmod, arginfo_fmod, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("fdiv", zif_fdiv, arginfo_fdiv, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("fpow", zif_fpow, arginfo_fpow, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) -#if defined(HAVE_GETTIMEOFDAY) ZEND_FE(microtime, arginfo_microtime) ZEND_FE(gettimeofday, arginfo_gettimeofday) -#endif #if defined(HAVE_GETRUSAGE) ZEND_FE(getrusage, arginfo_getrusage) #endif @@ -3457,9 +3447,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(is_callable, arginfo_is_callable) ZEND_RAW_FENTRY("is_iterable", zif_is_iterable, arginfo_is_iterable, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("is_countable", zif_is_countable, arginfo_is_countable, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) -#if defined(HAVE_GETTIMEOFDAY) ZEND_FE(uniqid, arginfo_uniqid) -#endif ZEND_RAW_FENTRY("parse_url", zif_parse_url, arginfo_parse_url, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("urlencode", zif_urlencode, arginfo_urlencode, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("urldecode", zif_urldecode, arginfo_urldecode, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c index 54687f6cdf307..b7a64300254c9 100644 --- a/ext/standard/crypt.c +++ b/ext/standard/crypt.c @@ -35,7 +35,6 @@ # include # endif #endif -#include #include #ifdef PHP_WIN32 diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 2b9e00a57554c..16c37b9f417d6 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -21,6 +21,7 @@ #include #include #include "php_network.h" +#include "zend_time.h" #include "file.h" static size_t php_fsockopen_format_host_port(char **message, const char *prefix, size_t prefix_len, @@ -55,11 +56,6 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) zval *zerrno = NULL, *zerrstr = NULL; double timeout; bool timeout_is_null = 1; -#ifndef PHP_WIN32 - time_t conv; -#else - long conv; -#endif struct timeval tv; char *hashkey = NULL; php_stream *stream = NULL; @@ -108,14 +104,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) zend_argument_value_error(6, "must be -1 or between 0 and " ZEND_ULONG_FMT, ((double) PHP_TIMEOUT_ULL_MAX / 1000000.0)); RETURN_THROWS(); } else { -#ifndef PHP_WIN32 - conv = (time_t) (timeout * 1000000.0); - tv.tv_sec = conv / 1000000; -#else - conv = (long) (timeout * 1000000.0); - tv.tv_sec = conv / 1000000; -#endif - tv.tv_usec = conv % 1000000; + zend_time_dbl2val(timeout, tv); } stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS, diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 9fefe153622fc..186fb3eede7d2 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -23,6 +23,7 @@ #include "php_streams.h" #include "php_network.h" #include "php_ini.h" +#include "zend_time.h" #include "ext/standard/basic_functions.h" #include "zend_smart_str.h" @@ -464,20 +465,9 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, php_url_free(resource); return NULL; } -#ifndef PHP_WIN32 - timeout.tv_sec = (time_t) d; - timeout.tv_usec = (size_t) ((d - timeout.tv_sec) * 1000000); -#else - timeout.tv_sec = (long) d; - timeout.tv_usec = (long) ((d - timeout.tv_sec) * 1000000); -#endif + zend_time_dbl2val(d, timeout); } else { -#ifndef PHP_WIN32 - timeout.tv_sec = FG(default_socket_timeout); -#else - timeout.tv_sec = (long)FG(default_socket_timeout); -#endif - timeout.tv_usec = 0; + zend_time_sec2val(FG(default_socket_timeout), timeout); } stream = php_stream_xport_create(ZSTR_VAL(transport_string), ZSTR_LEN(transport_string), options, diff --git a/ext/standard/microtime.c b/ext/standard/microtime.c index ca8643eb5196f..abf7fc576f1fc 100644 --- a/ext/standard/microtime.c +++ b/ext/standard/microtime.c @@ -15,15 +15,13 @@ */ #include "php.h" +#include "zend_time.h" #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef PHP_WIN32 -#include "win32/time.h" #include "win32/getrusage.h" -#else -#include #endif #ifdef HAVE_SYS_RESOURCE_H #include @@ -38,44 +36,38 @@ #include "ext/date/php_date.h" -#define NUL '\0' -#define MICRO_IN_SEC 1000000.00 -#define SEC_IN_MIN 60 - -#ifdef HAVE_GETTIMEOFDAY static void _php_gettimeofday(INTERNAL_FUNCTION_PARAMETERS, int mode) { bool get_as_float = 0; - struct timeval tp = {0}; + time_t sec; + long nsec; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_BOOL(get_as_float) ZEND_PARSE_PARAMETERS_END(); - if (gettimeofday(&tp, NULL)) { - ZEND_ASSERT(0 && "gettimeofday() can't fail"); - } + zend_realtime_get(&sec, &nsec); if (get_as_float) { - RETURN_DOUBLE((double)(tp.tv_sec + tp.tv_usec / MICRO_IN_SEC)); + RETURN_DOUBLE((double)(sec + nsec / 1000000000.00)); } if (mode) { timelib_time_offset *offset; - offset = timelib_get_time_zone_info(tp.tv_sec, get_timezone_info()); + offset = timelib_get_time_zone_info(sec, get_timezone_info()); array_init(return_value); - add_assoc_long(return_value, "sec", tp.tv_sec); - add_assoc_long(return_value, "usec", tp.tv_usec); + add_assoc_long(return_value, "sec", sec); + add_assoc_long(return_value, "usec", nsec / 1000); - add_assoc_long(return_value, "minuteswest", -offset->offset / SEC_IN_MIN); + add_assoc_long(return_value, "minuteswest", -offset->offset / 60); add_assoc_long(return_value, "dsttime", offset->is_dst); timelib_time_offset_dtor(offset); } else { - RETURN_NEW_STR(zend_strpprintf(0, "%.8F %ld", tp.tv_usec / MICRO_IN_SEC, (long)tp.tv_sec)); + RETURN_NEW_STR(zend_strpprintf(0, "0.%08ld %lld", nsec / 10, (long long) sec)); } } @@ -91,7 +83,6 @@ PHP_FUNCTION(gettimeofday) { _php_gettimeofday(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } -#endif /* }}} */ #ifdef HAVE_GETRUSAGE diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index bf7cbc9fa4623..511f52a50c049 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -23,6 +23,7 @@ #include "streamsfuncs.h" #include "php_network.h" #include "php_string.h" +#include "zend_time.h" #ifdef HAVE_UNISTD_H #include #endif @@ -99,7 +100,6 @@ PHP_FUNCTION(stream_socket_client) zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL; double timeout; bool timeout_is_null = 1; - php_timeout_ull conv; struct timeval tv; char *hashkey = NULL; php_stream *stream = NULL; @@ -138,14 +138,7 @@ PHP_FUNCTION(stream_socket_client) if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { tv_pointer = NULL; } else { - conv = (php_timeout_ull) (timeout * 1000000.0); -#ifdef PHP_WIN32 - tv.tv_sec = (long)(conv / 1000000); - tv.tv_usec = (long)(conv % 1000000); -#else - tv.tv_sec = conv / 1000000; - tv.tv_usec = conv % 1000000; -#endif + zend_time_dbl2val(timeout, tv); tv_pointer = &tv; } @@ -262,7 +255,6 @@ PHP_FUNCTION(stream_socket_accept) bool timeout_is_null = 1; zval *zpeername = NULL; zend_string *peername = NULL; - php_timeout_ull conv; struct timeval tv; php_stream *stream = NULL, *clistream = NULL; zend_string *errstr = NULL; @@ -286,14 +278,7 @@ PHP_FUNCTION(stream_socket_accept) if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { tv_pointer = NULL; } else { - conv = (php_timeout_ull) (timeout * 1000000.0); -#ifdef PHP_WIN32 - tv.tv_sec = (long)(conv / 1000000); - tv.tv_usec = (long)(conv % 1000000); -#else - tv.tv_sec = conv / 1000000; - tv.tv_usec = conv % 1000000; -#endif + zend_time_dbl2val(timeout, tv); tv_pointer = &tv; } @@ -813,7 +798,7 @@ PHP_FUNCTION(stream_select) } /* Windows, Solaris and BSD do not like microsecond values which are >= 1 sec */ - tv.tv_sec = (long)(sec + (usec / 1000000)); + zend_time_sec2val(sec + (usec / 1000000), tv); tv.tv_usec = (long)(usec % 1000000); tv_p = &tv; } @@ -1392,7 +1377,7 @@ PHP_FUNCTION(stream_set_blocking) PHP_FUNCTION(stream_set_timeout) { zend_long seconds, microseconds = 0; - struct timeval t; + struct timeval tv; php_stream *stream; int argc = ZEND_NUM_ARGS(); @@ -1403,27 +1388,14 @@ PHP_FUNCTION(stream_set_timeout) Z_PARAM_LONG(microseconds) ZEND_PARSE_PARAMETERS_END(); -#ifdef PHP_WIN32 - t.tv_sec = (long)seconds; - if (argc == 3) { - t.tv_usec = (long)(microseconds % 1000000); - t.tv_sec +=(long)(microseconds / 1000000); + zend_time_sec2val(seconds + (microseconds / 1000000), tv); + tv.tv_usec = (long)(microseconds % 1000000); } else { - t.tv_usec = 0; + zend_time_sec2val(seconds, tv); } -#else - t.tv_sec = seconds; - - if (argc == 3) { - t.tv_usec = microseconds % 1000000; - t.tv_sec += microseconds / 1000000; - } else { - t.tv_usec = 0; - } -#endif - if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) { + if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv)) { RETURN_TRUE; } diff --git a/ext/standard/uniqid.c b/ext/standard/uniqid.c index c0b9555ccefd0..513bd185d71dc 100644 --- a/ext/standard/uniqid.c +++ b/ext/standard/uniqid.c @@ -15,6 +15,7 @@ */ #include "php.h" +#include "zend_time.h" #include #ifdef HAVE_UNISTD_H @@ -25,17 +26,12 @@ #include #include -#ifdef PHP_WIN32 -#include "win32/time.h" -#else -#include -#endif #include "ext/random/php_random.h" #include "ext/random/php_random_csprng.h" -#ifdef HAVE_GETTIMEOFDAY -ZEND_TLS struct timeval prev_tv = { 0, 0 }; +ZEND_TLS time_t prev_sec = 0; +ZEND_TLS long prev_usec = 0; /* {{{ Generates a unique ID */ PHP_FUNCTION(uniqid) @@ -43,9 +39,10 @@ PHP_FUNCTION(uniqid) char *prefix = ""; bool more_entropy = 0; zend_string *uniqid; - int sec, usec; size_t prefix_len = 0; - struct timeval tv; + time_t sec; + long nsec, usec; + int isec, iusec; ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL @@ -53,20 +50,29 @@ PHP_FUNCTION(uniqid) Z_PARAM_BOOL(more_entropy) ZEND_PARSE_PARAMETERS_END(); - /* This implementation needs current microsecond to change, - * hence we poll time until it does. This is much faster than - * calling usleep(1) which may cause the kernel to schedule - * another process, causing a pause of around 10ms. + /* This implementation needs current microsecond to change. + * We will manually move the time forward if needed. This is + * more stable as polling or sleeping as it will not be + * effected by time changes (like ntp) and this is much faster + * than calling usleep(1) which may cause the kernel to + * schedule another process, causing a pause of around 10ms. */ - do { - (void)gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); - } while (tv.tv_sec == prev_tv.tv_sec && tv.tv_usec == prev_tv.tv_usec); + zend_realtime_get(&sec, &nsec); + usec = nsec / 1000; + if (usec <= prev_usec && sec <= prev_sec) { + if (usec == 999999) { + sec += 1; + usec = 0; + } else { + usec += 1; + } + } - prev_tv.tv_sec = tv.tv_sec; - prev_tv.tv_usec = tv.tv_usec; + prev_sec = sec; + prev_usec = usec; - sec = (int) tv.tv_sec; - usec = (int) (tv.tv_usec % 0x100000); + isec = (int) sec; + iusec = (int) (usec % 0x100000); /* The max value usec can have is 0xF423F, so we use only five hex * digits for usecs. @@ -78,12 +84,11 @@ PHP_FUNCTION(uniqid) bytes = php_random_generate_fallback_seed(); } seed = ((double) bytes / UINT32_MAX) * 10.0; - uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, sec, usec, seed); + uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, isec, iusec, seed); } else { - uniqid = strpprintf(0, "%s%08x%05x", prefix, sec, usec); + uniqid = strpprintf(0, "%s%08x%05x", prefix, isec, iusec); } RETURN_STR(uniqid); } -#endif /* }}} */ diff --git a/main/SAPI.c b/main/SAPI.c index 866b44c3eac7d..85ab0a2c663ec 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -24,14 +24,10 @@ #include "SAPI.h" #include "php_variables.h" #include "php_ini.h" +#include "zend_time.h" #ifdef ZTS #include "TSRM.h" #endif -#ifdef HAVE_SYS_TIME_H -#include -#elif defined(PHP_WIN32) -#include "win32/time.h" -#endif #include "rfc1867.h" @@ -1091,12 +1087,9 @@ SAPI_API double sapi_get_request_time(void) if (!sapi_module.get_request_time || sapi_module.get_request_time(&SG(global_request_time)) == FAILURE) { - struct timeval tp = {0}; - if (!gettimeofday(&tp, NULL)) { - SG(global_request_time) = (double)(tp.tv_sec + tp.tv_usec / 1000000.00); - } else { - SG(global_request_time) = (double)time(0); - } + struct timespec ts; + zend_realtime_spec(&ts); + SG(global_request_time) = (double)(ts.tv_sec + ts.tv_nsec / 1000000000.0); } return SG(global_request_time); } diff --git a/main/network.c b/main/network.c index 14f4ca4dff987..ddb4c6dfbd3ee 100644 --- a/main/network.c +++ b/main/network.c @@ -60,6 +60,7 @@ #endif #include "php_network.h" +#include "zend_time.h" #if defined(PHP_WIN32) || defined(__riscos__) #undef AF_UNIX @@ -72,7 +73,6 @@ #include "ext/standard/file.h" #ifdef PHP_WIN32 -# include "win32/time.h" # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR # define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT @@ -297,35 +297,6 @@ typedef int php_non_blocking_flags_t; fcntl(sock, F_SETFL, save) #endif -#ifdef HAVE_GETTIMEOFDAY -/* Subtract times */ -static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result) -{ - result->tv_usec = a.tv_usec - b.tv_usec; - if (result->tv_usec < 0L) { - a.tv_sec--; - result->tv_usec += 1000000L; - } - result->tv_sec = a.tv_sec - b.tv_sec; - if (result->tv_sec < 0L) { - result->tv_sec++; - result->tv_usec -= 1000000L; - } -} - -static inline void php_network_set_limit_time(struct timeval *limit_time, - struct timeval *timeout) -{ - gettimeofday(limit_time, NULL); - limit_time->tv_sec += timeout->tv_sec; - limit_time->tv_usec += timeout->tv_usec; - if (limit_time->tv_usec >= 1000000) { - limit_time->tv_usec -= 1000000; - limit_time->tv_sec++; - } -} -#endif - /* Connect to a socket using an interruptible connect with optional timeout. * Optionally, the connect can be made asynchronously, which will implicitly * enable non-blocking mode on the socket. @@ -383,34 +354,29 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd, int events = PHP_POLLREADABLE|POLLOUT; #endif struct timeval working_timeout; -#ifdef HAVE_GETTIMEOFDAY - struct timeval limit_time, time_now; -#endif - if (timeout) { + uint64_t now_us, limit_us; + int has_timeout = timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec > 0)); + if (has_timeout) { memcpy(&working_timeout, timeout, sizeof(working_timeout)); -#ifdef HAVE_GETTIMEOFDAY - php_network_set_limit_time(&limit_time, &working_timeout); -#endif + limit_us = (zend_monotime_fallback() / 1000) + (working_timeout.tv_sec * ZEND_MICRO_IN_SEC) + working_timeout.tv_usec; } while (true) { - n = php_pollfd_for(sockfd, events, timeout ? &working_timeout : NULL); + n = php_pollfd_for(sockfd, events, has_timeout ? &working_timeout : NULL); if (n < 0) { if (errno == EINTR) { -#ifdef HAVE_GETTIMEOFDAY - if (timeout) { - gettimeofday(&time_now, NULL); + if (has_timeout) { + now_us = zend_monotime_fallback() / 1000; - if (!timercmp(&time_now, &limit_time, <)) { + if (now_us > limit_us) { /* time limit expired; no need for another poll */ error = PHP_TIMEOUT_ERROR_VALUE; break; } else { /* work out remaining time */ - sub_times(limit_time, time_now, &working_timeout); + zend_time_usec2val(limit_us - now_us, working_timeout); } } -#endif continue; } ret = -1; @@ -822,10 +788,9 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short php_socket_t sock; struct sockaddr **sal, **psal, *sa; struct timeval working_timeout; + uint64_t now_us, limit_us; socklen_t socklen; -#ifdef HAVE_GETTIMEOFDAY - struct timeval limit_time, time_now; -#endif + int has_timeout = timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec > 0)); num_addrs = php_network_getaddresses(host, socktype, &psal, error_string); @@ -834,11 +799,9 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short return -1; } - if (timeout) { + if (has_timeout) { memcpy(&working_timeout, timeout, sizeof(working_timeout)); -#ifdef HAVE_GETTIMEOFDAY - php_network_set_limit_time(&limit_time, &working_timeout); -#endif + limit_us = (zend_monotime_fallback() / 1000) + (working_timeout.tv_sec * ZEND_MICRO_IN_SEC) + working_timeout.tv_usec; } for (sal = psal; !fatal && *sal != NULL; sal++) { @@ -940,7 +903,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short } #endif n = php_network_connect_socket(sock, sa, socklen, asynchronous, - timeout ? &working_timeout : NULL, + has_timeout ? &working_timeout : NULL, error_string, error_code); if (n != -1) { @@ -948,32 +911,17 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short } /* adjust timeout for next attempt */ -#ifdef HAVE_GETTIMEOFDAY - if (timeout) { - gettimeofday(&time_now, NULL); + if (has_timeout) { + now_us = zend_monotime_fallback() / 1000; - if (!timercmp(&time_now, &limit_time, <)) { + if (now_us > limit_us) { /* time limit expired; don't attempt any further connections */ fatal = 1; } else { /* work out remaining time */ - sub_times(limit_time, time_now, &working_timeout); + zend_time_usec2val(limit_us - now_us, working_timeout); } } -#else - if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) { - /* Don't even bother trying to connect to the next alternative; - * we have no way to determine how long we have already taken - * and it is quite likely that the next attempt will fail too. */ - fatal = 1; - } else { - /* re-use the same initial timeout. - * Not the best thing, but in practice it should be good-enough */ - if (timeout) { - memcpy(&working_timeout, timeout, sizeof(working_timeout)); - } - } -#endif closesocket(sock); } diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index e3cd6f49b9f0c..22e9c0dab97a5 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -30,16 +30,11 @@ #include #ifdef PHP_WIN32 -# include "win32/time.h" # include "win32/signal.h" # include "win32/winutil.h" # include #endif -#ifdef HAVE_SYS_TIME_H -# include -#endif - #ifdef HAVE_UNISTD_H # include #endif @@ -81,6 +76,7 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" +#include "zend_time.h" #include "php_getopt.h" @@ -1738,11 +1734,7 @@ int main(int argc, char *argv[]) int warmup_repeats = 0; int repeats = 1; int benchmark = 0; -#ifdef HAVE_GETTIMEOFDAY - struct timeval start, end; -#else - time_t start, end; -#endif + uint64_t start, elapsed; #ifndef PHP_WIN32 int status = 0; #endif @@ -2249,11 +2241,7 @@ consult the installation file that came with this distribution, or visit \n\ repeats = atoi(php_optarg); } } -#ifdef HAVE_GETTIMEOFDAY - gettimeofday(&start, NULL); -#else - time(&start); -#endif + start = zend_monotime_fallback(); break; case 'h': case '?': @@ -2584,11 +2572,7 @@ consult the installation file that came with this distribution, or visit \n\ if (warmup_repeats) { warmup_repeats--; if (!warmup_repeats) { -#ifdef HAVE_GETTIMEOFDAY - gettimeofday(&start, NULL); -#else - time(&start); -#endif + start = zend_monotime_fallback(); } continue; } else { @@ -2638,24 +2622,8 @@ consult the installation file that came with this distribution, or visit \n\ out: if (benchmark) { - int sec; -#ifdef HAVE_GETTIMEOFDAY - int usec; - - gettimeofday(&end, NULL); - sec = (int)(end.tv_sec - start.tv_sec); - if (end.tv_usec >= start.tv_usec) { - usec = (int)(end.tv_usec - start.tv_usec); - } else { - sec -= 1; - usec = (int)(end.tv_usec + 1000000 - start.tv_usec); - } - fprintf(stderr, "\nElapsed time: %d.%06d sec\n", sec, usec); -#else - time(&end); - sec = (int)(end - start); - fprintf(stderr, "\nElapsed time: %d sec\n", sec); -#endif + elapsed = zend_monotime_fallback() - start; + fprintf(stderr, "\nElapsed time: %lu.%09lu sec\n", (unsigned long)(elapsed / ZEND_NANO_IN_SEC), (unsigned long)(elapsed % ZEND_NANO_IN_SEC)); } parent_out: diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index e212a0f71a23d..48a5af3c7220f 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -33,15 +33,11 @@ #include #include "php.h" #ifdef PHP_WIN32 -#include "win32/time.h" #include "win32/signal.h" #include "win32/console.h" #include #include #endif -#ifdef HAVE_SYS_TIME_H -#include -#endif #ifdef HAVE_UNISTD_H #include #endif @@ -50,6 +46,7 @@ #include #include "zend.h" #include "zend_extensions.h" +#include "zend_time.h" #include "php_ini.h" #include "php_globals.h" #include "php_main.h" @@ -231,8 +228,7 @@ static inline bool sapi_cli_select(php_socket_t fd) PHP_SAFE_FD_SET(fd, &wfd); - tv.tv_sec = (long)FG(default_socket_timeout); - tv.tv_usec = 0; + zend_time_sec2val(FG(default_socket_timeout), tv); ret = php_select(fd+1, NULL, &wfd, NULL, &tv); diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index b7e3e5fa1be2a..20530db12a41a 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -93,6 +93,7 @@ #include "ext/standard/file.h" /* for php_set_sock_blocking() :-( */ #include "zend_smart_str.h" +#include "zend_time.h" #include "ext/standard/html.h" #include "ext/standard/url.h" /* for php_raw_url_decode() */ #include "ext/date/php_date.h" /* for php_format_date() */ @@ -265,12 +266,11 @@ static bool php_cli_server_get_system_time(char *buf) { } #else static bool php_cli_server_get_system_time(char *buf) { - struct timeval tv; + time_t sec; struct tm tm; - gettimeofday(&tv, NULL); - - if (!php_localtime_r(&tv.tv_sec, &tm)) { + zend_realtime_get(&sec, NULL); + if (!php_localtime_r(&sec, &tm)) { return false; } return php_asctime_r(&tm, buf) != NULL; @@ -359,7 +359,6 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, bool persistent, sapi_headers_struct *sapi_headers) /* {{{ */ { zval *val; - struct timeval tv = {0}; bool append_date_header = true; if (sapi_headers != NULL) { @@ -382,8 +381,13 @@ static void append_essential_headers(smart_str* buffer, php_cli_server_client *c smart_str_appends_ex(buffer, "\r\n", persistent); } - if (append_date_header && !gettimeofday(&tv, NULL)) { - zend_string *dt = php_format_date("D, d M Y H:i:s", sizeof("D, d M Y H:i:s") - 1, tv.tv_sec, 0); + if (append_date_header) { + zend_string *dt = php_format_date( + "D, d M Y H:i:s", + sizeof("D, d M Y H:i:s") - 1, + zend_realtime_get(NULL, NULL), + 0 + ); smart_str_appends_ex(buffer, "Date: ", persistent); smart_str_append_ex(buffer, dt, persistent); smart_str_appends_ex(buffer, " GMT\r\n", persistent); diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 4d4952eee86e7..858bf14d39ad5 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -529,7 +529,6 @@ if test "$PHP_FPM" != "no"; then PHP_FPM_FILES="fpm/fpm.c \ fpm/fpm_children.c \ fpm/fpm_cleanup.c \ - fpm/fpm_clock.c \ fpm/fpm_conf.c \ fpm/fpm_env.c \ fpm/fpm_events.c \ diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index 285df91a9b690..74ca7fec4bb1a 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -4,11 +4,12 @@ #include #include -#include #include #include #include +#include "zend_time.h" + #include "fpm.h" #include "fpm_children.h" #include "fpm_signals.h" @@ -19,7 +20,6 @@ #include "fpm_conf.h" #include "fpm_cleanup.h" #include "fpm_events.h" -#include "fpm_clock.h" #include "fpm_stdio.h" #include "fpm_unix.h" #include "fpm_env.h" @@ -283,23 +283,22 @@ void fpm_children_bury(void) if (child) { struct fpm_worker_pool_s *wp = child->wp; - struct timeval tv1, tv2; + uint64_t now_ns, elapsed_ns; fpm_child_unlink(child); fpm_scoreboard_proc_free(child); - fpm_clock_get(&tv1); - - timersub(&tv1, &child->started, &tv2); + now_ns = zend_monotime_fallback(); + elapsed_ns = now_ns - child->started_ns; if (restart_child) { if (!fpm_pctl_can_spawn_children()) { severity = ZLOG_DEBUG; } - zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", wp->config->name, (int) pid, buf, (long)tv2.tv_sec, (int) tv2.tv_usec); + zlog(severity, "[pool %s] child %d exited %s after %ld.%09ld seconds from start", wp->config->name, (int) pid, buf, (long) (elapsed_ns / ZEND_NANO_IN_SEC), (long) (elapsed_ns % ZEND_NANO_IN_SEC)); } else { - zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", wp->config->name, (int) pid, (long)tv2.tv_sec, (int) tv2.tv_usec); + zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%09ld seconds from start", wp->config->name, (int) pid, (long) (elapsed_ns / ZEND_NANO_IN_SEC), (long) (elapsed_ns % ZEND_NANO_IN_SEC)); } fpm_child_close(child, 1 /* in event_loop */); @@ -307,18 +306,18 @@ void fpm_children_bury(void) fpm_pctl_child_exited(); if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) { - time_t now = tv1.tv_sec; + time_t now_sec = (time_t) (now_ns / ZEND_NANO_IN_SEC); int restart_condition = 1; int i; - last_faults[fault++] = now; + last_faults[fault++] = now_sec; if (fault == fpm_global_config.emergency_restart_threshold) { fault = 0; } for (i = 0; i < fpm_global_config.emergency_restart_threshold; i++) { - if (now - last_faults[i] > fpm_global_config.emergency_restart_interval) { + if (now_sec - last_faults[i] > fpm_global_config.emergency_restart_interval) { restart_condition = 0; break; } @@ -473,7 +472,7 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to zlog(ZLOG_DEBUG, "unblocking signals, child born"); fpm_signals_unblock(); child->pid = pid; - fpm_clock_get(&child->started); + child->started_ns = zend_monotime_fallback(); fpm_parent_resources_use(child); zlog(is_debug ? ZLOG_DEBUG : ZLOG_NOTICE, "[pool %s] child %d started", wp->config->name, (int) pid); diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h index fe06eb3ba84cd..ccd2ac140625c 100644 --- a/sapi/fpm/fpm/fpm_children.h +++ b/sapi/fpm/fpm/fpm_children.h @@ -21,13 +21,13 @@ struct fpm_child_s *fpm_child_find(pid_t pid); struct fpm_child_s { struct fpm_child_s *prev, *next; - struct timeval started; + uint64_t started_ns; struct fpm_worker_pool_s *wp; struct fpm_event_s ev_stdout, ev_stderr, ev_free; int shm_slot_i; int fd_stdout, fd_stderr; void (*tracer)(struct fpm_child_s *); - struct timeval slow_logged; + uint64_t slow_logged_ns; bool idle_kill; bool postponed_free; pid_t pid; diff --git a/sapi/fpm/fpm/fpm_clock.c b/sapi/fpm/fpm/fpm_clock.c deleted file mode 100644 index 57faccbe9d80d..0000000000000 --- a/sapi/fpm/fpm/fpm_clock.c +++ /dev/null @@ -1,116 +0,0 @@ - /* (c) 2007,2008 Andrei Nigmatulin */ - -#include "fpm_config.h" - -#ifdef HAVE_CLOCK_GETTIME -#include /* for CLOCK_MONOTONIC */ -#endif - -#include "fpm_clock.h" -#include "zlog.h" - - -/* posix monotonic clock - preferred source of time */ -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) - -static int monotonic_works; - -int fpm_clock_init(void) -{ - struct timespec ts; - - monotonic_works = 0; - - if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) { - monotonic_works = 1; - } - - return 0; -} - -int fpm_clock_get(struct timeval *tv) /* {{{ */ -{ - if (monotonic_works) { - struct timespec ts; - - if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) { - zlog(ZLOG_SYSERROR, "clock_gettime() failed"); - return -1; - } - - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; - return 0; - } - - return gettimeofday(tv, 0); -} -/* }}} */ - -/* macOS clock */ -#elif defined(HAVE_CLOCK_GET_TIME) - -#include -#include -#include - -static clock_serv_t mach_clock; - -/* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */ -/* mach_clock also should be re-initialized in child process after fork */ -int fpm_clock_init(void) -{ - kern_return_t ret; - mach_timespec_t aTime; - - ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock); - - if (ret != KERN_SUCCESS) { - zlog(ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret)); - return -1; - } - - /* test if it works */ - ret = clock_get_time(mach_clock, &aTime); - - if (ret != KERN_SUCCESS) { - zlog(ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); - return -1; - } - - return 0; -} - -int fpm_clock_get(struct timeval *tv) /* {{{ */ -{ - kern_return_t ret; - mach_timespec_t aTime; - - ret = clock_get_time(mach_clock, &aTime); - - if (ret != KERN_SUCCESS) { - zlog(ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); - return -1; - } - - tv->tv_sec = aTime.tv_sec; - tv->tv_usec = aTime.tv_nsec / 1000; - - return 0; -} -/* }}} */ - -#else /* no clock */ - -int fpm_clock_init(void) -{ - return 0; -} - -int fpm_clock_get(struct timeval *tv) /* {{{ */ -{ - return gettimeofday(tv, 0); -} -/* }}} */ - -#endif diff --git a/sapi/fpm/fpm/fpm_clock.h b/sapi/fpm/fpm/fpm_clock.h deleted file mode 100644 index 1bf38ff63ef80..0000000000000 --- a/sapi/fpm/fpm/fpm_clock.h +++ /dev/null @@ -1,11 +0,0 @@ - /* (c) 2007,2008 Andrei Nigmatulin */ - -#ifndef FPM_CLOCK_H -#define FPM_CLOCK_H 1 - -#include - -int fpm_clock_init(void); -int fpm_clock_get(struct timeval *tv); - -#endif diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index 1ccf2c9c5490a..09e7570ee550e 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -8,6 +8,7 @@ #include #include +#include #include "fpm.h" #include "fpm_process_ctl.h" @@ -17,7 +18,6 @@ #include "fpm_signals.h" #include "fpm_children.h" #include "zlog.h" -#include "fpm_clock.h" #include "fpm_log.h" #include "events/select.h" @@ -380,10 +380,11 @@ void fpm_event_loop(int err) /* {{{ */ while (1) { struct fpm_event_queue_s *q, *q2; - struct timeval ms; + struct timeval timeout_tv; struct timeval tmp; - struct timeval now; - unsigned long int timeout; + struct timeval now_tv; + uint64_t now_ns; + unsigned long int timeout_ms; int ret; /* sanity check */ @@ -391,31 +392,32 @@ void fpm_event_loop(int err) /* {{{ */ return; } - fpm_clock_get(&now); - timerclear(&ms); + now_ns = zend_monotime_fallback(); + zend_time_usec2val(now_ns / 1000, now_tv); + timerclear(&timeout_tv); /* search in the timeout queue for the next timer to trigger */ q = fpm_event_queue_timer; while (q) { - if (!timerisset(&ms)) { - ms = q->ev->timeout; + if (!timerisset(&timeout_tv)) { + timeout_tv = q->ev->timeout; } else { - if (timercmp(&q->ev->timeout, &ms, <)) { - ms = q->ev->timeout; + if (timercmp(&q->ev->timeout, &timeout_tv, <)) { + timeout_tv = q->ev->timeout; } } q = q->next; } /* 1s timeout if none has been set */ - if (!timerisset(&ms) || timercmp(&ms, &now, <) || timercmp(&ms, &now, ==)) { - timeout = 1000; + if (!timerisset(&timeout_tv) || timercmp(&timeout_tv, &now_tv, <) || timercmp(&timeout_tv, &now_tv, ==)) { + timeout_ms = ZEND_MILLI_IN_SEC; } else { - timersub(&ms, &now, &tmp); - timeout = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000) + 1; + timersub(&timeout_tv, &now_tv, &tmp); + timeout_ms = (tmp.tv_sec * ZEND_MILLI_IN_SEC) + (tmp.tv_usec / ZEND_MILLI_IN_SEC) + 1; } - ret = module->wait(fpm_event_queue_fd, timeout); + ret = module->wait(fpm_event_queue_fd, timeout_ms); /* is a child, nothing to do here */ if (ret == -2) { @@ -430,12 +432,13 @@ void fpm_event_loop(int err) /* {{{ */ q = fpm_event_queue_timer; while (q) { struct fpm_event_queue_s *next = q->next; - fpm_clock_get(&now); + now_ns = zend_monotime_fallback(); + zend_time_usec2val(now_ns / 1000, now_tv); if (q->ev) { - if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) { + if (timercmp(&now_tv, &q->ev->timeout, >) || timercmp(&now_tv, &q->ev->timeout, ==)) { struct fpm_event_s *ev = q->ev; if (ev->flags & FPM_EV_PERSIST) { - fpm_event_set_timeout(ev, now); + fpm_event_set_timeout(ev, now_tv); } else { /* Delete the event. Make sure this happens before it is fired, * so that the event callback may register the same timer again. */ @@ -495,7 +498,8 @@ int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(st int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */ { - struct timeval now; + uint64_t now_ns; + struct timeval now_tv; struct timeval tmp; if (!ev) { @@ -516,7 +520,8 @@ int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */ /* it's a timer event */ ev->which = FPM_EV_TIMEOUT; - fpm_clock_get(&now); + now_ns = zend_monotime_fallback(); + zend_time_usec2val(now_ns / 1000, now_tv); if (frequency >= 1000) { tmp.tv_sec = frequency / 1000; tmp.tv_usec = (frequency % 1000) * 1000; @@ -525,7 +530,7 @@ int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */ tmp.tv_usec = frequency * 1000; } ev->frequency = tmp; - fpm_event_set_timeout(ev, now); + fpm_event_set_timeout(ev, now_tv); if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != 0) { return -1; diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c index 6619b7c26f064..08b18a9c47d7b 100644 --- a/sapi/fpm/fpm/fpm_log.c +++ b/sapi/fpm/fpm/fpm_log.c @@ -2,17 +2,15 @@ #include "php.h" #include "SAPI.h" + #include #include #include -#ifdef HAVE_TIMES -#include -#endif +#include "zend_time.h" #include "fpm_config.h" #include "fpm_log.h" -#include "fpm_clock.h" #include "fpm_process_ctl.h" #include "fpm_signals.h" #include "fpm_scoreboard.h" @@ -131,7 +129,7 @@ int fpm_log_write(char *log_format) /* {{{ */ test = 1; } - now_epoch = time(NULL); + now_epoch = zend_realtime_get(NULL, NULL); if (!test) { scoreboard = fpm_scoreboard_get(); @@ -207,7 +205,7 @@ int fpm_log_write(char *log_format) /* {{{ */ format[0] = '\0'; if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration_ns / (double)ZEND_NANO_IN_SEC) * 100.); } break; #endif @@ -216,7 +214,7 @@ int fpm_log_write(char *log_format) /* {{{ */ /* seconds */ if (format[0] == '\0' || !strcasecmp(format, "seconds")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration_ns / (double)ZEND_NANO_IN_SEC); } /* milliseconds */ @@ -225,13 +223,13 @@ int fpm_log_write(char *log_format) /* {{{ */ !strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili") ) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration_ns / 1000000.); } /* microseconds */ } else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", (unsigned long)(proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec)); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", (unsigned long)(proc.duration_ns / 1000)); } } else { diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 8af1e51d512fb..ba89bb0713485 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -34,10 +34,6 @@ #include #include "php.h" -#ifdef HAVE_SYS_TIME_H -# include -#endif - #ifdef HAVE_UNISTD_H # include #endif diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c index fca79e4bf70e8..37911513935c1 100644 --- a/sapi/fpm/fpm/fpm_php_trace.c +++ b/sapi/fpm/fpm/fpm_php_trace.c @@ -15,6 +15,8 @@ #include #include +#include "zend_time.h" + #include "fpm_trace.h" #include "fpm_php_trace.h" #include "fpm_children.h" @@ -38,15 +40,15 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog) /* {{{ * { int callers_limit = child->wp->config->request_slowlog_trace_depth; pid_t pid = child->pid; - struct timeval tv; + struct timespec ts; char buf[1024]; long execute_data; long path_translated; long l; - gettimeofday(&tv, 0); + zend_realtime_spec(&ts); - zlog_print_time(&tv, buf, sizeof(buf)); + zlog_print_time(&ts, buf, sizeof(buf)); fprintf(slowlog, "\n%s [pool %s] pid %d\n", buf, child->wp->config->name, (int) pid); diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index 4abffdf093d01..2e254e921e7ff 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -7,8 +7,9 @@ #include #include +#include "zend_time.h" + #include "fpm.h" -#include "fpm_clock.h" #include "fpm_children.h" #include "fpm_signals.h" #include "fpm_events.h" @@ -294,7 +295,7 @@ int fpm_pctl_init_main(void) return 0; } -static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */ +static void fpm_pctl_check_request_timeout(void) /* {{{ */ { struct fpm_worker_pool_s *wp; @@ -306,7 +307,7 @@ static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */ if (terminate_timeout || slowlog_timeout) { for (child = wp->children; child; child = child->next) { - fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout, track_finished); + fpm_request_check_timed_out(child, terminate_timeout, slowlog_timeout, track_finished); } } } @@ -324,7 +325,7 @@ static void fpm_pctl_kill_idle_child(struct fpm_child_s *child) /* {{{ */ } /* }}} */ -static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ */ +static void fpm_pctl_perform_idle_server_maintenance(void) /* {{{ */ { struct fpm_worker_pool_s *wp; @@ -363,7 +364,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ if (last_idle_child == NULL) { last_idle_child = child; } else { - if (timercmp(&child->started, &last_idle_child->started, <)) { + if (child->started_ns < last_idle_child->started_ns) { last_idle_child = child; } } @@ -377,17 +378,17 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ /* this is specific to PM_STYLE_ONDEMAND */ if (wp->config->pm == PM_STYLE_ONDEMAND) { - struct timeval last, now; + uint64_t last_ns, now_ns; zlog(ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children", wp->config->name, active, idle); if (!last_idle_child) continue; - fpm_request_last_activity(last_idle_child, &last); - fpm_clock_get(&now); - if (last.tv_sec < now.tv_sec - wp->config->pm_process_idle_timeout) { + now_ns = zend_monotime_fallback(); + fpm_request_last_activity(last_idle_child, &last_ns); + if (last_ns < now_ns - wp->config->pm_process_idle_timeout * ZEND_NANO_IN_SEC) { fpm_pctl_kill_idle_child(last_idle_child); - } + } continue; } @@ -459,15 +460,13 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */ { static struct fpm_event_s heartbeat; - struct timeval now; if (fpm_globals.parent_pid != getpid()) { return; /* sanity check */ } if (which == FPM_EV_TIMEOUT) { - fpm_clock_get(&now); - fpm_pctl_check_request_timeout(&now); + fpm_pctl_check_request_timeout(); return; } @@ -484,16 +483,14 @@ void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ * void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */ { static struct fpm_event_s heartbeat; - struct timeval now; if (fpm_globals.parent_pid != getpid()) { return; /* sanity check */ } if (which == FPM_EV_TIMEOUT) { - fpm_clock_get(&now); if (fpm_pctl_can_spawn_children()) { - fpm_pctl_perform_idle_server_maintenance(&now); + fpm_pctl_perform_idle_server_maintenance(); /* if it's a child, stop here without creating the next event * this event is reserved to the master process diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c index 4ec24c8084563..77bd058bdd729 100644 --- a/sapi/fpm/fpm/fpm_request.c +++ b/sapi/fpm/fpm/fpm_request.c @@ -1,14 +1,12 @@ /* (c) 2007,2008 Andrei Nigmatulin */ -#ifdef HAVE_TIMES -#include -#endif #include "fpm_config.h" +#include "zend_time.h" + #include "fpm.h" #include "fpm_php.h" #include "fpm_str.h" -#include "fpm_clock.h" #include "fpm_conf.h" #include "fpm_trace.h" #include "fpm_php_trace.h" @@ -38,9 +36,6 @@ const char *fpm_request_get_stage_name(int stage) { void fpm_request_accepting(void) { struct fpm_scoreboard_proc_s *proc; - struct timeval now; - - fpm_clock_get(&now); fpm_scoreboard_update_begin(NULL); @@ -51,7 +46,7 @@ void fpm_request_accepting(void) } proc->request_stage = FPM_REQUEST_ACCEPTING; - proc->tv = now; + proc->last_activity_ns = zend_monotime_fallback(); fpm_scoreboard_proc_release(proc); /* idle++, active-- */ @@ -62,14 +57,14 @@ void fpm_request_reading_headers(void) { struct fpm_scoreboard_proc_s *proc; - struct timeval now; - clock_t now_epoch; + uint64_t now_ns; + time_t now_epoch; #ifdef HAVE_TIMES struct tms cpu; #endif - fpm_clock_get(&now); - now_epoch = time(NULL); + now_ns = zend_monotime_fallback(); + now_epoch = zend_realtime_get(NULL, NULL); #ifdef HAVE_TIMES times(&cpu); #endif @@ -83,8 +78,8 @@ void fpm_request_reading_headers(void) } proc->request_stage = FPM_REQUEST_READING_HEADERS; - proc->tv = now; - proc->accepted = now; + proc->last_activity_ns = now_ns; + proc->accepted_ns = now_ns; proc->accepted_epoch = now_epoch; #ifdef HAVE_TIMES proc->cpu_accepted = cpu; @@ -111,9 +106,7 @@ void fpm_request_info(void) char *query_string = fpm_php_query_string(); char *auth_user = fpm_php_auth_user(); size_t content_length = fpm_php_content_length(); - struct timeval now; - - fpm_clock_get(&now); + uint64_t now_ns = zend_monotime_fallback(); proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); if (proc == NULL) { @@ -122,7 +115,7 @@ void fpm_request_info(void) } proc->request_stage = FPM_REQUEST_INFO; - proc->tv = now; + proc->last_activity_ns = now_ns; if (request_uri) { strlcpy(proc->request_uri, request_uri, sizeof(proc->request_uri)); @@ -154,9 +147,7 @@ void fpm_request_info(void) void fpm_request_executing(void) { struct fpm_scoreboard_proc_s *proc; - struct timeval now; - - fpm_clock_get(&now); + uint64_t now_ns = zend_monotime_fallback(); proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); if (proc == NULL) { @@ -165,20 +156,18 @@ void fpm_request_executing(void) } proc->request_stage = FPM_REQUEST_EXECUTING; - proc->tv = now; + proc->last_activity_ns = now_ns; fpm_scoreboard_proc_release(proc); } void fpm_request_end(void) { struct fpm_scoreboard_proc_s *proc; - struct timeval now; + uint64_t now_ns = zend_monotime_fallback(); #ifdef HAVE_TIMES struct tms cpu; #endif size_t memory = zend_memory_peak_usage(1); - - fpm_clock_get(&now); #ifdef HAVE_TIMES times(&cpu); #endif @@ -189,10 +178,10 @@ void fpm_request_end(void) return; } proc->request_stage = FPM_REQUEST_FINISHED; - proc->tv = now; - timersub(&now, &proc->accepted, &proc->duration); + proc->last_activity_ns = now_ns; + proc->duration_ns = now_ns - proc->accepted_ns; #ifdef HAVE_TIMES - timersub(&proc->tv, &proc->accepted, &proc->cpu_duration); + proc->cpu_duration_ns = now_ns - proc->accepted_ns; proc->last_request_cpu.tms_utime = cpu.tms_utime - proc->cpu_accepted.tms_utime; proc->last_request_cpu.tms_stime = cpu.tms_stime - proc->cpu_accepted.tms_stime; proc->last_request_cpu.tms_cutime = cpu.tms_cutime - proc->cpu_accepted.tms_cutime; @@ -208,9 +197,6 @@ void fpm_request_end(void) void fpm_request_finished(void) { struct fpm_scoreboard_proc_s *proc; - struct timeval now; - - fpm_clock_get(&now); proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); if (proc == NULL) { @@ -219,13 +205,14 @@ void fpm_request_finished(void) } proc->request_stage = FPM_REQUEST_FINISHED; - proc->tv = now; + proc->last_activity_ns = zend_monotime_fallback(); fpm_scoreboard_proc_release(proc); } -void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout, int track_finished) /* {{{ */ +void fpm_request_check_timed_out(struct fpm_child_s *child, int terminate_timeout, int slowlog_timeout, int track_finished) /* {{{ */ { struct fpm_scoreboard_proc_s proc, *proc_p; + uint64_t now_ns; proc_p = fpm_scoreboard_proc_acquire(child->wp->scoreboard, child->scoreboard_i, 1); if (!proc_p) { @@ -236,47 +223,45 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, proc = *proc_p; fpm_scoreboard_proc_release(proc_p); + now_ns = zend_monotime_fallback(); + #if HAVE_FPM_TRACE - if (child->slow_logged.tv_sec) { - if (child->slow_logged.tv_sec != proc.accepted.tv_sec || child->slow_logged.tv_usec != proc.accepted.tv_usec) { - child->slow_logged.tv_sec = 0; - child->slow_logged.tv_usec = 0; - } + if (child->slow_logged_ns && child->slow_logged_ns != proc.accepted_ns) { + child->slow_logged_ns = 0; } #endif if (proc.request_stage > FPM_REQUEST_ACCEPTING && ((proc.request_stage < FPM_REQUEST_END) || track_finished)) { char purified_script_filename[sizeof(proc.script_filename)]; - struct timeval tv; - - timersub(now, &proc.accepted, &tv); + uint64_t elapsed_ns = now_ns - proc.accepted_ns; + long elapsed_sec = (long) (elapsed_ns / ZEND_NANO_IN_SEC); #if HAVE_FPM_TRACE - if (child->slow_logged.tv_sec == 0 && slowlog_timeout && - proc.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { + if (child->slow_logged_ns == 0 && slowlog_timeout && + proc.request_stage == FPM_REQUEST_EXECUTING && elapsed_sec >= slowlog_timeout) { str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename)); - child->slow_logged = proc.accepted; + child->slow_logged_ns = proc.accepted_ns; child->tracer = fpm_php_trace; fpm_trace_signal(child->pid); - zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s%s%s\") executing too slow (%d.%06d sec), logging", + zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s%s%s\") executing too slow (%ld.%09ld sec), logging", child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri, (proc.query_string[0] ? "?" : ""), proc.query_string, - (int) tv.tv_sec, (int) tv.tv_usec); + elapsed_sec, (long) (elapsed_ns % ZEND_NANO_IN_SEC)); } else #endif - if (terminate_timeout && tv.tv_sec >= terminate_timeout) { + if (terminate_timeout && elapsed_sec >= terminate_timeout) { str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename)); fpm_pctl_kill(child->pid, FPM_PCTL_TERM); - zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s%s%s\") execution timed out (%d.%06d sec), terminating", + zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s%s%s\") execution timed out (%ld.%09ld sec), terminating", child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri, (proc.query_string[0] ? "?" : ""), proc.query_string, - (int) tv.tv_sec, (int) tv.tv_usec); + elapsed_sec, (long) (elapsed_ns % ZEND_NANO_IN_SEC)); } } } @@ -296,18 +281,18 @@ int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */ } /* }}} */ -int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /* {{{ */ +int fpm_request_last_activity(struct fpm_child_s *child, uint64_t *last_activity_ns) /* {{{ */ { struct fpm_scoreboard_proc_s *proc; - if (!tv) return -1; + if (!last_activity_ns) return -1; proc = fpm_scoreboard_proc_get_from_child(child); if (!proc) { return -1; } - *tv = proc->tv; + *last_activity_ns = proc->last_activity_ns; return 1; } diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h index 1dcc7f78902fc..b27ec461043a0 100644 --- a/sapi/fpm/fpm/fpm_request.h +++ b/sapi/fpm/fpm/fpm_request.h @@ -19,10 +19,10 @@ void fpm_request_finished(void); struct fpm_child_s; struct timeval; -void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout, int track_finished); +void fpm_request_check_timed_out(struct fpm_child_s *child, int terminate_timeout, int slowlog_timeout, int track_finished); int fpm_request_is_idle(struct fpm_child_s *child); const char *fpm_request_get_stage_name(int stage); -int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv); +int fpm_request_last_activity(struct fpm_child_s *child, uint64_t *last_activity_ns); enum fpm_request_stage_e { FPM_REQUEST_CREATING, diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c index 9a64dbb9c1d65..d6dab84c9c876 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.c +++ b/sapi/fpm/fpm/fpm_scoreboard.c @@ -11,7 +11,6 @@ #include "fpm_shm.h" #include "fpm_sockets.h" #include "fpm_worker_pool.h" -#include "fpm_clock.h" #include "zlog.h" static struct fpm_scoreboard_s *fpm_scoreboard = NULL; diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h index 5f298a41ae61b..3906896005063 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.h +++ b/sapi/fpm/fpm/fpm_scoreboard.h @@ -30,10 +30,10 @@ struct fpm_scoreboard_proc_s { pid_t pid; unsigned long requests; enum fpm_request_stage_e request_stage; - struct timeval accepted; - struct timeval duration; + uint64_t accepted_ns; + uint64_t duration_ns; time_t accepted_epoch; - struct timeval tv; + uint64_t last_activity_ns; char request_uri[128]; char query_string[512]; char request_method[16]; @@ -42,7 +42,7 @@ struct fpm_scoreboard_proc_s { char auth_user[32]; #ifdef HAVE_TIMES struct tms cpu_accepted; - struct timeval cpu_duration; + uint64_t cpu_duration_ns; struct tms last_request_cpu; struct timeval last_request_cpu_duration; #endif diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 96bdb96e408e8..0e6fdf68ea393 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -2,17 +2,19 @@ #include "php.h" #include "zend_long.h" +#include "zend_time.h" #include "SAPI.h" + #include #include "fpm_config.h" #include "fpm_scoreboard.h" #include "fpm_status.h" -#include "fpm_clock.h" #include "zlog.h" #include "fpm_atomic.h" #include "fpm_conf.h" #include "fpm_php.h" + #include "ext/standard/html.h" #include "ext/json/php_json.h" @@ -50,7 +52,7 @@ int fpm_status_export_to_zval(zval *status) struct fpm_scoreboard_s scoreboard, *scoreboard_p; zval fpm_proc_stats, fpm_proc_stat; time_t now_epoch; - struct timeval duration, now; + uint64_t duration_ns, now_ns; double cpu; int i; @@ -77,8 +79,8 @@ int fpm_status_export_to_zval(zval *status) } fpm_scoreboard_release(scoreboard_p); - now_epoch = time(NULL); - fpm_clock_get(&now); + now_epoch = zend_realtime_get(NULL, NULL); + now_ns = zend_monotime_fallback(); array_init(status); add_assoc_string(status, "pool", scoreboard.pool); @@ -104,10 +106,10 @@ int fpm_status_export_to_zval(zval *status) } proc_p = &procs[i]; /* prevent NaN */ - if (procs[i].cpu_duration.tv_sec == 0 && procs[i].cpu_duration.tv_usec == 0) { + if (!procs[i].cpu_duration_ns) { cpu = 0.; } else { - cpu = (procs[i].last_request_cpu.tms_utime + procs[i].last_request_cpu.tms_stime + procs[i].last_request_cpu.tms_cutime + procs[i].last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (procs[i].cpu_duration.tv_sec + procs[i].cpu_duration.tv_usec / 1000000.) * 100.; + cpu = (procs[i].last_request_cpu.tms_utime + procs[i].last_request_cpu.tms_stime + procs[i].last_request_cpu.tms_cutime + procs[i].last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (procs[i].cpu_duration_ns / (double)ZEND_NANO_IN_SEC) * 100.; } array_init(&fpm_proc_stat); @@ -117,11 +119,11 @@ int fpm_status_export_to_zval(zval *status) add_assoc_long(&fpm_proc_stat, "start-since", now_epoch - procs[i].start_epoch); add_assoc_long(&fpm_proc_stat, "requests", procs[i].requests); if (procs[i].request_stage == FPM_REQUEST_ACCEPTING) { - duration = procs[i].duration; + duration_ns = procs[i].duration_ns; } else { - timersub(&now, &procs[i].accepted, &duration); + duration_ns = now_ns - procs[i].accepted_ns; } - add_assoc_long(&fpm_proc_stat, "request-duration", duration.tv_sec * 1000000UL + duration.tv_usec); + add_assoc_long(&fpm_proc_stat, "request-duration", duration_ns / 1000); add_assoc_string(&fpm_proc_stat, "request-method", procs[i].request_method[0] != '\0' ? procs[i].request_method : "-"); add_assoc_string(&fpm_proc_stat, "request-uri", procs[i].request_uri); add_assoc_string(&fpm_proc_stat, "query-string", procs[i].query_string); @@ -541,10 +543,10 @@ int fpm_status_handle_request(void) /* {{{ */ int first; zend_string *tmp_query_string; char *query_string; - struct timeval duration, now; + uint64_t duration_ns, now_ns; float cpu; - fpm_clock_get(&now); + now_ns = zend_monotime_fallback(); if (full_pre) { PUTS(full_pre); @@ -590,16 +592,16 @@ int fpm_status_handle_request(void) /* {{{ */ } /* prevent NaN */ - if (proc->cpu_duration.tv_sec == 0 && proc->cpu_duration.tv_usec == 0) { + if (proc->cpu_duration_ns == 0) { cpu = 0.; } else { - cpu = (proc->last_request_cpu.tms_utime + proc->last_request_cpu.tms_stime + proc->last_request_cpu.tms_cutime + proc->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc->cpu_duration.tv_sec + proc->cpu_duration.tv_usec / 1000000.) * 100.; + cpu = (proc->last_request_cpu.tms_utime + proc->last_request_cpu.tms_stime + proc->last_request_cpu.tms_cutime + proc->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc->cpu_duration_ns / (double)ZEND_NANO_IN_SEC) * 100.; } if (proc->request_stage == FPM_REQUEST_ACCEPTING) { - duration = proc->duration; + duration_ns = proc->duration_ns; } else { - timersub(&now, &proc->accepted, &duration); + duration_ns = now_ns - proc->accepted_ns; } strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc->start_epoch)); spprintf(&buffer, 0, full_syntax, @@ -608,7 +610,7 @@ int fpm_status_handle_request(void) /* {{{ */ time_buffer, (unsigned long) (now_epoch - proc->start_epoch), proc->requests, - (unsigned long) (duration.tv_sec * 1000000UL + duration.tv_usec), + (unsigned long) (duration_ns / 1000), proc->request_method[0] != '\0' ? proc->request_method : "-", proc->request_uri[0] != '\0' ? proc->request_uri : "-", query_string ? "?" : "", diff --git a/sapi/fpm/fpm/fpm_systemd.c b/sapi/fpm/fpm/fpm_systemd.c index d5858ac780d64..5a38476053768 100644 --- a/sapi/fpm/fpm/fpm_systemd.c +++ b/sapi/fpm/fpm/fpm_systemd.c @@ -4,7 +4,6 @@ #include #include "fpm.h" -#include "fpm_clock.h" #include "fpm_worker_pool.h" #include "fpm_scoreboard.h" #include "zlog.h" diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index b2f0e71d83314..fcabfd11c2955 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -39,7 +39,6 @@ #include "fpm.h" #include "fpm_conf.h" #include "fpm_cleanup.h" -#include "fpm_clock.h" #include "fpm_stdio.h" #include "fpm_unix.h" #include "fpm_signals.h" @@ -520,10 +519,6 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ } #endif - if (0 > fpm_clock_init()) { - return -1; - } - #ifdef HAVE_APPARMOR if (wp->config->apparmor_hat) { char *con, *new_con; @@ -677,9 +672,6 @@ int fpm_unix_init_main(void) /* continue as a child */ setsid(); - if (0 > fpm_clock_init()) { - return -1; - } if (fpm_global_config.process_priority != 64) { if (is_root) { diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 39c6eec885bcd..eb2450b189022 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -2,18 +2,19 @@ #include "fpm_config.h" +#include "zend_time.h" + #include #include -#include #include #include -#include #include #include "php_syslog.h" #include "zlog.h" #include "fpm.h" + #include "zend_portability.h" /* buffer is used for fmt result and it should never be over 2048 */ @@ -74,15 +75,15 @@ void zlog_set_launched(void) /* {{{ */ } /* }}} */ -size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) /* {{{ */ +size_t zlog_print_time(struct timespec *ts, char *timebuf, size_t timebuf_len) /* {{{ */ { struct tm t; size_t len; len = strftime(timebuf, timebuf_len, "[%d-%b-%Y %H:%M:%S", - localtime_r((const time_t *) &tv->tv_sec, &t)); + localtime_r(&ts->tv_sec, &t)); if (zlog_level == ZLOG_DEBUG) { - len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec); + len += snprintf(timebuf + len, timebuf_len - len, ".%09ld", ts->tv_nsec); } len += snprintf(timebuf + len, timebuf_len - len, "] "); return len; @@ -158,7 +159,7 @@ static size_t zlog_buf_prefix( const char *function, int line, int flags, char *buf, size_t buf_size, int use_syslog) /* {{{ */ { - struct timeval tv; + struct timespec ts; size_t len = 0; #ifdef HAVE_SYSLOG_H @@ -173,8 +174,8 @@ static size_t zlog_buf_prefix( #endif { if (!fpm_globals.is_child) { - gettimeofday(&tv, 0); - len = zlog_print_time(&tv, buf, buf_size); + zend_realtime_spec(&ts); + len = zlog_print_time(&ts, buf, buf_size); } if (zlog_level == ZLOG_DEBUG) { if (!fpm_globals.is_child) { diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h index be22acc32f3ca..69cdef98b5f62 100644 --- a/sapi/fpm/fpm/zlog.h +++ b/sapi/fpm/fpm/zlog.h @@ -9,7 +9,7 @@ #define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__) #define zlog_msg(flags, prefix, msg) zlog_msg_ex(__func__, __LINE__, flags, prefix, msg) -struct timeval; +struct timespec; typedef unsigned char zlog_bool; @@ -24,7 +24,7 @@ int zlog_set_buffering(zlog_bool buffering); const char *zlog_get_level_name(int log_level); void zlog_set_launched(void); -size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len); +size_t zlog_print_time(struct timespec *ts, char *timebuf, size_t timebuf_len); void vzlog(const char *function, int line, int flags, const char *fmt, va_list args); void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index 432c0338c46da..2db46d911d69b 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -21,6 +21,7 @@ #include "php_variables.h" #include "zend_highlight.h" #include "zend_portability.h" +#include "zend_time.h" #include "zend.h" #include "ext/standard/basic_functions.h" #include "ext/standard/info.h" @@ -46,7 +47,6 @@ #include #include #include -#include #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #include "lscriu.c" @@ -1450,8 +1450,8 @@ int main( int argc, char * argv[] ) char * php_bind = NULL; int n; int climode = 0; - struct timeval tv_req_begin; - struct timeval tv_req_end; + int64_t req_begin_ns, req_end_ns; + time_t req_end_sec; int slow_script_msec = 0; char time_buf[40]; @@ -1563,16 +1563,16 @@ int main( int argc, char * argv[] ) } #endif if ( slow_script_msec ) { - gettimeofday( &tv_req_begin, NULL ); + req_begin_ns = zend_monotime_fallback(); } ret = processReq(); if ( slow_script_msec ) { - gettimeofday( &tv_req_end, NULL ); - n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000 - + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000; + req_end_ns = zend_monotime_fallback(); + n = (long) (req_end_ns - req_begin_ns) / 1000000; if ( n > slow_script_msec ) { - strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) ); + req_end_sec = (time_t) (req_end_ns / ZEND_NANO_IN_SEC); + strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &req_end_sec ) ); fprintf( stderr, "[%s] Slow PHP script: %d ms\n URL: %s %s\n Query String: %s\n Script: %s\n", time_buf, n, LSAPI_GetRequestMethod(), LSAPI_GetScriptName(), LSAPI_GetQueryString(), diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c index 9d8408c613395..802b1ffb8b064 100644 --- a/sapi/litespeed/lsapilib.c +++ b/sapi/litespeed/lsapilib.c @@ -93,6 +93,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include +#include struct lsapi_MD5Context { uint32 buf[4]; @@ -246,15 +247,15 @@ void LSAPI_Log(int flag, const char * fmt, ...) if ((flag & LSAPI_LOG_TIMESTAMP_BITS) && !(s_stderr_is_pipe)) { - struct timeval tv; + struct timespec ts; struct tm tm; - gettimeofday(&tv, NULL); - localtime_r(&tv.tv_sec, &tm); + zend_realtime_spec(&ts); + localtime_r(&ts.tv_sec, &tm); if (flag & LSAPI_LOG_TIMESTAMP_FULL) { - p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", + p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%09ld ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec); + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); } else if (flag & LSAPI_LOG_TIMESTAMP_HMS) { diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c index 63b61fb8eab04..194c2268d6066 100644 --- a/sapi/phpdbg/phpdbg_out.c +++ b/sapi/phpdbg/phpdbg_out.c @@ -21,12 +21,9 @@ #include "spprintf.h" #include "phpdbg.h" #include "phpdbg_io.h" +#include "zend_time.h" #include "ext/standard/html.h" -#ifdef _WIN32 -# include "win32/time.h" -#endif - ZEND_EXTERN_MODULE_GLOBALS(phpdbg) PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...) { @@ -101,12 +98,9 @@ int phpdbg_process_print(int fd, int type, const char *msg, int msglen) { /* no formatting on logging output */ case P_LOG: if (msg) { - struct timeval tp; - if (gettimeofday(&tp, NULL) == SUCCESS) { - msgoutlen = phpdbg_asprintf(&msgout, "[%ld %.8F]: %.*s\n", tp.tv_sec, tp.tv_usec / 1000000., msglen, msg); - } else { - msgoutlen = FAILURE; - } + struct timespec ts; + zend_realtime_spec(&ts); + msgoutlen = phpdbg_asprintf(&msgout, "[%lld %.8F]: %.*s\n", (long long)ts.tv_sec, ts.tv_nsec / 1000000000., msglen, msg); } break; EMPTY_SWITCH_DEFAULT_CASE() diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 403f0aa6efbfe..97e36659899ca 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -240,7 +240,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c zend_weakrefs.c \ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \ zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c zend_system_id.c \ - zend_enum.c zend_fibers.c zend_atomic.c zend_hrtime.c zend_frameless_function.c zend_property_hooks.c \ + zend_enum.c zend_fibers.c zend_atomic.c zend_time.c zend_hrtime.c zend_frameless_function.c zend_property_hooks.c \ zend_lazy_objects.c"); ADD_SOURCES("Zend\\Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c"); diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in index d8ff0c9dc6a50..354ea1025b089 100644 --- a/win32/build/config.w32.h.in +++ b/win32/build/config.w32.h.in @@ -50,6 +50,7 @@ #undef HAVE_SETITIMER #undef HAVE_IODBC #define HAVE_LIBDL 1 +#define HAVE_TIMESPEC_GET 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_PUTENV 1 #define HAVE_TZSET 1