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