]> granicus.if.org Git - gc/commitdiff
2009-09-19 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Sat, 19 Sep 2009 09:19:24 +0000 (09:19 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:47 +0000 (21:06 +0400)
(ivmai129.diff - superseding diff47)

* alloc.c (GC_default_stop_func): New static variable (initialized
to GC_never_stop_func).
* alloc.c (GC_set_stop_func, GC_get_stop_func): New function.
* alloc.c (GC_timeout_stop_func): Define as GC_default_stop_func
(instead of GC_never_stop_func) if SMALL_CONFIG (or NO_CLOCK),
else call GC_default_stop_func() before getting "current_time".
* alloc.c (GC_maybe_gc): Expand GC_gcollect_inner() macro (for
FIXME comment).
* alloc.c (GC_maybe_gc, GC_collect_a_little_inner): add FIXME for
replacing GC_never_stop_func with GC_default_stop_func (if
possible).
* alloc.c (GC_gcollect): Use GC_default_stop_func.
* alloc.c (GC_collect_or_expand): Use GC_default_stop_func
(instead of GC_never_stop_func) unless it is trigged due to out of
memory; don't increment GC_fail_count and don't output warning
(before trying to collect again) in case the collection has been
interrupted (by GC_default_stop_func) and the heap expansion has
failed too.
* include/gc.h (GC_set_stop_func, GC_get_stop_func): New function
prototypes.

ChangeLog
alloc.c
include/gc.h

index 6fe02981f53714609d18b77f7218991693884c6d..4911584472dde2824a18687018bb07e814bf65e4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2009-09-19  Ivan Maidanski <ivmai@mail.ru>
+       (ivmai129.diff - superseding diff47)
+
+       * alloc.c (GC_default_stop_func): New static variable (initialized
+       to GC_never_stop_func).
+       * alloc.c (GC_set_stop_func, GC_get_stop_func): New function.
+       * alloc.c (GC_timeout_stop_func): Define as GC_default_stop_func
+       (instead of GC_never_stop_func) if SMALL_CONFIG (or NO_CLOCK),
+       else call GC_default_stop_func() before getting "current_time".
+       * alloc.c (GC_maybe_gc): Expand GC_gcollect_inner() macro (for
+       FIXME comment).
+       * alloc.c (GC_maybe_gc, GC_collect_a_little_inner): add FIXME for
+       replacing GC_never_stop_func with GC_default_stop_func (if
+       possible).
+       * alloc.c (GC_gcollect): Use GC_default_stop_func.
+       * alloc.c (GC_collect_or_expand): Use GC_default_stop_func
+       (instead of GC_never_stop_func) unless it is trigged due to out of
+       memory; don't increment GC_fail_count and don't output warning
+       (before trying to collect again) in case the collection has been
+       interrupted (by GC_default_stop_func) and the heap expansion has
+       failed too.
+       * include/gc.h (GC_set_stop_func, GC_get_stop_func): New function
+       prototypes.
+
 2009-09-19  Ivan Maidanski <ivmai@mail.ru>
 
        * os_dep.c (GC_get_stack_base): Add FIXME; add assertion for
diff --git a/alloc.c b/alloc.c
index da938d6ff2f6ff69be59e1fb5988e648cdc2a864..2f61d5800a0362c1582436e42663b64f9910941d 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -140,8 +140,27 @@ STATIC CLOCK_TYPE GC_start_time;/* Time at which we stopped world. */
 STATIC int GC_n_attempts = 0;  /* Number of attempts at finishing      */
                                /* collection within GC_time_limit.     */
 
+STATIC GC_stop_func GC_default_stop_func = GC_never_stop_func;
+
+GC_API void GC_CALL GC_set_stop_func(GC_stop_func stop_func)
+{
+  GC_ASSERT(stop_func != 0);
+  LOCK();
+  GC_default_stop_func = stop_func;
+  UNLOCK();
+}
+
+GC_API GC_stop_func GC_CALL GC_get_stop_func(void)
+{
+  GC_stop_func stop_func;
+  LOCK();
+  stop_func = GC_default_stop_func;
+  UNLOCK();
+  return stop_func;
+}
+
 #if defined(SMALL_CONFIG) || defined(NO_CLOCK)
-#   define GC_timeout_stop_func GC_never_stop_func
+#   define GC_timeout_stop_func GC_default_stop_func
 #else
   STATIC int GC_CALLBACK GC_timeout_stop_func (void)
   {
@@ -149,6 +168,9 @@ STATIC int GC_n_attempts = 0;       /* Number of attempts at finishing      */
     static unsigned count = 0;
     unsigned long time_diff;
     
+    if ((*GC_default_stop_func)())
+      return(1);
+
     if ((count++ & 3) != 0) return(0);
     GET_TIME(current_time);
     time_diff = MS_TIME_DIFF(current_time,GC_start_time);
@@ -290,7 +312,8 @@ STATIC void GC_maybe_gc(void)
     GC_ASSERT(I_HOLD_LOCK());
     if (GC_should_collect()) {
         if (!GC_incremental) {
-            GC_gcollect_inner();
+           /* FIXME: If possible, GC_default_stop_func should be used here */
+            GC_try_to_collect_inner(GC_never_stop_func);
             n_partial_gcs = 0;
             return;
         } else {
@@ -321,6 +344,8 @@ STATIC void GC_maybe_gc(void)
 #      ifndef NO_CLOCK
           if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
 #      endif
+       /* FIXME: If possible, GC_default_stop_func should be   */
+       /* used instead of GC_never_stop_func here.             */
         if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED? 
                            GC_never_stop_func : GC_timeout_stop_func)) {
 #           ifdef SAVE_CALL_CHAIN
@@ -459,6 +484,8 @@ void GC_collect_a_little_inner(int n)
                    break;
                  }
                } else {
+                 /* FIXME: If possible, GC_default_stop_func should be */
+                 /* used here.                                         */
                  (void)GC_stopped_mark(GC_never_stop_func);
                }
                GC_finish_collection();
@@ -891,7 +918,7 @@ GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func)
 
 GC_API void GC_CALL GC_gcollect(void)
 {
-    (void)GC_try_to_collect(GC_never_stop_func);
+    (void)GC_try_to_collect(GC_default_stop_func);
     if (GC_have_errors) GC_print_all_errors();
 }
 
