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