1*dfc11533SChris Williamson /*
2*dfc11533SChris Williamson ** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $
3*dfc11533SChris Williamson ** Global State
4*dfc11533SChris Williamson ** See Copyright Notice in lua.h
5*dfc11533SChris Williamson */
6*dfc11533SChris Williamson
7*dfc11533SChris Williamson
8*dfc11533SChris Williamson #include <sys/zfs_context.h>
9*dfc11533SChris Williamson
10*dfc11533SChris Williamson #define lstate_c
11*dfc11533SChris Williamson #define LUA_CORE
12*dfc11533SChris Williamson
13*dfc11533SChris Williamson #include "lua.h"
14*dfc11533SChris Williamson
15*dfc11533SChris Williamson #include "lapi.h"
16*dfc11533SChris Williamson #include "ldebug.h"
17*dfc11533SChris Williamson #include "ldo.h"
18*dfc11533SChris Williamson #include "lfunc.h"
19*dfc11533SChris Williamson #include "lgc.h"
20*dfc11533SChris Williamson #include "llex.h"
21*dfc11533SChris Williamson #include "lmem.h"
22*dfc11533SChris Williamson #include "lstate.h"
23*dfc11533SChris Williamson #include "lstring.h"
24*dfc11533SChris Williamson #include "ltable.h"
25*dfc11533SChris Williamson #include "ltm.h"
26*dfc11533SChris Williamson
27*dfc11533SChris Williamson
28*dfc11533SChris Williamson #if !defined(LUAI_GCPAUSE)
29*dfc11533SChris Williamson #define LUAI_GCPAUSE 200 /* 200% */
30*dfc11533SChris Williamson #endif
31*dfc11533SChris Williamson
32*dfc11533SChris Williamson #if !defined(LUAI_GCMAJOR)
33*dfc11533SChris Williamson #define LUAI_GCMAJOR 200 /* 200% */
34*dfc11533SChris Williamson #endif
35*dfc11533SChris Williamson
36*dfc11533SChris Williamson #if !defined(LUAI_GCMUL)
37*dfc11533SChris Williamson #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
38*dfc11533SChris Williamson #endif
39*dfc11533SChris Williamson
40*dfc11533SChris Williamson
41*dfc11533SChris Williamson #define MEMERRMSG "not enough memory"
42*dfc11533SChris Williamson
43*dfc11533SChris Williamson
44*dfc11533SChris Williamson /*
45*dfc11533SChris Williamson ** a macro to help the creation of a unique random seed when a state is
46*dfc11533SChris Williamson ** created; the seed is used to randomize hashes.
47*dfc11533SChris Williamson */
48*dfc11533SChris Williamson #if !defined(luai_makeseed)
49*dfc11533SChris Williamson #define luai_makeseed() cast(unsigned int, gethrtime())
50*dfc11533SChris Williamson #endif
51*dfc11533SChris Williamson
52*dfc11533SChris Williamson
53*dfc11533SChris Williamson
54*dfc11533SChris Williamson /*
55*dfc11533SChris Williamson ** thread state + extra space
56*dfc11533SChris Williamson */
57*dfc11533SChris Williamson typedef struct LX {
58*dfc11533SChris Williamson #if defined(LUAI_EXTRASPACE)
59*dfc11533SChris Williamson char buff[LUAI_EXTRASPACE];
60*dfc11533SChris Williamson #endif
61*dfc11533SChris Williamson lua_State l;
62*dfc11533SChris Williamson } LX;
63*dfc11533SChris Williamson
64*dfc11533SChris Williamson
65*dfc11533SChris Williamson /*
66*dfc11533SChris Williamson ** Main thread combines a thread state and the global state
67*dfc11533SChris Williamson */
68*dfc11533SChris Williamson typedef struct LG {
69*dfc11533SChris Williamson LX l;
70*dfc11533SChris Williamson global_State g;
71*dfc11533SChris Williamson } LG;
72*dfc11533SChris Williamson
73*dfc11533SChris Williamson
74*dfc11533SChris Williamson
75*dfc11533SChris Williamson #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
76*dfc11533SChris Williamson
77*dfc11533SChris Williamson
78*dfc11533SChris Williamson /*
79*dfc11533SChris Williamson ** Compute an initial seed as random as possible. In ANSI, rely on
80*dfc11533SChris Williamson ** Address Space Layout Randomization (if present) to increase
81*dfc11533SChris Williamson ** randomness..
82*dfc11533SChris Williamson */
83*dfc11533SChris Williamson #define addbuff(b,p,e) \
84*dfc11533SChris Williamson { size_t t = cast(size_t, e); \
85*dfc11533SChris Williamson memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
86*dfc11533SChris Williamson
makeseed(lua_State * L)87*dfc11533SChris Williamson static unsigned int makeseed (lua_State *L) {
88*dfc11533SChris Williamson char buff[4 * sizeof(size_t)];
89*dfc11533SChris Williamson unsigned int h = luai_makeseed();
90*dfc11533SChris Williamson int p = 0;
91*dfc11533SChris Williamson addbuff(buff, p, L); /* heap variable */
92*dfc11533SChris Williamson addbuff(buff, p, &h); /* local variable */
93*dfc11533SChris Williamson addbuff(buff, p, luaO_nilobject); /* global variable */
94*dfc11533SChris Williamson addbuff(buff, p, &lua_newstate); /* public function */
95*dfc11533SChris Williamson lua_assert(p == sizeof(buff));
96*dfc11533SChris Williamson return luaS_hash(buff, p, h);
97*dfc11533SChris Williamson }
98*dfc11533SChris Williamson
99*dfc11533SChris Williamson
100*dfc11533SChris Williamson /*
101*dfc11533SChris Williamson ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
102*dfc11533SChris Williamson ** invariant
103*dfc11533SChris Williamson */
luaE_setdebt(global_State * g,l_mem debt)104*dfc11533SChris Williamson void luaE_setdebt (global_State *g, l_mem debt) {
105*dfc11533SChris Williamson g->totalbytes -= (debt - g->GCdebt);
106*dfc11533SChris Williamson g->GCdebt = debt;
107*dfc11533SChris Williamson }
108*dfc11533SChris Williamson
109*dfc11533SChris Williamson
luaE_extendCI(lua_State * L)110*dfc11533SChris Williamson CallInfo *luaE_extendCI (lua_State *L) {
111*dfc11533SChris Williamson CallInfo *ci = luaM_new(L, CallInfo);
112*dfc11533SChris Williamson lua_assert(L->ci->next == NULL);
113*dfc11533SChris Williamson L->ci->next = ci;
114*dfc11533SChris Williamson ci->previous = L->ci;
115*dfc11533SChris Williamson ci->next = NULL;
116*dfc11533SChris Williamson return ci;
117*dfc11533SChris Williamson }
118*dfc11533SChris Williamson
119*dfc11533SChris Williamson
luaE_freeCI(lua_State * L)120*dfc11533SChris Williamson void luaE_freeCI (lua_State *L) {
121*dfc11533SChris Williamson CallInfo *ci = L->ci;
122*dfc11533SChris Williamson CallInfo *next = ci->next;
123*dfc11533SChris Williamson ci->next = NULL;
124*dfc11533SChris Williamson while ((ci = next) != NULL) {
125*dfc11533SChris Williamson next = ci->next;
126*dfc11533SChris Williamson luaM_free(L, ci);
127*dfc11533SChris Williamson }
128*dfc11533SChris Williamson }
129*dfc11533SChris Williamson
130*dfc11533SChris Williamson
stack_init(lua_State * L1,lua_State * L)131*dfc11533SChris Williamson static void stack_init (lua_State *L1, lua_State *L) {
132*dfc11533SChris Williamson int i; CallInfo *ci;
133*dfc11533SChris Williamson /* initialize stack array */
134*dfc11533SChris Williamson L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
135*dfc11533SChris Williamson L1->stacksize = BASIC_STACK_SIZE;
136*dfc11533SChris Williamson for (i = 0; i < BASIC_STACK_SIZE; i++)
137*dfc11533SChris Williamson setnilvalue(L1->stack + i); /* erase new stack */
138*dfc11533SChris Williamson L1->top = L1->stack;
139*dfc11533SChris Williamson L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
140*dfc11533SChris Williamson /* initialize first ci */
141*dfc11533SChris Williamson ci = &L1->base_ci;
142*dfc11533SChris Williamson ci->next = ci->previous = NULL;
143*dfc11533SChris Williamson ci->callstatus = 0;
144*dfc11533SChris Williamson ci->func = L1->top;
145*dfc11533SChris Williamson setnilvalue(L1->top++); /* 'function' entry for this 'ci' */
146*dfc11533SChris Williamson ci->top = L1->top + LUA_MINSTACK;
147*dfc11533SChris Williamson L1->ci = ci;
148*dfc11533SChris Williamson }
149*dfc11533SChris Williamson
150*dfc11533SChris Williamson
freestack(lua_State * L)151*dfc11533SChris Williamson static void freestack (lua_State *L) {
152*dfc11533SChris Williamson if (L->stack == NULL)
153*dfc11533SChris Williamson return; /* stack not completely built yet */
154*dfc11533SChris Williamson L->ci = &L->base_ci; /* free the entire 'ci' list */
155*dfc11533SChris Williamson luaE_freeCI(L);
156*dfc11533SChris Williamson luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
157*dfc11533SChris Williamson }
158*dfc11533SChris Williamson
159*dfc11533SChris Williamson
160*dfc11533SChris Williamson /*
161*dfc11533SChris Williamson ** Create registry table and its predefined values
162*dfc11533SChris Williamson */
init_registry(lua_State * L,global_State * g)163*dfc11533SChris Williamson static void init_registry (lua_State *L, global_State *g) {
164*dfc11533SChris Williamson TValue mt;
165*dfc11533SChris Williamson /* create registry */
166*dfc11533SChris Williamson Table *registry = luaH_new(L);
167*dfc11533SChris Williamson sethvalue(L, &g->l_registry, registry);
168*dfc11533SChris Williamson luaH_resize(L, registry, LUA_RIDX_LAST, 0);
169*dfc11533SChris Williamson /* registry[LUA_RIDX_MAINTHREAD] = L */
170*dfc11533SChris Williamson setthvalue(L, &mt, L);
171*dfc11533SChris Williamson luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
172*dfc11533SChris Williamson /* registry[LUA_RIDX_GLOBALS] = table of globals */
173*dfc11533SChris Williamson sethvalue(L, &mt, luaH_new(L));
174*dfc11533SChris Williamson luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
175*dfc11533SChris Williamson }
176*dfc11533SChris Williamson
177*dfc11533SChris Williamson
178*dfc11533SChris Williamson /*
179*dfc11533SChris Williamson ** open parts of the state that may cause memory-allocation errors
180*dfc11533SChris Williamson */
f_luaopen(lua_State * L,void * ud)181*dfc11533SChris Williamson static void f_luaopen (lua_State *L, void *ud) {
182*dfc11533SChris Williamson global_State *g = G(L);
183*dfc11533SChris Williamson UNUSED(ud);
184*dfc11533SChris Williamson stack_init(L, L); /* init stack */
185*dfc11533SChris Williamson init_registry(L, g);
186*dfc11533SChris Williamson luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
187*dfc11533SChris Williamson luaT_init(L);
188*dfc11533SChris Williamson luaX_init(L);
189*dfc11533SChris Williamson /* pre-create memory-error message */
190*dfc11533SChris Williamson g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
191*dfc11533SChris Williamson luaS_fix(g->memerrmsg); /* it should never be collected */
192*dfc11533SChris Williamson g->gcrunning = 1; /* allow gc */
193*dfc11533SChris Williamson g->version = lua_version(NULL);
194*dfc11533SChris Williamson luai_userstateopen(L);
195*dfc11533SChris Williamson }
196*dfc11533SChris Williamson
197*dfc11533SChris Williamson
198*dfc11533SChris Williamson /*
199*dfc11533SChris Williamson ** preinitialize a state with consistent values without allocating
200*dfc11533SChris Williamson ** any memory (to avoid errors)
201*dfc11533SChris Williamson */
preinit_state(lua_State * L,global_State * g)202*dfc11533SChris Williamson static void preinit_state (lua_State *L, global_State *g) {
203*dfc11533SChris Williamson G(L) = g;
204*dfc11533SChris Williamson L->stack = NULL;
205*dfc11533SChris Williamson L->ci = NULL;
206*dfc11533SChris Williamson L->stacksize = 0;
207*dfc11533SChris Williamson L->errorJmp = NULL;
208*dfc11533SChris Williamson L->nCcalls = 0;
209*dfc11533SChris Williamson L->hook = NULL;
210*dfc11533SChris Williamson L->hookmask = 0;
211*dfc11533SChris Williamson L->basehookcount = 0;
212*dfc11533SChris Williamson L->allowhook = 1;
213*dfc11533SChris Williamson resethookcount(L);
214*dfc11533SChris Williamson L->openupval = NULL;
215*dfc11533SChris Williamson L->nny = 1;
216*dfc11533SChris Williamson L->status = LUA_OK;
217*dfc11533SChris Williamson L->errfunc = 0;
218*dfc11533SChris Williamson }
219*dfc11533SChris Williamson
220*dfc11533SChris Williamson
close_state(lua_State * L)221*dfc11533SChris Williamson static void close_state (lua_State *L) {
222*dfc11533SChris Williamson global_State *g = G(L);
223*dfc11533SChris Williamson luaF_close(L, L->stack); /* close all upvalues for this thread */
224*dfc11533SChris Williamson luaC_freeallobjects(L); /* collect all objects */
225*dfc11533SChris Williamson if (g->version) /* closing a fully built state? */
226*dfc11533SChris Williamson luai_userstateclose(L);
227*dfc11533SChris Williamson luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
228*dfc11533SChris Williamson luaZ_freebuffer(L, &g->buff);
229*dfc11533SChris Williamson freestack(L);
230*dfc11533SChris Williamson lua_assert(gettotalbytes(g) == sizeof(LG));
231*dfc11533SChris Williamson (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
232*dfc11533SChris Williamson }
233*dfc11533SChris Williamson
234*dfc11533SChris Williamson
lua_newthread(lua_State * L)235*dfc11533SChris Williamson LUA_API lua_State *lua_newthread (lua_State *L) {
236*dfc11533SChris Williamson lua_State *L1;
237*dfc11533SChris Williamson lua_lock(L);
238*dfc11533SChris Williamson luaC_checkGC(L);
239*dfc11533SChris Williamson L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th;
240*dfc11533SChris Williamson setthvalue(L, L->top, L1);
241*dfc11533SChris Williamson api_incr_top(L);
242*dfc11533SChris Williamson preinit_state(L1, G(L));
243*dfc11533SChris Williamson L1->hookmask = L->hookmask;
244*dfc11533SChris Williamson L1->basehookcount = L->basehookcount;
245*dfc11533SChris Williamson L1->hook = L->hook;
246*dfc11533SChris Williamson resethookcount(L1);
247*dfc11533SChris Williamson luai_userstatethread(L, L1);
248*dfc11533SChris Williamson stack_init(L1, L); /* init stack */
249*dfc11533SChris Williamson lua_unlock(L);
250*dfc11533SChris Williamson return L1;
251*dfc11533SChris Williamson }
252*dfc11533SChris Williamson
253*dfc11533SChris Williamson
luaE_freethread(lua_State * L,lua_State * L1)254*dfc11533SChris Williamson void luaE_freethread (lua_State *L, lua_State *L1) {
255*dfc11533SChris Williamson LX *l = fromstate(L1);
256*dfc11533SChris Williamson luaF_close(L1, L1->stack); /* close all upvalues for this thread */
257*dfc11533SChris Williamson lua_assert(L1->openupval == NULL);
258*dfc11533SChris Williamson luai_userstatefree(L, L1);
259*dfc11533SChris Williamson freestack(L1);
260*dfc11533SChris Williamson luaM_free(L, l);
261*dfc11533SChris Williamson }
262*dfc11533SChris Williamson
263*dfc11533SChris Williamson
lua_newstate(lua_Alloc f,void * ud)264*dfc11533SChris Williamson LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
265*dfc11533SChris Williamson int i;
266*dfc11533SChris Williamson lua_State *L;
267*dfc11533SChris Williamson global_State *g;
268*dfc11533SChris Williamson LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
269*dfc11533SChris Williamson if (l == NULL) return NULL;
270*dfc11533SChris Williamson L = &l->l.l;
271*dfc11533SChris Williamson g = &l->g;
272*dfc11533SChris Williamson L->next = NULL;
273*dfc11533SChris Williamson L->tt = LUA_TTHREAD;
274*dfc11533SChris Williamson g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
275*dfc11533SChris Williamson L->marked = luaC_white(g);
276*dfc11533SChris Williamson g->gckind = KGC_NORMAL;
277*dfc11533SChris Williamson preinit_state(L, g);
278*dfc11533SChris Williamson g->frealloc = f;
279*dfc11533SChris Williamson g->ud = ud;
280*dfc11533SChris Williamson g->mainthread = L;
281*dfc11533SChris Williamson g->seed = makeseed(L);
282*dfc11533SChris Williamson g->uvhead.u.l.prev = &g->uvhead;
283*dfc11533SChris Williamson g->uvhead.u.l.next = &g->uvhead;
284*dfc11533SChris Williamson g->gcrunning = 0; /* no GC while building state */
285*dfc11533SChris Williamson g->GCestimate = 0;
286*dfc11533SChris Williamson g->strt.size = 0;
287*dfc11533SChris Williamson g->strt.nuse = 0;
288*dfc11533SChris Williamson g->strt.hash = NULL;
289*dfc11533SChris Williamson setnilvalue(&g->l_registry);
290*dfc11533SChris Williamson luaZ_initbuffer(L, &g->buff);
291*dfc11533SChris Williamson g->panic = NULL;
292*dfc11533SChris Williamson g->version = NULL;
293*dfc11533SChris Williamson g->gcstate = GCSpause;
294*dfc11533SChris Williamson g->allgc = NULL;
295*dfc11533SChris Williamson g->finobj = NULL;
296*dfc11533SChris Williamson g->tobefnz = NULL;
297*dfc11533SChris Williamson g->sweepgc = g->sweepfin = NULL;
298*dfc11533SChris Williamson g->gray = g->grayagain = NULL;
299*dfc11533SChris Williamson g->weak = g->ephemeron = g->allweak = NULL;
300*dfc11533SChris Williamson g->totalbytes = sizeof(LG);
301*dfc11533SChris Williamson g->GCdebt = 0;
302*dfc11533SChris Williamson g->gcpause = LUAI_GCPAUSE;
303*dfc11533SChris Williamson g->gcmajorinc = LUAI_GCMAJOR;
304*dfc11533SChris Williamson g->gcstepmul = LUAI_GCMUL;
305*dfc11533SChris Williamson for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
306*dfc11533SChris Williamson if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
307*dfc11533SChris Williamson /* memory allocation error: free partial state */
308*dfc11533SChris Williamson close_state(L);
309*dfc11533SChris Williamson L = NULL;
310*dfc11533SChris Williamson }
311*dfc11533SChris Williamson return L;
312*dfc11533SChris Williamson }
313*dfc11533SChris Williamson
314*dfc11533SChris Williamson
lua_close(lua_State * L)315*dfc11533SChris Williamson LUA_API void lua_close (lua_State *L) {
316*dfc11533SChris Williamson L = G(L)->mainthread; /* only the main thread can be closed */
317*dfc11533SChris Williamson lua_lock(L);
318*dfc11533SChris Williamson close_state(L);
319*dfc11533SChris Williamson }
320*dfc11533SChris Williamson
321*dfc11533SChris Williamson
322