mirror of
https://github.com/lua/lua
synced 2024-12-24 03:16:50 +03:00
Lua kernel does not use malloc/free functions.
This commit is contained in:
parent
c7cf92e6f3
commit
b97fb932ec
19
lauxlib.c
19
lauxlib.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.c,v 1.102 2003/05/16 18:59:08 roberto Exp roberto $
|
||||
** $Id: lauxlib.c,v 1.103 2003/10/01 16:50:53 roberto Exp roberto $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -9,6 +9,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@ -558,6 +559,22 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||
(void)ud;
|
||||
if (nsize == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return realloc(ptr, nsize);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_State *luaL_newstate (void) {
|
||||
return lua_newstate(l_alloc, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** compatibility code
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.59 2003/03/18 12:25:32 roberto Exp roberto $
|
||||
** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp roberto $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -62,6 +62,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename);
|
||||
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
65
lmem.c
65
lmem.c
@ -1,11 +1,11 @@
|
||||
/*
|
||||
** $Id: lmem.c,v 1.60 2002/11/21 14:14:42 roberto Exp roberto $
|
||||
** $Id: lmem.c,v 1.61 2002/12/04 17:38:31 roberto Exp roberto $
|
||||
** Interface to Memory Manager
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define lmem_c
|
||||
|
||||
@ -20,21 +20,23 @@
|
||||
|
||||
|
||||
/*
|
||||
** definition for realloc function. It must assure that l_realloc(NULL,
|
||||
** 0, x) allocates a new block (ANSI C assures that). (`os' is the old
|
||||
** block size; some allocators may use that.)
|
||||
** About the realloc function:
|
||||
** void * realloc (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
** (`osize' is the old size, `nsize' is the new size)
|
||||
**
|
||||
** Lua ensures that (ptr == NULL) iff (osize == 0).
|
||||
**
|
||||
** * realloc(ud, NULL, 0, x) creates a new block of size `x'
|
||||
**
|
||||
** * realloc(ud, p, x, 0) frees the block `p'
|
||||
** (in this specific case, realloc must return NULL).
|
||||
** particularly, realloc(ud, NULL, 0, 0) does nothing
|
||||
** (which is equivalent to free(NULL) in ANSI C)
|
||||
**
|
||||
** realloc returns NULL if it cannot create or reallocate the area
|
||||
** (any reallocation to an equal or smaller size cannot fail!)
|
||||
*/
|
||||
#ifndef l_realloc
|
||||
#define l_realloc(b,os,s) realloc(b,s)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** definition for free function. (`os' is the old block size; some
|
||||
** allocators may use that.)
|
||||
*/
|
||||
#ifndef l_free
|
||||
#define l_free(b,os) free(b)
|
||||
#endif
|
||||
|
||||
|
||||
#define MINSIZEARRAY 4
|
||||
@ -62,30 +64,17 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
|
||||
/*
|
||||
** generic allocation routine.
|
||||
*/
|
||||
void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
|
||||
lua_assert((oldsize == 0) == (block == NULL));
|
||||
if (size == 0) {
|
||||
if (block != NULL) {
|
||||
l_free(block, oldsize);
|
||||
block = NULL;
|
||||
}
|
||||
else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
|
||||
}
|
||||
else if (size >= MAX_SIZET)
|
||||
void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) {
|
||||
global_State *g = G(L);
|
||||
lua_assert((osize == 0) == (block == NULL));
|
||||
if (nsize >= MAX_SIZET)
|
||||
luaG_runerror(L, "memory allocation error: block too big");
|
||||
else {
|
||||
block = l_realloc(block, oldsize, size);
|
||||
if (block == NULL) {
|
||||
if (L)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
else return NULL; /* error before creating state! */
|
||||
}
|
||||
}
|
||||
if (L) {
|
||||
lua_assert(G(L) != NULL && G(L)->nblocks > 0);
|
||||
G(L)->nblocks -= oldsize;
|
||||
G(L)->nblocks += size;
|
||||
}
|
||||
block = (*g->realloc)(g->ud, block, osize, nsize);
|
||||
if (block == NULL && nsize > 0)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
lua_assert((nsize == 0) == (block == NULL));
|
||||
g->nblocks -= osize;
|
||||
g->nblocks += nsize;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
51
lstate.c
51
lstate.c
@ -1,11 +1,11 @@
|
||||
/*
|
||||
** $Id: lstate.c,v 1.125 2003/07/16 20:51:47 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 1.126 2003/09/04 20:19:07 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define lstate_c
|
||||
|
||||
@ -34,6 +34,11 @@ union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
|
||||
#endif
|
||||
|
||||
|
||||
#define state_size(x) (sizeof(x) + EXTRASPACE)
|
||||
#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + EXTRASPACE))
|
||||
#define fromstate(l) (cast(lu_byte *, (l)) - EXTRASPACE)
|
||||
|
||||
|
||||
/*
|
||||
** Main thread combines a thread state and the global state
|
||||
*/
|
||||
@ -44,23 +49,6 @@ typedef struct LG {
|
||||
|
||||
|
||||
|
||||
|
||||
static lua_State *mallocstate (lua_State *L, size_t size) {
|
||||
lu_byte *block = (lu_byte *)luaM_malloc(L, size + EXTRASPACE);
|
||||
if (block == NULL) return NULL;
|
||||
else {
|
||||
block += EXTRASPACE;
|
||||
return cast(lua_State *, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void freestate (lua_State *L, lua_State *L1, size_t size) {
|
||||
luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
|
||||
size + EXTRASPACE);
|
||||
}
|
||||
|
||||
|
||||
static void stack_init (lua_State *L1, lua_State *L) {
|
||||
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
||||
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
|
||||
@ -122,20 +110,21 @@ static void preinit_state (lua_State *L) {
|
||||
|
||||
|
||||
static void close_state (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
luaC_sweep(L, 1); /* collect all elements */
|
||||
lua_assert(G(L)->rootgc == NULL);
|
||||
lua_assert(G(L)->rootudata == NULL);
|
||||
lua_assert(g->rootgc == NULL);
|
||||
lua_assert(g->rootudata == NULL);
|
||||
luaS_freeall(L);
|
||||
luaZ_freebuffer(L, &G(L)->buff);
|
||||
luaZ_freebuffer(L, &g->buff);
|
||||
freestack(L, L);
|
||||
lua_assert(G(L)->nblocks == sizeof(LG));
|
||||
freestate(NULL, L, sizeof(LG));
|
||||
lua_assert(g->nblocks == sizeof(LG));
|
||||
(*g->realloc)(g->ud, fromstate(L), state_size(LG), 0);
|
||||
}
|
||||
|
||||
|
||||
lua_State *luaE_newthread (lua_State *L) {
|
||||
lua_State *L1 = mallocstate(L, sizeof(lua_State));
|
||||
lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
|
||||
luaC_link(L, valtogco(L1), LUA_TTHREAD);
|
||||
preinit_state(L1);
|
||||
L1->l_G = L->l_G;
|
||||
@ -149,20 +138,24 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
|
||||
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
|
||||
lua_assert(L1->openupval == NULL);
|
||||
freestack(L, L1);
|
||||
freestate(L, L1, sizeof(lua_State));
|
||||
luaM_free(L, fromstate(L1), state_size(lua_State));
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_State *lua_open (void) {
|
||||
lua_State *L = mallocstate(NULL, sizeof(LG));
|
||||
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||
lua_State *L;
|
||||
global_State *g;
|
||||
if (L == NULL) return NULL;
|
||||
void *l = (*f)(ud, NULL, 0, state_size(LG));
|
||||
if (l == NULL) return NULL;
|
||||
L = tostate(l);
|
||||
g = &((LG *)L)->g;
|
||||
L->tt = LUA_TTHREAD;
|
||||
L->marked = 0;
|
||||
L->next = L->gclist = NULL;
|
||||
preinit_state(L);
|
||||
L->l_G = g;
|
||||
g->realloc = f;
|
||||
g->ud = ud;
|
||||
g->mainthread = L;
|
||||
g->GCthreshold = 0; /* mark it as unfinished state */
|
||||
g->strt.size = 0;
|
||||
|
4
lstate.h
4
lstate.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstate.h,v 1.110 2003/04/28 19:26:16 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 1.111 2003/07/16 20:49:02 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -101,6 +101,8 @@ typedef struct global_State {
|
||||
GCObject *rootgc; /* list of (almost) all collectable objects */
|
||||
GCObject *rootudata; /* (separated) list of all userdata */
|
||||
GCObject *tmudata; /* list of userdata to be GC */
|
||||
lua_Alloc realloc; /* function to reallocate memory */
|
||||
void *ud; /* auxiliary data to `realloc' */
|
||||
Mbuffer buff; /* temporary buffer for string concatentation */
|
||||
lu_mem GCthreshold;
|
||||
lu_mem nblocks; /* number of `bytes' currently allocated */
|
||||
|
47
ltests.c
47
ltests.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltests.c,v 1.162 2003/07/09 12:08:43 roberto Exp roberto $
|
||||
** $Id: ltests.c,v 1.163 2003/07/29 19:26:34 roberto Exp roberto $
|
||||
** Internal Module for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -80,10 +80,8 @@ static void setnameval (lua_State *L, const char *name, int val) {
|
||||
#define fillmem(mem,size) /* empty */
|
||||
#endif
|
||||
|
||||
unsigned long memdebug_numblocks = 0;
|
||||
unsigned long memdebug_total = 0;
|
||||
unsigned long memdebug_maxmem = 0;
|
||||
unsigned long memdebug_memlimit = ULONG_MAX;
|
||||
|
||||
Memcontrol memcontrol = {0L, 0L, 0L, ULONG_MAX};
|
||||
|
||||
|
||||
static void *checkblock (void *block, size_t size) {
|
||||
@ -95,27 +93,26 @@ static void *checkblock (void *block, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
static void freeblock (void *block, size_t size) {
|
||||
static void freeblock (Memcontrol *mc, void *block, size_t size) {
|
||||
if (block) {
|
||||
lua_assert(checkblocksize(block, size));
|
||||
block = checkblock(block, size);
|
||||
fillmem(block, size+HEADER+MARKSIZE); /* erase block */
|
||||
free(block); /* free original block */
|
||||
memdebug_numblocks--;
|
||||
memdebug_total -= size;
|
||||
mc->numblocks--;
|
||||
mc->total -= size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *debug_realloc (void *block, size_t oldsize, size_t size) {
|
||||
void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
|
||||
Memcontrol *mc = cast(Memcontrol *, ud);
|
||||
lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
|
||||
/* ISO does not specify what realloc(NULL, 0) does */
|
||||
lua_assert(block != NULL || size > 0);
|
||||
if (size == 0) {
|
||||
freeblock(block, oldsize);
|
||||
freeblock(mc, block, oldsize);
|
||||
return NULL;
|
||||
}
|
||||
else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit)
|
||||
else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
|
||||
return NULL; /* to test memory allocation errors */
|
||||
else {
|
||||
void *newblock;
|
||||
@ -127,14 +124,14 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) {
|
||||
if (newblock == NULL) return NULL;
|
||||
if (block) {
|
||||
memcpy(cast(char *, newblock)+HEADER, block, commonsize);
|
||||
freeblock(block, oldsize); /* erase (and check) old copy */
|
||||
freeblock(mc, block, oldsize); /* erase (and check) old copy */
|
||||
}
|
||||
/* initialize new part of the block with something `weird' */
|
||||
fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
|
||||
memdebug_total += size;
|
||||
if (memdebug_total > memdebug_maxmem)
|
||||
memdebug_maxmem = memdebug_total;
|
||||
memdebug_numblocks++;
|
||||
mc->total += size;
|
||||
if (mc->total > mc->maxmem)
|
||||
mc->maxmem = mc->total;
|
||||
mc->numblocks++;
|
||||
setsize(newblock, size);
|
||||
for (i=0;i<MARKSIZE;i++)
|
||||
*(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
|
||||
@ -260,13 +257,13 @@ static int setgcthreshold (lua_State *L) {
|
||||
|
||||
static int mem_query (lua_State *L) {
|
||||
if (lua_isnone(L, 1)) {
|
||||
lua_pushintegral(L, memdebug_total);
|
||||
lua_pushintegral(L, memdebug_numblocks);
|
||||
lua_pushintegral(L, memdebug_maxmem);
|
||||
lua_pushintegral(L, memcontrol.total);
|
||||
lua_pushintegral(L, memcontrol.numblocks);
|
||||
lua_pushintegral(L, memcontrol.maxmem);
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
memdebug_memlimit = luaL_checkint(L, 1);
|
||||
memcontrol.memlimit = luaL_checkint(L, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -830,8 +827,8 @@ static const struct luaL_reg tests_funcs[] = {
|
||||
static void fim (void) {
|
||||
if (!islocked)
|
||||
lua_close(lua_state);
|
||||
lua_assert(memdebug_numblocks == 0);
|
||||
lua_assert(memdebug_total == 0);
|
||||
lua_assert(memcontrol.numblocks == 0);
|
||||
lua_assert(memcontrol.total == 0);
|
||||
}
|
||||
|
||||
|
||||
@ -856,7 +853,7 @@ int luaB_opentests (lua_State *L) {
|
||||
int main (int argc, char *argv[]) {
|
||||
char *limit = getenv("MEMLIMIT");
|
||||
if (limit)
|
||||
memdebug_memlimit = strtoul(limit, NULL, 10);
|
||||
memcontrol.memlimit = strtoul(limit, NULL, 10);
|
||||
l_main(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
20
ltests.h
20
ltests.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltests.h,v 1.19 2002/11/19 17:42:32 roberto Exp roberto $
|
||||
** $Id: ltests.h,v 1.20 2002/12/04 17:29:05 roberto Exp roberto $
|
||||
** Internal Header for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -27,16 +27,20 @@
|
||||
|
||||
|
||||
/* memory allocator control variables */
|
||||
extern unsigned long memdebug_numblocks;
|
||||
extern unsigned long memdebug_total;
|
||||
extern unsigned long memdebug_maxmem;
|
||||
extern unsigned long memdebug_memlimit;
|
||||
typedef struct Memcontrol {
|
||||
unsigned long numblocks;
|
||||
unsigned long total;
|
||||
unsigned long maxmem;
|
||||
unsigned long memlimit;
|
||||
} Memcontrol;
|
||||
|
||||
extern Memcontrol memcontrol;
|
||||
|
||||
#define l_realloc(b, os, s) debug_realloc(b, os, s)
|
||||
#define l_free(b, os) debug_realloc(b, os, 0)
|
||||
void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
|
||||
|
||||
void *debug_realloc (void *block, size_t oldsize, size_t size);
|
||||
#ifdef lua_c
|
||||
#define luaL_newstate() lua_newstate(debug_realloc, &memcontrol)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
11
lua.h
11
lua.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lua.h,v 1.177 2003/05/15 12:20:04 roberto Exp roberto $
|
||||
** $Id: lua.h,v 1.178 2003/07/07 13:30:57 roberto Exp roberto $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
||||
** http://www.lua.org mailto:info@lua.org
|
||||
@ -56,6 +56,12 @@ typedef int (*lua_Chunkwriter) (lua_State *L, const void* p,
|
||||
size_t sz, void* ud);
|
||||
|
||||
|
||||
/*
|
||||
** prototype for memory-allocation functions
|
||||
*/
|
||||
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
|
||||
|
||||
/*
|
||||
** basic types
|
||||
*/
|
||||
@ -101,7 +107,7 @@ typedef LUA_NUMBER lua_Number;
|
||||
/*
|
||||
** state manipulation
|
||||
*/
|
||||
LUA_API lua_State *lua_open (void);
|
||||
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud);
|
||||
LUA_API void lua_close (lua_State *L);
|
||||
LUA_API lua_State *lua_newthread (lua_State *L);
|
||||
|
||||
@ -261,6 +267,7 @@ LUA_API void lua_concat (lua_State *L, int n);
|
||||
** compatibility macros and functions
|
||||
*/
|
||||
|
||||
#define lua_open() luaL_newstate()
|
||||
|
||||
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
|
||||
#define lua_setglobal(L,s) \
|
||||
|
Loading…
Reference in New Issue
Block a user