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