From: Chris Porter Date: Fri, 29 Feb 2008 01:15:03 +0000 (+0000) Subject: nsfree is now O(1), add nsrealloc and statistics. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/4800549612f8790dba82398f60de2a9c598c7aca nsfree is now O(1), add nsrealloc and statistics. --- diff --git a/core/nsmalloc.c b/core/nsmalloc.c index d7d093e3..ea6a216e 100644 --- a/core/nsmalloc.c +++ b/core/nsmalloc.c @@ -11,10 +11,16 @@ void nsfreeall(unsigned int poolid); struct nsminfo { struct nsminfo *next; + union { + struct nsminfo *prev; + unsigned long count; + } p; + + size_t size; char data[]; }; -struct nsminfo *pools[MAXPOOL]; +struct nsminfo pools[MAXPOOL]; void *nsmalloc(unsigned int poolid, size_t size) { struct nsminfo *nsmp; @@ -28,28 +34,75 @@ void *nsmalloc(unsigned int poolid, size_t size) { if (!nsmp) return NULL; - nsmp->next=pools[poolid]; - pools[poolid]=nsmp; - + nsmp->size=size; + pools[poolid].size+=size; + pools[poolid].p.count++; + + nsmp->next=pools[poolid].next; + nsmp->p.prev=&pools[poolid]; + if (pools[poolid].next) + pools[poolid].next->p.prev=nsmp; + pools[poolid].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) 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->p.prev->next=nsmp->next; + if (nsmp->next) + nsmp->next->p.prev=nsmp->p.prev; + + pools[poolid].size-=nsmp->size; + pools[poolid].p.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; + + pools[poolid].size+=size-nsmpn->size; + nsmpn->size=size; + + /* always set as we have a sentinel */ + nsmpn->p.prev->next=nsmpn; + + if (nsmpn->next) + nsmpn->next->p.prev=nsmpn; + + return (void *)nsmpn->data; } void nsfreeall(unsigned int poolid) { @@ -58,22 +111,33 @@ void nsfreeall(unsigned int poolid) { if (poolid >= MAXPOOL) return; - for (nsmp=pools[poolid];nsmp;nsmp=nnsmp) { + for (nsmp=pools[poolid].next;nsmp;nsmp=nnsmp) { nnsmp=nsmp->next; free(nsmp); } - pools[poolid]=NULL; + pools[poolid].next=NULL; + pools[poolid].size=0; + pools[poolid].p.count=0; } void nsexit() { unsigned int i; for (i=0;i= MAXPOOL) + return 0; + + *size = pools[poolid].size; + *count = pools[poolid].p.count; + + return 1; +} diff --git a/core/nsmalloc.h b/core/nsmalloc.h index e1bcd2dc..47d69684 100644 --- a/core/nsmalloc.h +++ b/core/nsmalloc.h @@ -6,6 +6,8 @@ void *nsmalloc(unsigned int poolid, size_t size); void nsfree(unsigned int poolid, void *ptr); void nsfreeall(unsigned int poolid); void nsexit(void); +void *nsrealloc(unsigned int poolid, void *ptr, size_t size); +int nspoolstats(unsigned int poolid, size_t *size, unsigned long *count); #define MAXPOOL 100 @@ -20,3 +22,4 @@ void nsexit(void); #define POOL_AUTHTRACKER 7 #define POOL_PROXYSCAN 8 #define POOL_LUA 9 +#define POOL_TROJANSCAN 10