From 89dc19deb125e4040e7884fca083fea4596b79e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 3 Aug 2016 17:29:28 +0200 Subject: [PATCH 1/2] Add suspend and resume API This allows a native thread to suspend its Duktape thread while for example calling out to an external blocking API, allowing other native threads to cooperatively run code on the same heap in the meantime. It is left up to the application to synchronize its native threads so only a single native thread executes code at a time, each taking care to use distinct Duktape threads while doing so. Related to #834. --- src/duk_api_heap.c | 58 +++++++++++++++++++++++++++++++++++++++++ src/duk_api_public.h.in | 9 +++++++ 2 files changed, 67 insertions(+) diff --git a/src/duk_api_heap.c b/src/duk_api_heap.c index 6cb1837e..54fcf95b 100644 --- a/src/duk_api_heap.c +++ b/src/duk_api_heap.c @@ -4,6 +4,15 @@ #include "duk_internal.h" +typedef struct duk_internal_thread_state duk_internal_thread_state; + +struct duk_internal_thread_state { + duk_ljstate lj; + duk_bool_t handling_error; + duk_hthread *curr_thread; + duk_int_t call_recursion_depth; +}; + DUK_EXTERNAL duk_context *duk_create_heap(duk_alloc_function alloc_func, duk_realloc_function realloc_func, @@ -69,6 +78,55 @@ DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx) { duk_heap_free(heap); } +DUK_EXTERNAL void duk_suspend(duk_context *ctx, duk_thread_state *state) { + duk_hthread *thr = (duk_hthread *) ctx; + duk_internal_thread_state *snapshot = (duk_internal_thread_state *) state; + duk_heap *heap; + duk_ljstate *lj; + + DUK_ASSERT_CTX_VALID(ctx); + DUK_ASSERT(thr != NULL); + DUK_ASSERT(thr->heap != NULL); + + heap = thr->heap; + lj = &heap->lj; + + duk_push_tval(ctx, &lj->value1); + duk_push_tval(ctx, &lj->value2); + + DUK_MEMMOVE((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate)); + snapshot->handling_error = heap->handling_error; + snapshot->curr_thread = heap->curr_thread; + snapshot->call_recursion_depth = heap->call_recursion_depth; + + lj->jmpbuf_ptr = NULL; + lj->type = DUK_LJ_TYPE_UNKNOWN; + DUK_TVAL_SET_UNDEFINED(&lj->value1); + DUK_TVAL_SET_UNDEFINED(&lj->value2); + heap->handling_error = 0; + heap->curr_thread = NULL; + heap->call_recursion_depth = 0; +} + +DUK_EXTERNAL void duk_resume(duk_context *ctx, const duk_thread_state *state) { + duk_hthread *thr = (duk_hthread *) ctx; + const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) state; + duk_heap *heap; + + DUK_ASSERT_CTX_VALID(ctx); + DUK_ASSERT(thr != NULL); + DUK_ASSERT(thr->heap != NULL); + + heap = thr->heap; + + DUK_MEMMOVE((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate)); + heap->handling_error = snapshot->handling_error; + heap->curr_thread = snapshot->curr_thread; + heap->call_recursion_depth = snapshot->call_recursion_depth; + + duk_pop_2(ctx); +} + /* XXX: better place for this */ DUK_EXTERNAL void duk_set_global_object(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; diff --git a/src/duk_api_public.h.in b/src/duk_api_public.h.in index 21d8bed2..1fc4a988 100644 --- a/src/duk_api_public.h.in +++ b/src/duk_api_public.h.in @@ -32,6 +32,7 @@ extern "C" { * in Duktape web documentation. */ +struct duk_thread_state; struct duk_memory_functions; struct duk_function_list_entry; struct duk_number_list_entry; @@ -40,6 +41,7 @@ struct duk_time_components; /* duk_context is now defined in duk_config.h because it may also be * referenced there by prototypes. */ +typedef struct duk_thread_state duk_thread_state; typedef struct duk_memory_functions duk_memory_functions; typedef struct duk_function_list_entry duk_function_list_entry; typedef struct duk_number_list_entry duk_number_list_entry; @@ -61,6 +63,10 @@ typedef void (*duk_debug_write_flush_function) (void *udata); typedef duk_idx_t (*duk_debug_request_function) (duk_context *ctx, void *udata, duk_idx_t nvalues); typedef void (*duk_debug_detached_function) (duk_context *ctx, void *udata); +struct duk_thread_state { + char data[128]; +}; + struct duk_memory_functions { duk_alloc_function alloc_func; duk_realloc_function realloc_func; @@ -256,6 +262,9 @@ duk_context *duk_create_heap(duk_alloc_function alloc_func, duk_fatal_function fatal_handler); DUK_EXTERNAL_DECL void duk_destroy_heap(duk_context *ctx); +DUK_EXTERNAL_DECL void duk_suspend(duk_context *ctx, duk_thread_state *state); +DUK_EXTERNAL_DECL void duk_resume(duk_context *ctx, const duk_thread_state *state); + #define duk_create_heap_default() \ duk_create_heap(NULL, NULL, NULL, NULL, NULL) From cf796d4d2d460aac2356981e98f3545725eabdfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 3 Aug 2016 17:31:46 +0200 Subject: [PATCH 2/2] Move my name in AUTHORS.rst to Authors --- AUTHORS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index d13d6cd8..9ac602f1 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -34,6 +34,7 @@ and agreed to irrevocably license their contributions under the Duktape * Ondřej Jirman (https://github.com/megous) * Saúl Ibarra Corretgé * Jeremy HU +* Ole André Vadla Ravnås (https://github.com/oleavr) Other contributions =================== @@ -71,7 +72,6 @@ bugs, provided ideas, etc; roughly in order of appearance): * Michael Drake (https://github.com/tlsa) * https://github.com/chris-y * Laurent Zubiaur (https://github.com/lzubiaur) -* Ole André Vadla Ravnås (https://github.com/oleavr) If you are accidentally missing from this list, send me an e-mail (``sami.vaarala@iki.fi``) and I'll fix the omission.