OSDN Git Service

* allchblk.c (GC_allochblk_nth): Dont overlook available space if
authorhboehm <hboehm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Feb 2005 21:33:02 +0000 (21:33 +0000)
committerhboehm <hboehm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Feb 2005 21:33:02 +0000 (21:33 +0000)
  GC disabled, correctly convert GC_finalizer_mem_freed to byte,
     total_size to words.
   * dyn_load.c (win32 GC_register_dynamic_libraries): Consider only
  MEM_IMAGE regions.
   * mach_dep.c (GC_with_callee_saves_pushed): separate into new function,
  and indent appropriately.
   * mark_rts.c (GC_approx_sp): Access stack.
* pthread_stop_world.c: (GC_suspend_handler): Explicitly push
  callee-saves registers when appropriate.
     (GC_stop_world): Handle EINTR from sem_wait (sync with Mono GC).

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94776 138bc75d-0d04-0410-961f-82ee72b054a4

boehm-gc/ChangeLog
boehm-gc/allchblk.c
boehm-gc/dyn_load.c
boehm-gc/mach_dep.c
boehm-gc/mark_rts.c
boehm-gc/pthread_stop_world.c

index 5bb9d45..b9c7c46 100644 (file)
@@ -1,3 +1,17 @@
+2005-02-07  Hans Boehm  <Hans.Boehm@hp.com>
+
+       * allchblk.c (GC_allochblk_nth): Dont overlook available space if
+         GC disabled, correctly convert GC_finalizer_mem_freed to byte,
+         total_size to words.
+       * dyn_load.c (win32 GC_register_dynamic_libraries): Consider only
+         MEM_IMAGE regions.
+       * mach_dep.c (GC_with_callee_saves_pushed): separate into new function,
+         and indent appropriately.
+       * mark_rts.c (GC_approx_sp): Access stack.
+       * pthread_stop_world.c: (GC_suspend_handler): Explicitly push
+         callee-saves registers when appropriate.
+         (GC_stop_world): Handle EINTR from sem_wait (sync with Mono GC).
+
 2005-01-01  Bryce McKinlay  <mckinlay@redhat.com>
 
        * configure.ac (AC_CONFIG_HEADERS): Build both include/gc_config.h 
index 793c468..f9c31e0 100644 (file)
@@ -590,8 +590,9 @@ int n;
            GET_HDR(hbp, hhdr);
            size_avail = hhdr->hb_sz;
            if (size_avail < size_needed) continue;
