Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_bi_thread.c File Reference
#include "duk_internal.h"

Go to the source code of this file.

Functions

DUK_INTERNAL duk_ret_t duk_bi_thread_constructor (duk_context *ctx)
 
DUK_INTERNAL duk_ret_t duk_bi_thread_resume (duk_context *ctx)
 
DUK_INTERNAL duk_ret_t duk_bi_thread_yield (duk_context *ctx)
 
DUK_INTERNAL duk_ret_t duk_bi_thread_current (duk_context *ctx)
 

Function Documentation

◆ duk_bi_thread_constructor()

DUK_INTERNAL duk_ret_t duk_bi_thread_constructor ( duk_context * ctx)

Definition at line 11 of file duktape-1.5.2/src-separate/duk_bi_thread.c.

11 {
12 duk_hthread *new_thr;
13 duk_hobject *func;
14
15 /* XXX: need a duk_require_func_or_lfunc_coerce() */
16 if (!duk_is_callable(ctx, 0)) {
17 return DUK_RET_TYPE_ERROR;
18 }
20 DUK_ASSERT(func != NULL);
21
22 duk_push_thread(ctx);
23 new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
24 DUK_ASSERT(new_thr != NULL);
26
27 /* push initial function call to new thread stack; this is
28 * picked up by resume().
29 */
30 duk_push_hobject((duk_context *) new_thr, func);
31
32 return 1; /* return thread */
33}
#define DUK_HTHREAD_STATE_INACTIVE
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h)
#define duk_push_thread(ctx)
#define duk_is_callable(ctx, index)
#define NULL
Definition gmacros.h:924

References DUK_ASSERT, duk_get_hobject(), DUK_HTHREAD_STATE_INACTIVE, duk_is_callable, duk_push_hobject(), duk_push_thread, duk_require_hobject_or_lfunc_coerce(), DUK_RET_TYPE_ERROR, NULL, and duk_hthread::state.

◆ duk_bi_thread_current()

DUK_INTERNAL duk_ret_t duk_bi_thread_current ( duk_context * ctx)

Definition at line 302 of file duktape-1.5.2/src-separate/duk_bi_thread.c.

302 {
304 return 1;
305}
DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx)

References duk_push_current_thread().

◆ duk_bi_thread_resume()

DUK_INTERNAL duk_ret_t duk_bi_thread_resume ( duk_context * ctx)

Definition at line 50 of file duktape-1.5.2/src-separate/duk_bi_thread.c.

