LCOV - code coverage report
Current view: top level - src - lstate.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 98.1 % 160 157
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $
       3              : ** Global State
       4              : ** See Copyright Notice in lua.h
       5              : */
       6              : 
       7              : 
       8              : #include <stddef.h>
       9              : #include <string.h>
      10              : 
      11              : #define lstate_c
      12              : #define LUA_CORE
      13              : 
      14              : #include "lua.h"
      15              : 
      16              : #include "lapi.h"
      17              : #include "ldebug.h"
      18              : #include "ldo.h"
      19              : #include "lfunc.h"
      20              : #include "lgc.h"
      21              : #include "llex.h"
      22              : #include "lmem.h"
      23              : #include "lstate.h"
      24              : #include "lstring.h"
      25              : #include "ltable.h"
      26              : #include "ltm.h"
      27              : 
      28              : 
      29              : #if !defined(LUAI_GCPAUSE)
      30              : #define LUAI_GCPAUSE    200  /* 200% */
      31              : #endif
      32              : 
      33              : #if !defined(LUAI_GCMAJOR)
      34              : #define LUAI_GCMAJOR    200  /* 200% */
      35              : #endif
      36              : 
      37              : #if !defined(LUAI_GCMUL)
      38              : #define LUAI_GCMUL      200 /* GC runs 'twice the speed' of memory allocation */
      39              : #endif
      40              : 
      41              : 
      42              : #define MEMERRMSG       "not enough memory"
      43              : 
      44              : 
      45              : /*
      46              : ** a macro to help the creation of a unique random seed when a state is
      47              : ** created; the seed is used to randomize hashes.
      48              : */
      49              : #if !defined(luai_makeseed)
      50              : #include <time.h>
      51              : #define luai_makeseed()         cast(unsigned int, time(NULL))
      52              : #endif
      53              : 
      54              : 
      55              : 
      56              : /*
      57              : ** thread state + extra space
      58              : */
      59              : typedef struct LX {
      60              : #if defined(LUAI_EXTRASPACE)
      61              :   char buff[LUAI_EXTRASPACE];
      62              : #endif
      63              :   lua_State l;
      64              : } LX;
      65              : 
      66              : 
      67              : /*
      68              : ** Main thread combines a thread state and the global state
      69              : */
      70              : typedef struct LG {
      71              :   LX l;
      72              :   global_State g;
      73              : } LG;
      74              : 
      75              : 
      76              : 
      77              : #define fromstate(L)    (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
      78              : 
      79              : 
      80              : /*
      81              : ** Compute an initial seed as random as possible. In ANSI, rely on
      82              : ** Address Space Layout Randomization (if present) to increase
      83              : ** randomness..
      84              : */
      85              : #define addbuff(b,p,e) \
      86              :   { size_t t = cast(size_t, e); \
      87              :     memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
      88              : 
      89          104 : static unsigned int makeseed (lua_State *L) {
      90              :   char buff[4 * sizeof(size_t)];
      91          104 :   unsigned int h = luai_makeseed();
      92          104 :   int p = 0;
      93          104 :   addbuff(buff, p, L);  /* heap variable */
      94          104 :   addbuff(buff, p, &h);  /* local variable */
      95          104 :   addbuff(buff, p, luaO_nilobject);  /* global variable */
      96          104 :   addbuff(buff, p, &lua_newstate);  /* public function */
      97              :   lua_assert(p == sizeof(buff));
      98          104 :   return luaS_hash(buff, p, h);
      99              : }
     100              : 
     101              : 
     102              : /*
     103              : ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
     104              : ** invariant
     105              : */
     106         2032 : void luaE_setdebt (global_State *g, l_mem debt) {
     107         2032 :   g->totalbytes -= (debt - g->GCdebt);
     108         2032 :   g->GCdebt = debt;
     109         2032 : }
     110              : 
     111              : 
     112          782 : CallInfo *luaE_extendCI (lua_State *L) {
     113          782 :   CallInfo *ci = luaM_new(L, CallInfo);
     114              :   lua_assert(L->ci->next == NULL);
     115          782 :   L->ci->next = ci;
     116          782 :   ci->previous = L->ci;
     117          782 :   ci->next = NULL;
     118          782 :   return ci;
     119              : }
     120              : 
     121              : 
     122          316 : void luaE_freeCI (lua_State *L) {
     123          316 :   CallInfo *ci = L->ci;
     124          316 :   CallInfo *next = ci->next;
     125          316 :   ci->next = NULL;
     126         1040 :   while ((ci = next) != NULL) {
     127          724 :     next = ci->next;
     128          724 :     luaM_free(L, ci);
     129              :   }
     130          316 : }
     131              : 
     132              : 
     133          130 : static void stack_init (lua_State *L1, lua_State *L) {
     134              :   int i; CallInfo *ci;
     135              :   /* initialize stack array */
     136          130 :   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
     137          130 :   L1->stacksize = BASIC_STACK_SIZE;
     138         5330 :   for (i = 0; i < BASIC_STACK_SIZE; i++)
     139         5200 :     setnilvalue(L1->stack + i);  /* erase new stack */
     140          130 :   L1->top = L1->stack;
     141          130 :   L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
     142              :   /* initialize first ci */
     143          130 :   ci = &L1->base_ci;
     144          130 :   ci->next = ci->previous = NULL;
     145          130 :   ci->callstatus = 0;
     146          130 :   ci->func = L1->top;
     147          130 :   setnilvalue(L1->top++);  /* 'function' entry for this 'ci' */
     148          130 :   ci->top = L1->top + LUA_MINSTACK;
     149          130 :   L1->ci = ci;
     150          130 : }
     151              : 
     152              : 
     153          114 : static void freestack (lua_State *L) {
     154          114 :   if (L->stack == NULL)
     155            0 :     return;  /* stack not completely built yet */
     156          114 :   L->ci = &L->base_ci;  /* free the entire 'ci' list */
     157          114 :   luaE_freeCI(L);
     158          114 :   luaM_freearray(L, L->stack, L->stacksize);  /* free stack array */
     159              : }
     160              : 
     161              : 
     162              : /*
     163              : ** Create registry table and its predefined values
     164              : */
     165          104 : static void init_registry (lua_State *L, global_State *g) {
     166              :   TValue mt;
     167              :   /* create registry */
     168          104 :   Table *registry = luaH_new(L);
     169          104 :   sethvalue(L, &g->l_registry, registry);
     170          104 :   luaH_resize(L, registry, LUA_RIDX_LAST, 0);
     171              :   /* registry[LUA_RIDX_MAINTHREAD] = L */
     172          104 :   setthvalue(L, &mt, L);
     173          104 :   luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
     174              :   /* registry[LUA_RIDX_GLOBALS] = table of globals */
     175          104 :   sethvalue(L, &mt, luaH_new(L));
     176          104 :   luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
     177          104 : }
     178              : 
     179              : 
     180              : /*
     181              : ** open parts of the state that may cause memory-allocation errors
     182              : */
     183          104 : static void f_luaopen (lua_State *L, void *ud) {
     184          104 :   global_State *g = G(L);
     185              :   UNUSED(ud);
     186          104 :   stack_init(L, L);  /* init stack */
     187          104 :   init_registry(L, g);
     188          104 :   luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
     189          104 :   luaT_init(L);
     190          104 :   luaX_init(L);
     191              :   /* pre-create memory-error message */
     192          104 :   g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
     193          104 :   luaS_fix(g->memerrmsg);  /* it should never be collected */
     194          104 :   g->gcrunning = 1;  /* allow gc */
     195          104 :   g->version = lua_version(NULL);
     196              :   luai_userstateopen(L);
     197          104 : }
     198              : 
     199              : 
     200              : /*
     201              : ** preinitialize a state with consistent values without allocating
     202              : ** any memory (to avoid errors)
     203              : */
     204          130 : static void preinit_state (lua_State *L, global_State *g) {
     205          130 :   G(L) = g;
     206          130 :   L->stack = NULL;
     207          130 :   L->ci = NULL;
     208          130 :   L->stacksize = 0;
     209          130 :   L->errorJmp = NULL;
     210          130 :   L->nCcalls = 0;
     211          130 :   L->hook = NULL;
     212          130 :   L->hookmask = 0;
     213          130 :   L->basehookcount = 0;
     214          130 :   L->allowhook = 1;
     215          130 :   resethookcount(L);
     216          130 :   L->openupval = NULL;
     217          130 :   L->nny = 1;
     218          130 :   L->status = LUA_OK;
     219          130 :   L->errfunc = 0;
     220          130 : }
     221              : 
     222              : 
     223           88 : static void close_state (lua_State *L) {
     224           88 :   global_State *g = G(L);
     225           88 :   luaF_close(L, L->stack);  /* close all upvalues for this thread */
     226           88 :   luaC_freeallobjects(L);  /* collect all objects */
     227           88 :   if (g->version)  /* closing a fully built state? */
     228              :     luai_userstateclose(L);
     229           88 :   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
     230           88 :   luaZ_freebuffer(L, &g->buff);
     231           88 :   freestack(L);
     232              :   lua_assert(gettotalbytes(g) == sizeof(LG));
     233           88 :   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
     234           88 : }
     235              : 
     236              : 
     237           26 : LUA_API lua_State *lua_newthread (lua_State *L) {
     238              :   lua_State *L1;
     239              :   lua_lock(L);
     240           26 :   luaC_checkGC(L);
     241           26 :   L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th;
     242           26 :   setthvalue(L, L->top, L1);
     243           26 :   api_incr_top(L);
     244           26 :   preinit_state(L1, G(L));
     245           26 :   L1->hookmask = L->hookmask;
     246           26 :   L1->basehookcount = L->basehookcount;
     247           26 :   L1->hook = L->hook;
     248           26 :   resethookcount(L1);
     249              :   luai_userstatethread(L, L1);
     250           26 :   stack_init(L1, L);  /* init stack */
     251              :   lua_unlock(L);
     252           26 :   return L1;
     253              : }
     254              : 
     255              : 
     256           26 : void luaE_freethread (lua_State *L, lua_State *L1) {
     257           26 :   LX *l = fromstate(L1);
     258           26 :   luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
     259              :   lua_assert(L1->openupval == NULL);
     260              :   luai_userstatefree(L, L1);
     261           26 :   freestack(L1);
     262           26 :   luaM_free(L, l);
     263           26 : }
     264              : 
     265              : 
     266          104 : LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
     267              :   int i;
     268              :   lua_State *L;
     269              :   global_State *g;
     270          104 :   LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
     271          104 :   if (l == NULL) return NULL;
     272          104 :   L = &l->l.l;
     273          104 :   g = &l->g;
     274          104 :   L->next = NULL;
     275          104 :   L->tt = LUA_TTHREAD;
     276          104 :   g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
     277          104 :   L->marked = luaC_white(g);
     278          104 :   g->gckind = KGC_NORMAL;
     279          104 :   preinit_state(L, g);
     280          104 :   g->frealloc = f;
     281          104 :   g->ud = ud;
     282          104 :   g->mainthread = L;
     283          104 :   g->seed = makeseed(L);
     284          104 :   g->uvhead.u.l.prev = &g->uvhead;
     285          104 :   g->uvhead.u.l.next = &g->uvhead;
     286          104 :   g->gcrunning = 0;  /* no GC while building state */
     287          104 :   g->GCestimate = 0;
     288          104 :   g->strt.size = 0;
     289          104 :   g->strt.nuse = 0;
     290          104 :   g->strt.hash = NULL;
     291          104 :   setnilvalue(&g->l_registry);
     292          104 :   luaZ_initbuffer(L, &g->buff);
     293          104 :   g->panic = NULL;
     294          104 :   g->version = NULL;
     295          104 :   g->gcstate = GCSpause;
     296          104 :   g->allgc = NULL;
     297          104 :   g->finobj = NULL;
     298          104 :   g->tobefnz = NULL;
     299          104 :   g->sweepgc = g->sweepfin = NULL;
     300          104 :   g->gray = g->grayagain = NULL;
     301          104 :   g->weak = g->ephemeron = g->allweak = NULL;
     302          104 :   g->totalbytes = sizeof(LG);
     303          104 :   g->GCdebt = 0;
     304          104 :   g->gcpause = LUAI_GCPAUSE;
     305          104 :   g->gcmajorinc = LUAI_GCMAJOR;
     306          104 :   g->gcstepmul = LUAI_GCMUL;
     307         1040 :   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
     308          104 :   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
     309              :     /* memory allocation error: free partial state */
     310            0 :     close_state(L);
     311            0 :     L = NULL;
     312              :   }
     313          104 :   return L;
     314              : }
     315              : 
     316              : 
     317           88 : LUA_API void lua_close (lua_State *L) {
     318           88 :   L = G(L)->mainthread;  /* only the main thread can be closed */
     319              :   lua_lock(L);
     320           88 :   close_state(L);
     321           88 : }
     322              : 
     323              : 
        

Generated by: LCOV version 2.0-1