1.0.9.39: thread stack memory leaks
[sbcl.git] / src / runtime / save.c
index 9273ce1..78a56ad 100644 (file)
 #include "genesis/static-symbols.h"
 #include "genesis/symbol.h"
 
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+#include "genesis/lutex.h"
+#endif
+
 static void
 write_lispobj(lispobj obj, FILE *file)
 {
@@ -76,10 +80,83 @@ write_bytes(FILE *file, char *addr, long bytes, os_vm_offset_t file_offset)
     return ((data - file_offset) / os_vm_page_size) - 1;
 }
 
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+/* saving lutexes in the core */
+static void **lutex_addresses;
+static long n_lutexes = 0;
+static long max_lutexes = 0;
+
+static long
+default_scan_action(lispobj *obj)
+{
+    return (sizetab[widetag_of(*obj)])(obj);
+}
+
+static long
+lutex_scan_action(lispobj *obj)
+{
+    /* note the address of the lutex */
+    if(n_lutexes >= max_lutexes) {
+        max_lutexes *= 2;
+        lutex_addresses = realloc(lutex_addresses, max_lutexes * sizeof(void *));
+        gc_assert(lutex_addresses);
+    }
+
+    lutex_addresses[n_lutexes++] = obj;
+
+    return (*sizetab[widetag_of(*obj)])(obj);
+}
+
+typedef long (*scan_table[256])(lispobj *obj);
+
+static void
+scan_objects(lispobj *start, long n_words, scan_table table)
+{
+    lispobj *end = start + n_words;
+    lispobj *object_ptr;
+    long n_words_scanned;
+    for (object_ptr = start;
+         object_ptr < end;
+         object_ptr += n_words_scanned) {
+        lispobj obj = *object_ptr;
+
+        n_words_scanned = (table[widetag_of(obj)])(object_ptr);
+    }
+}
+
+static void
+scan_for_lutexes(lispobj *addr, long n_words)
+{
+    static int initialized = 0;
+    static scan_table lutex_scan_table;
+
+    if (!initialized) {
+        int i;
+
+        /* allocate a little space to get started */
+        lutex_addresses = malloc(16*sizeof(void *));
+        gc_assert(lutex_addresses);
+        max_lutexes = 16;
+
+        /* initialize the mapping table */
+        for(i = 0; i < ((sizeof lutex_scan_table)/(sizeof lutex_scan_table[0])); ++i) {
+            lutex_scan_table[i] = default_scan_action;
+        }
+
+        lutex_scan_table[LUTEX_WIDETAG] = lutex_scan_action;
+
+        initialized = 1;
+    }
+
+    /* do the scan */
+    scan_objects(addr, n_words, lutex_scan_table);
+}
+#endif
+
 static void
 output_space(FILE *file, int id, lispobj *addr, lispobj *end, os_vm_offset_t file_offset)
 {
-    int words, bytes, data;
+    size_t words, bytes, data;
     static char *names[] = {NULL, "dynamic", "static", "read-only"};
 
     write_lispobj(id, file);
@@ -88,8 +165,13 @@ output_space(FILE *file, int id, lispobj *addr, lispobj *end, os_vm_offset_t fil
 
     bytes = words * sizeof(lispobj);
 
-    printf("writing %d bytes from the %s space at 0x%08lx\n",
-           bytes, names[id], (unsigned long)addr);
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+    printf("scanning space for lutexes...\n");
+    scan_for_lutexes((char *)addr, words);
+#endif
+
+    printf("writing %lu bytes from the %s space at 0x%08lx\n",
+           (unsigned long)bytes, names[id], (unsigned long)addr);
 
     data = write_bytes(file, (char *)addr, bytes, file_offset);
 
@@ -148,7 +230,7 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function,
          file);
     {
         unsigned char *p;
-        for (p = build_id; *p; ++p)
+        for (p = (unsigned char *)build_id; *p; ++p)
             write_lispobj(*p, file);
     }
 
@@ -166,18 +248,26 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function,
                  (lispobj *)STATIC_SPACE_START,
                  (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0),
                  core_start_pos);
+#ifdef LISP_FEATURE_GENCGC
+    /* Flush the current_region, updating the tables. */
+    gc_alloc_update_all_page_tables();
+    update_dynamic_space_free_pointer();
+#endif
 #ifdef reg_ALLOC
+#ifdef LISP_FEATURE_GENCGC
     output_space(file,
                  DYNAMIC_CORE_SPACE_ID,
-                 (lispobj *)current_dynamic_space,
+                 (lispobj *)DYNAMIC_SPACE_START,
                  dynamic_space_free_pointer,
                  core_start_pos);
 #else
-#ifdef LISP_FEATURE_GENCGC
-    /* Flush the current_region, updating the tables. */
-    gc_alloc_update_all_page_tables();
-    update_dynamic_space_free_pointer();
+    output_space(file,
+                 DYNAMIC_CORE_SPACE_ID,
+                 (lispobj *)current_dynamic_space,
+                 dynamic_space_free_pointer,
+                 core_start_pos);
 #endif
+#else
     output_space(file,
                  DYNAMIC_CORE_SPACE_ID,
                  (lispobj *)DYNAMIC_SPACE_START,
@@ -209,6 +299,24 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function,
     }
 #endif
 
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+    if(n_lutexes > 0) {
+        long offset;
+        printf("writing %ld lutexes to the core...\n", n_lutexes);
+        write_lispobj(LUTEX_TABLE_CORE_ENTRY_TYPE_CODE, file);
+        /* word count of the entry */
+        write_lispobj(4, file);
+        /* indicate how many lutexes we saved */
+        write_lispobj(n_lutexes, file);
+        /* save the lutexes */
+        offset = write_bytes(file, (char *) lutex_addresses,
+                             n_lutexes * sizeof(*lutex_addresses),
+                             core_start_pos);
+
+        write_lispobj(offset, file);
+    }
+#endif
+
     write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
 
     /* Write a trailing header, ignored when parsing the core normally.