diff --git a/list.h b/list.h index 0a1bc5a49..c9be5de7d 100644 --- a/list.h +++ b/list.h @@ -45,6 +45,11 @@ static inline void init_list_head(struct list_head *head) head->next = head; } +static inline int list_empty(const struct list_head *el) +{ + return el->next == el; +} + /* insert 'el' between 'prev' and 'next' */ static inline void __list_add(struct list_head *el, struct list_head *prev, struct list_head *next) @@ -67,6 +72,20 @@ static inline void list_add_tail(struct list_head *el, struct list_head *head) __list_add(el, head->prev, head); } +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + struct list_head *a = list->next; + struct list_head *b = list->prev; + struct list_head *c = head->next; + head->next = a; + a->prev = head; + b->next = c; + c->prev = b; + } +} + static inline void list_del(struct list_head *el) { struct list_head *prev, *next; @@ -78,11 +97,6 @@ static inline void list_del(struct list_head *el) el->next = NULL; /* fail safe */ } -static inline int list_empty(struct list_head *el) -{ - return el->next == el; -} - #define list_for_each(el, head) \ for(el = (head)->next; el != (head); el = el->next) diff --git a/quickjs.c b/quickjs.c index 0e28e7311..db4a8d01f 100644 --- a/quickjs.c +++ b/quickjs.c @@ -308,6 +308,13 @@ struct JSRuntime { void *user_opaque; }; +typedef struct JSRuntimeInternalThreadState { + uintptr_t stack_top; + JSValue current_exception; + struct JSStackFrame *current_stack_frame; + struct list_head job_list; +} JSRuntimeInternalThreadState; + struct JSClass { uint32_t class_id; /* 0 means free entry */ JSAtom class_name; @@ -1769,6 +1776,42 @@ JSRuntime *JS_NewRuntime(void) return JS_NewRuntime2(&def_malloc_funcs, NULL); } +void JS_Enter(JSRuntime *rt) +{ + rt->stack_top = js_get_stack_pointer(); +} + +void JS_Suspend(JSRuntime *rt, JSRuntimeThreadState *state) +{ + JSRuntimeInternalThreadState *s = (JSRuntimeInternalThreadState *)state; + + s->stack_top = rt->stack_top; + s->current_exception = rt->current_exception; + s->current_stack_frame = rt->current_stack_frame; + memcpy(&s->job_list, &rt->job_list, sizeof(rt->job_list)); + + rt->stack_top = 0; + rt->current_exception = JS_NULL; + rt->current_stack_frame = NULL; + init_list_head(&rt->job_list); +} + +void JS_Resume(JSRuntime *rt, const JSRuntimeThreadState *state) +{ + const JSRuntimeInternalThreadState *s = + (const JSRuntimeInternalThreadState *)state; + + rt->stack_top = s->stack_top; + rt->current_exception = s->current_exception; + rt->current_stack_frame = s->current_stack_frame; + list_splice(&s->job_list, &rt->job_list); +} + +void JS_Leave(JSRuntime *rt) +{ + rt->stack_top = 0; +} + void JS_SetMemoryLimit(JSRuntime *rt, size_t limit) { rt->malloc_state.malloc_limit = limit; diff --git a/quickjs.h b/quickjs.h index d4a5cd311..816f848d5 100644 --- a/quickjs.h +++ b/quickjs.h @@ -312,6 +312,10 @@ typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSV typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data); +typedef struct JSRuntimeThreadState { + char data[64]; +} JSRuntimeThreadState; + typedef struct JSMallocState { size_t malloc_count; size_t malloc_size; @@ -329,6 +333,10 @@ typedef struct JSMallocFunctions { typedef struct JSGCObjectHeader JSGCObjectHeader; JSRuntime *JS_NewRuntime(void); +void JS_Enter(JSRuntime *rt); +void JS_Suspend(JSRuntime *rt, JSRuntimeThreadState *state); +void JS_Resume(JSRuntime *rt, const JSRuntimeThreadState *state); +void JS_Leave(JSRuntime *rt); /* info lifetime must exceed that of rt */ void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);