diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-05 20:38:37 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-05 20:38:37 -0200 |
commit | addbe8c8b0587fd316f33fb013034e035f9217ed (patch) | |
tree | 63c320066a2a1dec6df662e16cf41e529289ecd9 | |
parent | 6bb5cb1cbd7a0f0f99242c09ecec7d081cb42000 (diff) | |
download | lua-addbe8c8b0587fd316f33fb013034e035f9217ed.tar.gz lua-addbe8c8b0587fd316f33fb013034e035f9217ed.tar.bz2 lua-addbe8c8b0587fd316f33fb013034e035f9217ed.zip |
protected execution of `resume'
-rw-r--r-- | ldo.c | 64 |
1 files changed, 38 insertions, 26 deletions
@@ -36,7 +36,6 @@ struct lua_longjmp { | |||
36 | struct lua_longjmp *previous; | 36 | struct lua_longjmp *previous; |
37 | CallInfo *ci; /* index of call info of active function that set protection */ | 37 | CallInfo *ci; /* index of call info of active function that set protection */ |
38 | StkId top; /* top stack when protection was set */ | 38 | StkId top; /* top stack when protection was set */ |
39 | TObject *stack; /* active stack for this entry */ | ||
40 | int allowhooks; /* `allowhook' state when protection was set */ | 39 | int allowhooks; /* `allowhook' state when protection was set */ |
41 | volatile int status; /* error code */ | 40 | volatile int status; /* error code */ |
42 | }; | 41 | }; |
@@ -47,10 +46,8 @@ static void correctstack (lua_State *L, TObject *oldstack) { | |||
47 | CallInfo *ci; | 46 | CallInfo *ci; |
48 | UpVal *up; | 47 | UpVal *up; |
49 | L->top = (L->top - oldstack) + L->stack; | 48 | L->top = (L->top - oldstack) + L->stack; |
50 | for (lj = L->errorJmp; lj && lj->stack == oldstack; lj = lj->previous) { | 49 | for (lj = L->errorJmp; lj != NULL; lj = lj->previous) |
51 | lj->top = (lj->top - oldstack) + L->stack; | 50 | lj->top = (lj->top - oldstack) + L->stack; |
52 | lj->stack = L->stack; | ||
53 | } | ||
54 | for (up = L->openupval; up != NULL; up = up->next) | 51 | for (up = L->openupval; up != NULL; up = up->next) |
55 | up->v = (up->v - oldstack) + L->stack; | 52 | up->v = (up->v - oldstack) + L->stack; |
56 | for (ci = L->base_ci; ci <= L->ci; ci++) { | 53 | for (ci = L->base_ci; ci <= L->ci; ci++) { |
@@ -147,7 +144,7 @@ static void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) { | |||
147 | 144 | ||
148 | static void correctCI (lua_State *L, CallInfo *oldci) { | 145 | static void correctCI (lua_State *L, CallInfo *oldci) { |
149 | struct lua_longjmp *lj; | 146 | struct lua_longjmp *lj; |
150 | for (lj = L->errorJmp; lj && lj->stack == L->stack; lj = lj->previous) { | 147 | for (lj = L->errorJmp; lj != NULL; lj = lj->previous) { |
151 | lj->ci = (lj->ci - oldci) + L->base_ci; | 148 | lj->ci = (lj->ci - oldci) + L->base_ci; |
152 | } | 149 | } |
153 | } | 150 | } |
@@ -287,35 +284,51 @@ LUA_API void lua_cobegin (lua_State *L, int nargs) { | |||
287 | } | 284 | } |
288 | 285 | ||
289 | 286 | ||
290 | static void resume_results (lua_State *L, lua_State *from, int numresults) { | 287 | static void move_results (lua_State *L, TObject *from, TObject *to) { |
291 | while (numresults) { | 288 | while (from < to) { |
292 | setobj(L->top, from->top - numresults); | 289 | setobj(L->top, from); |
293 | numresults--; | 290 | from++; |
294 | incr_top(L); | 291 | incr_top(L); |
295 | } | 292 | } |
296 | } | 293 | } |
297 | 294 | ||
298 | 295 | ||
299 | LUA_API void lua_resume (lua_State *L, lua_State *co) { | 296 | static void resume (lua_State *L, void *numres) { |
300 | StkId firstResult; | 297 | StkId firstResult; |
301 | lua_lock(L); | 298 | CallInfo *ci = L->ci; |
302 | if (co->ci == co->base_ci) /* no activation record? ?? */ | 299 | if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */ |
303 | luaD_error(L, "thread is dead - cannot be resumed"); | 300 | /* finish interupted execution of `OP_CALL' */ |
304 | lua_assert(co->errorJmp == NULL); | 301 | int nresults; |
305 | co->errorJmp = L->errorJmp; | 302 | lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL); |
306 | firstResult = luaV_execute(co); | 303 | nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1; |
307 | if (firstResult != NULL) { /* `return'? */ | 304 | luaD_poscall(L, nresults, L->top); /* complete it */ |
308 | resume_results(L, co, co->top - firstResult); | 305 | if (nresults >= 0) L->top = L->ci->top; |
309 | luaD_poscall(co, 0, firstResult); /* ends this coroutine */ | ||
310 | } | 306 | } |
311 | else { /* `yield' */ | 307 | firstResult = luaV_execute(L); |
312 | int nresults = GETARG_C(*((co->ci-1)->savedpc - 1)) - 1; | 308 | if (firstResult == NULL) /* yield? */ |
313 | resume_results(L, co, co->ci->yield_results); | 309 | *(int *)numres = L->ci->yield_results; |
314 | luaD_poscall(co, nresults, co->top); /* complete it */ | 310 | else { /* return */ |
315 | if (nresults >= 0) co->top = co->ci->top; | 311 | *(int *)numres = L->top - firstResult; |
312 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | ||
316 | } | 313 | } |
317 | co->errorJmp = NULL; | 314 | } |
315 | |||
316 | |||
317 | LUA_API int lua_resume (lua_State *L, lua_State *co) { | ||
318 | CallInfo *ci; | ||
319 | int numres; | ||
320 | int status; | ||
321 | lua_lock(L); | ||
322 | ci = co->ci; | ||
323 | if (ci == co->base_ci) /* no activation record? ?? */ | ||
324 | luaD_error(L, "thread is dead - cannot be resumed"); | ||
325 | if (co->errorJmp != NULL) /* ?? */ | ||
326 | luaD_error(L, "thread is active - cannot be resumed"); | ||
327 | status = luaD_runprotected(co, resume, &numres); | ||
328 | if (status == 0) | ||
329 | move_results(L, co->top - numres, co->top); | ||
318 | lua_unlock(L); | 330 | lua_unlock(L); |
331 | return status; | ||
319 | } | 332 | } |
320 | 333 | ||
321 | 334 | ||
@@ -486,7 +499,6 @@ int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | |||
486 | struct lua_longjmp lj; | 499 | struct lua_longjmp lj; |
487 | lj.ci = L->ci; | 500 | lj.ci = L->ci; |
488 | lj.top = L->top; | 501 | lj.top = L->top; |
489 | lj.stack = L->stack; | ||
490 | lj.allowhooks = L->allowhooks; | 502 | lj.allowhooks = L->allowhooks; |
491 | lj.status = 0; | 503 | lj.status = 0; |
492 | lj.previous = L->errorJmp; /* chain new error handler */ | 504 | lj.previous = L->errorJmp; /* chain new error handler */ |