Skip to content

Commit

Permalink
Merge pull request #1659 from svaarala/add-monotonic-clock-config
Browse files Browse the repository at this point in the history
Add monotonic clock config option, use it for debugger transport peeks
  • Loading branch information
svaarala authored Aug 3, 2017
2 parents e1f47c0 + 5d8f5c0 commit 1b073c8
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 8 deletions.
10 changes: 10 additions & 0 deletions RELEASES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2983,6 +2983,16 @@ Planned
* Make error message summary strings longer (32 -> 96 character) to better
capture error messages for e.g. uncaught errors (GH-1653)

* Add DUK_USE_GET_MONOTONIC_TIME() to allow an application to provide a
monotonic time source (similar to clock_gettime() CLOCK_MONOTONIC) which
Duktape will then use for performance.now() and internal rate limiting
mechanisms; if absent (default), monotonic time defaults to
DUK_USE_DATE_GET_NOW() (GH-1659)

* Use monotonic time (if available) for debugger transport peeking, so that
the peek callback is called with the same realtime rate even if the
Ecmascript time source jumps or doesn't advance in realtime (GH-1659)

* Fix incorrect handling of register bound unary operation target for
unary minus, unary plus, and bitwise NOT (GH-1623, GH-1624)

Expand Down
4 changes: 4 additions & 0 deletions config/config-options/DUK_USE_DATE_GET_NOW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ tags:
- portability
description: >
Mandatory macro for getting the current time, see datetime.rst.
If the time provided experiences time jumps or doesn't advance in realtime
(which is useful in some time virtualization scenarios), consider defining
DUK_USE_GET_MONOTONIC_TIME.
21 changes: 21 additions & 0 deletions config/config-options/DUK_USE_GET_MONOTONIC_TIME.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
define: DUK_USE_GET_MONOTONIC_TIME
introduced: 2.2.0
default: false
tags:
- date
- portability
description: >
Optional macro for getting monotonic time starting from an arbitrary
starting point (device startup, program startup, script startup, etc).
The time returned must increase monotonically, and must not jump
discontinuously even if system date/time is reset. The semantics are
similar to POSIX clock_gettime() CLOCK_MONOTONIC.
Monotonic time is used by Duktape for its internal needs, such as rate
limiting debugger transport peek callbacks. If this option is not provided,
Duktape falls back to using DUK_USE_DATE_GET_NOW() which is usually fine.
If DUK_USE_DATE_GET_NOW() experiences time jumps or doesn't run in realtime
(which may be useful for some time virtualization cases) it's recommended
to provide this config option so that internals which need a reliable
realtime rate have a reliable time basis.
3 changes: 3 additions & 0 deletions src-input/duk_api_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,7 @@ DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t n
(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
(thr)->valstack_bottom - 1)

DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);

#endif /* DUK_API_INTERNAL_H_INCLUDED */
22 changes: 21 additions & 1 deletion src-input/duk_api_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,31 @@

#include "duk_internal.h"

DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
}

DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
#if defined(DUK_USE_GET_MONOTONIC_TIME)
return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
#else
return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
#endif
}

DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);

return ((duk_double_t) DUK_USE_DATE_GET_NOW(thr));
return duk_time_get_ecmascript_time(thr);
}

#if 0 /* XXX: worth exposing? */
DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);

return duk_time_get_monotonic_time(thr);
}
#endif

DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
Expand Down
4 changes: 2 additions & 2 deletions src-input/duk_bi_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
*/

if (nargs == 0 || !is_cons) {
d = duk__timeclip(DUK_USE_DATE_GET_NOW(thr));
d = duk__timeclip(duk_time_get_ecmascript_time(thr));
duk_push_number(thr, d);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
if (!is_cons) {
Expand Down Expand Up @@ -1496,7 +1496,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
duk_double_t d;

d = DUK_USE_DATE_GET_NOW(thr);
d = duk_time_get_ecmascript_time(thr);
DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */
duk_push_number(thr, d);
return 1;
Expand Down
4 changes: 2 additions & 2 deletions src-input/duk_heap_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1105,10 +1105,10 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,

#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
res->rnd_state = (duk_uint32_t) DUK_USE_DATE_GET_NOW(res->heap_thread);
res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
duk_util_tinyrandom_prepare_seed(res->heap_thread);
#else
res->rnd_state[0] = (duk_uint64_t) DUK_USE_DATE_GET_NOW(res->heap_thread);
res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
DUK_ASSERT(res->rnd_state[1] == 0); /* Not filled here, filled in by seed preparation. */
#if 0 /* Manual test values matching misc/xoroshiro128plus_test.c. */
res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
Expand Down
8 changes: 5 additions & 3 deletions src-input/duk_js_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1800,12 +1800,14 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
duk_double_t now, diff_last;

thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
now = DUK_USE_DATE_GET_NOW(thr);
now = duk_time_get_monotonic_time(thr);

diff_last = now - thr->heap->dbg_last_time;
if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
/* Negative value checked so that a "time jump" works
* reasonably.
/* Monotonic time should not experience time jumps,
* but the provider may be missing and we're actually
* using Ecmascript time. So, tolerate negative values
* so that a time jump works reasonably.
*
* Same interval is now used for status sending and
* peeking.
Expand Down

0 comments on commit 1b073c8

Please sign in to comment.