Skip to content

Commit c8bf0da

Browse files
committed
implement clock_gettime(CLOCK_MONOTONIC)
It's bad to pretend to support every clock - we should correctly return -1 with EINVAL for the clocks we don't implement. It's also nice to give implementations a way to detect if they have access to a monotonic clock. For comparison, old Linux machines (RHEL 3 for example) don't have CLOCK_MONOTONIC, new ones do.
1 parent bfd61a0 commit c8bf0da

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

src/library.js

+20-5
Original file line numberDiff line numberDiff line change
@@ -5783,32 +5783,40 @@ LibraryManager.library = {
57835783
}
57845784
return _usleep((seconds * 1e6) + (nanoseconds / 1000));
57855785
},
5786-
clock_gettime__deps: ['emscripten_get_now'],
5786+
clock_gettime__deps: ['emscripten_get_now','emscripten_get_now_monotonic','$ERRNO_CODES', '__setErrNo'],
57875787
clock_gettime: function(clk_id, tp) {
57885788
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
57895789
var now;
57905790
if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
57915791
now = Date.now();
5792-
} else {
5792+
} else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_monotonic()) {
57935793
now = _emscripten_get_now();
5794+
} else {
5795+
___setErrNo(ERRNO_CODES.EINVAL);
5796+
return -1;
57945797
}
57955798
{{{ makeSetValue('tp', C_STRUCTS.timespec.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds
57965799
{{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '((now % 1000)*1000*1000)|0', 'i32') }}}; // nanoseconds
57975800
return 0;
57985801
},
5802+
clock_settime__deps: ['$ERRNO_CODES', '__setErrNo'],
57995803
clock_settime: function(clk_id, tp) {
58005804
// int clock_settime(clockid_t clk_id, const struct timespec *tp);
58015805
// Nothing.
5802-
return 0;
5806+
___setErrNo(ERRNO_CODES.EPERM);
5807+
return -1;
58035808
},
5804-
clock_getres__deps: ['emscripten_get_now_res'],
5809+
clock_getres__deps: ['emscripten_get_now_res','emscripten_get_now_monotonic','$ERRNO_CODES', '__setErrNo'],
58055810
clock_getres: function(clk_id, res) {
58065811
// int clock_getres(clockid_t clk_id, struct timespec *res);
58075812
var nsec;
58085813
if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
58095814
nsec = 1000 * 1000;
5815+
} else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_monotonic()) {
5816+
now = _emscripten_get_now_res();
58105817
} else {
5811-
nsec = _emscripten_get_now_res();
5818+
___setErrNo(ERRNO_CODES.EINVAL);
5819+
return -1;
58125820
}
58135821
{{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}};
58145822
{{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is milliseconds
@@ -8494,6 +8502,13 @@ LibraryManager.library = {
84948502
}
84958503
},
84968504

8505+
emscripten_get_now_monotonic__deps: ['emscripten_get_now'],
8506+
emscripten_get_now_monotonic: function() {
8507+
// return whether emscripten_get_now is guaranteed monotonic; the Date.now
8508+
// implementation is not :(
8509+
return (_emscripten_get_now() == Date.now)|0;
8510+
},
8511+
84978512
// Returns [parentFuncArguments, functionName, paramListName]
84988513
_emscripten_traverse_stack: function(args) {
84998514
if (!args || !args.callee || !args.callee.name) {

src/struct_info.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@
172172
"file": "libc/time.h",
173173
"defines": [
174174
["li", "CLOCKS_PER_SEC"],
175-
"CLOCK_REALTIME"
175+
"CLOCK_REALTIME",
176+
"CLOCK_MONOTONIC"
176177
],
177178
"structs": {
178179
"timezone": [

0 commit comments

Comments
 (0)