X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/34da4416e8e4a0d7c20acc39b524b679bb7e42d2..3898f97325dbed800d4b424e68a0c2858b8d8be7:/core/nsmalloc.c diff --git a/core/nsmalloc.c b/core/nsmalloc.c index 287ed003..7208b0f0 100644 --- a/core/nsmalloc.c +++ b/core/nsmalloc.c @@ -1,20 +1,20 @@ /* nsmalloc: Simple pooled malloc() thing. */ #include +#include +#include #include "nsmalloc.h" -#include "../core/error.h" - -void *nsmalloc(unsigned int poolid, size_t size); -void nsfree(unsigned int poolid, void *ptr); -void nsfreeall(unsigned int poolid); +#define __NSMALLOC_C +#undef __NSMALLOC_H +#include "nsmalloc.h" -struct nsminfo { - struct nsminfo *next; - char data[1]; -}; +#include "../lib/valgrind.h" +#include "../lib/memcheck.h" +#include "../core/hooks.h" +#include "../core/error.h" -struct nsminfo *pools[MAXPOOL]; +struct nsmpool nsmpools[MAXPOOL]; void *nsmalloc(unsigned int poolid, size_t size) { struct nsminfo *nsmp; @@ -22,35 +22,120 @@ void *nsmalloc(unsigned int poolid, size_t size) { if (poolid >= MAXPOOL) return NULL; - /* Allocate enough for the structure and the required data - but subtract - * 1 since the first byte lives in the structure */ - nsmp=(struct nsminfo *)malloc(sizeof(struct nsminfo)+(size-1)); + /* Allocate enough for the structure and the required data */ + nsmp=(struct nsminfo *)malloc(sizeof(struct nsminfo)+size); if (!nsmp) return NULL; - - nsmp->next=pools[poolid]; - pools[poolid]=nsmp; - + + VALGRIND_CREATE_MEMPOOL(nsmp, 0, 0); + + nsmp->size=size; + nsmpools[poolid].size+=size; + nsmpools[poolid].count++; + + if (nsmpools[poolid].blocks) { + nsmpools[poolid].blocks->prev = nsmp; + } + nsmp->next=nsmpools[poolid].blocks; + nsmp->prev=NULL; + nsmpools[poolid].blocks=nsmp; + + VALGRIND_MEMPOOL_ALLOC(nsmp, nsmp->data, nsmp->size); + + nsmp->redzone = REDZONE_MAGIC; + VALGRIND_MAKE_MEM_NOACCESS(&nsmp->redzone, sizeof(nsmp->redzone)); + return (void *)nsmp->data; } +void *nscalloc(unsigned int poolid, size_t nmemb, size_t size) { + size_t total = nmemb * size; + void *m; + + m = nsmalloc(poolid, total); + if(!m) + return NULL; + + memset(m, 0, total); + + return m; +} + void nsfree(unsigned int poolid, void *ptr) { - struct nsminfo *nsmp, **nsmh; + struct nsminfo *nsmp; - if (poolid >= MAXPOOL) + if (!ptr || poolid >= MAXPOOL) return; - - for (nsmh=&(pools[poolid]);*nsmh;nsmh=&((*nsmh)->next)) { - if ((void *)&((*nsmh)->data) == ptr) { - nsmp=*nsmh; - *nsmh = nsmp->next; - free(nsmp); - return; - } + + /* evil */ + nsmp=(struct nsminfo*)ptr - 1; + + VALGRIND_MAKE_MEM_DEFINED(&nsmp->redzone, sizeof(nsmp->redzone)); + assert(nsmp->redzone == REDZONE_MAGIC); + + if (nsmp->prev) { + nsmp->prev->next = nsmp->next; + } else + nsmpools[poolid].blocks = NULL; + + if (nsmp->next) { + nsmp->next->prev = nsmp->prev; } - - Error("core",ERR_WARNING,"Attempt to free unknown pointer %p in pool %d\n",ptr,poolid); + + nsmpools[poolid].size-=nsmp->size; + nsmpools[poolid].count--; + + VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data); + free(nsmp); + VALGRIND_DESTROY_MEMPOOL(nsmp); + + return; +} + +void *nsrealloc(unsigned int poolid, void *ptr, size_t size) { + struct nsminfo *nsmp, *nsmpn; + + if (ptr == NULL) + return nsmalloc(poolid, size); + + if (size == 0) { + nsfree(poolid, ptr); + return NULL; + } + + if (poolid >= MAXPOOL) + return NULL; + + /* evil */ + nsmp=(struct nsminfo *)ptr - 1; + + VALGRIND_MAKE_MEM_DEFINED(nsmp, sizeof(struct nsminfo)); + + if (size == nsmp->size) + return (void *)nsmp->data; + + nsmpn=(struct nsminfo *)realloc(nsmp, sizeof(struct nsminfo)+size); + if (!nsmpn) + return NULL; + + VALGRIND_MOVE_MEMPOOL(nsmp, nsmpn); + + nsmpools[poolid].size+=size-nsmpn->size; + nsmpn->size=size; + + if (nsmpn->prev) { + nsmpn->prev->next=nsmpn; + } else + nsmpools[poolid].blocks = nsmpn; + + if (nsmpn->next) { + nsmpn->next->prev=nsmpn; + } + + VALGRIND_MEMPOOL_CHANGE(nsmpn, nsmp->data, nsmpn->data, nsmpn->size); + + return (void *)nsmpn->data; } void nsfreeall(unsigned int poolid) { @@ -59,11 +144,36 @@ void nsfreeall(unsigned int poolid) { if (poolid >= MAXPOOL) return; - for (nsmp=pools[poolid];nsmp;nsmp=nnsmp) { + for (nsmp=nsmpools[poolid].blocks;nsmp;nsmp=nnsmp) { nnsmp=nsmp->next; + VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data); free(nsmp); + VALGRIND_DESTROY_MEMPOOL(nsmp); } - pools[poolid]=NULL; + nsmpools[poolid].blocks=NULL; + nsmpools[poolid].size=0; + nsmpools[poolid].count=0; +} + +void nscheckfreeall(unsigned int poolid) { + if (poolid >= MAXPOOL) + return; + + if (nsmpools[poolid].blocks) { + Error("core",ERR_INFO,"nsmalloc: Blocks still allocated in pool #%d (%s): %zub, %lu items",poolid,nsmpoolnames[poolid]?nsmpoolnames[poolid]:"??",nsmpools[poolid].size,nsmpools[poolid].count); + nsfreeall(poolid); + } +} + +void nsinit(void) { + memset(nsmpools, 0, sizeof(nsmpools)); +} + +void nsexit(void) { + unsigned int i; + + for (i=0;i