LCOV - code coverage report
Current view: top level - AP_Scripting/lua/src - lstate.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 146 174 83.9 %
Date: 2026-09-09 11:02:08 Functions: 13 15 86.7 %

          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             : #include "lauxlib.h"
      30             : 
      31             : // lua code does lots of casting, these warnings are not helpful
      32             : #pragma GCC diagnostic ignored "-Wcast-align"
      33             : 
      34             : 
      35             : #if !defined(LUAI_GCPAUSE)
      36             : #define LUAI_GCPAUSE    200  /* 200% */
      37             : #endif
      38             : 
      39             : #if !defined(LUAI_GCMUL)
      40             : #define LUAI_GCMUL      200 /* GC runs 'twice the speed' of memory allocation */
      41             : #endif
      42             : 
      43             : 
      44             : /*
      45             : ** a macro to help the creation of a unique random seed when a state is
      46             : ** created; the seed is used to randomize hashes.
      47             : */
      48             : #if defined(ARDUPILOT_BUILD)
      49             : #define luai_makeseed() lua_random32()
      50             : #else
      51             : #if !defined(luai_makeseed)
      52             : #include <time.h>
      53             : #define luai_makeseed()         cast(unsigned int, time(NULL))
      54             : #endif
      55             : #endif
      56             : 
      57             : 
      58             : 
      59             : /*
      60             : ** thread state + extra space
      61             : */
      62             : typedef struct LX {
      63             :   lu_byte extra_[LUA_EXTRASPACE];
      64             :   lua_State l;
      65             : } LX;
      66             : 
      67             : 
      68             : /*
      69             : ** Main thread combines a thread state and the global state
      70             : */
      71             : typedef struct LG {
      72             :   LX l;
      73             :   global_State g;
      74             : } LG;
      75             : 
      76             : 
      77             : 
      78             : #define fromstate(L)    (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
      79             : 
      80             : 
      81             : /*
      82             : ** Compute an initial seed as random as possible. Rely on Address Space
      83             : ** Layout Randomization (if present) to increase randomness..
      84             : */
      85             : #define addbuff(b,p,e) \
      86             :   { size_t t = cast(size_t, e); \
      87             :     memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
      88             : 
      89          97 : static unsigned int makeseed (lua_State *L) {
      90             :   char buff[4 * sizeof(size_t)];
      91          97 :   unsigned int h = luai_makeseed();
      92          97 :   int p = 0;
      93          97 :   addbuff(buff, p, L);  /* heap variable */
      94          97 :   addbuff(buff, p, &h);  /* local variable */
      95          97 :   addbuff(buff, p, luaO_nilobject);  /* global variable */
      96          97 :   addbuff(buff, p, &lua_newstate);  /* public function */
      97             :   lua_assert(p == sizeof(buff));
      98          97 :   return luaS_hash(buff, p, h);
      99             : }
     100             : 
     101             : 
     102             : /*
     103             : ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
     104             : ** invariant (and avoiding underflows in 'totalbytes')
     105             : */
     106       91685 : void luaE_setdebt (global_State *g, l_mem debt) {
     107       91685 :   l_mem tb = gettotalbytes(g);
     108             :   lua_assert(tb > 0);
     109       91685 :   if (debt < tb - MAX_LMEM)
     110           0 :     debt = tb - MAX_LMEM;  /* will make 'totalbytes == MAX_LMEM' */
     111       91685 :   g->totalbytes = tb - debt;
     112       91685 :   g->GCdebt = debt;
     113       91685 : }
     114             : 
     115             : 
     116      183022 : CallInfo *luaE_extendCI (lua_State *L) {
     117      183022 :   CallInfo *ci = luaM_new(L, CallInfo);
     118             :   lua_assert(L->ci->next == NULL);
     119      183022 :   L->ci->next = ci;
     120      183022 :   ci->previous = L->ci;
     121      183022 :   ci->next = NULL;
     122      183022 :   L->nci++;
     123      183022 :   return ci;
     124             : }
     125             : 
     126             : 
     127             : /*
     128             : ** free all CallInfo structures not in use by a thread
     129             : */
     130          56 : void luaE_freeCI (lua_State *L) {
     131          56 :   CallInfo *ci = L->ci;
     132          56 :   CallInfo *next = ci->next;
     133          56 :   ci->next = NULL;
     134         204 :   while ((ci = next) != NULL) {
     135         148 :     next = ci->next;
     136         148 :     luaM_free(L, ci);
     137         148 :     L->nci--;
     138             :   }
     139          56 : }
     140             : 
     141             : 
     142             : /*
     143             : ** free half of the CallInfo structures not in use by a thread
     144             : */
     145       90721 : void luaE_shrinkCI (lua_State *L) {
     146       90721 :   CallInfo *ci = L->ci;
     147             :   CallInfo *next2;  /* next's next */
     148             :   /* while there are two nexts */
     149      273475 :   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
     150      182754 :     luaM_free(L, ci->next);  /* free next */
     151      182754 :     L->nci--;
     152      182754 :     ci->next = next2;  /* remove 'next' from the list */
     153      182754 :     next2->previous = ci;
     154      182754 :     ci = next2;  /* keep next's next */
     155             :   }
     156       90721 : }
     157             : 
     158             : 
     159          97 : static void stack_init (lua_State *L1, lua_State *L) {
     160             :   int i; CallInfo *ci;
     161             :   /* initialize stack array */
     162          97 :   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
     163          97 :   L1->stacksize = BASIC_STACK_SIZE;
     164        3977 :   for (i = 0; i < BASIC_STACK_SIZE; i++)
     165        3880 :     setnilvalue(L1->stack + i);  /* erase new stack */
     166          97 :   L1->top = L1->stack;
     167          97 :   L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
     168             :   /* initialize first ci */
     169          97 :   ci = &L1->base_ci;
     170          97 :   ci->next = ci->previous = NULL;
     171          97 :   ci->callstatus = 0;
     172          97 :   ci->func = L1->top;
     173          97 :   setnilvalue(L1->top++);  /* 'function' entry for this 'ci' */
     174          97 :   ci->top = L1->top + LUA_MINSTACK;
     175          97 :   L1->ci = ci;
     176          97 : }
     177             : 
     178             : 
     179          56 : static void freestack (lua_State *L) {
     180          56 :   if (L->stack == NULL)
     181           0 :     return;  /* stack not completely built yet */
     182          56 :   L->ci = &L->base_ci;  /* free the entire 'ci' list */
     183          56 :   luaE_freeCI(L);
     184             :   lua_assert(L->nci == 0);
     185          56 :   luaM_freearray(L, L->stack, L->stacksize);  /* free stack array */
     186             : }
     187             : 
     188             : 
     189             : /*
     190             : ** Create registry table and its predefined values
     191             : */
     192          97 : static void init_registry (lua_State *L, global_State *g) {
     193             :   TValue temp;
     194             :   /* create registry */
     195          97 :   Table *registry = luaH_new(L);
     196          97 :   sethvalue(L, &g->l_registry, registry);
     197          97 :   luaH_resize(L, registry, LUA_RIDX_LAST, 0);
     198             :   /* registry[LUA_RIDX_MAINTHREAD] = L */
     199          97 :   setthvalue(L, &temp, L);  /* temp = L */
     200          97 :   luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
     201             :   /* registry[LUA_RIDX_GLOBALS] = table of globals */
     202          97 :   sethvalue(L, &temp, luaH_new(L));  /* temp = new table (global table) */
     203          97 :   luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
     204          97 : }
     205             : 
     206             : 
     207             : /*
     208             : ** open parts of the state that may cause memory-allocation errors.
     209             : ** ('g->version' != NULL flags that the state was completely build)
     210             : */
     211          97 : static void f_luaopen (lua_State *L, void *ud) {
     212          97 :   global_State *g = G(L);
     213             :   UNUSED(ud);
     214          97 :   stack_init(L, L);  /* init stack */
     215          97 :   init_registry(L, g);
     216          97 :   luaS_init(L);
     217          97 :   luaT_init(L);
     218          97 :   luaX_init(L);
     219          97 :   g->gcrunning = 1;  /* allow gc */
     220          97 :   g->version = lua_version(NULL);
     221             :   luai_userstateopen(L);
     222          97 : }
     223             : 
     224             : 
     225             : /*
     226             : ** preinitialize a thread with consistent values without allocating
     227             : ** any memory (to avoid errors)
     228             : */
     229          97 : static void preinit_thread (lua_State *L, global_State *g) {
     230          97 :   G(L) = g;
     231          97 :   L->stack = NULL;
     232          97 :   L->ci = NULL;
     233          97 :   L->nci = 0;
     234          97 :   L->stacksize = 0;
     235          97 :   L->twups = L;  /* thread has no upvalues */
     236          97 :   L->errorJmp = NULL;
     237          97 :   L->nCcalls = 0;
     238          97 :   L->hook = NULL;
     239          97 :   L->hookmask = 0;
     240          97 :   L->basehookcount = 0;
     241          97 :   L->allowhook = 1;
     242          97 :   resethookcount(L);
     243          97 :   L->openupval = NULL;
     244          97 :   L->nny = 1;
     245          97 :   L->status = LUA_OK;
     246          97 :   L->errfunc = 0;
     247          97 : }
     248             : 
     249             : 
     250          56 : static void close_state (lua_State *L) {
     251          56 :   global_State *g = G(L);
     252          56 :   luaF_close(L, L->stack);  /* close all upvalues for this thread */
     253          56 :   luaC_freeallobjects(L);  /* collect all objects */
     254          56 :   if (g->version)  /* closing a fully built state? */
     255             :     luai_userstateclose(L);
     256          56 :   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
     257          56 :   freestack(L);
     258             :   lua_assert(gettotalbytes(g) == sizeof(LG));
     259          56 :   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
     260          56 : }
     261             : 
     262             : 
     263           0 : LUA_API lua_State *lua_newthread (lua_State *L) {
     264           0 :   global_State *g = G(L);
     265             :   lua_State *L1;
     266             :   lua_lock(L);
     267           0 :   luaC_checkGC(L);
     268             :   /* create new thread */
     269           0 :   L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
     270           0 :   L1->marked = luaC_white(g);
     271           0 :   L1->tt = LUA_TTHREAD;
     272             :   /* link it on list 'allgc' */
     273           0 :   L1->next = g->allgc;
     274           0 :   g->allgc = obj2gco(L1);
     275             :   /* anchor it on L stack */
     276           0 :   setthvalue(L, L->top, L1);
     277           0 :   api_incr_top(L);
     278           0 :   preinit_thread(L1, g);
     279           0 :   L1->hookmask = L->hookmask;
     280           0 :   L1->basehookcount = L->basehookcount;
     281           0 :   L1->hook = L->hook;
     282           0 :   resethookcount(L1);
     283             :   /* initialize L1 extra space */
     284           0 :   memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
     285             :          LUA_EXTRASPACE);
     286             :   luai_userstatethread(L, L1);
     287           0 :   stack_init(L1, L);  /* init stack */
     288             :   lua_unlock(L);
     289           0 :   return L1;
     290             : }
     291             : 
     292             : 
     293           0 : void luaE_freethread (lua_State *L, lua_State *L1) {
     294           0 :   LX *l = fromstate(L1);
     295           0 :   luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
     296             :   lua_assert(L1->openupval == NULL);
     297             :   luai_userstatefree(L, L1);
     298           0 :   freestack(L1);
     299           0 :   luaM_free(L, l);
     300           0 : }
     301             : 
     302             : 
     303          97 : LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
     304             :   int i;
     305             :   lua_State *L;
     306             :   global_State *g;
     307          97 :   LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
     308          97 :   if (l == NULL) return NULL;
     309          97 :   L = &l->l.l;
     310          97 :   g = &l->g;
     311          97 :   L->next = NULL;
     312          97 :   L->tt = LUA_TTHREAD;
     313          97 :   g->currentwhite = bitmask(WHITE0BIT);
     314          97 :   L->marked = luaC_white(g);
     315          97 :   preinit_thread(L, g);
     316          97 :   g->frealloc = f;
     317          97 :   g->ud = ud;
     318          97 :   g->mainthread = L;
     319          97 :   g->seed = makeseed(L);
     320          97 :   g->gcrunning = 0;  /* no GC while building state */
     321          97 :   g->GCestimate = 0;
     322          97 :   g->strt.size = g->strt.nuse = 0;
     323          97 :   g->strt.hash = NULL;
     324          97 :   setnilvalue(&g->l_registry);
     325          97 :   g->panic = NULL;
     326          97 :   g->version = NULL;
     327          97 :   g->gcstate = GCSpause;
     328          97 :   g->gckind = KGC_NORMAL;
     329          97 :   g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
     330          97 :   g->sweepgc = NULL;
     331          97 :   g->gray = g->grayagain = NULL;
     332          97 :   g->weak = g->ephemeron = g->allweak = NULL;
     333          97 :   g->twups = NULL;
     334          97 :   g->totalbytes = sizeof(LG);
     335          97 :   g->GCdebt = 0;
     336          97 :   g->gcfinnum = 0;
     337          97 :   g->gcpause = LUAI_GCPAUSE;
     338          97 :   g->gcstepmul = LUAI_GCMUL;
     339         970 :   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
     340          97 :   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
     341             :     /* memory allocation error: free partial state */
     342           0 :     close_state(L);
     343           0 :     L = NULL;
     344             :   }
     345          97 :   return L;
     346             : }
     347             : 
     348             : 
     349          56 : LUA_API void lua_close (lua_State *L) {
     350          56 :   L = G(L)->mainthread;  /* only the main thread can be closed */
     351             :   lua_lock(L);
     352          56 :   close_state(L);
     353          56 : }
     354             : 
     355             : 

Generated by: LCOV version 1.14