]> granicus.if.org Git - gc/commitdiff
2009-10-09 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Fri, 9 Oct 2009 17:03:35 +0000 (17:03 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:50 +0000 (21:06 +0400)
* alloc.c (GC_collect_or_expand): Add "retry" argument; add the
comments; don't use "default" stop_func on a retry if
GC_dont_expand.
* alloc.c (GC_collect_or_expand): Reformat the code (make the
indentation style uniform across the function).
* alloc.c (GC_allocobj): Pass "retry" argument to
GC_collect_or_expand().
* malloc.c (GC_alloc_large): Ditto.
* include/private/gc_priv.h (GC_collect_or_expand): Move the
declaration to malloc.c; add "retry" argument.

ChangeLog
alloc.c
include/private/gc_priv.h
malloc.c

index 68f7c0b0fa9d625ddee778b8e566fb6d16f4ca33..30f2c6b4510f4739585b8f3f8ed8e864445630c8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-10-09  Ivan Maidanski <ivmai@mail.ru>
+
+       * alloc.c (GC_collect_or_expand): Add "retry" argument; add the
+       comments; don't use "default" stop_func on a retry if
+       GC_dont_expand.
+       * alloc.c (GC_collect_or_expand): Reformat the code (make the
+       indentation style uniform across the function).
+       * alloc.c (GC_allocobj): Pass "retry" argument to
+       GC_collect_or_expand().
+       * malloc.c (GC_alloc_large): Ditto.
+       * include/private/gc_priv.h (GC_collect_or_expand): Move the
+       declaration to malloc.c; add "retry" argument.
+
 2009-10-09  Ivan Maidanski <ivmai@mail.ru>
 
        * alloc.c (GC_start_call_back): Move the variable definition from
diff --git a/alloc.c b/alloc.c
index 76a7a935a0a29f65441aef192cfa07eb41d12342..d5309ce79fe1b39a6f71c4bbf29bb70dcc1baea6 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -1184,62 +1184,74 @@ unsigned GC_fail_count = 0;
                         /* How many consecutive GC/expansion failures?  */
                         /* Reset by GC_allochblk.                       */
 
-GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page)
+/* Collect or expand heap in an attempt make the indicated number of    */
+/* free blocks available.  Should be called until the blocks are        */
+/* available (seting retry value to TRUE unless this is the first call  */
+/* in a loop) or until it fails by returning FALSE.                     */
+GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page,
+                             GC_bool retry)
 {
     GC_bool gc_not_stopped = TRUE;
+    word blocks_to_get;
     IF_CANCEL(int cancel_state;)
 
     DISABLE_CANCEL(cancel_state);
-    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;
-
-      if (blocks_to_get > MAXHINCR) {
-          word slop;
-
-          /* Get the minimum required to make it likely that we         */
-          /* can satisfy the current request in the presence of black-  */
-          /* listing.  This will probably be more than MAXHINCR.        */
-          if (ignore_off_page) {
-              slop = 4;
-          } else {
-              slop = 2*divHBLKSZ(BL_LIMIT);
-              if (slop > needed_blocks) slop = needed_blocks;
-          }
-          if (needed_blocks + slop > MAXHINCR) {
-              blocks_to_get = needed_blocks + slop;
-          } else {
-              blocks_to_get = MAXHINCR;
-          }
+    if (!GC_incremental && !GC_dont_gc &&
+        ((GC_dont_expand && GC_bytes_allocd > 0) || GC_should_collect())) {
+      /* Try to do a full collection using 'default' stop_func (unless  */
+      /* nothing has been allocated since the latest collection or heap */
+      /* expansion is disabled).                                        */
+      gc_not_stopped = GC_try_to_collect_inner(
+                        GC_bytes_allocd > 0 && (!GC_dont_expand || !retry) ?
+                        GC_default_stop_func : GC_never_stop_func);
+      if (gc_not_stopped == TRUE || !retry) {
+        /* Either the collection hasn't been aborted or this is the     */
+        /* first attempt (in a loop).                                   */
+        RESTORE_CANCEL(cancel_state);
+        return(TRUE);
+      }
+    }
+
+    blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
+                        + needed_blocks;
+    if (blocks_to_get > MAXHINCR) {
+      word slop;
+
+      /* Get the minimum required to make it likely that we can satisfy */
+      /* the current request in the presence of black-listing.          */
+      /* This will probably be more than MAXHINCR.                      */
+      if (ignore_off_page) {
+        slop = 4;
+      } else {
+        slop = 2 * divHBLKSZ(BL_LIMIT);
+        if (slop > needed_blocks) slop = needed_blocks;
+      }
+      if (needed_blocks + slop > MAXHINCR) {
+        blocks_to_get = needed_blocks + slop;
+      } else {
+        blocks_to_get = MAXHINCR;
       }
-      if (!GC_expand_hp_inner(blocks_to_get)
+    }
+
+    if (!GC_expand_hp_inner(blocks_to_get)
         && !GC_expand_hp_inner(needed_blocks)) {
-        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 {
-#           if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
-              WARN("Out of Memory! Heap size: %" GC_PRIdPTR " MiB."
-                   " Returning NIL!\n",
-                   (GC_heapsize - GC_unmapped_bytes) >> 20);
-#           endif
-            RESTORE_CANCEL(cancel_state);
-            return(FALSE);
-        }
+      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 {
-          if (GC_fail_count && GC_print_stats) {
-              GC_printf("Memory available again ...\n");
-          }
+#       if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
+          WARN("Out of Memory! Heap size: %" GC_PRIdPTR " MiB."
+               " Returning NIL!\n", (GC_heapsize - GC_unmapped_bytes) >> 20);
+#       endif
+        RESTORE_CANCEL(cancel_state);
+        return(FALSE);
       }
+    } else if (GC_fail_count && GC_print_stats) {
+      GC_printf("Memory available again ...\n");
     }
     RESTORE_CANCEL(cancel_state);
     return(TRUE);
@@ -1255,6 +1267,7 @@ ptr_t GC_allocobj(size_t gran, int kind)
 {
     void ** flh = &(GC_obj_kinds[kind].ok_freelist[gran]);
     GC_bool tried_minor = FALSE;
+    GC_bool retry = FALSE;
 
     if (gran == 0) return(0);
 
@@ -1271,14 +1284,15 @@ ptr_t GC_allocobj(size_t gran, int kind)
       if (*flh == 0) {
         ENTER_GC();
         if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED
-            && ! tried_minor ) {
-            GC_collect_a_little_inner(1);
-            tried_minor = TRUE;
+            && !tried_minor) {
+         GC_collect_a_little_inner(1);
+         tried_minor = TRUE;
         } else {
-          if (!GC_collect_or_expand((word)1,FALSE)) {
+          if (!GC_collect_or_expand(1, FALSE, retry)) {
             EXIT_GC();
             return(0);
           }
+          retry = TRUE;
         }
         EXIT_GC();
       }
index dc6f801f303700b07802042291704bc41fc6694b..02bc359442d0d89741fada9cfe4ea9d95ad50c1a 100644 (file)
@@ -1675,12 +1675,6 @@ GC_bool GC_try_to_collect_inner(GC_stop_func f);
                                 /* completes successfully.              */
 # define GC_gcollect_inner() \
         (void) GC_try_to_collect_inner(GC_never_stop_func)
-GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page);
-                                /* Collect or expand heap in an attempt */
-                                /* make the indicated number of free    */
-                                /* blocks available.  Should be called  */
-                                /* until the blocks are available or    */
-                                /* until it fails by returning FALSE.   */
 
 extern GC_bool GC_is_initialized; /* GC_init() has been run. */
 
index 12642563a305aaac0280d9dfbb010fa90bcb846b..e8d397c48870d24c2a88cf5406af3a630de9ae8e 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -35,6 +35,9 @@ STATIC GC_bool GC_alloc_reclaim_list(struct obj_kind *kind)
     return(TRUE);
 }
 
+GC_bool GC_collect_or_expand(word needed_blocks, GC_bool ignore_off_page,
+                             GC_bool retry); /* from alloc.c */
+
 /* Allocate a large block of size lb bytes.     */
 /* The block is not cleared.                    */
 /* Flags is 0 or IGNORE_OFF_PAGE.               */
@@ -45,13 +48,14 @@ ptr_t GC_alloc_large(size_t lb, int k, unsigned flags)
     struct hblk * h;
     word n_blocks;
     ptr_t result;
+    GC_bool retry = FALSE;
 
     /* Round up to a multiple of a granule. */
       lb = (lb + GRANULE_BYTES - 1) & ~(GRANULE_BYTES - 1);
     n_blocks = OBJ_SZ_TO_BLOCKS(lb);
     if (!GC_is_initialized) GC_init();
     /* Do our share of marking work */
-        if(GC_incremental && !GC_dont_gc)
+        if (GC_incremental && !GC_dont_gc)
             GC_collect_a_little_inner((int)n_blocks);
     h = GC_allochblk(lb, k, flags);
 #   ifdef USE_MUNMAP
@@ -60,8 +64,9 @@ ptr_t GC_alloc_large(size_t lb, int k, unsigned flags)
             h = GC_allochblk(lb, k, flags);
         }
 #   endif
-    while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
+    while (0 == h && GC_collect_or_expand(n_blocks, flags != 0, retry)) {
         h = GC_allochblk(lb, k, flags);
+        retry = TRUE;
     }
     if (h == 0) {
         result = 0;