rpm
4.5
|
00001 /* 00002 ** $Id: lstate.c,v 1.1 2004/03/16 21:58:30 niemeyer Exp $ 00003 ** Global State 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <stdlib.h> 00009 00010 #define lstate_c 00011 00012 #include "lua.h" 00013 00014 #include "ldebug.h" 00015 #include "ldo.h" 00016 #include "lfunc.h" 00017 #include "lgc.h" 00018 #include "llex.h" 00019 #include "lmem.h" 00020 #include "lstate.h" 00021 #include "lstring.h" 00022 #include "ltable.h" 00023 #include "ltm.h" 00024 00025 00026 /* 00027 ** macro to allow the inclusion of user information in Lua state 00028 */ 00029 #ifndef LUA_USERSTATE 00030 #define EXTRASPACE 0 00031 #else 00032 union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;}; 00033 #define EXTRASPACE (sizeof(union UEXTRASPACE)) 00034 #endif 00035 00036 00037 00038 /* 00039 ** you can change this function through the official API: 00040 ** call `lua_setpanicf' 00041 */ 00042 static int default_panic (lua_State *L) 00043 /*@*/ 00044 { 00045 UNUSED(L); 00046 return 0; 00047 } 00048 00049 00050 /*@null@*/ 00051 static lua_State *mallocstate (/*@null@*/ lua_State *L) 00052 /*@modifies L @*/ 00053 { 00054 lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE); 00055 if (block == NULL) return NULL; 00056 else { 00057 block += EXTRASPACE; 00058 return cast(lua_State *, block); 00059 } 00060 } 00061 00062 00063 static void freestate (/*@null@*/ lua_State *L, lua_State *L1) 00064 /*@modifies L @*/ 00065 { 00066 luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, 00067 sizeof(lua_State) + EXTRASPACE); 00068 } 00069 00070 00071 static void stack_init (lua_State *L1, lua_State *L) 00072 /*@modifies L1, L @*/ 00073 { 00074 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject); 00075 L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; 00076 L1->top = L1->stack; 00077 L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; 00078 L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); 00079 L1->ci = L1->base_ci; 00080 L1->ci->state = CI_C; /* not a Lua function */ 00081 setnilvalue(L1->top++); /* `function' entry for this `ci' */ 00082 L1->base = L1->ci->base = L1->top; 00083 L1->ci->top = L1->top + LUA_MINSTACK; 00084 L1->size_ci = BASIC_CI_SIZE; 00085 L1->end_ci = L1->base_ci + L1->size_ci; 00086 } 00087 00088 00089 static void freestack (lua_State *L, lua_State *L1) 00090 /*@modifies L, L1 @*/ 00091 { 00092 luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); 00093 luaM_freearray(L, L1->stack, L1->stacksize, TObject); 00094 } 00095 00096 00097 /* 00098 ** open parts that may cause memory-allocation errors 00099 */ 00100 static void f_luaopen (lua_State *L, void *ud) 00101 /*@modifies L @*/ 00102 { 00103 /* create a new global state */ 00104 global_State *g = luaM_new(NULL, global_State); 00105 UNUSED(ud); 00106 if (g == NULL) luaD_throw(L, LUA_ERRMEM); 00107 L->l_G = g; 00108 g->mainthread = L; 00109 g->GCthreshold = 0; /* mark it as unfinished state */ 00110 g->strt.size = 0; 00111 g->strt.nuse = 0; 00112 g->strt.hash = NULL; 00113 setnilvalue(defaultmeta(L)); 00114 setnilvalue(registry(L)); 00115 luaZ_initbuffer(L, &g->buff); 00116 g->panic = default_panic; 00117 g->rootgc = NULL; 00118 g->rootudata = NULL; 00119 g->tmudata = NULL; 00120 setnilvalue(gkey(g->dummynode)); 00121 setnilvalue(gval(g->dummynode)); 00122 g->dummynode->next = NULL; 00123 g->nblocks = sizeof(lua_State) + sizeof(global_State); 00124 stack_init(L, L); /* init stack */ 00125 /* create default meta table with a dummy table, and then close the loop */ 00126 defaultmeta(L)->tt = LUA_TTABLE; 00127 sethvalue(defaultmeta(L), luaH_new(L, 0, 0)); 00128 hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L)); 00129 sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ 00130 sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */ 00131 luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ 00132 luaT_init(L); 00133 luaX_init(L); 00134 luaS_fix(luaS_newliteral(L, MEMERRMSG)); 00135 g->GCthreshold = 4*G(L)->nblocks; 00136 } 00137 00138 00139 static void preinit_state (lua_State *L) 00140 /*@modifies L @*/ 00141 { 00142 L->stack = NULL; 00143 L->stacksize = 0; 00144 L->errorJmp = NULL; 00145 L->hook = NULL; 00146 L->hookmask = L->hookinit = 0; 00147 L->basehookcount = 0; 00148 L->allowhook = 1; 00149 resethookcount(L); 00150 L->openupval = NULL; 00151 L->size_ci = 0; 00152 L->nCcalls = 0; 00153 L->ci = L->base_ci = NULL; 00154 L->errfunc = 0; 00155 setnilvalue(gt(L)); 00156 } 00157 00158 00159 static void close_state (lua_State *L) 00160 /*@modifies L @*/ 00161 { 00162 luaF_close(L, L->stack); /* close all upvalues for this thread */ 00163 if (G(L)) { /* close global state */ 00164 luaC_sweep(L, 1); /* collect all elements */ 00165 lua_assert(G(L)->rootgc == NULL); 00166 lua_assert(G(L)->rootudata == NULL); 00167 luaS_freeall(L); 00168 luaZ_freebuffer(L, &G(L)->buff); 00169 } 00170 freestack(L, L); 00171 if (G(L)) { 00172 lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State)); 00173 luaM_freelem(NULL, G(L)); 00174 } 00175 freestate(NULL, L); 00176 } 00177 00178 00179 lua_State *luaE_newthread (lua_State *L) { 00180 lua_State *L1 = mallocstate(L); 00181 luaC_link(L, valtogco(L1), LUA_TTHREAD); 00182 preinit_state(L1); 00183 L1->l_G = L->l_G; 00184 stack_init(L1, L); /* init stack */ 00185 setobj2n(gt(L1), gt(L)); /* share table of globals */ 00186 return L1; 00187 } 00188 00189 00190 void luaE_freethread (lua_State *L, lua_State *L1) { 00191 luaF_close(L1, L1->stack); /* close all upvalues for this thread */ 00192 lua_assert(L1->openupval == NULL); 00193 freestack(L, L1); 00194 freestate(L, L1); 00195 } 00196 00197 00198 /*@null@*/ 00199 LUA_API lua_State *lua_open (void) { 00200 lua_State *L = mallocstate(NULL); 00201 if (L) { /* allocation OK? */ 00202 L->tt = LUA_TTHREAD; 00203 L->marked = 0; 00204 L->next = L->gclist = NULL; 00205 preinit_state(L); 00206 L->l_G = NULL; 00207 if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { 00208 /* memory allocation error: free partial state */ 00209 close_state(L); 00210 L = NULL; 00211 } 00212 } 00213 lua_userstateopen(L); 00214 return L; 00215 } 00216 00217 00218 static void callallgcTM (lua_State *L, void *ud) 00219 /*@modifies L @*/ 00220 { 00221 UNUSED(ud); 00222 luaC_callGCTM(L); /* call GC metamethods for all udata */ 00223 } 00224 00225 00226 LUA_API void lua_close (lua_State *L) { 00227 lua_lock(L); 00228 L = G(L)->mainthread; /* only the main thread can be closed */ 00229 luaF_close(L, L->stack); /* close all upvalues for this thread */ 00230 luaC_separateudata(L); /* separate udata that have GC metamethods */ 00231 L->errfunc = 0; /* no error function during GC metamethods */ 00232 do { /* repeat until no more errors */ 00233 L->ci = L->base_ci; 00234 L->base = L->top = L->ci->base; 00235 L->nCcalls = 0; 00236 } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); 00237 lua_assert(G(L)->tmudata == NULL); 00238 close_state(L); 00239 } 00240