-           if (!GC_use_entire_heap
-               && size_avail != size_needed
+           if (size_avail != size_needed
+               && !GC_use_entire_heap
+               && !GC_dont_gc
                && USED_HEAP_SIZE >= GC_requested_heapsize
                && !TRUE_INCREMENTAL && GC_should_collect()) {
 #              ifdef USE_MUNMAP
@@ -608,7 +609,8 @@ int n;
                    /* If we are deallocating lots of memory from       */
                    /* finalizers, fail and collect sooner rather       */
                    /* than later.                                      */
-                   if (GC_finalizer_mem_freed > (GC_heapsize >> 4))  {
+                   if (WORDS_TO_BYTES(GC_finalizer_mem_freed)
+                       > (GC_heapsize >> 4))  {
                      continue;
                    }
 #              endif /* !USE_MUNMAP */
@@ -698,7 +700,7 @@ int n;
                      struct hblk * h;
                      struct hblk * prev = hhdr -> hb_prev;
                      
-                     GC_words_wasted += total_size;
+                     GC_words_wasted += BYTES_TO_WORDS(total_size);
                      GC_large_free_bytes -= total_size;
                      GC_remove_from_fl(hhdr, n);
                      for (h = hbp; h < limit; h++) {
index 9bd9e06..dfe0a3c 100644 (file)
@@ -735,6 +735,10 @@ void GC_register_dynamic_libraries()
   
 # define HAVE_REGISTER_MAIN_STATIC_DATA
 
+  /* The frame buffer testing code is dead in this version.    */
+  /* We leave it here temporarily in case the switch to just   */
+  /* testing for MEM_IMAGE sections causes un expected                 */
+  /* problems.                                                 */
   GC_bool GC_warn_fb = TRUE;   /* Warn about traced likely     */
                                /* graphics memory.             */
   GC_bool GC_disallow_ignore_fb = FALSE;
@@ -856,7 +860,11 @@ void GC_register_dynamic_libraries()
                && (protect == PAGE_EXECUTE_READWRITE
                    || protect == PAGE_READWRITE)
                && !GC_is_heap_base(buf.AllocationBase)
-               && !is_frame_buffer(p, buf.RegionSize)) {  
+               /* This used to check for
+                * !is_frame_buffer(p, buf.RegionSize, buf.Type)
+                * instead of just checking for MEM_IMAGE.
+                * If something breaks, change it back. */
+               && buf.Type == MEM_IMAGE) {
 #              ifdef DEBUG_VIRTUALQUERY
                  GC_dump_meminfo(&buf);
 #              endif
index 327e11c..5412b8b 100644 (file)
@@ -400,64 +400,79 @@ void GC_push_regs()
 }
 #endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
 
+void GC_with_callee_saves_pushed(fn, arg)
+void (*fn)();
+ptr_t arg;
+{
+    word dummy;
+
+#   if defined(USE_GENERIC_PUSH_REGS)
+#     ifdef HAVE_BUILTIN_UNWIND_INIT
+        /* This was suggested by Richard Henderson as the way to       */
+        /* force callee-save registers and register windows onto       */
+        /* the stack.                                          */
+        __builtin_unwind_init();
+#     else /* !HAVE_BUILTIN_UNWIND_INIT */
+        /* Generic code                          */
+        /* The idea is due to Parag Patel at HP. */
+        /* We're not sure whether he would like  */
+        /* to be he acknowledged for it or not.  */
+        jmp_buf regs;
+        register word * i = (word *) regs;
+        register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
+  
+        /* Setjmp doesn't always clear all of the buffer.              */
+        /* That tends to preserve garbage.  Clear it.                  */
+       for (; (char *)i < lim; i++) {
+           *i = 0;
+       }
+#       if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
+                  || defined(UTS4) || defined(LINUX) || defined(EWS4800)
+         (void) setjmp(regs);
+#       else
+            (void) _setjmp(regs);
+         /* We don't want to mess with signals. According to   */
+         /* SUSV3, setjmp() may or may not save signal mask.   */
+         /* _setjmp won't, but is less portable.               */
+#       endif
+#     endif /* !HAVE_BUILTIN_UNWIND_INIT */
+#   elif defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */
+      /* We may still need this to save thread contexts.       */
+      /* This should probably be used in all Posix/non-gcc     */
+      /* settings.  We defer that change to minimize risk.     */
+      ucontext_t ctxt;
+      getcontext(&ctxt);
+#   else  /* Shouldn't be needed */
+      ABORT("Unexpected call to GC_with_callee_saves_pushed");
+#   endif
+#   if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
+       || defined(IA64)
+      /* On a register window machine, we need to save register        */
+      /* contents on the stack for this to work.  The setjmp   */
+      /* is probably not needed on SPARC, since pointers are   */
+      /* only stored in windowed or scratch registers.  It is  */
+      /* needed on IA64, since some non-windowed registers are */
+      /* preserved.                                            */
+      {
+        GC_save_regs_ret_val = GC_save_regs_in_stack();
+       /* On IA64 gcc, could use __builtin_ia64_flushrs() and  */
+       /* __builtin_ia64_flushrs().  The latter will be done   */
+       /* implicitly by __builtin_unwind_init() for gcc3.0.1   */
+       /* and later.                                           */
+      }
+#   endif
+    fn(arg);
+    /* Strongly discourage the compiler from treating the above        */
+    /* as a tail-call, since that would pop the register       */
+    /* contents before we get a chance to look at them.                */
+    GC_noop1((word)(&dummy));
+}
+
 #if defined(USE_GENERIC_PUSH_REGS)
 void GC_generic_push_regs(cold_gc_frame)
 ptr_t cold_gc_frame;
 {
-       {
-           word dummy;
-
-#          ifdef HAVE_BUILTIN_UNWIND_INIT
-             /* This was suggested by Richard Henderson as the way to  */
-             /* force callee-save registers and register windows onto  */
-             /* the stack.                                             */
-             __builtin_unwind_init();
-#          else /* !HAVE_BUILTIN_UNWIND_INIT */
-             /* Generic code                          */
-             /* The idea is due to Parag Patel at HP. */
-             /* We're not sure whether he would like  */
-             /* to be he acknowledged for it or not.  */
-             jmp_buf regs;
-             register word * i = (word *) regs;
-             register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
-
-             /* Setjmp doesn't always clear all of the buffer.         */
-             /* That tends to preserve garbage.  Clear it.             */
-               for (; (char *)i < lim; i++) {
-                   *i = 0;
-               }
-#            if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
-                || defined(UTS4) || defined(LINUX) || defined(EWS4800)
-                 (void) setjmp(regs);
-#            else
-                 (void) _setjmp(regs);
-                 /* We don't want to mess with signals. According to   */
-                 /* SUSV3, setjmp() may or may not save signal mask.   */
-                 /* _setjmp won't, but is less portable.               */
-#            endif
-#          endif /* !HAVE_BUILTIN_UNWIND_INIT */
-#           if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
-               || defined(IA64)
-             /* On a register window machine, we need to save register */
-             /* contents on the stack for this to work.  The setjmp    */
-             /* is probably not needed on SPARC, since pointers are    */
-             /* only stored in windowed or scratch registers.  It is   */
-             /* needed on IA64, since some non-windowed registers are  */
-             /* preserved.                                             */
-             {
-               GC_save_regs_ret_val = GC_save_regs_in_stack();
-               /* On IA64 gcc, could use __builtin_ia64_flushrs() and  */
-               /* __builtin_ia64_flushrs().  The latter will be done   */
-               /* implicitly by __builtin_unwind_init() for gcc3.0.1   */
-               /* and later.                                           */
-             }
-#           endif
-           GC_push_current_stack(cold_gc_frame);
-           /* Strongly discourage the compiler from treating the above */
-           /* as a tail-call, since that would pop the register        */
-           /* contents before we get a chance to look at them.         */
-           GC_noop1((word)(&dummy));
-       }
+    GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);
 }
 #endif /* USE_GENERIC_PUSH_REGS */
 
index 55eb5d5..4074879 100644 (file)
@@ -368,8 +368,11 @@ ptr_t p;
 
 ptr_t GC_approx_sp()
 {
-    word dummy;
+    VOLATILE word dummy;
 
+    dummy = 42;        /* Force stack to grow if necessary.    Otherwise the   */
+               /* later accesses might cause the kernel to think we're */
+               /* doing something wrong.                               */
 #   ifdef _MSC_VER
 #     pragma warning(disable:4172)
 #   endif
index 832c49c..b5e7fae 100644 (file)
@@ -101,8 +101,28 @@ word GC_stop_count;        /* Incremented at the beginning of GC_stop_world. */
 
 sem_t GC_suspend_ack_sem;
 
+void GC_suspend_handler_inner(ptr_t sig_arg);
+
+#if defined(IA64) || defined(HP_PA)
+extern void GC_with_callee_saves_pushed();
+
 void GC_suspend_handler(int sig)
 {
+  GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
+}
+
+#else
+/* We believe that in all other cases the full context is already      */
+/* in the signal handler frame.                                                */
+void GC_suspend_handler(int sig)
+{
+  GC_suspend_handler_inner((ptr_t)(word)sig);
+}
+#endif
+
+void GC_suspend_handler_inner(ptr_t sig_arg)
+{
+    int sig = (int)(word)sig_arg;
     int dummy;
     pthread_t my_thread = pthread_self();
     GC_thread me;
@@ -369,9 +389,11 @@ void GC_stop_world()
          }
       }
     for (i = 0; i < n_live_threads; i++) {
-         if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
+         while (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
+           if (errno != EINTR) {
              GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
              ABORT("sem_wait for handler failed");
+           }
          }
     }
 #   ifdef PARALLEL_MARK