@@ -1105,10 +1132,13 @@ unsigned GC_fail_count = 0;
 
 GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page)
 {
-    if (!GC_incremental && !GC_dont_gc &&
-       ((GC_dont_expand && GC_bytes_allocd > 0) || GC_should_collect())) {
-      GC_gcollect_inner();
-    } else {
+    GC_bool gc_not_stopped = TRUE;
+    if (GC_incremental || GC_dont_gc ||
+       ((!GC_dont_expand || GC_bytes_allocd == 0) && !GC_should_collect()) ||
+       (gc_not_stopped = GC_try_to_collect_inner(GC_bytes_allocd > 0 ?
+                                       GC_default_stop_func :
+                                       GC_never_stop_func)) == FALSE) {
+
       word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
                           + needed_blocks;
       
@@ -1132,7 +1162,11 @@ GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page)
       }
       if (!GC_expand_hp_inner(blocks_to_get)
         && !GC_expand_hp_inner(needed_blocks)) {
-       if (GC_fail_count++ < GC_max_retries) {
+        if (gc_not_stopped == FALSE) {
+           /* Don't increment GC_fail_count here (and no warning).     */
+           GC_gcollect_inner();
+           GC_ASSERT(GC_bytes_allocd == 0);
+       } else if (GC_fail_count++ < GC_max_retries) {
            WARN("Out of Memory!  Trying to continue ...\n", 0);
            GC_gcollect_inner();
        } else {
index 57a6be521b27165aa6e019b45de4d6b200ad48f1..e13381daa8076c12f5b9a5427eb8d38b29de8a1b 100644 (file)
@@ -486,6 +486,12 @@ GC_API void GC_CALL GC_gcollect(void);
 typedef int (GC_CALLBACK * GC_stop_func)(void);
 GC_API int GC_CALL GC_try_to_collect(GC_stop_func /* stop_func */);
 
+/* Set and get the default stop_func.  The default stop_func is used by        */
+/* GC_gcollect() and by implicitly trigged collections (except for the */
+/* case when handling out of memory).  Must not be 0.                  */
+GC_API void GC_CALL GC_set_stop_func(GC_stop_func /* stop_func */);
+GC_API GC_stop_func GC_CALL GC_get_stop_func(void);
+
 /* Return the number of bytes in the heap.  Excludes collector private */
 /* data structures.  Excludes the unmapped memory (retuned to the OS). */
 /* Includes empty blocks and fragmentation loss.  Includes some pages  */