2006-04-28 Hans Boehm <Hans.Boehm@hp.com>
authorhboehm <hboehm>
Sat, 29 Apr 2006 00:05:26 +0000 (00:05 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:37 +0000 (21:06 +0400)
* NT_STATIC_THREADS_MAKEFILE: Assorted cleanups and bug fixes for VC++.net
* mark.c (alloc_mark_stack): Recycle old stack only if it doesn't break
GWW_VDB.
* misc.c: Try to initialize GWW_VDB earlier.  Remove seemingly obsolete
initialization code.  More consistently use GC_LOF_FILE.
* os_dep.c (GC_unix_get_mem): Ensure sbrk lock release on Irix, even in the
really obscure cases.
Fix GetWriteWatch error handling; work around slightly late calls to
GC_enable_incremental().

NT_STATIC_THREADS_MAKEFILE
doc/README.changes
mark.c
misc.c
os_dep.c

index 88cd67d1583a269e2039b0af2792c941a70812c7..6b145603abe74f5536092650617aa547e012673e 100644 (file)
@@ -22,7 +22,7 @@ all: gctest.exe cord\de.exe test_cpp.exe
        $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS $*.c /Fo$*.obj
 
 .cpp.obj:
-       $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS /Fo$*.obj
+       $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS /Fo$*.obj
 
 $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\private\msvc_dbg.h
 
@@ -35,7 +35,7 @@ gctest.exe: tests\test.obj gc.lib
 #      and add mapsympe line.
 #  This produces a "GUI" applications that opens no windows and writes to the log file
 #  "gc.log".  This is done to make the result runnable under win32s.
-       $(link) -debug:full -debugtype:cv /MT $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
+       $(link) -debug:full -debugtype:cv $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
 #      mapsympe -n -o gctest.sym gctest.exe
 
 cord\de_win.rbj: cord\de_win.res
@@ -44,11 +44,11 @@ cord\de_win.rbj: cord\de_win.res
 cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
 
 cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h
-       $(rc) $(rcvars) -r -fo cord\de_win.res $(cvarsmt) cord\de_win.rc
+       $(rc) $(rcvars) -r -fo cord\de_win.res cord\de_win.rc
 
 # Cord/de is a real win32 gui application.
 cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib
-       $(link) -debug:full -debugtype:cv /MT $(guiflags) -stack:16384 -out:cord\de.exe  cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
+       $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe  cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
 
 gc_cpp.obj: include\gc_cpp.h include\gc.h
 
index ff9b5431debac0b3ff4499db54cfba9fe44054ea..e8e4cf5e9ca4989a0baa3272baa508a5380aa585 100644 (file)
@@ -2280,6 +2280,9 @@ Since gc6.7:
    Thomas Klausner.)
  - Improvements to the HP/UX section of configure.in/configure.ac.
    (Thanks to Andreas Tobler)
+ - GC_unix_get_mem could neglect to release the malloc lock on Irix, under
+   extremely unlikely circumstances.  Thanks to Jean-Baptiste Nivois for
+   some careful code reading.
 
 Since gc6.8:
  - Remove GC_PROTO, VOLATILE, GC_PTR, and GC_CONST.  Assume ANSI C compiler
@@ -2495,6 +2498,11 @@ Since gc7.0alpha5
    are almost certainly already out of date, but better than what we had
    before.
  - Fixed some win32 threads bugs, and added support for _beginthreadex.
+ - Fix zero size thread local allocation so that explicit deallocation
+   works correctly.
+ - Removed serious bug in GC_malloc_uncollectable(large size).
+ - Do not try to do thread-local gcj allocation in incremental mode.  There
+   are races in setting up the descriptor.
   
 To do:
  - REDIRECT_MALLOC and threads combination is getting closer, but currently
