diff options
author | Robin Watts <Robin.Watts@artifex.com> | 2011-05-17 22:33:15 +0100 |
---|---|---|
committer | Robin Watts <Robin.Watts@artifex.com> | 2011-05-17 22:38:09 +0100 |
commit | 8d9bc767c0c59a7effa7652cbcbde14ab82de249 (patch) | |
tree | 3e827a8d3ba75b730786c1bc80f5286b1562ce91 | |
parent | cbe9dcfc93812aae26ffd5c2bebbe5b2dc1a4623 (diff) |
Make Memento work with valgrind, plus fix unix build issues.
Various fixes for Memento, most especially to ensure it works with
Valgrind (lots of valgrind calls to make memory readable/hide it again).
No cluster differences expected.
-rw-r--r-- | gs/base/lib.mak | 2 | ||||
-rw-r--r-- | gs/base/memento.c | 258 | ||||
-rw-r--r-- | gs/base/memento.h | 36 | ||||
-rw-r--r-- | gs/base/unix-aux.mak | 2 |
4 files changed, 200 insertions, 98 deletions
diff --git a/gs/base/lib.mak b/gs/base/lib.mak index ae1043a37..2f3f1fff9 100644 --- a/gs/base/lib.mak +++ b/gs/base/lib.mak @@ -261,7 +261,7 @@ $(GLOBJ)gsargs.$(OBJ) : $(GLSRC)gsargs.c\ $(GLCC) $(GLO_)gsargs.$(OBJ) $(C_) $(GLSRC)gsargs.c $(GLOBJ)gsmisc.$(OBJ) : $(GLSRC)gsmisc.c $(GXERR)\ - $(vmsmath_h)\ + $(vmsmath_h) $(memento_h)\ $(ctype__h) $(malloc__h) $(math__h) $(memory__h) $(string__h)\ $(gpcheck_h) $(gserror_h) $(gxfarith_h) $(gxfixed_h) $(stdint__h) $(stdio__h) $(GLCC) $(GLO_)gsmisc.$(OBJ) $(C_) $(GLSRC)gsmisc.c diff --git a/gs/base/memento.c b/gs/base/memento.c index 014484a75..92bf0ca27 100644 --- a/gs/base/memento.c +++ b/gs/base/memento.c @@ -22,8 +22,17 @@ void MEMENTO_UNDERLYING_FREE(void *); void *MEMENTO_UNDERLYING_REALLOC(void *,size_t); void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t); +/* And some other standard functions we use. We don't include the header + * files, just in case they pull in unexpected others. */ +int atoi(const char *); +char *getenv(const char *); +void *memset(void *,unsigned char,size_t); +int atexit(void (*)(void)); + #ifdef MEMENTO +#include "valgrind.h" + enum { Memento_PreSize = 16, Memento_PostSize = 16 @@ -60,6 +69,8 @@ static struct { int countdown; int lastChecked; int breakAt; + int failAt; + int failing; size_t alloc; size_t peakAlloc; size_t totalAlloc; @@ -93,12 +104,21 @@ void Memento_breakpoint(void) #endif } -static void Memento_addBlock(Memento_Blocks *blks, Memento_BlkHeader *b) +static void Memento_addBlock(Memento_Blocks *blks, + Memento_BlkHeader *b, + int type) { b->next = blks->head; blks->head = b; memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize); memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize); + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize); + if (type == 0) { /* malloc */ + VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize); + } else if (type == 1) { /* free */ + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize); + } + VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader)); } typedef struct BlkCheckData { @@ -115,7 +135,6 @@ static int Memento_Internal_checkAllocedBlock(Memento_BlkHeader *b, void *arg) char *p; int corrupt = 0; BlkCheckData *data = (BlkCheckData *)arg; - int res = 0; p = b->preblk; i = Memento_PreSize; @@ -163,38 +182,34 @@ static void Memento_removeBlock(Memento_Blocks *blks, const char *listName, Memento_BlkHeader *b) { - Memento_BlkHeader **head = &blks->head; - while ((*head) && (*head != b)) { - head = &(*head)->next; - } - if (*head == NULL) { - /* FAIL! Will have been reported to user earlier, so just exit. */ - return; - } - (*head) = (*head)->next; -} - -static void Memento_touchBlock(Memento_Blocks *blks, - const char *listName, - Memento_BlkHeader *b) -{ Memento_BlkHeader *head = blks->head; - while (head && (head != b)) { - head = head->next; + Memento_BlkHeader *prev = NULL; + while ((head) && (head != b)) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + prev = head; + head = head->next; + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); } if (head == NULL) { - /* FAIL! */ - /* FIXME: Check the free list */ - fprintf(stderr, "Block %x not in %s list!\n", MEMBLK_TOBLK(b), listName); - Memento_breakpoint(); + /* FAIL! Will have been reported to user earlier, so just exit. */ return; } - Memento_Internal_checkBlock(b, NULL); + if (prev == NULL) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + blks->head = head->next; + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head)); + } else { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev)); + prev->next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head)); + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); + } } static int Memento_Internal_makeSpace(size_t space) { - Memento_BlkHeader **head, **next; + Memento_BlkHeader *head, *prev; size_t listSize = globals.freeListSize; /* If too big, it can never go on the freelist */ if (space > MEMENTO_FREELIST_MAX) @@ -207,21 +222,32 @@ static int Memento_Internal_makeSpace(size_t space) } /* We need to bin some entries from the list */ listSize = MEMENTO_FREELIST_MAX-space; - head = &globals.free.head; - while (*head && listSize != 0) { - if (listSize < MEMBLK_SIZE((*head)->rawsize)) { + head = globals.free.head; + prev = NULL; + while (head && listSize != 0) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + if (listSize < MEMBLK_SIZE(head->rawsize)) { break; } - listSize -= MEMBLK_SIZE((*head)->rawsize); - head = &(*head)->next; + listSize -= MEMBLK_SIZE(head->rawsize); + prev = head; + head = head->next; + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); } /* Free all blocks forwards from here */ - *head = NULL; - while (*head) { - next = &(*head)->next; - globals.freeListSize -= MEMBLK_SIZE((*head)->rawsize); - MEMENTO_UNDERLYING_FREE((*head)); - head = next; + if (prev == NULL) { + globals.free.head = NULL; + } else { + VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev)); + prev->next = NULL; + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); + } + while (head) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + prev = head; + head = prev->next; + globals.freeListSize -= MEMBLK_SIZE(prev->rawsize); + MEMENTO_UNDERLYING_FREE(prev); } return 1; } @@ -232,12 +258,19 @@ static int Memento_appBlocks(Memento_Blocks *blks, void *arg) { Memento_BlkHeader *head = blks->head; + Memento_BlkHeader *next; int result; while (head) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head), + head->rawsize + Memento_PostSize); result = app(head, arg); + next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader)); if (result) return result; - head = head->next; + head = next; } return 0; } @@ -249,12 +282,22 @@ static int Memento_appBlock(Memento_Blocks *blks, Memento_BlkHeader *b) { Memento_BlkHeader *head = blks->head; + Memento_BlkHeader *next; int result; while (head && head != b) { - head = head->next; + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + head = next; } if (head == b) { - return app(head, arg); + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head), + head->rawsize + Memento_PostSize); + result = app(head, arg); + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader)); + return result; } return 0; } @@ -270,7 +313,7 @@ static int Memento_listBlock(Memento_BlkHeader *b, return 0; } -void Memento_listBlocks(void) { +static void Memento_listBlocks(void) { int counts[2]; counts[0] = 0; counts[1] = 0; @@ -282,6 +325,7 @@ void Memento_listBlocks(void) { static void Memento_fin(void) { + Memento_checkAllMemory(); fprintf(stderr, "Total memory malloced = %d bytes\n", globals.totalAlloc); fprintf(stderr, "Peak memory malloced = %d bytes\n", globals.peakAlloc); fprintf(stderr, "%d mallocs, %d frees, %d reallocs\n", globals.numMallocs, @@ -296,13 +340,25 @@ static void Memento_fin(void) static void Memento_init(void) { + char *env; memset(&globals, 0, sizeof(globals)); globals.inited = 1; globals.used.head = NULL; globals.free.head = NULL; globals.sequence = 1; - globals.paranoia = 1024; globals.countdown = 1024; + + env = getenv("MEMENTO_FAILAT"); + globals.failAt = (env ? atoi(env) : 0); + + env = getenv("MEMENTO_PARANOIA"); + globals.paranoia = (env ? atoi(env) : 0); + if (globals.paranoia == 0) + globals.paranoia = 1024; + + env = getenv("MEMENTO_PARANOIDAT"); + globals.paranoidAt = (env ? atoi(env) : 0); + atexit(Memento_fin); } @@ -313,6 +369,10 @@ static void Memento_event(void) globals.paranoia = 1; globals.countdown = 1; } + if ((globals.sequence == globals.failAt) && + (globals.sequence != 0)) { + globals.failing = 1; + } if (--globals.countdown == 0) { Memento_checkAllMemory(); @@ -324,15 +384,15 @@ static void Memento_event(void) Memento_breakpoint(); } -void Memento_breakAt(int event) +int Memento_breakAt(int event) { globals.breakAt = event; + return event; } void *Memento_malloc(size_t s) { Memento_BlkHeader *memblk; - int *blk; size_t smem = MEMBLK_SIZE(s); if (!globals.inited) @@ -340,6 +400,9 @@ void *Memento_malloc(size_t s) Memento_event(); + if (globals.failing) + return NULL; + if (s == 0) return NULL; @@ -356,7 +419,7 @@ void *Memento_malloc(size_t s) memblk->rawsize = s; memblk->sequence = globals.sequence; memblk->lastCheckedOK = memblk->sequence; - Memento_addBlock(&globals.used, memblk); + Memento_addBlock(&globals.used, memblk, 0); return MEMBLK_TOBLK(memblk); } @@ -402,7 +465,6 @@ static int checkBlock(Memento_BlkHeader *memblk, const char *action) void Memento_free(void *blk) { Memento_BlkHeader *memblk; - int res; if (!globals.inited) Memento_init(); @@ -413,18 +475,23 @@ void Memento_free(void *blk) return; memblk = MEMBLK_FROMBLK(blk); - + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); if (checkBlock(memblk, "free")) return; + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); globals.alloc -= memblk->rawsize; globals.numFrees++; Memento_removeBlock(&globals.used, "allocated", memblk); + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); if (Memento_Internal_makeSpace(MEMBLK_SIZE(memblk->rawsize))) { - Memento_addBlock(&globals.free, memblk); + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(memblk), + memblk->rawsize + Memento_PostSize); memset(MEMBLK_TOBLK(memblk), MEMENTO_FREEFILL, memblk->rawsize); + Memento_addBlock(&globals.free, memblk, 1); } else { MEMENTO_UNDERLYING_FREE(memblk); } @@ -444,6 +511,8 @@ void *Memento_realloc(void *blk, size_t newsize) Memento_free(blk); return NULL; } + if (globals.failing) + return NULL; memblk = MEMBLK_FROMBLK(blk); @@ -458,7 +527,7 @@ void *Memento_realloc(void *blk, size_t newsize) newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem); if (newmemblk == NULL) { - Memento_addBlock(&globals.used, memblk); + Memento_addBlock(&globals.used, memblk, 2); return NULL; } globals.numReallocs++; @@ -467,25 +536,26 @@ void *Memento_realloc(void *blk, size_t newsize) globals.alloc += newsize; if (globals.peakAlloc < globals.alloc) globals.peakAlloc = globals.alloc; - if (newmemblk->rawsize < newsize) - memset(((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize, - MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize); + if (newmemblk->rawsize < newsize) { + char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize; + memset(newbytes, MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize); + VALGRIND_MAKE_MEM_UNDEFINED(newbytes, newsize - newmemblk->rawsize); + } newmemblk->rawsize = newsize; - Memento_addBlock(&globals.used, newmemblk); memset(newmemblk->preblk, MEMENTO_PREFILL, Memento_PreSize); memset(MEMBLK_POSTPTR(newmemblk), MEMENTO_POSTFILL, Memento_PostSize); + Memento_addBlock(&globals.used, newmemblk, 2); return MEMBLK_TOBLK(newmemblk); } -void Memento_checkBlock(void *blk) +int Memento_checkBlock(void *blk) { Memento_BlkHeader *memblk; if (blk == NULL) - return; + return 0; memblk = MEMBLK_FROMBLK(blk); - if (checkBlock(memblk, "check")) - return; + return checkBlock(memblk, "check"); } static int Memento_Internal_checkAllAlloced(Memento_BlkHeader *memblk, void *arg) @@ -556,25 +626,30 @@ static int Memento_Internal_checkAllFreed(Memento_BlkHeader *memblk, void *arg) return 0; } -void Memento_checkAllMemory(void) +int Memento_checkAllMemory(void) { BlkCheckData data; memset(&data, 0, sizeof(data)); Memento_appBlocks(&globals.used, Memento_Internal_checkAllAlloced, &data); Memento_appBlocks(&globals.free, Memento_Internal_checkAllFreed, &data); - if (data.found & 6) + if (data.found & 6) { Memento_breakpoint(); + return 1; + } + return 0; } -void Memento_setParanoia(int i) +int Memento_setParanoia(int i) { globals.paranoia = i; + return i; } -void Memento_paranoidAt(int i) +int Memento_paranoidAt(int i) { globals.paranoidAt = i; + return i; } int Memento_getBlockNum(void *b) @@ -586,11 +661,14 @@ int Memento_getBlockNum(void *b) return (memblk->sequence); } -void Memento_check(void) +int Memento_check(void) { + int result; + fprintf(stderr, "Checking memory\n"); - Memento_checkAllMemory(); + result = Memento_checkAllMemory(); fprintf(stderr, "Memory checked!\n"); + return result; } typedef struct findBlkData { @@ -605,7 +683,7 @@ static int Memento_containsAddr(Memento_BlkHeader *b, findBlkData *data = (findBlkData *)arg; char *blkend = &((char *)MEMBLK_TOBLK(b))[b->rawsize]; if ((MEMBLK_TOBLK(b) <= data->addr) && - (blkend > data->addr)) { + ((void *)blkend > data->addr)) { data->blk = b; data->flags = 1; return 1; @@ -616,8 +694,8 @@ static int Memento_containsAddr(Memento_BlkHeader *b, data->flags = 2; return 1; } - if ((blkend <= data->addr) && - (blkend + Memento_PostSize > data->addr)) { + if (((void *)blkend <= data->addr) && + ((void *)(blkend + Memento_PostSize) > data->addr)) { data->blk = b; data->flags = 3; return 1; @@ -625,7 +703,7 @@ static int Memento_containsAddr(Memento_BlkHeader *b, return 0; } -void Memento_find(void *a) +int Memento_find(void *a) { findBlkData data; @@ -634,24 +712,34 @@ void Memento_find(void *a) data.flags = 0; Memento_appBlocks(&globals.used, Memento_containsAddr, &data); if (data.blk != NULL) { - fprintf(stderr, "Address %x is in %sallocated block %x(%d)\n", + fprintf(stderr, "Address %x is in %sallocated block %x(size=%d,num=%d)\n", data.addr, (data.flags == 1 ? "" : (data.flags == 2 ? "preguard of " : "postguard of ")), - data.blk, data.blk->rawsize); - return; + MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence); + return data.blk->sequence; } data.blk = NULL; data.flags = 0; Memento_appBlocks(&globals.free, Memento_containsAddr, &data); if (data.blk != NULL) { - fprintf(stderr, "Address %x is in %sfreed block %x(%d)\n", + fprintf(stderr, "Address %x is in %sfreed block %x(size=%d,num=%d)\n", data.addr, (data.flags == 1 ? "" : (data.flags == 2 ? "preguard of " : "postguard of ")), - data.blk, data.blk->rawsize); - return; + MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence); + return data.blk->sequence; } + return 0; +} + +int Memento_failAt(int i) +{ + globals.failAt = i; + if ((globals.sequence > globals.failAt) && + (globals.failing != 0)) + globals.failing = 1; + return i; } #else @@ -661,28 +749,34 @@ void (Memento_breakpoint)(void) { } -void (Memento_checkBlock)(void *b) +int (Memento_checkBlock)(void *b) { + return 0; } -void (Memento_checkAllMemory)(void) +int (Memento_checkAllMemory)(void) { + return 0; } -void (Memento_check)(void) +int (Memento_check)(void) { + return 0; } -void (Memento_setParanoia)(int i) +int (Memento_setParanoia)(int i) { + return 0; } -void (Memento_paranoidAt)(int i) +int (Memento_paranoidAt)(int i) { + return 0; } -void (Memento_breakAt)(int i) +int (Memento_breakAt)(int i) { + return 0; } int (Memento_getBlockNum)(void *i) @@ -690,8 +784,14 @@ int (Memento_getBlockNum)(void *i) return 0; } -void (Memento_find)(void *a) +int (Memento_find)(void *a) { + return 0; +} + +int (Memento_failAt)(int i) +{ + return 0; } #undef Memento_malloc diff --git a/gs/base/memento.h b/gs/base/memento.h index bf6462385..7133c933a 100644 --- a/gs/base/memento.h +++ b/gs/base/memento.h @@ -99,16 +99,17 @@ #define MEMENTO_FREELIST_MAX 0x2000000 -void Memento_checkBlock(void *); -void Memento_checkAllMemory(void); -void Memento_check(void); - -void Memento_setParanoia(int); -void Memento_paranoidAt(int); -void Memento_breakAt(int); -int Memento_getBlockNum(void *); -void Memento_find(void *a); +int Memento_checkBlock(void *); +int Memento_checkAllMemory(void); +int Memento_check(void); + +int Memento_setParanoia(int); +int Memento_paranoidAt(int); +int Memento_breakAt(int); +int Memento_getBlockNum(void *); +int Memento_find(void *a); void Memento_breakpoint(void); +int Memento_failAt(int); void *Memento_malloc(size_t s); void *Memento_realloc(void *, size_t s); @@ -131,15 +132,16 @@ void *Memento_calloc(size_t, size_t); #define Memento_realloc MEMENTO_UNDERLYING_REALLOC #define Memento_calloc MEMENTO_UNDERLYING_CALLOC -#define Memento_checkBlock(A) do {} while (0) -#define Memento_checkAllMemory() do {} while (0) -#define Memento_check() do {} while (0) -#define Memento_setParanoia(A) do {} while (0) -#define Memento_paranoidAt(A) do {} while (0) -#define Memento_breakAt(A) do {} while (0) +#define Memento_checkBlock(A) 0 +#define Memento_checkAllMemory() 0 +#define Memento_check() 0 +#define Memento_setParanoia(A) 0 +#define Memento_paranoidAt(A) 0 +#define Memento_breakAt(A) 0 #define Memento_getBlockNum(A) 0 -#define Memento_find(A) do {} while (0) -#define Memento_breakpoint(void) do {} while (0) +#define Memento_find(A) 0 +#define Memento_breakpoint() do {} while (0) +#define Memento_failAt(A) 0 #endif /* MEMENTO */ diff --git a/gs/base/unix-aux.mak b/gs/base/unix-aux.mak index 58599705f..e56c2f403 100644 --- a/gs/base/unix-aux.mak +++ b/gs/base/unix-aux.mak @@ -80,7 +80,7 @@ $(GENHT_XE): $(GLSRC)genht.c $(AK) $(GENHT_DEPS) MKROMFS_OBJS_0=$(MKROMFS_ZLIB_OBJS) $(GLOBJ)gscdefs.$(OBJ) $(GLOBJ)gsmisc.$(OBJ) \ $(GLOBJ)gpmisc.$(OBJ) $(GLOBJ)gslibctx.$(OBJ) $(GLOBJ)gp_getnv.$(OBJ) \ $(GLOBJ)gp_unix.$(OBJ) $(GLOBJ)gp_unifs.$(OBJ) $(GLOBJ)gp_unifn.$(OBJ) \ - $(GLOBJ)gp_stdia.$(OBJ) $(GLOBJ)gsutil.$(OBJ) + $(GLOBJ)gp_stdia.$(OBJ) $(GLOBJ)gsutil.$(OBJ) $(GLOBJ)memento.$(OBJ) $(MKROMFS_XE)_0: $(GLSRC)mkromfs.c $(MKROMFS_COMMON_DEPS) $(MKROMFS_OBJS_0) $(CCAUX) $(GENOPT) $(CFLAGS) $(I_)$(GLSRCDIR)$(_I) $(I_)$(GLOBJ)$(_I) $(I_)$(ZSRCDIR)$(_I) $(GLSRC)mkromfs.c $(O_)$(MKROMFS_XE)_0 $(MKROMFS_OBJS_0) -lm $(EXTRALIBS) |