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