don't make -ddump-if-trace imply -no-recomp
[ghc-hetmet.git] / rts / RtsUtils.c
index 9f50e3a..0123531 100644 (file)
 #include <time.h>
 #endif
 
+/* HACK: On Mac OS X 10.4 (at least), time.h doesn't declare ctime_r with
+ *       _POSIX_C_SOURCE. If this is the case, we declare it ourselves.
+ */
+#if HAVE_CTIME_R && !HAVE_DECL_CTIME_R
+extern char *ctime_r(const time_t *, char *);
+#endif
+
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
@@ -86,51 +93,94 @@ initAllocator(void)
 void
 shutdownAllocator(void)
 {
+    Allocated *prev, *a;
+
+    if (allocs == NULL) {
+        barf("Allocator shutdown requested, but not initialised!");
+    }
+
 #ifdef THREADED_RTS
     closeMutex(&allocator_mutex);
 #endif
+
+    prev = allocs;
+    while (1) {
+        a = prev->next;
+        free(prev);
+        if (a == NULL) return;
+        IF_DEBUG(sanity,
+                 debugBelch("Warning: %p still allocated at shutdown\n",
+                            a->addr);)
+        prev = a;
+    }
 }
 
-static void allocate(void *addr, size_t len) {
+static void addAllocation(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);
+    if (allocs != NULL) {
+        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);
+    }
+    else {
+        /* This doesn't actually help as we haven't looked at the flags
+         * at the time that it matters (while running constructors) */
+        IF_DEBUG(sanity,
+                 debugBelch("Ignoring allocation %p %zd as allocs is NULL\n",
+                            addr, len);)
     }
-    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) {
+static void removeAllocation(void *addr, int overwrite_with_aa) {
     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;
+    if (allocs != NULL) {
+        ACQUIRE_LOCK(&allocator_mutex);
+        prev = allocs;
+        a = prev->next;
+        while (a != NULL) {
+            if (a->addr == addr) {
+                prev->next = a->next;
+                if (overwrite_with_aa) {
+                    memset(addr, 0xaa, a->len);
+                }
+                free(a);
+                RELEASE_LOCK(&allocator_mutex);
+                return;
+            }
+            prev = a;
+            a = a->next;
         }
-        prev = a;
-        a = a->next;
+        /* We would like to barf here, but we can't as conc021
+         * allocates some stuff in a constructor which then gets freed
+         * during hs_exit */
+        /* barf("Freeing non-allocated memory at %p", addr); */
+        IF_DEBUG(sanity,
+                 debugBelch("Warning: Freeing non-allocated memory at %p\n",
+                            addr);)
+        RELEASE_LOCK(&allocator_mutex);
+    }
+    else {
+        IF_DEBUG(sanity,
+                 debugBelch("Ignoring free of %p as allocs is NULL\n",
+                            addr);)
     }
-    barf("Freeing non-allocated memory at %p", addr);
 }
 #endif
 
@@ -151,7 +201,7 @@ stgMallocBytes (int n, char *msg)
       stg_exit(EXIT_INTERNAL_ERROR);
     }
 #if defined(DEBUG)
-    allocate(space, n2);
+    addAllocation(space, n2);
 #endif
     return space;
 }
@@ -169,8 +219,8 @@ stgReallocBytes (void *p, int n, char *msg)
       stg_exit(EXIT_INTERNAL_ERROR);
     }
 #if defined(DEBUG)
-    deallocate(p);
-    allocate(space, n2);
+    removeAllocation(p, 0);
+    addAllocation(space, n2);
 #endif
     return space;
 }
@@ -186,7 +236,7 @@ stgCallocBytes (int n, int m, char *msg)
       stg_exit(EXIT_INTERNAL_ERROR);
     }
 #if defined(DEBUG)
-    allocate(space, (size_t) n * (size_t) m);
+    addAllocation(space, (size_t) n * (size_t) m);
 #endif
     return space;
 }
@@ -198,7 +248,7 @@ void
 stgFree(void* p)
 {
 #if defined(DEBUG)
-  deallocate(p);
+  removeAllocation(p, 1);
 #endif
   free(p);
 }
@@ -255,14 +305,14 @@ nat stg_strlen(char *s)
    ToDo: put this somewhere sensible.
    -------------------------------------------------------------------------  */
 
-static I_ __GenSymCounter = 0;
+static HsInt __GenSymCounter = 0;
 
-I_
+HsInt
 genSymZh(void)
 {
     return(__GenSymCounter++);
 }
-I_
+HsInt
 resetGenSymZh(void) /* it's your funeral */
 {
     __GenSymCounter=0;
@@ -273,7 +323,6 @@ resetGenSymZh(void) /* it's your funeral */
    Get the current time as a string.  Used in profiling reports.
    -------------------------------------------------------------------------- */
 
-#if defined(PROFILING) || defined(DEBUG) || defined(PAR) || defined(GRAN)
 char *
 time_str(void)
 {
@@ -292,7 +341,6 @@ time_str(void)
     }
     return nowstr;
 }
-#endif
 
 /* -----------------------------------------------------------------------------
  * Reset a file handle to blocking mode.  We do this for the standard
@@ -419,3 +467,23 @@ int genericRaise(int sig) {
         return raise(sig);
 #endif
 }
+
+static void mkRtsInfoPair(char *key, char *val) {
+    /* XXX should check for "s, \s etc in key and val */
+    printf(" ,(\"%s\", \"%s\")\n", key, val);
+}
+
+void printRtsInfo(void) {
+    /* The first entry is just a hack to make it easy to get the
+     * commas right */
+    printf(" [(\"GHC RTS\", \"Yes\")\n");
+    mkRtsInfoPair("GHC version",             ProjectVersion);
+    mkRtsInfoPair("RTS way",                 RtsWay);
+    mkRtsInfoPair("Host platform",           HostPlatform);
+    mkRtsInfoPair("Build platform",          BuildPlatform);
+    mkRtsInfoPair("Target platform",         TargetPlatform);
+    mkRtsInfoPair("Compiler unregisterised", GhcUnregisterised);
+    mkRtsInfoPair("Tables next to code",     GhcEnableTablesNextToCode);
+    printf(" ]\n");
+}
+