summaryrefslogtreecommitdiff
path: root/rts/RtsUtils.c
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2006-12-11 12:49:50 +0000
committerIan Lynagh <igloo@earth.li>2006-12-11 12:49:50 +0000
commitd526504719676871376324858fe2073aa2011424 (patch)
treea879addf6cf10eb1f4e4c55902ea9e4b673e8cac /rts/RtsUtils.c
parent2423c249f5ca7785d0ec89eb33e72662da7561c1 (diff)
downloadhaskell-d526504719676871376324858fe2073aa2011424.tar.gz
When debugging, have the allocator help us a bit
We now check for freeing memory that isn't allocated, and overwrite memory we are about to free with 0xaa. It might be nice to also have a flag to control whether the memory actually gets free'd.
Diffstat (limited to 'rts/RtsUtils.c')
-rw-r--r--rts/RtsUtils.c111
1 files changed, 109 insertions, 2 deletions
diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c
index bf02c328fb..9f50e3a770 100644
--- a/rts/RtsUtils.c
+++ b/rts/RtsUtils.c
@@ -45,6 +45,96 @@
#endif
/* -----------------------------------------------------------------------------
+ Debugging allocator
+ -------------------------------------------------------------------------- */
+
+#if defined(DEBUG)
+
+typedef struct Allocated_ {
+ void *addr;
+ size_t len;
+ struct Allocated_ *next;
+} Allocated;
+
+static Allocated *allocs = NULL;
+
+#ifdef THREADED_RTS
+static Mutex allocator_mutex;
+#endif
+
+void
+initAllocator(void)
+{
+ Allocated *a;
+ size_t alloc_size;
+
+#ifdef THREADED_RTS
+ initMutex(&allocator_mutex);
+#endif
+ alloc_size = sizeof(Allocated);
+ if ((a = (Allocated *) malloc(alloc_size)) == NULL) {
+ /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+ MallocFailHook((W_) alloc_size, "initialising debugging allocator");
+ stg_exit(EXIT_INTERNAL_ERROR);
+ }
+ a->addr = NULL;
+ a->len = 0;
+ a->next = NULL;
+ allocs = a;
+}
+
+void
+shutdownAllocator(void)
+{
+#ifdef THREADED_RTS
+ closeMutex(&allocator_mutex);
+#endif
+}
+
+static void allocate(void *addr, size_t len) {
+ Allocated *a;
+ size_t alloc_size;
+
+ alloc_size = sizeof(Allocated);
+ if ((a = (Allocated *) malloc(alloc_size)) == NULL) {
+ /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+ MallocFailHook((W_) alloc_size, "creating info for debugging allocator");
+ stg_exit(EXIT_INTERNAL_ERROR);
+ }
+ a->addr = addr;
+ a->len = len;
+ ACQUIRE_LOCK(&allocator_mutex);
+ a->next = allocs->next;
+ allocs->next = a;
+ RELEASE_LOCK(&allocator_mutex);
+}
+
+static void deallocate(void *addr) {
+ Allocated *prev, *a;
+
+ if (addr == NULL) {
+ barf("Freeing NULL!");
+ }
+
+ ACQUIRE_LOCK(&allocator_mutex);
+ prev = allocs;
+ a = prev->next;
+ while (a != NULL) {
+ if (a->addr == addr) {
+ prev->next = a->next;
+ memset(addr, 0xaa, a->len);
+ free(a);
+ RELEASE_LOCK(&allocator_mutex);
+ return;
+ }
+ prev = a;
+ a = a->next;
+ }
+ barf("Freeing non-allocated memory at %p", addr);
+}
+#endif
+
+/* -----------------------------------------------------------------------------
Result-checking malloc wrappers.
-------------------------------------------------------------------------- */
@@ -52,12 +142,17 @@ void *
stgMallocBytes (int n, char *msg)
{
char *space;
+ size_t n2;
- if ((space = (char *) malloc((size_t) n)) == NULL) {
+ n2 = (size_t) n;
+ if ((space = (char *) malloc(n2)) == NULL) {
/* don't fflush(stdout); WORKAROUND bug in Linux glibc */
MallocFailHook((W_) n, msg); /*msg*/
stg_exit(EXIT_INTERNAL_ERROR);
}
+#if defined(DEBUG)
+ allocate(space, n2);
+#endif
return space;
}
@@ -65,12 +160,18 @@ void *
stgReallocBytes (void *p, int n, char *msg)
{
char *space;
+ size_t n2;
- if ((space = (char *) realloc(p, (size_t) n)) == NULL) {
+ n2 = (size_t) n;
+ if ((space = (char *) realloc(p, (size_t) n2)) == NULL) {
/* don't fflush(stdout); WORKAROUND bug in Linux glibc */
MallocFailHook((W_) n, msg); /*msg*/
stg_exit(EXIT_INTERNAL_ERROR);
}
+#if defined(DEBUG)
+ deallocate(p);
+ allocate(space, n2);
+#endif
return space;
}
@@ -84,6 +185,9 @@ stgCallocBytes (int n, int m, char *msg)
MallocFailHook((W_) n*m, msg); /*msg*/
stg_exit(EXIT_INTERNAL_ERROR);
}
+#if defined(DEBUG)
+ allocate(space, (size_t) n * (size_t) m);
+#endif
return space;
}
@@ -93,6 +197,9 @@ stgCallocBytes (int n, int m, char *msg)
void
stgFree(void* p)
{
+#if defined(DEBUG)
+ deallocate(p);
+#endif
free(p);
}