aboutsummaryrefslogtreecommitdiff
path: root/boehm-gc/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'boehm-gc/alloc.c')
-rw-r--r--boehm-gc/alloc.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/boehm-gc/alloc.c b/boehm-gc/alloc.c
index f2e5af05720..f53061f872d 100644
--- a/boehm-gc/alloc.c
+++ b/boehm-gc/alloc.c
@@ -72,6 +72,13 @@ int GC_full_freq = 19; /* Every 20th collection is a full */
GC_bool GC_need_full_gc = FALSE;
/* Need full GC do to heap growth. */
+#ifdef THREADS
+ GC_bool GC_world_stopped = FALSE;
+# define IF_THREADS(x) x
+#else
+# define IF_THREADS(x)
+#endif
+
word GC_used_heap_size_after_full = 0;
char * GC_copyright[] =
@@ -160,7 +167,7 @@ static word min_words_allocd()
+ (GC_large_free_bytes >> 2)
/* use a bit more of large empty heap */
+ total_root_size);
- if (GC_incremental) {
+ if (TRUE_INCREMENTAL) {
return scan_size / (2 * GC_free_space_divisor);
} else {
return scan_size / GC_free_space_divisor;
@@ -182,7 +189,8 @@ word GC_adj_words_allocd()
/* managed object should not alter result, assuming the client */
/* is playing by the rules. */
result = (signed_word)GC_words_allocd
- - (signed_word)GC_mem_freed - expl_managed;
+ - (signed_word)GC_mem_freed
+ + (signed_word)GC_finalizer_mem_freed - expl_managed;
if (result > (signed_word)GC_words_allocd) {
result = GC_words_allocd;
/* probably client bug or unfortunate scheduling */
@@ -250,7 +258,6 @@ void GC_maybe_gc()
if (GC_should_collect()) {
if (!GC_incremental) {
- GC_notify_full_gc();
GC_gcollect_inner();
n_partial_gcs = 0;
return;
@@ -302,10 +309,14 @@ void GC_maybe_gc()
/*
* Stop the world garbage collection. Assumes lock held, signals disabled.
* If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE.
+ * Return TRUE if we successfully completed the collection.
*/
GC_bool GC_try_to_collect_inner(stop_func)
GC_stop_func stop_func;
{
+# ifdef CONDPRINT
+ CLOCK_TYPE start_time, current_time;
+# endif
if (GC_dont_gc) return FALSE;
if (GC_incremental && GC_collection_in_progress()) {
# ifdef CONDPRINT
@@ -320,8 +331,10 @@ GC_stop_func stop_func;
GC_collect_a_little_inner(1);
}
}
+ if (stop_func == GC_never_stop_func) GC_notify_full_gc();
# ifdef CONDPRINT
if (GC_print_stats) {
+ if (GC_print_stats) GET_TIME(start_time);
GC_printf2(
"Initiating full world-stop collection %lu after %ld allocd bytes\n",
(unsigned long) GC_gc_no+1,
@@ -360,6 +373,13 @@ GC_stop_func stop_func;
return(FALSE);
}
GC_finish_collection();
+# if defined(CONDPRINT)
+ if (GC_print_stats) {
+ GET_TIME(current_time);
+ GC_printf1("Complete collection took %lu msecs\n",
+ MS_TIME_DIFF(current_time,start_time));
+ }
+# endif
return(TRUE);
}
@@ -430,6 +450,7 @@ int GC_collect_a_little GC_PROTO(())
result = (int)GC_collection_in_progress();
UNLOCK();
ENABLE_SIGNALS();
+ if (!result && GC_debugging_started) GC_print_all_smashed();
return(result);
}
@@ -448,16 +469,17 @@ GC_stop_func stop_func;
CLOCK_TYPE start_time, current_time;
# endif
-# if defined(REGISTER_LIBRARIES_EARLY)
- GC_cond_register_dynamic_libraries();
-# endif
- STOP_WORLD();
# ifdef PRINTTIMES
GET_TIME(start_time);
# endif
# if defined(CONDPRINT) && !defined(PRINTTIMES)
if (GC_print_stats) GET_TIME(start_time);
# endif
+# if defined(REGISTER_LIBRARIES_EARLY)
+ GC_cond_register_dynamic_libraries();
+# endif
+ STOP_WORLD();
+ IF_THREADS(GC_world_stopped = TRUE);
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf1("--> Marking for collection %lu ",
@@ -488,6 +510,7 @@ GC_stop_func stop_func;
}
# endif
GC_deficit = i; /* Give the mutator a chance. */
+ IF_THREADS(GC_world_stopped = FALSE);
START_WORLD();
return(FALSE);
}
@@ -521,6 +544,8 @@ GC_stop_func stop_func;
(*GC_check_heap)();
}
+ IF_THREADS(GC_world_stopped = FALSE);
+ START_WORLD();
# ifdef PRINTTIMES
GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n",
@@ -534,7 +559,6 @@ GC_stop_func stop_func;
}
# endif
# endif
- START_WORLD();
return(TRUE);
}
@@ -611,6 +635,7 @@ void GC_finish_collection()
GC_print_address_map();
}
# endif
+ COND_DUMP;
if (GC_find_leak) {
/* Mark all objects on the free list. All objects should be */
/* marked when we're done. */
@@ -707,6 +732,7 @@ void GC_finish_collection()
GC_words_allocd = 0;
GC_words_wasted = 0;
GC_mem_freed = 0;
+ GC_finalizer_mem_freed = 0;
# ifdef USE_MUNMAP
GC_unmap_old();
@@ -730,6 +756,7 @@ void GC_finish_collection()
int result;
DCL_LOCK_STATE;
+ if (GC_debugging_started) GC_print_all_smashed();
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
@@ -741,14 +768,17 @@ void GC_finish_collection()
EXIT_GC();
UNLOCK();
ENABLE_SIGNALS();
- if(result) GC_INVOKE_FINALIZERS();
+ if(result) {
+ if (GC_debugging_started) GC_print_all_smashed();
+ GC_INVOKE_FINALIZERS();
+ }
return(result);
}
void GC_gcollect GC_PROTO(())
{
- GC_notify_full_gc();
(void)GC_try_to_collect(GC_never_stop_func);
+ if (GC_have_errors) GC_print_all_errors();
}
word GC_n_heap_sects = 0; /* Number of sections currently in heap. */
@@ -950,7 +980,6 @@ GC_bool ignore_off_page;
{
if (!GC_incremental && !GC_dont_gc &&
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
- GC_notify_full_gc();
GC_gcollect_inner();
} else {
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
@@ -975,7 +1004,6 @@ GC_bool ignore_off_page;
&& !GC_expand_hp_inner(needed_blocks)) {
if (GC_fail_count++ < GC_max_retries) {
WARN("Out of Memory! Trying to continue ...\n", 0);
- GC_notify_full_gc();
GC_gcollect_inner();
} else {
# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
@@ -1005,29 +1033,38 @@ ptr_t GC_allocobj(sz, kind)
word sz;
int kind;
{
- register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]);
+ ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]);
+ GC_bool tried_minor = FALSE;
if (sz == 0) return(0);
while (*flh == 0) {
ENTER_GC();
/* Do our share of marking work */
- if(GC_incremental && !GC_dont_gc) GC_collect_a_little_inner(1);
+ if(TRUE_INCREMENTAL) GC_collect_a_little_inner(1);
/* Sweep blocks for objects of this size */
- GC_continue_reclaim(sz, kind);
+ GC_continue_reclaim(sz, kind);
EXIT_GC();
if (*flh == 0) {
GC_new_hblk(sz, kind);
}
if (*flh == 0) {
ENTER_GC();
- if (!GC_collect_or_expand((word)1,FALSE)) {
+ if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED
+ && ! tried_minor ) {
+ GC_collect_a_little_inner(1);
+ tried_minor = TRUE;
+ } else {
+ if (!GC_collect_or_expand((word)1,FALSE)) {
EXIT_GC();
return(0);
+ }
}
EXIT_GC();
}
}
+ /* Successful allocation; reset failure count. */
+ GC_fail_count = 0;
return(*flh);
}