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