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