]> jfr.im git - irc/quakenet/newserv.git/blobdiff - core/nsmalloc.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / core / nsmalloc.c
index ea6a216e08789d4b575e9fdcb6050f8d24e2ee8c..801d02daed506069c5f69790965b0c7afa740d47 100644 (file)
@@ -1,26 +1,20 @@
 /* nsmalloc: Simple pooled malloc() thing. */
 
 #include <stdlib.h>
+#include <string.h>
+#include <assert.h>
 
 #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);
-
-struct nsminfo {
-  struct nsminfo *next;
-  union {
-    struct nsminfo *prev;
-    unsigned long count;
-  } p;
+#define __NSMALLOC_C
+#undef __NSMALLOC_H
+#include "nsmalloc.h"
 
-  size_t size;
-  char data[];
-};
+#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;
@@ -33,39 +27,70 @@ void *nsmalloc(unsigned int poolid, size_t size) {
 
   if (!nsmp)
     return NULL;
-  
+
+  VALGRIND_CREATE_MEMPOOL(nsmp, 0, 0);
+
   nsmp->size=size;
-  pools[poolid].size+=size;
-  pools[poolid].p.count++;
+  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;
 
-  nsmp->next=pools[poolid].next;
-  nsmp->p.prev=&pools[poolid];
-  if (pools[poolid].next)
-    pools[poolid].next->p.prev=nsmp;
-  pools[poolid].next=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;
 }
 
-/* we dump core on ptr == NULL */
+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;
   
-  if (poolid >= MAXPOOL)
+  if (!ptr || poolid >= MAXPOOL)
     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;
+  VALGRIND_MAKE_MEM_DEFINED(&nsmp->redzone, sizeof(nsmp->redzone));
+  assert(nsmp->redzone == REDZONE_MAGIC);
 
-  pools[poolid].size-=nsmp->size;
-  pools[poolid].p.count--;
+  if (nsmp->prev) {
+    nsmp->prev->next = nsmp->next;
+  } else
+    nsmpools[poolid].blocks = NULL;
+
+  if (nsmp->next) {
+    nsmp->next->prev = nsmp->prev;
+  }
 
+  nsmpools[poolid].size-=nsmp->size;
+  nsmpools[poolid].count--;
+
+  VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data);
+
+  VALGRIND_DESTROY_MEMPOOL(nsmp);
   free(nsmp);
+
   return;
 }
 
@@ -86,6 +111,8 @@ void *nsrealloc(unsigned int poolid, void *ptr, size_t size) {
   /* evil */
   nsmp=(struct nsminfo *)ptr - 1;
 
+  VALGRIND_MAKE_MEM_DEFINED(nsmp, sizeof(struct nsminfo));
+
   if (size == nsmp->size)
     return (void *)nsmp->data;
 
@@ -93,14 +120,21 @@ void *nsrealloc(unsigned int poolid, void *ptr, size_t size) {
   if (!nsmpn)
     return NULL;
 
-  pools[poolid].size+=size-nsmpn->size;
+  VALGRIND_MOVE_MEMPOOL(nsmp, nsmpn);
+
+  nsmpools[poolid].size+=size-nsmpn->size;
   nsmpn->size=size;
 
-  /* always set as we have a sentinel */
-  nsmpn->p.prev->next=nsmpn;
+  if (nsmpn->prev) {
+    nsmpn->prev->next=nsmpn;
+  } else
+    nsmpools[poolid].blocks = nsmpn;
 
-  if (nsmpn->next)
-    nsmpn->next->p.prev=nsmpn;
+  if (nsmpn->next) {
+    nsmpn->next->prev=nsmpn;
+  }
+
+  VALGRIND_MEMPOOL_CHANGE(nsmpn, nsmp->data, nsmpn->data, nsmpn->size);
 
   return (void *)nsmpn->data;
 }
@@ -111,33 +145,37 @@ void nsfreeall(unsigned int poolid) {
   if (poolid >= MAXPOOL)
     return;
  
-  for (nsmp=pools[poolid].next;nsmp;nsmp=nnsmp) {
+  for (nsmp=nsmpools[poolid].blocks;nsmp;nsmp=nnsmp) {
     nnsmp=nsmp->next;
+    VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data);
+
+    VALGRIND_DESTROY_MEMPOOL(nsmp);
     free(nsmp);
   }
   
-  pools[poolid].next=NULL;
-  pools[poolid].size=0;
-  pools[poolid].p.count=0;
+  nsmpools[poolid].blocks=NULL;
+  nsmpools[poolid].size=0;
+  nsmpools[poolid].count=0;
 }
 
-void nsexit() {
-  unsigned int i;
-  
-  for (i=0;i<MAXPOOL;i++) {
-    if (pools[i].next) {
-      Error("core",ERR_INFO,"nsmalloc: Blocks still allocated in pool #%d (%lub, %lu items)\n",i,pools[i].size, pools[i].p.count);
-      nsfreeall(i);
-    }
+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);
   }
 }
 
-int nspoolstats(unsigned int poolid, size_t *size, unsigned long *count) {
-  if (poolid >= MAXPOOL)
-    return 0;
-
-  *size = pools[poolid].size;
-  *count = pools[poolid].p.count;
+void nsinit(void) {
+  memset(nsmpools, 0, sizeof(nsmpools));
+}
 
-  return 1;
+void nsexit(void) {
+  unsigned int i;
+  
+  for (i=0;i<MAXPOOL;i++)
+    nsfreeall(i);
 }
+