|
1 /* |
|
2 ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ |
|
3 ** Global State |
|
4 ** See Copyright Notice in lua.h |
|
5 */ |
|
6 |
|
7 |
|
8 #include <stddef.h> |
|
9 |
|
10 #define lstate_c |
|
11 #define LUA_CORE |
|
12 |
|
13 #include "lua.h" |
|
14 |
|
15 #include "ldebug.h" |
|
16 #include "ldo.h" |
|
17 #include "lfunc.h" |
|
18 #include "lgc.h" |
|
19 #include "llex.h" |
|
20 #include "lmem.h" |
|
21 #include "lstate.h" |
|
22 #include "lstring.h" |
|
23 #include "ltable.h" |
|
24 #include "ltm.h" |
|
25 |
|
26 |
|
27 #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) |
|
28 #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) |
|
29 #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) |
|
30 |
|
31 |
|
32 /* |
|
33 ** Main thread combines a thread state and the global state |
|
34 */ |
|
35 typedef struct LG { |
|
36 lua_State l; |
|
37 global_State g; |
|
38 } LG; |
|
39 |
|
40 |
|
41 |
|
42 static void stack_init (lua_State *L1, lua_State *L) { |
|
43 /* initialize CallInfo array */ |
|
44 L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); |
|
45 L1->ci = L1->base_ci; |
|
46 L1->size_ci = BASIC_CI_SIZE; |
|
47 L1->end_ci = L1->base_ci + L1->size_ci - 1; |
|
48 /* initialize stack array */ |
|
49 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); |
|
50 L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; |
|
51 L1->top = L1->stack; |
|
52 L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; |
|
53 /* initialize first ci */ |
|
54 L1->ci->func = L1->top; |
|
55 setnilvalue(L1->top++); /* `function' entry for this `ci' */ |
|
56 L1->base = L1->ci->base = L1->top; |
|
57 L1->ci->top = L1->top + LUA_MINSTACK; |
|
58 } |
|
59 |
|
60 |
|
61 static void freestack (lua_State *L, lua_State *L1) { |
|
62 luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); |
|
63 luaM_freearray(L, L1->stack, L1->stacksize, TValue); |
|
64 } |
|
65 |
|
66 |
|
67 /* |
|
68 ** open parts that may cause memory-allocation errors |
|
69 */ |
|
70 static void f_luaopen (lua_State *L, void *ud) { |
|
71 global_State *g = G(L); |
|
72 UNUSED(ud); |
|
73 stack_init(L, L); /* init stack */ |
|
74 sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ |
|
75 sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ |
|
76 luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ |
|
77 luaT_init(L); |
|
78 luaX_init(L); |
|
79 luaS_fix(luaS_newliteral(L, MEMERRMSG)); |
|
80 g->GCthreshold = 4*g->totalbytes; |
|
81 } |
|
82 |
|
83 |
|
84 static void preinit_state (lua_State *L, global_State *g) { |
|
85 G(L) = g; |
|
86 L->stack = NULL; |
|
87 L->stacksize = 0; |
|
88 L->errorJmp = NULL; |
|
89 L->hook = NULL; |
|
90 L->hookmask = 0; |
|
91 L->basehookcount = 0; |
|
92 L->allowhook = 1; |
|
93 resethookcount(L); |
|
94 L->openupval = NULL; |
|
95 L->size_ci = 0; |
|
96 L->nCcalls = L->baseCcalls = 0; |
|
97 L->status = 0; |
|
98 L->base_ci = L->ci = NULL; |
|
99 L->savedpc = NULL; |
|
100 L->errfunc = 0; |
|
101 setnilvalue(gt(L)); |
|
102 } |
|
103 |
|
104 |
|
105 static void close_state (lua_State *L) { |
|
106 global_State *g = G(L); |
|
107 luaF_close(L, L->stack); /* close all upvalues for this thread */ |
|
108 luaC_freeall(L); /* collect all objects */ |
|
109 lua_assert(g->rootgc == obj2gco(L)); |
|
110 lua_assert(g->strt.nuse == 0); |
|
111 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); |
|
112 luaZ_freebuffer(L, &g->buff); |
|
113 freestack(L, L); |
|
114 lua_assert(g->totalbytes == sizeof(LG)); |
|
115 (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); |
|
116 } |
|
117 |
|
118 |
|
119 lua_State *luaE_newthread (lua_State *L) { |
|
120 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); |
|
121 luaC_link(L, obj2gco(L1), LUA_TTHREAD); |
|
122 preinit_state(L1, G(L)); |
|
123 stack_init(L1, L); /* init stack */ |
|
124 setobj2n(L, gt(L1), gt(L)); /* share table of globals */ |
|
125 L1->hookmask = L->hookmask; |
|
126 L1->basehookcount = L->basehookcount; |
|
127 L1->hook = L->hook; |
|
128 resethookcount(L1); |
|
129 lua_assert(iswhite(obj2gco(L1))); |
|
130 return L1; |
|
131 } |
|
132 |
|
133 |
|
134 void luaE_freethread (lua_State *L, lua_State *L1) { |
|
135 luaF_close(L1, L1->stack); /* close all upvalues for this thread */ |
|
136 lua_assert(L1->openupval == NULL); |
|
137 luai_userstatefree(L1); |
|
138 freestack(L, L1); |
|
139 luaM_freemem(L, fromstate(L1), state_size(lua_State)); |
|
140 } |
|
141 |
|
142 |
|
143 LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { |
|
144 int i; |
|
145 lua_State *L; |
|
146 global_State *g; |
|
147 void *l = (*f)(ud, NULL, 0, state_size(LG)); |
|
148 if (l == NULL) return NULL; |
|
149 L = tostate(l); |
|
150 g = &((LG *)L)->g; |
|
151 L->next = NULL; |
|
152 L->tt = LUA_TTHREAD; |
|
153 g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); |
|
154 L->marked = luaC_white(g); |
|
155 set2bits(L->marked, FIXEDBIT, SFIXEDBIT); |
|
156 preinit_state(L, g); |
|
157 g->frealloc = f; |
|
158 g->ud = ud; |
|
159 g->mainthread = L; |
|
160 g->uvhead.u.l.prev = &g->uvhead; |
|
161 g->uvhead.u.l.next = &g->uvhead; |
|
162 g->GCthreshold = 0; /* mark it as unfinished state */ |
|
163 g->strt.size = 0; |
|
164 g->strt.nuse = 0; |
|
165 g->strt.hash = NULL; |
|
166 setnilvalue(registry(L)); |
|
167 luaZ_initbuffer(L, &g->buff); |
|
168 g->panic = NULL; |
|
169 g->gcstate = GCSpause; |
|
170 g->rootgc = obj2gco(L); |
|
171 g->sweepstrgc = 0; |
|
172 g->sweepgc = &g->rootgc; |
|
173 g->gray = NULL; |
|
174 g->grayagain = NULL; |
|
175 g->weak = NULL; |
|
176 g->tmudata = NULL; |
|
177 g->totalbytes = sizeof(LG); |
|
178 g->gcpause = LUAI_GCPAUSE; |
|
179 g->gcstepmul = LUAI_GCMUL; |
|
180 g->gcdept = 0; |
|
181 for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; |
|
182 if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { |
|
183 /* memory allocation error: free partial state */ |
|
184 close_state(L); |
|
185 L = NULL; |
|
186 } |
|
187 else |
|
188 luai_userstateopen(L); |
|
189 return L; |
|
190 } |
|
191 |
|
192 |
|
193 static void callallgcTM (lua_State *L, void *ud) { |
|
194 UNUSED(ud); |
|
195 luaC_callGCTM(L); /* call GC metamethods for all udata */ |
|
196 } |
|
197 |
|
198 |
|
199 LUA_API void lua_close (lua_State *L) { |
|
200 L = G(L)->mainthread; /* only the main thread can be closed */ |
|
201 lua_lock(L); |
|
202 luaF_close(L, L->stack); /* close all upvalues for this thread */ |
|
203 luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ |
|
204 L->errfunc = 0; /* no error function during GC metamethods */ |
|
205 do { /* repeat until no more errors */ |
|
206 L->ci = L->base_ci; |
|
207 L->base = L->top = L->ci->base; |
|
208 L->nCcalls = L->baseCcalls = 0; |
|
209 } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); |
|
210 lua_assert(G(L)->tmudata == NULL); |
|
211 luai_userstateclose(L); |
|
212 close_state(L); |
|
213 } |
|
214 |