50 {
51 duk_hthread *thr = (duk_hthread *) ctx;
52 duk_hthread *thr_resume;
53 duk_tval *tv;
54 duk_hobject *func;
55 duk_hobject *caller_func;
56 duk_small_int_t is_error;
57
58 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
59 (duk_tval *) duk_get_tval(ctx, 0),
60 (duk_tval *) duk_get_tval(ctx, 1),
61 (duk_tval *) duk_get_tval(ctx, 2)));
62
64 DUK_ASSERT(thr->heap->curr_thread == thr);
65
66 thr_resume = duk_require_hthread(ctx, 0);
67 is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
68 duk_set_top(ctx, 2);
69
70 /* [ thread value ] */
71
72 /*
73 * Thread state and calling context checks
74 */
75
76 if (thr->callstack_top < 2) {
77 DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
78 goto state_error;
79 }
80 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
82 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
83
84 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
85 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
86 DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
87 goto state_error;
88 }
89
90 /* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
91 * like for yield.
92 */
93
94 if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
95 thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
96 DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
97 goto state_error;
98 }
99
101 thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
102
103 /* Further state-dependent pre-checks */
104
105 if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
106 /* no pre-checks now, assume a previous yield() has left things in
107 * tip-top shape (longjmp handler will assert for these).
108 */
109 } else {
111
112 if ((thr_resume->callstack_top != 0) ||
113 (thr_resume->valstack_top - thr_resume->valstack != 1)) {
114 goto state_invalid_initial;
115 }
116 tv = &thr_resume->valstack_top[-1];
117 DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
118 if (!DUK_TVAL_IS_OBJECT(tv)) {
119 goto state_invalid_initial;
120 }
121 func = DUK_TVAL_GET_OBJECT(tv);
122 DUK_ASSERT(func != NULL);
124 /* Note: cannot be a bound function either right now,
125 * this would be easy to relax though.
126 */
127 goto state_invalid_initial;
128 }
129
130 }
131
132 /*
133 * The error object has been augmented with a traceback and other
134 * info from its creation point -- usually another thread. The
135 * error handler is called here right before throwing, but it also
136 * runs in the resumer's thread. It might be nice to get a traceback
137 * from the resumee but this is not the case now.
138 */
139
140#if defined(DUK_USE_AUGMENT_ERROR_THROW)
141 if (is_error) {
142 DUK_ASSERT_TOP(ctx, 2); /* value (error) is at stack top */
143 duk_err_augment_error_throw(thr); /* in resumer's context */
144 }
145#endif
146
147#ifdef DUK_USE_DEBUG
148 if (is_error) {
149 DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
150 (duk_tval *) duk_get_tval(ctx, 0),
151 (duk_tval *) duk_get_tval(ctx, 1)));
152 } else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
153 DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
154 (duk_tval *) duk_get_tval(ctx, 0),
155 (duk_tval *) duk_get_tval(ctx, 1)));
156 } else {
157 DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
158 (duk_tval *) duk_get_tval(ctx, 0),
159 (duk_tval *) duk_get_tval(ctx, 1)));
160 }
161#endif
162
164
165 /* lj value2: thread */
167 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
168
169 /* lj value1: value */
170 DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
171 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
173
174 thr->heap->lj.iserror = is_error;
175
176 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
177 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
178 return 0; /* never here */
179
180 state_invalid_initial:
181 DUK_ERROR_TYPE(thr, "invalid initial thread state/stack");
182 return 0; /* never here */
183
184 state_error:
185 DUK_ERROR_TYPE(thr, "invalid state");
186 return 0; /* never here */
187}
DUK_INTERNAL_DECL duk_hthread * duk_require_hthread(duk_context *ctx, duk_idx_t index)
#define DUK_ERROR_TYPE(thr, msg)
DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr)
#define DUK_TVAL_GET_OBJECT(tv)
#define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)
#define DUK_TVAL_IS_OBJECT(tv)
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_SET_TVAL_UPDREF
#define DUK_HOBJECT_IS_NATIVEFUNCTION(h)
DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index)
#define DUK_HTHREAD_STATE_RUNNING
#define DUK_TVAL_CHKFAST_INPLACE(v)
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr)
#define DUK_ASSERT_TOP(ctx, n)
#define DUK_ACT_GET_FUNC(act)
#define DUK_HTHREAD_STATE_YIELDED
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_context *ctx, duk_idx_t index)

References duk_hthread::callstack, duk_hthread::callstack_top, duk_heap::curr_thread, DUK_ACT_GET_FUNC, DUK_ASSERT, DUK_ASSERT_TOP, DUK_DD, DUK_DDD, DUK_DDDPRINT, DUK_DDPRINT, duk_err_augment_error_throw(), duk_err_longjmp(), DUK_ERROR_TYPE, duk_get_tval(), DUK_HOBJECT_IS_COMPILEDFUNCTION, DUK_HOBJECT_IS_NATIVEFUNCTION, DUK_HTHREAD_STATE_INACTIVE, DUK_HTHREAD_STATE_RUNNING, DUK_HTHREAD_STATE_YIELDED, DUK_LJ_TYPE_RESUME, duk_require_hthread(), duk_set_top(), duk_to_boolean(), DUK_TVAL_CHKFAST_INPLACE, DUK_TVAL_GET_OBJECT, DUK_TVAL_IS_OBJECT, DUK_TVAL_SET_TVAL_UPDREF, duk_hthread::heap, duk_ljstate::iserror, duk_ljstate::jmpbuf_ptr, duk_heap::lj, NULL, duk_hthread::state, duk_ljstate::type, duk_hthread::valstack, duk_hthread::valstack_bottom, duk_hthread::valstack_top, duk_ljstate::value1, and duk_ljstate::value2.

