Skip to content

Commit 071e9be

Browse files
committed
Move more time functions to native code. NFC
I'm pretty this is going to be codesize win for a lot of codebases even though its not showing up in our (minimal) codesize tests.
1 parent 9af72c0 commit 071e9be

File tree

4 files changed

+87
-72
lines changed

4 files changed

+87
-72
lines changed

src/library.js

+13-67
Original file line numberDiff line numberDiff line change
@@ -391,25 +391,9 @@ LibraryManager.library = {
391391
// time.h
392392
// ==========================================================================
393393

394-
clock__sig: 'i',
395-
clock: function() {
396-
if (_clock.start === undefined) _clock.start = Date.now();
397-
return ((Date.now() - _clock.start) * ({{{ cDefine('CLOCKS_PER_SEC') }}} / 1000))|0;
398-
},
399-
400-
time__sig: 'ii',
401-
time: function(ptr) {
402-
{{{ from64('ptr') }}};
403-
var ret = (Date.now()/1000)|0;
404-
if (ptr) {
405-
{{{ makeSetValue('ptr', 0, 'ret', 'i32') }}};
406-
}
407-
return ret;
408-
},
409-
410-
difftime__sig: 'dii',
411-
difftime: function(time1, time0) {
412-
return time1 - time0;
394+
_emscripten_date_now__sig: 'j',
395+
_emscripten_date_now: function() {
396+
return Date.now();
413397
},
414398

415399
_mktime_js__sig: 'ii',
@@ -549,11 +533,6 @@ LibraryManager.library = {
549533
return ret;
550534
},
551535

552-
dysize: function(year) {
553-
var leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
554-
return leap ? 366 : 365;
555-
},
556-
557536
// TODO: Initialize these to defaults on startup from system settings.
558537
// Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm)
559538
_tzset_js__deps: ['tzset_impl'],
@@ -1246,48 +1225,17 @@ LibraryManager.library = {
12461225
return _strptime(buf, format, tm); // no locale support yet
12471226
},
12481227

1249-
timespec_get__deps: ['clock_gettime', '$setErrNo'],
1250-
timespec_get: function(ts, base) {
1251-
//int timespec_get(struct timespec *ts, int base);
1252-
if (base !== {{{ cDefine('TIME_UTC') }}}) {
1253-
// There is no other implemented value than TIME_UTC; all other values are considered erroneous.
1254-
setErrNo({{{ cDefine('EINVAL') }}});
1255-
return 0;
1256-
}
1257-
var ret = _clock_gettime({{{ cDefine('CLOCK_REALTIME') }}}, ts);
1258-
return ret < 0 ? 0 : base;
1259-
},
1260-
12611228
// ==========================================================================
12621229
// sys/time.h
12631230
// ==========================================================================
12641231

1265-
clock_gettime__sig: 'iii',
1266-
clock_gettime__deps: ['emscripten_get_now', 'emscripten_get_now_is_monotonic', '$setErrNo'],
1267-
clock_gettime: function(clk_id, tp) {
1268-
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
1269-
var now;
1270-
if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
1271-
now = Date.now();
1272-
} else if ((clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} || clk_id === {{{ cDefine('CLOCK_MONOTONIC_RAW') }}}) && _emscripten_get_now_is_monotonic) {
1273-
now = _emscripten_get_now();
1274-
} else {
1275-
setErrNo({{{ cDefine('EINVAL') }}});
1276-
return -1;
1277-
}
1278-
{{{ makeSetValue('tp', C_STRUCTS.timespec.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds
1279-
{{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '((now % 1000)*1000*1000)|0', 'i32') }}}; // nanoseconds
1280-
return 0;
1281-
},
1282-
__clock_gettime__sig: 'iii',
1283-
__clock_gettime: 'clock_gettime', // musl internal alias
1284-
clock_getres__deps: ['emscripten_get_now_res', 'emscripten_get_now_is_monotonic', '$setErrNo'],
1232+
clock_getres__deps: ['emscripten_get_now_res', '$nowIsMonotonic', '$setErrNo'],
12851233
clock_getres: function(clk_id, res) {
12861234
// int clock_getres(clockid_t clk_id, struct timespec *res);
12871235
var nsec;
12881236
if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
12891237
nsec = 1000 * 1000; // educated guess that it's milliseconds
1290-
} else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic) {
1238+
} else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && nowIsMonotonic) {
12911239
nsec = _emscripten_get_now_res();
12921240
} else {
12931241
setErrNo({{{ cDefine('EINVAL') }}});
@@ -1297,14 +1245,6 @@ LibraryManager.library = {
12971245
{{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is nanoseconds
12981246
return 0;
12991247
},
1300-
gettimeofday__sig: 'iii',
1301-
// http://pubs.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html
1302-
gettimeofday: function(ptr) {
1303-
var now = Date.now();
1304-
{{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds
1305-
{{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_usec, '((now % 1000)*1000)|0', 'i32') }}}; // microseconds
1306-
return 0;
1307-
},
13081248

13091249
// ==========================================================================
13101250
// sys/timeb.h
@@ -2405,6 +2345,7 @@ LibraryManager.library = {
24052345
},
24062346

24072347
emscripten_get_now__import: true,
2348+
emscripten_get_now__sig: 'vd',
24082349
emscripten_get_now: ';' +
24092350
#if ENVIRONMENT_MAY_BE_NODE
24102351
"if (ENVIRONMENT_IS_NODE) {\n" +
@@ -2464,7 +2405,7 @@ LibraryManager.library = {
24642405
// Represents whether emscripten_get_now is guaranteed monotonic; the Date.now
24652406
// implementation is not :(
24662407
#if MIN_IE_VERSION <= 9 || MIN_FIREFOX_VERSION <= 14 || MIN_CHROME_VERSION <= 23 || MIN_SAFARI_VERSION <= 80400 // https://caniuse.com/#feat=high-resolution-time
2467-
emscripten_get_now_is_monotonic: `
2408+
$nowIsMonotonic: `
24682409
((typeof performance == 'object' && performance && typeof performance['now'] == 'function')
24692410
#if ENVIRONMENT_MAY_BE_NODE
24702411
|| ENVIRONMENT_IS_NODE
@@ -2475,9 +2416,14 @@ LibraryManager.library = {
24752416
);`,
24762417
#else
24772418
// Modern environment where performance.now() is supported: (rely on minifier to return true unconditionally from this function)
2478-
emscripten_get_now_is_monotonic: 'true;',
2419+
$nowIsMonotonic: 'true;',
24792420
#endif
24802421

2422+
_emscripten_get_now_is_monotonic__deps: ['$nowIsMonotonic'],
2423+
_emscripten_get_now_is_monotonic: function() {
2424+
return nowIsMonotonic;
2425+
},
2426+
24812427
#if MINIMAL_RUNTIME
24822428
$warnOnce: function(text) {
24832429
if (!warnOnce.shown) warnOnce.shown = {};

src/library_wasi.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ var WasiLibrary = {
137137
// either wait for BigInt support or to legalize on the client.
138138
clock_time_get__nothrow: true,
139139
clock_time_get__sig: 'iiiii',
140-
clock_time_get__deps: ['emscripten_get_now', 'emscripten_get_now_is_monotonic', '$checkWasiClock'],
140+
clock_time_get__deps: ['emscripten_get_now', '$nowIsMonotonic', '$checkWasiClock'],
141141
clock_time_get: function(clk_id, {{{ defineI64Param('precision') }}}, ptime) {
142142
{{{ receiveI64ParamAsI32s('precision') }}}
143143
if (!checkWasiClock(clk_id)) {
@@ -147,7 +147,7 @@ var WasiLibrary = {
147147
// all wasi clocks but realtime are monotonic
148148
if (clk_id === {{{ cDefine('__WASI_CLOCKID_REALTIME') }}}) {
149149
now = Date.now();
150-
} else if (_emscripten_get_now_is_monotonic) {
150+
} else if (nowIsMonotonic) {
151151
now = _emscripten_get_now();
152152
} else {
153153
return {{{ cDefine('ENOSYS') }}};
@@ -161,7 +161,7 @@ var WasiLibrary = {
161161

162162
clock_res_get__nothrow: true,
163163
clock_res_get__sig: 'iii',
164-
clock_res_get__deps: ['emscripten_get_now', 'emscripten_get_now_res', 'emscripten_get_now_is_monotonic', '$checkWasiClock'],
164+
clock_res_get__deps: ['emscripten_get_now', 'emscripten_get_now_res', '$nowIsMonotonic', '$checkWasiClock'],
165165
clock_res_get: function(clk_id, pres) {
166166
if (!checkWasiClock(clk_id)) {
167167
return {{{ cDefine('EINVAL') }}};
@@ -170,7 +170,7 @@ var WasiLibrary = {
170170
// all wasi clocks but realtime are monotonic
171171
if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
172172
nsec = 1000 * 1000; // educated guess that it's milliseconds
173-
} else if (_emscripten_get_now_is_monotonic) {
173+
} else if (nowIsMonotonic) {
174174
nsec = _emscripten_get_now_res();
175175
} else {
176176
return {{{ cDefine('ENOSYS') }}};

system/lib/libc/emscripten_time.c

+68
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
* found in the LICENSE file.
66
*/
77

8+
#include <emscripten/emscripten.h>
89
#include <time.h>
910
#include <stdbool.h>
11+
#include <sys/time.h>
12+
#include <threads.h>
1013
#include "libc.h"
1114

15+
1216
// Replaces musl's __tz.c
1317

1418
__attribute__((__weak__)) long timezone = 0;
@@ -57,5 +61,69 @@ struct tm *__gmtime_r(const time_t *restrict t, struct tm *restrict tm) {
5761
return tm;
5862
}
5963

64+
double _emscripten_date_now();
65+
66+
__attribute__((__weak__))
67+
clock_t __clock() {
68+
static thread_local double start = 0;
69+
if (!start) {
70+
start = _emscripten_date_now();
71+
}
72+
return (_emscripten_date_now() - start) * (CLOCKS_PER_SEC / 1000);
73+
}
74+
75+
__attribute__((__weak__))
76+
time_t __time(time_t *t) {
77+
double ret = _emscripten_date_now() / 1000;
78+
if (t) {
79+
*t = ret;
80+
}
81+
return ret;
82+
}
83+
84+
extern bool _emscripten_get_now_is_monotonic();
85+
86+
__attribute__((__weak__))
87+
int __clock_gettime(clockid_t clk, struct timespec *ts) {
88+
static thread_local bool checked_monotonic = false;
89+
static thread_local bool is_monotonic = 0;
90+
if (!checked_monotonic) {
91+
is_monotonic = _emscripten_get_now_is_monotonic();
92+
checked_monotonic = true;
93+
}
94+
95+
double now_ms;
96+
if (clk == CLOCK_REALTIME) {
97+
now_ms = _emscripten_date_now();
98+
} else if ((clk == CLOCK_MONOTONIC || clk == CLOCK_MONOTONIC_RAW) && is_monotonic) {
99+
now_ms = emscripten_get_now();
100+
} else {
101+
errno = EINVAL;
102+
return -1;
103+
}
104+
105+
long long now_s = now_ms / 1000;
106+
ts->tv_sec = now_s; // seconds
107+
ts->tv_nsec = (now_ms - (now_s * 1000)) * 1000 * 1000; // nanoseconds
108+
return 0;
109+
}
110+
111+
int __gettimeofday(struct timeval *restrict tv, void *restrict tz) {
112+
double now_ms = _emscripten_date_now();
113+
long long now_s = now_ms / 1000;
114+
tv->tv_sec = now_s; // seconds
115+
tv->tv_usec = (now_ms - (now_s * 1000)) * 1000; // nicroseconds
116+
return 0;
117+
}
118+
119+
int dysize(int year) {
120+
int leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
121+
return leap ? 366 : 365;
122+
}
123+
60124
weak_alias(__gmtime_r, gmtime_r);
61125
weak_alias(__localtime_r, localtime_r);
126+
weak_alias(__time, time);
127+
weak_alias(__clock, clock);
128+
weak_alias(__clock_gettime, clock_gettime);
129+
weak_alias(__gettimeofday, gettimeofday);

tools/system_libs.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -915,11 +915,13 @@ def get_files(self):
915915
'asctime_r.c',
916916
'asctime.c',
917917
'ctime.c',
918+
'difftime.c',
918919
'gmtime.c',
919920
'localtime.c',
920921
'nanosleep.c',
921922
'clock_nanosleep.c',
922923
'ctime_r.c',
924+
'timespec_get.c',
923925
'utime.c',
924926
])
925927
libc_files += files_in_path(
@@ -1644,7 +1646,6 @@ def get_files(self):
16441646
'__year_to_secs.c',
16451647
'clock.c',
16461648
'clock_gettime.c',
1647-
'difftime.c',
16481649
'gettimeofday.c',
16491650
'localtime_r.c',
16501651
'gmtime_r.c',

0 commit comments

Comments
 (0)