hrtime.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Niklas Keller <kelunik@php.net> |
  16. | Author: Anatol Belski <ab@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #include "php.h"
  20. #include "hrtime.h"
  21. /* {{{ */
  22. /* This file reuses code parts from the cross-platform timer library
  23. Public Domain - 2011 Mattias Jansson / Rampant Pixels */
  24. #if PHP_HRTIME_PLATFORM_POSIX
  25. # include <unistd.h>
  26. # include <time.h>
  27. # include <string.h>
  28. #elif PHP_HRTIME_PLATFORM_WINDOWS
  29. # define WIN32_LEAN_AND_MEAN
  30. static double _timer_scale = .0;
  31. #elif PHP_HRTIME_PLATFORM_APPLE
  32. # include <mach/mach_time.h>
  33. # include <string.h>
  34. static mach_timebase_info_data_t _timerlib_info;
  35. #elif PHP_HRTIME_PLATFORM_HPUX
  36. # include <sys/time.h>
  37. #elif PHP_HRTIME_PLATFORM_AIX
  38. # include <sys/time.h>
  39. # include <sys/systemcfg.h>
  40. #endif
  41. #define NANO_IN_SEC 1000000000
  42. /* }}} */
  43. static int _timer_init()
  44. {/*{{{*/
  45. #if PHP_HRTIME_PLATFORM_WINDOWS
  46. LARGE_INTEGER tf = {0};
  47. if (!QueryPerformanceFrequency(&tf) || 0 == tf.QuadPart) {
  48. return -1;
  49. }
  50. _timer_scale = (double)NANO_IN_SEC / (php_hrtime_t)tf.QuadPart;
  51. #elif PHP_HRTIME_PLATFORM_APPLE
  52. if (mach_timebase_info(&_timerlib_info)) {
  53. return -1;
  54. }
  55. #elif PHP_HRTIME_PLATFORM_POSIX
  56. #if !_POSIX_MONOTONIC_CLOCK
  57. #ifdef _SC_MONOTONIC_CLOCK
  58. if (0 >= sysconf(_SC_MONOTONIC_CLOCK)) {
  59. return -1;
  60. }
  61. #endif
  62. #endif
  63. #elif PHP_HRTIME_PLATFORM_HPUX
  64. /* pass */
  65. #elif PHP_HRTIME_PLATFORM_AIX
  66. /* pass */
  67. #else
  68. /* Timer unavailable. */
  69. return -1;
  70. #endif
  71. return 0;
  72. }/*}}}*/
  73. /* {{{ */
  74. PHP_MINIT_FUNCTION(hrtime)
  75. {
  76. if (0 > _timer_init()) {
  77. php_error_docref(NULL, E_WARNING, "Failed to initialize high-resolution timer");
  78. return FAILURE;
  79. }
  80. return SUCCESS;
  81. }
  82. /* }}} */
  83. static zend_always_inline php_hrtime_t _timer_current(void)
  84. {/*{{{*/
  85. #if PHP_HRTIME_PLATFORM_WINDOWS
  86. LARGE_INTEGER lt = {0};
  87. QueryPerformanceCounter(&lt);
  88. return (php_hrtime_t)((php_hrtime_t)lt.QuadPart * _timer_scale);
  89. #elif PHP_HRTIME_PLATFORM_APPLE
  90. return (php_hrtime_t)mach_absolute_time() * _timerlib_info.numer / _timerlib_info.denom;
  91. #elif PHP_HRTIME_PLATFORM_POSIX
  92. struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
  93. if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) {
  94. return ((php_hrtime_t) ts.tv_sec * (php_hrtime_t)NANO_IN_SEC) + ts.tv_nsec;
  95. }
  96. return 0;
  97. #elif PHP_HRTIME_PLATFORM_HPUX
  98. return (php_hrtime_t) gethrtime();
  99. #elif PHP_HRTIME_PLATFORM_AIX
  100. timebasestruct_t t;
  101. read_wall_time(&t, TIMEBASE_SZ);
  102. time_base_to_time(&t, TIMEBASE_SZ);
  103. return (php_hrtime_t) t.tb_high * (php_hrtime_t)NANO_IN_SEC + t.tb_low;
  104. #else
  105. return 0;
  106. #endif
  107. }/*}}}*/
  108. #if ZEND_ENABLE_ZVAL_LONG64
  109. #define PHP_RETURN_HRTIME(t) RETURN_LONG((zend_long)t)
  110. #else
  111. #ifdef _WIN32
  112. # define HRTIME_U64A(i, s, len) _ui64toa_s(i, s, len, 10)
  113. #else
  114. # define HRTIME_U64A(i, s, len) \
  115. do { \
  116. int st = snprintf(s, len, "%llu", i); \
  117. s[st] = '\0'; \
  118. } while (0)
  119. #endif
  120. #define PHP_RETURN_HRTIME(t) do { \
  121. char _a[ZEND_LTOA_BUF_LEN]; \
  122. double _d; \
  123. HRTIME_U64A(t, _a, ZEND_LTOA_BUF_LEN); \
  124. _d = zend_strtod(_a, NULL); \
  125. RETURN_DOUBLE(_d); \
  126. } while (0)
  127. #endif
  128. /* {{{ proto mixed hrtime([bool get_as_number = false])
  129. Returns an array of integers in form [seconds, nanoseconds] counted
  130. from an arbitrary point in time. If an optional boolean argument is
  131. passed, returns an integer on 64-bit platforms or float on 32-bit
  132. containing the current high-resolution time in nanoseconds. The
  133. delivered timestamp is monotonic and can not be adjusted. */
  134. PHP_FUNCTION(hrtime)
  135. {
  136. #if HRTIME_AVAILABLE
  137. zend_bool get_as_num = 0;
  138. php_hrtime_t t = _timer_current();
  139. ZEND_PARSE_PARAMETERS_START(0, 1)
  140. Z_PARAM_OPTIONAL
  141. Z_PARAM_BOOL(get_as_num)
  142. ZEND_PARSE_PARAMETERS_END();
  143. if (UNEXPECTED(get_as_num)) {
  144. PHP_RETURN_HRTIME(t);
  145. } else {
  146. array_init_size(return_value, 2);
  147. zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
  148. add_next_index_long(return_value, (zend_long)(t / (php_hrtime_t)NANO_IN_SEC));
  149. add_next_index_long(return_value, (zend_long)(t % (php_hrtime_t)NANO_IN_SEC));
  150. }
  151. #else
  152. RETURN_FALSE
  153. #endif
  154. }
  155. /* }}} */
  156. PHPAPI php_hrtime_t php_hrtime_current(void)
  157. {/*{{{*/
  158. return _timer_current();
  159. }/*}}}*/
  160. /*
  161. * Local variables:
  162. * tab-width: 4
  163. * c-basic-offset: 4
  164. * End:
  165. * vim600: sw=4 ts=4 fdm=marker
  166. * vim<600: sw=4 ts=4
  167. */