X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/74620ebafeb4a94b61a3747e39d27a4ec7a9fe5a..a05832ea10a61d2db9acbb5a8914a34b72e6f841:/core/nsmalloc.c diff --git a/core/nsmalloc.c b/core/nsmalloc.c index d7d093e3..901987cc 100644 --- a/core/nsmalloc.c +++ b/core/nsmalloc.c @@ -3,18 +3,16 @@ #include #include "nsmalloc.h" -#include "../core/error.h" +#define __NSMALLOC_C +#undef __NSMALLOC_H +#include "nsmalloc.h" -void *nsmalloc(unsigned int poolid, size_t size); -void nsfree(unsigned int poolid, void *ptr); -void nsfreeall(unsigned int poolid); +#include "../core/hooks.h" +#include "../core/error.h" -struct nsminfo { - struct nsminfo *next; - char data[]; -}; +struct nsmpool nsmpools[MAXPOOL]; -struct nsminfo *pools[MAXPOOL]; +#ifndef USE_NSMALLOC_VALGRIND void *nsmalloc(unsigned int poolid, size_t size) { struct nsminfo *nsmp; @@ -28,28 +26,75 @@ void *nsmalloc(unsigned int poolid, size_t size) { if (!nsmp) return NULL; - nsmp->next=pools[poolid]; - pools[poolid]=nsmp; - + nsmp->size=size; + nsmpools[poolid].size+=size; + nsmpools[poolid].count++; + + nsmp->next=nsmpools[poolid].first.next; + nsmp->prev=&nsmpools[poolid].first; + if (nsmpools[poolid].first.next) + nsmpools[poolid].first.next->prev=nsmp; + nsmpools[poolid].first.next=nsmp; + return (void *)nsmp->data; } +/* we dump core on ptr == NULL */ 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; + + /* always set as we have a sentinel */ + nsmp->prev->next=nsmp->next; + if (nsmp->next) + nsmp->next->prev=nsmp->prev; + + nsmpools[poolid].size-=nsmp->size; + nsmpools[poolid].count--; + + free(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; } - - Error("core",ERR_WARNING,"Attempt to free unknown pointer %p in pool %d\n",ptr,poolid); + + if (poolid >= MAXPOOL) + return NULL; + + /* evil */ + nsmp=(struct nsminfo *)ptr - 1; + + if (size == nsmp->size) + return (void *)nsmp->data; + + nsmpn=(struct nsminfo *)realloc(nsmp, sizeof(struct nsminfo)+size); + if (!nsmpn) + return NULL; + + nsmpools[poolid].size+=size-nsmpn->size; + nsmpn->size=size; + + /* always set as we have a sentinel */ + nsmpn->prev->next=nsmpn; + + if (nsmpn->next) + nsmpn->next->prev=nsmpn; + + return (void *)nsmpn->data; } void nsfreeall(unsigned int poolid) { @@ -58,22 +103,56 @@ void nsfreeall(unsigned int poolid) { if (poolid >= MAXPOOL) return; - for (nsmp=pools[poolid];nsmp;nsmp=nnsmp) { + for (nsmp=nsmpools[poolid].first.next;nsmp;nsmp=nnsmp) { nnsmp=nsmp->next; free(nsmp); } - pools[poolid]=NULL; + nsmpools[poolid].first.next=NULL; + nsmpools[poolid].size=0; + nsmpools[poolid].count=0; } -void nsexit() { +void nscheckfreeall(unsigned int poolid) { + if (poolid >= MAXPOOL) + return; + + if (nsmpools[poolid].first.next) { + 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 nsexit(void) { unsigned int i; - for (i=0;i