diff --git a/mark.c b/mark.c
index d46c1ac718e0c31a5801a740de1c8c38d1a1d46d..10df674933c1fa74781e7f661c7f39768db09351 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1173,20 +1173,33 @@ void GC_help_marker(word my_mark_no)
 static void alloc_mark_stack(size_t n)
 {
     mse * new_stack = (mse *)GC_scratch_alloc(n * sizeof(struct GC_ms_entry));
+#   ifdef GWW_VDB
+      /* Don't recycle a stack segment obtained with the wrong flags.  */
+      /* Win32 GetWriteWatch requires the right kind of memory.                */
+      static GC_incremental_at_stack_alloc = 0;
+      GC_bool recycle_old = (!GC_incremental || GC_incremental_at_stack_alloc);
+
+      GC_incremental_at_stack_alloc = GC_incremental;
+#   else
+#     define recycle_old 1
+#   endif
     
     GC_mark_stack_too_small = FALSE;
     if (GC_mark_stack_size != 0) {
         if (new_stack != 0) {
-          word displ = (word)GC_mark_stack & (GC_page_size - 1);
-          signed_word size = GC_mark_stack_size * sizeof(struct GC_ms_entry);
+         if (recycle_old) {
+            /* Recycle old space */
+              size_t page_offset = (word)GC_mark_stack & (GC_page_size - 1);
+              size_t size = GC_mark_stack_size * sizeof(struct GC_ms_entry);
+             size_t displ = 0;
           
-          /* Recycle old space */
-             if (0 != displ) displ = GC_page_size - displ;
+             if (0 != page_offset) displ = GC_page_size - page_offset;
              size = (size - displ) & ~(GC_page_size - 1);
              if (size > 0) {
                GC_add_to_heap((struct hblk *)
                                ((word)GC_mark_stack + displ), (word)size);
              }
+         }
           GC_mark_stack = new_stack;
           GC_mark_stack_size = n;
          GC_mark_stack_limit = new_stack + n;
diff --git a/misc.c b/misc.c
index b077de022af4619c9737dbc0a3436b2ddea5e652..6e12e514ed96b440dbe2f518032441721e7007bc 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -627,10 +627,6 @@ void GC_init_inner()
        || defined(GC_WIN32_THREADS)
         GC_thr_init();
 #   endif
-#   ifdef GC_SOLARIS_THREADS
-       /* We need dirty bits in order to find live stack sections.     */
-        GC_dirty_init();
-#   endif
 #   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
        || defined(GC_SOLARIS_THREADS)
       if (GC_stackbottom == 0) {
@@ -674,6 +670,17 @@ void GC_init_inner()
       /* word should be unsigned */
 #   endif
     GC_ASSERT((signed_word)(-1) < (signed_word)0);
+#   if !defined(SMALL_CONFIG)
+      if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
+       /* This used to test for !GC_no_win32_dlls.  Why? */
+        GC_setpagesize();
+       /* For GWW_MPROTECT on Win32, this needs to happen before any   */
+       /* heap memory is allocated.                                    */
+        GC_dirty_init();
+        GC_ASSERT(GC_bytes_allocd == 0)
+       GC_incremental = TRUE;
+      }
+#   endif /* !SMALL_CONFIG */
     
     /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
     /* might be used.                                                  */
@@ -721,17 +728,6 @@ void GC_init_inner()
       PCR_IL_Unlock();
       GC_pcr_install();
 #   endif
-#   if !defined(SMALL_CONFIG)
-      if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
-       GC_ASSERT(!GC_incremental);
-        GC_setpagesize();
-#       ifndef GC_SOLARIS_THREADS
-          GC_dirty_init();
-#       endif
-        GC_ASSERT(GC_bytes_allocd == 0)
-       GC_incremental = TRUE;
-      }
-#   endif /* !SMALL_CONFIG */
     COND_DUMP;
     /* Get black list set up and/or incremental GC started */
       if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
@@ -769,16 +765,15 @@ void GC_enable_incremental(void)
     LOCK();
     if (GC_incremental) goto out;
     GC_setpagesize();
-    if (GC_no_win32_dlls) goto out;
-#   ifndef GC_SOLARIS_THREADS 
-      maybe_install_looping_handler();  /* Before write fault handler! */
-      GC_dirty_init();
-      if (!GC_dirty_maintained) goto out;
-#   endif
+    /* if (GC_no_win32_dlls) goto out; Should be win32S test? */
+    maybe_install_looping_handler();  /* Before write fault handler! */
+    GC_incremental = TRUE;
     if (!GC_is_initialized) {
         GC_init_inner();
+    } else {
+       GC_dirty_init();
     }
-    if (GC_incremental) goto out;
+    if (!GC_dirty_maintained) goto out;
     if (GC_dont_gc) {
         /* Can't easily do it. */
         UNLOCK();
@@ -791,10 +786,13 @@ void GC_enable_incremental(void)
        /* clean since nothing can point to an          */
        /* unmarked object.                             */
     GC_read_dirty();
-    GC_incremental = TRUE;
 out:
     UNLOCK();
+  } else {
+    GC_init();
   }
+# else
+    GC_init();
 # endif
 }
 
@@ -828,18 +826,23 @@ out:
       if (GC_stdout == INVALID_HANDLE_VALUE) {
          return -1;
       } else if (GC_stdout == 0) {
-         char logPath[_MAX_PATH + 5];
+       char * file_name = GETENV("GC_LOG_FILE");
+       char logPath[_MAX_PATH + 5];
+
+        if (0 == file_name) {
 #         ifdef OLD_WIN32_LOG_FILE
            strcpy(logPath, LOG_FILE);
 #        else
            GetModuleFileName(NULL, logPath, _MAX_PATH);
            strcat(logPath, ".log");
 #        endif
-         GC_stdout = CreateFile(logPath, GENERIC_WRITE,
-                                FILE_SHARE_READ,
-                                NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
-                                NULL); 
-         if (GC_stdout == INVALID_HANDLE_VALUE)
+         file_name = logPath;
+       }
+       GC_stdout = CreateFile(logPath, GENERIC_WRITE,
+                              FILE_SHARE_READ,
+                              NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
+                              NULL); 
+       if (GC_stdout == INVALID_HANDLE_VALUE)
            ABORT("Open of log file failed");
       }
       tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
@@ -868,6 +871,9 @@ int GC_tmp;  /* Should really be local ... */
     if (GC_stderr == NULL) {
        GC_stderr = stderr;
     }
+    if (GC_log == NULL) {
+       GC_log = stderr;
+    }
   }
 #endif
 
