xref: /minix/external/mit/lua/dist/src/lstate.c (revision 0a6a1f1d)
1 /*	$NetBSD: lstate.c,v 1.4 2015/10/08 13:21:00 mbalmer Exp $	*/
2 
3 /*
4 ** Id: lstate.c,v 2.128 2015/03/04 13:31:21 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
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(buff + p, &t, sizeof(t)); p += sizeof(t); }
84 
makeseed(lua_State * L)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
101 */
luaE_setdebt(global_State * g,l_mem debt)102 void luaE_setdebt (global_State *g, l_mem debt) {
103   g->totalbytes -= (debt - g->GCdebt);
104   g->GCdebt = debt;
105 }
106 
107 
luaE_extendCI(lua_State * L)108 CallInfo *luaE_extendCI (lua_State *L) {
109   CallInfo *ci = luaM_new(L, CallInfo);
110   lua_assert(L->ci->next == NULL);
111   L->ci->next = ci;
112   ci->previous = L->ci;
113   ci->next = NULL;
114   return ci;
115 }
116 
117 
118 /*
119 ** free all CallInfo structures not in use by a thread
120 */
luaE_freeCI(lua_State * L)121 void luaE_freeCI (lua_State *L) {
122   CallInfo *ci = L->ci;
123   CallInfo *next = ci->next;
124   ci->next = NULL;
125   while ((ci = next) != NULL) {
126     next = ci->next;
127     luaM_free(L, ci);
128   }
129 }
130 
131 
132 /*
133 ** free half of the CallInfo structures not in use by a thread
134 */
luaE_shrinkCI(lua_State * L)135 void luaE_shrinkCI (lua_State *L) {
136   CallInfo *ci = L->ci;
137   while (ci->next != NULL) {  /* while there is 'next' */
138     CallInfo *next2 = ci->next->next;  /* next's next */
139     if (next2 == NULL) break;
140     luaM_free(L, ci->next);  /* remove next */
141     ci->next = next2;  /* remove 'next' from the list */
142     next2->previous = ci;
143     ci = next2;
144   }
145 }
146 
147 
stack_init(lua_State * L1,lua_State * L)148 static void stack_init (lua_State *L1, lua_State *L) {
149   int i; CallInfo *ci;
150   /* initialize stack array */
151   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
152   L1->stacksize = BASIC_STACK_SIZE;
153   for (i = 0; i < BASIC_STACK_SIZE; i++)
154     setnilvalue(L1->stack + i);  /* erase new stack */
155   L1->top = L1->stack;
156   L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
157   /* initialize first ci */
158   ci = &L1->base_ci;
159   ci->next = ci->previous = NULL;
160   ci->callstatus = 0;
161   ci->func = L1->top;
162   setnilvalue(L1->top++);  /* 'function' entry for this 'ci' */
163   ci->top = L1->top + LUA_MINSTACK;
164   L1->ci = ci;
165 }
166 
167 
freestack(lua_State * L)168 static void freestack (lua_State *L) {
169   if (L->stack == NULL)
170     return;  /* stack not completely built yet */
171   L->ci = &L->base_ci;  /* free the entire 'ci' list */
172   luaE_freeCI(L);
173   luaM_freearray(L, L->stack, L->stacksize);  /* free stack array */
174 }
175 
176 
177 /*
178 ** Create registry table and its predefined values
179 */
init_registry(lua_State * L,global_State * g)180 static void init_registry (lua_State *L, global_State *g) {
181   TValue temp;
182   /* create registry */
183   Table *registry = luaH_new(L);
184   sethvalue(L, &g->l_registry, registry);
185   luaH_resize(L, registry, LUA_RIDX_LAST, 0);
186   /* registry[LUA_RIDX_MAINTHREAD] = L */
187   setthvalue(L, &temp, L);  /* temp = L */
188   luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
189   /* registry[LUA_RIDX_GLOBALS] = table of globals */
190   sethvalue(L, &temp, luaH_new(L));  /* temp = new table (global table) */
191   luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
192 }
193 
194 
195 /*
196 ** open parts of the state that may cause memory-allocation errors.
197 ** ('g->version' != NULL flags that the state was completely build)
198 */
f_luaopen(lua_State * L,void * ud)199 static void f_luaopen (lua_State *L, void *ud) {
200   global_State *g = G(L);
201   UNUSED(ud);
202   stack_init(L, L);  /* init stack */
203   init_registry(L, g);
204   luaS_init(L);
205   luaT_init(L);
206   luaX_init(L);
207   g->gcrunning = 1;  /* allow gc */
208   g->version = lua_version(NULL);
209   luai_userstateopen(L);
210 }
211 
212 
213 /*
214 ** preinitialize a thread with consistent values without allocating
215 ** any memory (to avoid errors)
216 */
preinit_thread(lua_State * L,global_State * g)217 static void preinit_thread (lua_State *L, global_State *g) {
218   G(L) = g;
219   L->stack = NULL;
220   L->ci = NULL;
221   L->stacksize = 0;
222   L->twups = L;  /* thread has no upvalues */
223   L->errorJmp = NULL;
224   L->nCcalls = 0;
225   L->hook = NULL;
226   L->hookmask = 0;
227   L->basehookcount = 0;
228   L->allowhook = 1;
229   resethookcount(L);
230   L->openupval = NULL;
231   L->nny = 1;
232   L->status = LUA_OK;
233   L->errfunc = 0;
234 }
235 
236 
close_state(lua_State * L)237 static void close_state (lua_State *L) {
238   global_State *g = G(L);
239   luaF_close(L, L->stack);  /* close all upvalues for this thread */
240   luaC_freeallobjects(L);  /* collect all objects */
241   if (g->version)  /* closing a fully built state? */
242     luai_userstateclose(L);
243   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
244   luaZ_freebuffer(L, &g->buff);
245   freestack(L);
246   lua_assert(gettotalbytes(g) == sizeof(LG));
247   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
248 }
249 
250 
lua_newthread(lua_State * L)251 LUA_API lua_State *lua_newthread (lua_State *L) {
252   global_State *g = G(L);
253   lua_State *L1;
254   lua_lock(L);
255   luaC_checkGC(L);
256   /* create new thread */
257   L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
258   L1->marked = luaC_white(g);
259   L1->tt = LUA_TTHREAD;
260   /* link it on list 'allgc' */
261   L1->next = g->allgc;
262   g->allgc = obj2gco(L1);
263   /* anchor it on L stack */
264   setthvalue(L, L->top, L1);
265   api_incr_top(L);
266   preinit_thread(L1, g);
267   L1->hookmask = L->hookmask;
268   L1->basehookcount = L->basehookcount;
269   L1->hook = L->hook;
270   resethookcount(L1);
271   /* initialize L1 extra space */
272   memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
273          LUA_EXTRASPACE);
274   luai_userstatethread(L, L1);
275   stack_init(L1, L);  /* init stack */
276   lua_unlock(L);
277   return L1;
278 }
279 
280 
luaE_freethread(lua_State * L,lua_State * L1)281 void luaE_freethread (lua_State *L, lua_State *L1) {
282   LX *l = fromstate(L1);
283   luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
284   lua_assert(L1->openupval == NULL);
285   luai_userstatefree(L, L1);
286   freestack(L1);
287   luaM_free(L, l);
288 }
289 
290 
lua_newstate(lua_Alloc f,void * ud)291 LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
292   int i;
293   lua_State *L;
294   global_State *g;
295   LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
296   if (l == NULL) return NULL;
297   L = &l->l.l;
298   g = &l->g;
299   L->next = NULL;
300   L->tt = LUA_TTHREAD;
301   g->currentwhite = bitmask(WHITE0BIT);
302   L->marked = luaC_white(g);
303   preinit_thread(L, g);
304   g->frealloc = f;
305   g->ud = ud;
306   g->mainthread = L;
307   g->seed = makeseed(L);
308   g->gcrunning = 0;  /* no GC while building state */
309   g->GCestimate = 0;
310   g->strt.size = g->strt.nuse = 0;
311   g->strt.hash = NULL;
312   setnilvalue(&g->l_registry);
313   luaZ_initbuffer(L, &g->buff);
314   g->panic = NULL;
315   g->version = NULL;
316   g->gcstate = GCSpause;
317   g->gckind = KGC_NORMAL;
318   g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
319   g->sweepgc = NULL;
320   g->gray = g->grayagain = NULL;
321   g->weak = g->ephemeron = g->allweak = NULL;
322   g->twups = NULL;
323   g->totalbytes = sizeof(LG);
324   g->GCdebt = 0;
325   g->gcfinnum = 0;
326   g->gcpause = LUAI_GCPAUSE;
327   g->gcstepmul = LUAI_GCMUL;
328   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
329   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
330     /* memory allocation error: free partial state */
331     close_state(L);
332     L = NULL;
333   }
334   return L;
335 }
336 
337 
lua_close(lua_State * L)338 LUA_API void lua_close (lua_State *L) {
339   L = G(L)->mainthread;  /* only the main thread can be closed */
340   lua_lock(L);
341   close_state(L);
342 }
343 
344 
345