diff --git a/emscripten-version.txt b/emscripten-version.txt index 1a90c51133d32..14094f3776cc6 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.23.2 +1.23.3 diff --git a/src/library.js b/src/library.js index 55c1959c11093..91f8774753e12 100644 --- a/src/library.js +++ b/src/library.js @@ -5783,13 +5783,13 @@ LibraryManager.library = { } return _usleep((seconds * 1e6) + (nanoseconds / 1000)); }, - clock_gettime__deps: ['emscripten_get_now','emscripten_get_now_monotonic','$ERRNO_CODES', '__setErrNo'], + clock_gettime__deps: ['emscripten_get_now', 'emscripten_get_now_is_monotonic', '$ERRNO_CODES', '__setErrNo'], clock_gettime: function(clk_id, tp) { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now; if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { now = Date.now(); - } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_monotonic()) { + } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic()) { now = _emscripten_get_now(); } else { ___setErrNo(ERRNO_CODES.EINVAL); @@ -5803,23 +5803,24 @@ LibraryManager.library = { clock_settime: function(clk_id, tp) { // int clock_settime(clockid_t clk_id, const struct timespec *tp); // Nothing. - ___setErrNo(ERRNO_CODES.EPERM); + ___setErrNo(clk_id === {{{ cDefine('CLOCK_REALTIME') }}} ? ERRNO_CODES.EPERM + : ERRNO_CODES.EINVAL); return -1; }, - clock_getres__deps: ['emscripten_get_now_res','emscripten_get_now_monotonic','$ERRNO_CODES', '__setErrNo'], + clock_getres__deps: ['emscripten_get_now_res', 'emscripten_get_now_is_monotonic', '$ERRNO_CODES', '__setErrNo'], clock_getres: function(clk_id, res) { // int clock_getres(clockid_t clk_id, struct timespec *res); var nsec; if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { - nsec = 1000 * 1000; - } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_monotonic()) { - now = _emscripten_get_now_res(); + nsec = 1000 * 1000; // educated guess that it's milliseconds + } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic()) { + nsec = _emscripten_get_now_res(); } else { ___setErrNo(ERRNO_CODES.EINVAL); return -1; } - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}}; - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is milliseconds + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '(nsec/1000000000)|0', 'i32') }}}; + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is nanoseconds return 0; }, @@ -8502,11 +8503,12 @@ LibraryManager.library = { } }, - emscripten_get_now_monotonic__deps: ['emscripten_get_now'], - emscripten_get_now_monotonic: function() { + emscripten_get_now_is_monotonic__deps: ['emscripten_get_now'], + emscripten_get_now_is_monotonic: function() { // return whether emscripten_get_now is guaranteed monotonic; the Date.now // implementation is not :( - return (_emscripten_get_now() == Date.now)|0; + return ENVIRONMENT_IS_NODE || (typeof dateNow !== 'undefined') || + (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']); }, // Returns [parentFuncArguments, functionName, paramListName] diff --git a/tests/core/test_posixtime.in b/tests/core/test_posixtime.in new file mode 100644 index 0000000000000..d07bd61fd4f37 --- /dev/null +++ b/tests/core/test_posixtime.in @@ -0,0 +1,47 @@ +#include +#include +#include + +int main() { + clockid_t clocks[] = { CLOCK_REALTIME, CLOCK_MONOTONIC }; + for (int i = 0; i < (int)(sizeof(clocks)/sizeof(*clocks)); ++i) { + printf("%sTests for clockid_t=%d\n-----------------\n", + i == 0 ? "" : "\n", clocks[i]); + struct timespec ts; + int rv = clock_getres(clocks[i], &ts); + if (rv) + printf("clock_getres failed\n"); + else if (ts.tv_sec || ts.tv_nsec > 50000000) + printf("clock_getres resolution not enough (%ld.%09ld)\n", + (long)ts.tv_sec, ts.tv_nsec); + else + printf("clock_getres resolution OK\n"); + rv = clock_gettime(clocks[i], &ts); + printf(rv ? "clock_gettime failed\n" : "clock_gettime OK\n"); + errno = 0; + if (clock_settime(clocks[i], &ts) == 0) + printf("clock_settime should have failed\n"); + else if (errno == EPERM && clocks[i] == CLOCK_REALTIME) + printf("clock_settime failed with EPERM (OK)\n"); + else if (errno == EINVAL && clocks[i] == CLOCK_MONOTONIC) + printf("clock_settime failed with EINVAL (OK)\n"); + else + printf("clock_settime failed with wrong error code\n"); + } + clockid_t bogus = 42; + struct timespec ts; + printf("\nTests for clockid_t=%d\n-----------------\n", bogus); + if (clock_gettime(bogus, &ts) == 0 || errno != EINVAL) + printf("clock_gettime should have failed\n"); + else + printf("clock_gettime failed with EINVAL (OK)\n"); + if (clock_getres(bogus, &ts) == 0 || errno != EINVAL) + printf("clock_getres should have failed\n"); + else + printf("clock_getres failed with EINVAL (OK)\n"); + if (clock_settime(bogus, &ts) == 0 || errno != EINVAL) + printf("clock_settime should have failed\n"); + else + printf("clock_settime failed with EINVAL (OK)\n"); + return 0; +} diff --git a/tests/core/test_posixtime.out b/tests/core/test_posixtime.out new file mode 100644 index 0000000000000..84417e293820a --- /dev/null +++ b/tests/core/test_posixtime.out @@ -0,0 +1,17 @@ +Tests for clockid_t=0 +----------------- +clock_getres resolution OK +clock_gettime OK +clock_settime failed with EPERM (OK) + +Tests for clockid_t=1 +----------------- +clock_getres resolution OK +clock_gettime OK +clock_settime failed with EINVAL (OK) + +Tests for clockid_t=42 +----------------- +clock_gettime failed with EINVAL (OK) +clock_getres failed with EINVAL (OK) +clock_settime failed with EINVAL (OK) diff --git a/tests/test_core.py b/tests/test_core.py index c68b040e90727..7d37a09ab3ff1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4629,6 +4629,12 @@ def test_unistd_misc(self): Building.COMPILER_TEST_OPTS += ['-D' + fs] self.do_run(src, expected, js_engines=[NODE_JS]) + def test_posixtime(self): + test_path = path_from_root('tests', 'core', 'test_posixtime') + src, output = (test_path + s for s in ('.in', '.out')) + + self.do_run_from_file(src, output) + def test_uname(self): test_path = path_from_root('tests', 'core', 'test_uname') src, output = (test_path + s for s in ('.in', '.out')) diff --git a/tests/time/src.c b/tests/time/src.c index 61faedfe39312..cbc1a20728255 100644 --- a/tests/time/src.c +++ b/tests/time/src.c @@ -67,7 +67,7 @@ int main() { time_t t4 = 0; time(&t4); timespec ts; - assert(clock_gettime(0, &ts) == 0); + assert(clock_gettime(CLOCK_REALTIME, &ts) == 0); assert(abs(ts.tv_sec - t4) <= 2); printf("time: %d\n", t4 > 1309635200ll && t4 < 1893362400ll);