new macro `lua_threadyield' + lock stuff in `luaconf.h' + details

This commit is contained in:
Roberto Ierusalimschy 2004-06-02 16:07:55 -03:00
parent b8691f13a8
commit e8d4fe7236
6 changed files with 84 additions and 90 deletions

View File

@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $
** $Id: ldebug.c,v 2.5 2004/05/31 18:51:50 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@ -35,7 +35,7 @@ static const char *getfuncname (CallInfo *ci, const char **name);
static int currentpc (CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
return pcRel(ci->savedpc, ci_func(ci)->l.p);
}
@ -86,7 +86,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--;
if (f_isLua(ci)) /* Lua function? */
level -= ci->u.l.tailcalls; /* skip lost tail calls */
level -= ci->tailcalls; /* skip lost tail calls */
}
if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */
else if (level < 0) { /* level is of a lost tail call */
@ -255,8 +255,9 @@ static int precheck (const Proto *pt) {
}
static int checkopenop (const Proto *pt, int pc) {
Instruction i = pt->code[pc+1];
#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
int luaG_checkopenop (Instruction i) {
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL:
@ -487,7 +488,7 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
static const char *getfuncname (CallInfo *ci, const char **name) {
Instruction i;
if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
return NULL; /* calling function is not Lua (or is unknown) */
ci--; /* calling function */
i = ci_func(ci)->l.p->code[currentpc(ci)];

View File

@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 1.33 2003/07/16 20:49:02 roberto Exp roberto $
** $Id: ldebug.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@ -25,6 +25,6 @@ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2);
void luaG_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L);
int luaG_checkcode (const Proto *pt);
int luaG_checkopenop (Instruction i);
#endif

12
ldo.c
View File

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 2.5 2004/05/14 19:25:09 roberto Exp roberto $
** $Id: ldo.c,v 2.6 2004/05/31 18:51:50 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -256,8 +256,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
ci->func = func;
L->base = ci->base = base;
ci->top = L->base + p->maxstacksize;
ci->u.l.savedpc = p->code; /* starting point */
ci->u.l.tailcalls = 0;
ci->savedpc = p->code; /* starting point */
ci->tailcalls = 0;
ci->nresults = nresults;
for (st = L->top; st < ci->top; st++)
setnilvalue(st);
@ -293,7 +293,7 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
if (f_isLua(L->ci)) { /* Lua function? */
while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
while (L->ci->tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
@ -352,8 +352,8 @@ static void resume (lua_State *L, void *ud) {
if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
int nresults = ci->nresults;
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
luaD_poscall(L, nresults, L->top - nargs); /* complete it */
if (nresults >= 0) L->top = L->ci->top;
} /* else yielded inside a hook: just continue its execution */

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.3 2004/05/14 19:25:09 roberto Exp roberto $
** $Id: lstate.h,v 2.4 2004/05/31 18:51:50 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -14,30 +14,6 @@
#include "lzio.h"
/*
** macros for thread synchronization inside Lua core machine:
** all accesses to the global state and to global objects are synchronized.
** Because threads can read the stack of other threads
** (when running garbage collection),
** a thread must also synchronize any write-access to its own stack.
** Unsynchronized accesses are allowed only when reading its own stack,
** or when reading immutable fields from global objects
** (such as string values and udata values).
*/
#ifndef lua_lock
#define lua_lock(L) ((void) 0)
#endif
#ifndef lua_unlock
#define lua_unlock(L) ((void) 0)
#endif
#ifndef lua_userstateopen
#define lua_userstateopen(l)
#endif
struct lua_longjmp; /* defined in ldo.c */
@ -74,15 +50,8 @@ typedef struct CallInfo {
StkId func; /* function index in the stack */
StkId top; /* top for this function */
int nresults; /* expected number of results from this function */
union {
struct { /* for Lua functions */
const Instruction *savedpc;
int tailcalls; /* number of tail calls lost under this entry */
} l;
struct { /* for C functions */
int dummy; /* just to avoid an empty struct */
} c;
} u;
const Instruction *savedpc;
int tailcalls; /* number of tail calls lost under this entry */
} CallInfo;

View File

@ -1,5 +1,5 @@
/*
** $Id: luaconf.h,v 1.4 2004/05/28 18:32:51 roberto Exp roberto $
** $Id: luaconf.h,v 1.5 2004/06/02 13:24:43 roberto Exp roberto $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@ -215,6 +215,32 @@
#endif
/*
** macros for thread synchronization inside Lua core machine:
** all accesses to the global state and to global objects are synchronized.
** Because threads can read the stack of other threads
** (when running garbage collection),
** a thread must also synchronize any write-access to its own stack.
** Unsynchronized accesses are allowed only when reading its own stack,
** or when reading immutable fields from global objects
** (such as string values and udata values).
*/
#define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0)
/*
** this macro allows a thread switch in appropriate places in the Lua
** core
*/
#define lua_threadyield(L) {lua_unlock(L); lua_lock(L);}
/* allows user-specific initialization on new threads */
#define lua_userstateopen(l) /* empty */
#endif
/* }====================================================== */

80
lvm.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.6 2004/05/14 19:25:09 roberto Exp $
** $Id: lvm.c,v 2.7 2004/05/31 18:51:50 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -58,8 +58,8 @@ int luaV_tostring (lua_State *L, StkId obj) {
static void traceexec (lua_State *L, const Instruction *pc) {
lu_byte mask = L->hookmask;
CallInfo *ci = L->ci;
const Instruction *oldpc = ci->u.l.savedpc;
ci->u.l.savedpc = pc;
const Instruction *oldpc = ci->savedpc;
ci->savedpc = pc;
if (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) {
resethookcount(L);
@ -122,18 +122,18 @@ StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val,
/* else will try the tag method */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) {
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaG_typeerror(L, t, "index");
}
if (ttisfunction(tm)) {
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
prepTMcall(L, tm, t, key);
callTMres(L, val);
return L->base;
}
t = tm; /* else repeat with `tm' */
}
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaG_runerror(L, "loop in gettable");
return NULL; /* to avoid warnings */
}
@ -156,11 +156,11 @@ StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val,
/* else will try the tag method */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) {
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaG_typeerror(L, t, "index");
}
if (ttisfunction(tm)) {
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
prepTMcall(L, tm, t, key);
setobj2s(L, L->top+3, val); /* 3th argument */
callTM(L);
@ -168,7 +168,7 @@ StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val,
}
t = tm; /* else repeat with `tm' */
}
if (pc) L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaG_runerror(L, "loop in settable");
return NULL; /* to avoid warnings */
}
@ -331,7 +331,7 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb,
const TValue *rc, TMS op, const Instruction *pc) {
TValue tempb, tempc;
const TValue *b, *c;
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
(c = luaV_tonumber(rc, &tempc)) != NULL) {
switch (op) {
@ -374,7 +374,7 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb,
#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
#define dojump(pc, i) ((pc) += (i))
#define dojump(L,pc,i) {(pc) += (i); lua_threadyield(L);}
StkId luaV_execute (lua_State *L, int nexeccalls) {
@ -386,7 +386,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
retentry: /* entry point when returning to old functions */
pc = L->ci->u.l.savedpc;
pc = L->ci->savedpc;
cl = &clvalue(L->ci->func)->l;
base = L->base;
k = cl->p->k;
@ -398,7 +398,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L, pc); /***/
if (L->isSuspended) { /* did hook yield? */
L->ci->u.l.savedpc = pc - 1;
L->ci->savedpc = pc - 1;
return NULL;
}
base = L->base;
@ -406,10 +406,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
lua_assert(base == L->ci->base && base == L->base);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
lua_assert(L->top == L->ci->top ||
GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
switch (GET_OPCODE(i)) {
case OP_MOVE: {
setobjs2s(L, ra, RB(i));
@ -465,7 +463,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
int b = GETARG_B(i);
b = fb2int(b);
sethvalue(L, ra, luaH_new(L, b, GETARG_C(i)));
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaC_checkGC(L); /***/
base = L->base;
break;
@ -528,7 +526,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else {
setnilvalue(&temp);
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) /***/
luaG_aritherror(L, RB(i), &temp);
base = L->base;
@ -543,7 +541,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
case OP_CONCAT: {
int b = GETARG_B(i);
int c = GETARG_C(i);
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ /***/
luaC_checkGC(L); /***/
base = L->base;
@ -551,27 +549,27 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
break;
}
case OP_JMP: {
dojump(pc, GETARG_sBx(i));
dojump(L, pc, GETARG_sBx(i));
break;
}
case OP_EQ: {
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
break;
}
case OP_LT: {
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
break;
}
case OP_LE: {
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
break;
}
@ -580,7 +578,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
if (l_isfalse(rb) == GETARG_C(i)) pc++;
else {
setobjs2s(L, ra, rb);
dojump(pc, GETARG_sBx(*pc) + 1);
dojump(L, pc, GETARG_sBx(*pc) + 1);
}
break;
}
@ -589,7 +587,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
pcr = luaD_precall(L, ra, nresults);
if (pcr == PCRLUA) {
nexeccalls++;
@ -610,7 +608,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
int pcr;
int b = GETARG_B(i);
if (b != 0) L->top = ra+b; /* else previous instruction set top */
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
pcr = luaD_precall(L, ra, LUA_MULTRET);
if (pcr == PCRLUA) {
@ -625,8 +623,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
setobjs2s(L, func+aux, pfunc+aux);
ci->top = L->top = base+aux; /* correct top */
ci->u.l.savedpc = L->ci->u.l.savedpc;
ci->u.l.tailcalls++; /* one more call lost */
ci->savedpc = L->ci->savedpc;
ci->tailcalls++; /* one more call lost */
L->ci--; /* remove new frame */
goto callentry;
}
@ -645,13 +643,13 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (L->openupval) luaF_close(L, base);
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (--nexeccalls == 0) /* was previous function running `here'? */
return ra; /* no: return */
else { /* yes: continue its execution */
int nresults = (ci+1)->nresults;
lua_assert(isLua(ci));
lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
lua_assert(GET_OPCODE(*(ci->savedpc - 1)) == OP_CALL);
luaD_poscall(L, nresults, ra);
if (nresults >= 0) L->top = L->ci->top;
goto retentry;
@ -662,7 +660,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
lua_Number idx = nvalue(ra) + step; /* increment index */
lua_Number limit = nvalue(ra+1);
if (step > 0 ? idx <= limit : idx >= limit) {
dojump(pc, GETARG_sBx(i)); /* jump back */
dojump(L, pc, GETARG_sBx(i)); /* jump back */
setnvalue(ra, idx); /* update internal index... */
setnvalue(ra+3, idx); /* ...and external index */
}
@ -672,7 +670,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
const TValue *init = ra;
const TValue *plimit = ra+1;
const TValue *pstep = ra+2;
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
if (!tonumber(init, ra))
luaG_runerror(L, "`for' initial value must be a number");
else if (!tonumber(plimit, ra+1))
@ -680,7 +678,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
else if (!tonumber(pstep, ra+2))
luaG_runerror(L, "`for' step must be a number");
setnvalue(ra, nvalue(ra) - nvalue(pstep));
dojump(pc, GETARG_sBx(i));
dojump(L, pc, GETARG_sBx(i));
break;
}
case OP_TFORLOOP: {
@ -689,7 +687,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
setobjs2s(L, cb+1, ra+1);
setobjs2s(L, cb, ra);
L->top = cb+3; /* func. + 2 args (state and index) */
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaD_call(L, cb, GETARG_C(i)); /***/
L->top = L->ci->top;
base = L->base;
@ -698,7 +696,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
pc++; /* skip jump (break loop) */
else {
setobjs2s(L, cb-1, cb); /* save control variable */
dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
dojump(L, pc, GETARG_sBx(*pc) + 1); /* jump back */
}
break;
}
@ -707,7 +705,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
setobjs2s(L, ra+1, ra);
setobj2s(L, ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
}
dojump(pc, GETARG_sBx(i));
dojump(L, pc, GETARG_sBx(i));
break;
}
case OP_SETLIST:
@ -755,7 +753,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
}
setclvalue(L, ra, ncl);
L->ci->u.l.savedpc = pc;
L->ci->savedpc = pc;
luaC_checkGC(L); /***/
base = L->base;
break;