LCOV - code coverage report
Current view: top level - src - lstate.c Coverage Total Hit
Test: Lua 5.3.6 Lines: 97.7 % 174 170
Test Date: 2024-04-28 10:23:15
Legend: Lines: hit not hit

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

Generated by: LCOV version 2.0-1