From 1537d6680bb66dc2484e11815bc2cd0e31ca39cc Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 26 Feb 2021 11:41:02 -0300 Subject: New control for reentrancy of emergency collections Instead of assuming that shrinking a block may be an emergency collection, use an explicit field ('gcstopem') to stop emergency collections while GC is working. --- lmem.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'lmem.c') diff --git a/lmem.c b/lmem.c index e90f991a..9029d588 100644 --- a/lmem.c +++ b/lmem.c @@ -24,12 +24,12 @@ #if defined(EMERGENCYGCTESTS) /* -** First allocation will fail whenever not building initial state -** and not shrinking a block. (This fail will trigger 'tryagain' and -** a full GC cycle at every allocation.) +** First allocation will fail whenever not building initial state. +** (This fail will trigger 'tryagain' and a full GC cycle at every +** allocation.) */ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { - if (completestate(g) && ns > os) + if (completestate(g) && ns > 0) /* frees never fail */ return NULL; /* fail */ else /* normal allocation */ return (*g->frealloc)(g->ud, block, os, ns); @@ -138,15 +138,17 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { /* -** In case of allocation fail, this function will call the GC to try -** to free some memory and then try the allocation again. -** (It should not be called when shrinking a block, because then the -** interpreter may be in the middle of a collection step.) +** In case of allocation fail, this function will do an emergency +** collection to free some memory and then try the allocation again. +** The GC should not be called while state is not fully built, as the +** collector is not yet fully initialized. Also, it should not be called +** when 'gcstopem' is true, because then the interpreter is in the +** middle of a collection step. */ static void *tryagain (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); - if (completestate(g)) { /* is state fully build? */ + if (completestate(g) && !g->gcstopem) { luaC_fullgc(L, 1); /* try to free some memory... */ return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ } @@ -156,8 +158,6 @@ static void *tryagain (lua_State *L, void *block, /* ** Generic allocation routine. -** If allocation fails while shrinking a block, do not try again; the -** GC shrinks some blocks and it is not reentrant. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { void *newblock; @@ -165,8 +165,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { lua_assert((osize == 0) == (block == NULL)); newblock = firsttry(g, block, osize, nsize); if (l_unlikely(newblock == NULL && nsize > 0)) { - if (nsize > osize) /* not shrinking a block? */ - newblock = tryagain(L, block, osize, nsize); + newblock = tryagain(L, block, osize, nsize); if (newblock == NULL) /* still no memory? */ return NULL; /* do not update 'GCdebt' */ } -- cgit v1.2.3-55-g6feb