aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-06-11 13:01:55 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-06-11 13:01:55 -0300
commitd94bb6c273d05005504be78f2caab2451aeb2cee (patch)
tree2504f8ced9139875edcb6b924015966b1700284d
parent578433176865773ddd4c935f0a936c2a897826b3 (diff)
downloadlua-d94bb6c273d05005504be78f2caab2451aeb2cee.tar.gz
lua-d94bb6c273d05005504be78f2caab2451aeb2cee.tar.bz2
lua-d94bb6c273d05005504be78f2caab2451aeb2cee.zip
janitor work on 'lua_resume' and related code
-rw-r--r--ldo.c60
1 files changed, 32 insertions, 28 deletions
diff --git a/ldo.c b/ldo.c
index 51450b92..6e695a5c 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.119 2014/06/10 18:51:21 roberto Exp roberto $ 2** $Id: ldo.c,v 2.120 2014/06/10 19:18:50 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -33,6 +33,8 @@
33 33
34 34
35 35
36#define errorstatus(s) ((s) > LUA_YIELD)
37
36 38
37/* 39/*
38** {====================================================== 40** {======================================================
@@ -419,8 +421,10 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
419static void finishCcall (lua_State *L, int status) { 421static void finishCcall (lua_State *L, int status) {
420 CallInfo *ci = L->ci; 422 CallInfo *ci = L->ci;
421 int n; 423 int n;
422 lua_assert(ci->u.c.k != NULL); /* must have a continuation */ 424 /* must have a continuation and must be able to call it */
423 lua_assert(L->nny == 0); 425 lua_assert(ci->u.c.k != NULL && L->nny == 0);
426 /* error status can only happen in a protected call */
427 lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
424 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ 428 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
425 ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ 429 ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
426 L->errfunc = ci->u.c.old_errfunc; 430 L->errfunc = ci->u.c.old_errfunc;
@@ -443,16 +447,15 @@ static void finishCcall (lua_State *L, int status) {
443** previously interrupted coroutine until the stack is empty (or another 447** previously interrupted coroutine until the stack is empty (or another
444** interruption long-jumps out of the loop). If the coroutine is 448** interruption long-jumps out of the loop). If the coroutine is
445** recovering from an error, 'ud' points to the error status, which must 449** recovering from an error, 'ud' points to the error status, which must
446** be passed to the first (only the first) continuation (otherwise the 450** be passed to the first continuation function (otherwise the default
447** default status is LUA_YIELD). 451** status is LUA_YIELD).
448*/ 452*/
449static void unroll (lua_State *L, void *ud) { 453static void unroll (lua_State *L, void *ud) {
450 int status = (ud) ? *(int *)ud : LUA_YIELD; 454 if (ud != NULL) /* error status? */
455 finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */
451 while (L->ci != &L->base_ci) { /* something in the stack */ 456 while (L->ci != &L->base_ci) { /* something in the stack */
452 if (!isLua(L->ci)) { /* C function? */ 457 if (!isLua(L->ci)) /* C function? */
453 finishCcall(L, status); /* complete its execution */ 458 finishCcall(L, LUA_YIELD); /* complete its execution */
454 status = LUA_YIELD; /* back to default status */
455 }
456 else { /* Lua function */ 459 else { /* Lua function */
457 luaV_finishOp(L); /* finish interrupted instruction */ 460 luaV_finishOp(L); /* finish interrupted instruction */
458 luaV_execute(L); /* execute down to higher C 'boundary' */ 461 luaV_execute(L); /* execute down to higher C 'boundary' */
@@ -511,7 +514,11 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
511 514
512 515
513/* 516/*
514** do the work for 'lua_resume' in protected mode 517** Do the work for 'lua_resume' in protected mode. Most of the work
518** depends on the status of the coroutine: initial state, suspended
519** inside a hook, or regulary suspended (optionally with a continuation
520** function), plus erroneous cases: non-suspended coroutine or dead
521** coroutine.
515*/ 522*/
516static void resume (lua_State *L, void *ud) { 523static void resume (lua_State *L, void *ud) {
517 int nCcalls = L->nCcalls; 524 int nCcalls = L->nCcalls;
@@ -529,12 +536,12 @@ static void resume (lua_State *L, void *ud) {
529 else if (L->status != LUA_YIELD) 536 else if (L->status != LUA_YIELD)
530 resume_error(L, "cannot resume dead coroutine", firstArg); 537 resume_error(L, "cannot resume dead coroutine", firstArg);
531 else { /* resuming from previous yield */ 538 else { /* resuming from previous yield */
532 L->status = LUA_OK; 539 L->status = LUA_OK; /* mark that it is running (again) */
533 ci->func = restorestack(L, ci->extra); 540 ci->func = restorestack(L, ci->extra);
534 if (isLua(ci)) /* yielded inside a hook? */ 541 if (isLua(ci)) /* yielded inside a hook? */
535 luaV_execute(L); /* just continue running Lua code */ 542 luaV_execute(L); /* just continue running Lua code */
536 else { /* 'common' yield */ 543 else { /* 'common' yield */
537 if (ci->u.c.k != NULL) { /* does it have a continuation? */ 544 if (ci->u.c.k != NULL) { /* does it have a continuation function? */
538 int n; 545 int n;
539 lua_unlock(L); 546 lua_unlock(L);
540 n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ 547 n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
@@ -544,7 +551,7 @@ static void resume (lua_State *L, void *ud) {
544 } 551 }
545 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ 552 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
546 } 553 }
547 unroll(L, NULL); 554 unroll(L, NULL); /* run continuation */
548 } 555 }
549 lua_assert(nCcalls == L->nCcalls); 556 lua_assert(nCcalls == L->nCcalls);
550} 557}
@@ -552,7 +559,7 @@ static void resume (lua_State *L, void *ud) {
552 559
553LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { 560LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
554 int status; 561 int status;
555 int oldnny = L->nny; /* save 'nny' */ 562 int oldnny = L->nny; /* save "number of non-yieldable" calls */
556 lua_lock(L); 563 lua_lock(L);
557 luai_userstateresume(L, nargs); 564 luai_userstateresume(L, nargs);
558 L->nCcalls = (from) ? from->nCcalls + 1 : 1; 565 L->nCcalls = (from) ? from->nCcalls + 1 : 1;
@@ -561,20 +568,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
561 status = luaD_rawrunprotected(L, resume, L->top - nargs); 568 status = luaD_rawrunprotected(L, resume, L->top - nargs);
562 if (status == -1) /* error calling 'lua_resume'? */ 569 if (status == -1) /* error calling 'lua_resume'? */
563 status = LUA_ERRRUN; 570 status = LUA_ERRRUN;
564 else { /* yield or error running coroutine */ 571 else { /* continue running after recoverable errors */
565 while (status != LUA_OK && status != LUA_YIELD) { /* error? */ 572 while (errorstatus(status) && recover(L, status)) {
566 if (recover(L, status)) { /* recover point? */ 573 /* unroll continuation */
567 /* unroll continuation */ 574 status = luaD_rawrunprotected(L, unroll, &status);
568 status = luaD_rawrunprotected(L, unroll, &status); 575 }
569 } 576 if (errorstatus(status)) { /* unrecoverable error? */
570 else { /* unrecoverable error */ 577 L->status = cast_byte(status); /* mark thread as `dead' */
571 L->status = cast_byte(status); /* mark thread as `dead' */ 578 seterrorobj(L, status, L->top); /* push error message */
572 seterrorobj(L, status, L->top); 579 L->ci->top = L->top;
573 L->ci->top = L->top;
574 break; /* stop running it */
575 }
576 } 580 }
577 lua_assert(status == L->status); 581 else lua_assert(status == L->status); /* normal end or yield */
578 } 582 }
579 L->nny = oldnny; /* restore 'nny' */ 583 L->nny = oldnny; /* restore 'nny' */
580 L->nCcalls--; 584 L->nCcalls--;