@@ -922,6 +928,7 @@ int GC_write(fd, buf, len)
 
 
 #if defined(MSWIN32) || defined(MSWINCE)
+    /* FIXME: This is pretty ugly ... */
 #   define WRITE(f, buf, len) GC_write(buf, len)
 #else
 #   if defined(OS2) || defined(MACOS)
index 974c8ed5b26d420ed3326f4f000678fb87ffb5c2..2f1fa9bae0941f154e6b23a6cf4221769451dc25 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -1232,7 +1232,9 @@ void GC_register_data_segments(void)
           PVOID pages[16];
           DWORD count = 16;
           DWORD page_size;
-          /* On recent W2K versions, everything may exist, but always fail. */
+          /* Check that it actually works.  In spite of some           */
+         /* documentation it actually seems to exist on W2K.           */
+         /* This test may be unnecessary, but ...                      */
           if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
                                  page, GC_page_size,
                                  pages,
@@ -1259,7 +1261,7 @@ void GC_register_data_segments(void)
       done = TRUE;
     }
 
-# endif
+# endif /* GWW_VDB */
 
   GC_bool GC_wnt = FALSE;
          /* This is a Windows NT derivative, i.e. NT, W2K, XP or later.  */
@@ -1662,13 +1664,19 @@ ptr_t GC_unix_get_mem(word bytes)
     ptr_t cur_brk = (ptr_t)sbrk(0);
     SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
     
-    if ((SBRK_ARG_T)bytes < 0) return(0); /* too big */
+    if ((SBRK_ARG_T)bytes < 0) {
+       result = 0; /* too big */
+       goto out;
+    }
     if (lsbs != 0) {
-        if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) return(0);
+        if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
+           result = 0;
+           goto out;
+       }
     }
 #   ifdef ADD_HEAP_GUARD_PAGES
-      /* This is useful for catching severe memory overwrite problems that span        */
-      /* heap sections.  It shouldn't otherwise be turned on.                  */
+      /* This is useful for catching severe memory overwrite problems that */
+      /* span heap sections.  It shouldn't otherwise be turned on.        */
       {
        ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
        if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
@@ -1678,6 +1686,7 @@ ptr_t GC_unix_get_mem(word bytes)
     result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
     if (result == (ptr_t)(-1)) result = 0;
   }
+ out:
 # ifdef IRIX5
     __UNLOCK_MALLOC();
 # endif
@@ -2160,32 +2169,52 @@ void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
         /*
         * GetWriteWatch is documented as returning non-zero when it fails,
         * but the documentation doesn't explicitly say why it would fail or
-        * what its behaviour will be if it fails.  If there are more dirty
+        * what its behaviour will be if it fails.
+       * It does appear to fail, at least on recent W2K instances, if
+       * the underlying memory was not allocated with the appropriate
+       * flag.  This is common if GC_enable_incremental is called
+       * shortly after GC initialization.  To avoid modifying the
+       * interface, we silently work around such a failure, it it only
+       * affects the initial (small) heap allocation.
+       * If there are more dirty
         * pages than will fit in the buffer, this is not treated as a
         * failure; we must check the page count in the loop condition.
+       * Since each partial call will reset the status of some
+       * pages, this should eventually terminate even in the overflow
+       * case.
         */
         if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
                                GC_heap_sects[i].hs_start,
                                GC_heap_sects[i].hs_bytes,
                                pages,
                                &count,
-                               &page_size) != 0)
-        {
-          GC_err_printf(
-            "GC_gww_read_dirty unexpectedly failed: "
-            "Falling back to marking all pages dirty\n");
-          memset(GC_grungy_pages, 0xff, sizeof(page_hash_table));
-          memset(GC_written_pages, 0xff, sizeof(page_hash_table));
-          return;
-        }
-
-        pages_end = pages + count;
-        while (pages != pages_end) {
-          struct hblk * h = (struct hblk *) *pages++;
-          struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
-          do
-            set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
-          while (++h < h_end);
+                               &page_size) != 0) {
+          static int warn_count = 0;
+          unsigned j;
+          struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
+          static struct hblk *last_warned = 0;
+          unsigned nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
+
+          if ( i != 0 && last_warned != start && warn_count++ < 5) {
+            last_warned = start;
+            WARN(
+              "GC_gww_read_dirty unexpectedly failed at %ld: "
+              "Falling back to marking all pages dirty\n", start);
+          }
+          for (j = 0; j < nblocks; ++j) {
+              word hash = PHT_HASH(start + j);
+              set_pht_entry_from_index(GC_grungy_pages, hash);
+          }
+          count = 1;  /* Done with this section. */
+        } else /* succeeded */{
+          pages_end = pages + count;
+          while (pages != pages_end) {
+            struct hblk * h = (struct hblk *) *pages++;
+            struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
+            do
+              set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
+            while (++h < h_end);
+          }
         }
       } while (count == GC_GWW_BUF_LEN);
     }