mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

lstate.cc (8495B)


      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