1198090Srdivacky/* $NetBSD$ */ 2198090Srdivacky 3198090Srdivacky/* 4198090Srdivacky** Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp 5198090Srdivacky** Global State 6198090Srdivacky** See Copyright Notice in lua.h 7198090Srdivacky*/ 8198090Srdivacky 9198090Srdivacky 10198090Srdivacky#include <stddef.h> 11198090Srdivacky 12198090Srdivacky#define lstate_c 13234353Sdim#define LUA_CORE 14239462Sdim 15198090Srdivacky#include "lua.h" 16198090Srdivacky 17234353Sdim#include "ldebug.h" 18234353Sdim#include "ldo.h" 19199989Srdivacky#include "lfunc.h" 20198090Srdivacky#include "lgc.h" 21198090Srdivacky#include "llex.h" 22263508Sdim#include "lmem.h" 23199481Srdivacky#include "lstate.h" 24204642Srdivacky#include "lstring.h" 25234353Sdim#include "ltable.h" 26234353Sdim#include "ltm.h" 27198090Srdivacky 28234353Sdim 29234353Sdim#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) 30234353Sdim#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) 31234353Sdim#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) 32234353Sdim 33234353Sdim 34198090Srdivacky/* 35198090Srdivacky** Main thread combines a thread state and the global state 36198090Srdivacky*/ 37198090Srdivackytypedef struct LG { 38198090Srdivacky lua_State l; 39198090Srdivacky global_State g; 40198090Srdivacky} LG; 41198090Srdivacky 42198090Srdivacky 43198090Srdivacky 44202375Srdivackystatic void stack_init (lua_State *L1, lua_State *L) { 45198090Srdivacky /* initialize CallInfo array */ 46198090Srdivacky L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); 47198396Srdivacky L1->ci = L1->base_ci; 48198090Srdivacky L1->size_ci = BASIC_CI_SIZE; 49198090Srdivacky L1->end_ci = L1->base_ci + L1->size_ci - 1; 50198090Srdivacky /* initialize stack array */ 51198090Srdivacky L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); 52198090Srdivacky L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; 53198090Srdivacky L1->top = L1->stack; 54198090Srdivacky L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; 55199989Srdivacky /* initialize first ci */ 56199989Srdivacky L1->ci->func = L1->top; 57199989Srdivacky setnilvalue(L1->top++); /* `function' entry for this `ci' */ 58207618Srdivacky L1->base = L1->ci->base = L1->top; 59207618Srdivacky L1->ci->top = L1->top + LUA_MINSTACK; 60249423Sdim} 61223017Sdim 62223017Sdim 63223017Sdimstatic void freestack (lua_State *L, lua_State *L1) { 64223017Sdim luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); 65223017Sdim luaM_freearray(L, L1->stack, L1->stacksize, TValue); 66223017Sdim} 67249423Sdim 68198090Srdivacky 69198090Srdivacky/* 70198090Srdivacky** open parts that may cause memory-allocation errors 71198090Srdivacky*/ 72198090Srdivackystatic void f_luaopen (lua_State *L, void *ud) { 73198090Srdivacky global_State *g = G(L); 74198090Srdivacky UNUSED(ud); 75198090Srdivacky stack_init(L, L); /* init stack */ 76198396Srdivacky sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ 77223017Sdim sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ 78223017Sdim luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ 79223017Sdim luaT_init(L); 80223017Sdim luaX_init(L); 81198396Srdivacky luaS_fix(luaS_newliteral(L, MEMERRMSG)); 82198090Srdivacky g->GCthreshold = 4*g->totalbytes; 83198396Srdivacky} 84223017Sdim 85223017Sdim 86223017Sdimstatic void preinit_state (lua_State *L, global_State *g) { 87223017Sdim G(L) = g; 88198090Srdivacky L->stack = NULL; 89198090Srdivacky L->stacksize = 0; 90198396Srdivacky L->errorJmp = NULL; 91199481Srdivacky L->hook = NULL; 92198090Srdivacky L->hookmask = 0; 93198090Srdivacky L->basehookcount = 0; 94198090Srdivacky L->allowhook = 1; 95198090Srdivacky resethookcount(L); 96198090Srdivacky L->openupval = NULL; 97198090Srdivacky L->size_ci = 0; 98198090Srdivacky L->nCcalls = L->baseCcalls = 0; 99198090Srdivacky L->status = 0; 100198090Srdivacky L->base_ci = L->ci = NULL; 101198090Srdivacky L->savedpc = NULL; 102198090Srdivacky L->errfunc = 0; 103198090Srdivacky setnilvalue(gt(L)); 104198090Srdivacky} 105198090Srdivacky 106198090Srdivacky 107198090Srdivackystatic void close_state (lua_State *L) { 108198090Srdivacky global_State *g = G(L); 109198090Srdivacky luaF_close(L, L->stack); /* close all upvalues for this thread */ 110198090Srdivacky luaC_freeall(L); /* collect all objects */ 111198090Srdivacky lua_assert(g->rootgc == obj2gco(L)); 112198090Srdivacky lua_assert(g->strt.nuse == 0); 113198090Srdivacky luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); 114198090Srdivacky luaZ_freebuffer(L, &g->buff); 115198090Srdivacky freestack(L, L); 116198090Srdivacky lua_assert(g->totalbytes == sizeof(LG)); 117198090Srdivacky (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); 118198090Srdivacky} 119198090Srdivacky 120198396Srdivacky 121198090Srdivackylua_State *luaE_newthread (lua_State *L) { 122198090Srdivacky lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); 123198090Srdivacky luaC_link(L, obj2gco(L1), LUA_TTHREAD); 124198090Srdivacky preinit_state(L1, G(L)); 125198090Srdivacky stack_init(L1, L); /* init stack */ 126198090Srdivacky setobj2n(L, gt(L1), gt(L)); /* share table of globals */ 127198090Srdivacky L1->hookmask = L->hookmask; 128198090Srdivacky L1->basehookcount = L->basehookcount; 129199481Srdivacky L1->hook = L->hook; 130198396Srdivacky resethookcount(L1); 131223017Sdim lua_assert(iswhite(obj2gco(L1))); 132198090Srdivacky return L1; 133198090Srdivacky} 134199481Srdivacky 135199481Srdivacky 136199481Srdivackyvoid luaE_freethread (lua_State *L, lua_State *L1) { 137199481Srdivacky luaF_close(L1, L1->stack); /* close all upvalues for this thread */ 138199481Srdivacky lua_assert(L1->openupval == NULL); 139198090Srdivacky luai_userstatefree(L1); 140243830Sdim freestack(L, L1); 141199481Srdivacky luaM_freemem(L, fromstate(L1), state_size(lua_State)); 142198090Srdivacky} 143223017Sdim 144198090Srdivacky 145198090SrdivackyLUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { 146198090Srdivacky int i; 147198090Srdivacky lua_State *L; 148198090Srdivacky global_State *g; 149198090Srdivacky void *l = (*f)(ud, NULL, 0, state_size(LG)); 150198090Srdivacky if (l == NULL) return NULL; 151198090Srdivacky L = tostate(l); 152199481Srdivacky g = &((LG *)L)->g; 153199481Srdivacky L->next = NULL; 154199481Srdivacky L->tt = LUA_TTHREAD; 155208599Srdivacky g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); 156208599Srdivacky L->marked = luaC_white(g); 157208599Srdivacky set2bits(L->marked, FIXEDBIT, SFIXEDBIT); 158208599Srdivacky preinit_state(L, g); 159218893Sdim g->frealloc = f; 160201360Srdivacky g->ud = ud; 161201360Srdivacky g->mainthread = L; 162201360Srdivacky g->uvhead.u.l.prev = &g->uvhead; 163201360Srdivacky g->uvhead.u.l.next = &g->uvhead; 164201360Srdivacky g->GCthreshold = 0; /* mark it as unfinished state */ 165201360Srdivacky g->strt.size = 0; 166201360Srdivacky g->strt.nuse = 0; 167201360Srdivacky g->strt.hash = NULL; 168201360Srdivacky setnilvalue(registry(L)); 169218893Sdim luaZ_initbuffer(L, &g->buff); 170218893Sdim g->panic = NULL; 171218893Sdim g->gcstate = GCSpause; 172218893Sdim g->rootgc = obj2gco(L); 173201360Srdivacky g->sweepstrgc = 0; 174201360Srdivacky g->sweepgc = &g->rootgc; 175201360Srdivacky g->gray = NULL; 176201360Srdivacky g->grayagain = NULL; 177218893Sdim g->weak = NULL; 178263508Sdim g->tmudata = NULL; 179201360Srdivacky g->totalbytes = sizeof(LG); 180198090Srdivacky g->gcpause = LUAI_GCPAUSE; 181212904Sdim g->gcstepmul = LUAI_GCMUL; 182212904Sdim g->gcdept = 0; 183212904Sdim for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; 184212904Sdim if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { 185198090Srdivacky /* memory allocation error: free partial state */ 186198090Srdivacky close_state(L); 187198090Srdivacky L = NULL; 188198090Srdivacky } 189198090Srdivacky else 190198396Srdivacky luai_userstateopen(L); 191198090Srdivacky return L; 192198396Srdivacky} 193198090Srdivacky 194198090Srdivacky 195198090Srdivackystatic void callallgcTM (lua_State *L, void *ud) { 196198090Srdivacky UNUSED(ud); 197198090Srdivacky luaC_callGCTM(L); /* call GC metamethods for all udata */ 198198090Srdivacky} 199198090Srdivacky 200198090Srdivacky 201198090SrdivackyLUA_API void lua_close (lua_State *L) { 202198090Srdivacky L = G(L)->mainthread; /* only the main thread can be closed */ 203198090Srdivacky lua_lock(L); 204198090Srdivacky luaF_close(L, L->stack); /* close all upvalues for this thread */ 205198090Srdivacky luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ 206198090Srdivacky L->errfunc = 0; /* no error function during GC metamethods */ 207243830Sdim do { /* repeat until no more errors */ 208199481Srdivacky L->ci = L->base_ci; 209201360Srdivacky L->base = L->top = L->ci->base; 210223017Sdim L->nCcalls = L->baseCcalls = 0; 211198090Srdivacky } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); 212198090Srdivacky lua_assert(G(L)->tmudata == NULL); 213263508Sdim luai_userstateclose(L); 214263508Sdim close_state(L); 215263508Sdim} 216243830Sdim 217199481Srdivacky