◆ duk_bi_thread_yield()

DUK_INTERNAL duk_ret_t duk_bi_thread_yield ( duk_context * ctx)

Definition at line 204 of file duktape-1.5.2/src-separate/duk_bi_thread.c.

204 {
205 duk_hthread *thr = (duk_hthread *) ctx;
206 duk_hobject *caller_func;
207 duk_small_int_t is_error;
208
209 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
210 (duk_tval *) duk_get_tval(ctx, 0),
211 (duk_tval *) duk_get_tval(ctx, 1)));
212
214 DUK_ASSERT(thr->heap->curr_thread == thr);
215
216 is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
217 duk_set_top(ctx, 1);
218
219 /* [ value ] */
220
221 /*
222 * Thread state and calling context checks
223 */
224
225 if (!thr->resumer) {
226 DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
227 goto state_error;
228 }
230
231 if (thr->callstack_top < 2) {
232 DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
233 goto state_error;
234 }
235 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
237 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
238
239 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
240 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
241 DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
242 goto state_error;
243 }
244
245 DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
246 if (thr->callstack_preventcount != 1) {
247 /* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
248 DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
249 (long) thr->callstack_preventcount));
250 goto state_error;
251 }
252
253 /*
254 * The error object has been augmented with a traceback and other
255 * info from its creation point -- usually the current thread.
256 * The error handler, however, is called right before throwing
257 * and runs in the yielder's thread.
258 */
259
260#if defined(DUK_USE_AUGMENT_ERROR_THROW)
261 if (is_error) {
262 DUK_ASSERT_TOP(ctx, 1); /* value (error) is at stack top */
263 duk_err_augment_error_throw(thr); /* in yielder's context */
264 }
265#endif
266
267#ifdef DUK_USE_DEBUG
268 if (is_error) {
269 DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
270 (duk_tval *) duk_get_tval(ctx, 0)));
271 } else {
272 DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
273 (duk_tval *) duk_get_tval(ctx, 0)));
274 }
275#endif
276
277 /*
278 * Process yield
279 *
280 * After longjmp(), processing continues in bytecode executor longjmp
281 * handler, which will e.g. update thr->resumer to NULL.
282 */
283
285
286 /* lj value1: value */
288 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
290
291 thr->heap->lj.iserror = is_error;
292
293 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
294 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
295 return 0; /* never here */
296
297 state_error:
298 DUK_ERROR_TYPE(thr, "invalid state");
299 return 0; /* never here */
300}
#define DUK_HTHREAD_STATE_RESUMED

References duk_hthread::callstack, duk_hthread::callstack_preventcount, duk_hthread::callstack_top, duk_heap::curr_thread, DUK_ACT_GET_FUNC, DUK_ASSERT, DUK_ASSERT_TOP, DUK_DD, DUK_DDD, DUK_DDDPRINT, DUK_DDPRINT, duk_err_augment_error_throw(), duk_err_longjmp(), DUK_ERROR_TYPE, duk_get_tval(), DUK_HOBJECT_IS_COMPILEDFUNCTION, DUK_HOBJECT_IS_NATIVEFUNCTION, DUK_HTHREAD_STATE_RESUMED, DUK_HTHREAD_STATE_RUNNING, DUK_LJ_TYPE_YIELD, duk_set_top(), duk_to_boolean(), DUK_TVAL_CHKFAST_INPLACE, DUK_TVAL_SET_TVAL_UPDREF, duk_hthread::heap, duk_ljstate::iserror, duk_ljstate::jmpbuf_ptr, duk_heap::lj, NULL, duk_hthread::resumer, duk_hthread::state, duk_ljstate::type, duk_hthread::valstack_bottom, duk_hthread::valstack_top, and duk_ljstate::value1.