summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/ChangeLog33
-rw-r--r--libguile/gc-freelist.c5
-rw-r--r--libguile/gc-malloc.c10
-rw-r--r--libguile/gc-segment.c83
-rw-r--r--libguile/gc.c63
-rw-r--r--libguile/private-gc.h43
6 files changed, 165 insertions, 72 deletions
diff --git a/libguile/ChangeLog b/libguile/ChangeLog
index af7502e2e..1da6c4c28 100644
--- a/libguile/ChangeLog
+++ b/libguile/ChangeLog
@@ -1,3 +1,36 @@
+2006-01-04 Ludovic Court<E8>s <ludovic.courtes@laas.fr>
+
+ * gc-segment.c (scm_i_sweep_some_cards): Take a SWEEP_STATS
+ argument. Don't refer to SCM_GC_CELLS_COLLECTED and
+ SCM_CELLS_ALLOCATED. If SEG->FIRST_TIME, let CELLS_COLLECTED as zero.
+ Take into account SEG->SPAN when computing CELLS_SWEPT.
+ (scm_i_sweep_segment): Take one more argument, similarly.
+ (scm_i_sweep_all_segments): Likewise.
+ (scm_i_sweep_some_segments): Likewise.
+ (scm_i_adjust_min_yield): Change the way MIN_CELLS is computed: do not
+ refer to SCM_GC_CELLS_COLLECTED.
+
+ * gc-freelist.c (scm_i_adjust_min_yield): Take one more
+ argument, an `scm_i_sweep_statistics' object.
+ Change the way DELTA is collected: don't take into account
+ SCM_GC_CELLS_COLLECTED_1, only SWEEP_STATS.COLLECTED.
+
+ * gc-malloc.c (scm_realloc): Pass an extra argument
+ to `scm_i_sweep_all_segments ()'.
+
+ * gc.c (gc_start_stats): Updated accordingly.
+ (gc_end_stats): Take an additional SWEEP_STATS argument.
+ Decrement SCM_CELLS_ALLOCATED after calls to `scm_i_sweep_* ()'.
+ (scm_gc_for_newcell): Updated callers of `scm_i_sweep_*'.
+ Decrement SCM_CELLS_ALLOCATED.
+ (scm_i_gc): Likewise.
+
+ * private-gc.h (scm_i_sweep_*): Updated function
+ prototypes accordingly.
+ (scm_t_sweep_statistics): New type.
+ (scm_i_sweep_statistics_init): New macro.
+ (scm_i_sweep_statistics_sum): New macro
+
2006-02-12 Marius Vollmer <mvo@zagadka.de>
* unif.c (scm_dimensions_to_uniform_array): Use the prototype for
diff --git a/libguile/gc-freelist.c b/libguile/gc-freelist.c
index 8bf3cc6d1..7a144c228 100644
--- a/libguile/gc-freelist.c
+++ b/libguile/gc-freelist.c
@@ -78,7 +78,8 @@ SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1
*/
void
-scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist)
+scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
+ scm_t_sweep_statistics sweep_stats)
{
/* min yield is adjusted upwards so that next predicted total yield
* (allocated cells actually freed by GC) becomes
@@ -98,7 +99,7 @@ scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist)
{
/* Pick largest of last two yields. */
long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100)
- - (long) SCM_MAX (scm_gc_cells_collected_1, scm_gc_cells_collected));
+ - (long) sweep_stats.collected);
#ifdef DEBUGINFO
fprintf (stderr, " after GC = %lu, delta = %ld\n",
(unsigned long) scm_cells_allocated,
diff --git a/libguile/gc-malloc.c b/libguile/gc-malloc.c
index e88263afb..ccdc58323 100644
--- a/libguile/gc-malloc.c
+++ b/libguile/gc-malloc.c
@@ -105,6 +105,7 @@ void *
scm_realloc (void *mem, size_t size)
{
void *ptr;
+ scm_t_sweep_statistics sweep_stats;
SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr)
@@ -113,7 +114,7 @@ scm_realloc (void *mem, size_t size)
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1;
- scm_i_sweep_all_segments ("realloc");
+ scm_i_sweep_all_segments ("realloc", &sweep_stats);
SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr)
@@ -124,7 +125,7 @@ scm_realloc (void *mem, size_t size)
}
scm_i_gc ("realloc");
- scm_i_sweep_all_segments ("realloc");
+ scm_i_sweep_all_segments ("realloc", &sweep_stats);
scm_gc_running_p = 0;
scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
@@ -220,13 +221,14 @@ increase_mtrigger (size_t size, const char *what)
{
unsigned long prev_alloced;
float yield;
-
+ scm_t_sweep_statistics sweep_stats;
+
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1;
prev_alloced = mallocated;
scm_i_gc (what);
- scm_i_sweep_all_segments ("mtrigger");
+ scm_i_sweep_all_segments ("mtrigger", &sweep_stats);
yield = (((float) prev_alloced - (float) scm_mallocated)
/ (float) prev_alloced);
diff --git a/libguile/gc-segment.c b/libguile/gc-segment.c
index 925582629..9e3f3f8e3 100644
--- a/libguile/gc-segment.c
+++ b/libguile/gc-segment.c
@@ -140,15 +140,13 @@ scm_i_clear_segment_mark_space (scm_t_heap_segment *seg)
scm_i_segment_card_count (seg) * SCM_GC_CARD_BVEC_SIZE_IN_LONGS * SCM_SIZEOF_LONG);
}
-/*
- Sweep cards from SEG until we've gathered THRESHOLD cells
-
- RETURN:
-
- Freelist.
-*/
+/* Sweep cards from SEG until we've gathered THRESHOLD cells. On return,
+ *CELLS_SWEPT contains the number of cells that have been visited and
+ *CELLS_COLLECTED contains the number of cells actually collected. A
+ freelist is returned, potentially empty. */
SCM
-scm_i_sweep_some_cards (scm_t_heap_segment *seg)
+scm_i_sweep_some_cards (scm_t_heap_segment *seg,
+ scm_t_sweep_statistics *sweep_stats)
{
SCM cells = SCM_EOL;
int threshold = 512;
@@ -158,7 +156,7 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg)
scm_t_cell * next_free = seg->next_free_card;
int cards_swept = 0;
-
+
while (collected < threshold && next_free < seg->bounds[1])
{
collected += (*sweeper) (next_free, &cells, seg);
@@ -166,14 +164,18 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg)
cards_swept ++;
}
- scm_gc_cells_swept += cards_swept * (SCM_GC_CARD_N_CELLS - SCM_GC_CARD_N_HEADER_CELLS);
- scm_gc_cells_collected += collected * seg->span;
+ sweep_stats->swept = cards_swept * seg->span
+ * (SCM_GC_CARD_N_CELLS - SCM_GC_CARD_N_HEADER_CELLS);
if (!seg->first_time)
- scm_cells_allocated -= collected * seg->span;
-
- seg->freelist->collected += collected * seg->span;
-
+ {
+ /* scm_cells_allocated -= collected * seg->span; */
+ sweep_stats->collected = collected * seg->span;
+ }
+ else
+ sweep_stats->collected = 0;
+
+ seg->freelist->collected += collected * seg->span;
if(next_free == seg->bounds[1])
{
@@ -196,31 +198,33 @@ scm_i_sweep_some_cards (scm_t_heap_segment *seg)
segment again, the statistics are off.
*/
void
-scm_i_sweep_segment (scm_t_heap_segment * seg)
+scm_i_sweep_segment (scm_t_heap_segment *seg,
+ scm_t_sweep_statistics *sweep_stats)
{
+ scm_t_sweep_statistics sweep;
scm_t_cell * p = seg->next_free_card;
- int yield = scm_gc_cells_collected;
- int coll = seg->freelist->collected;
- unsigned long alloc = scm_cells_allocated ;
-
- while (scm_i_sweep_some_cards (seg) != SCM_EOL)
- ;
- scm_gc_cells_collected = yield;
- scm_cells_allocated = alloc;
- seg->freelist->collected = coll;
-
+ scm_i_sweep_statistics_init (sweep_stats);
+
+ while (scm_i_sweep_some_cards (seg, &sweep) != SCM_EOL)
+ scm_i_sweep_statistics_sum (sweep_stats, sweep);
+
seg->next_free_card =p;
}
void
-scm_i_sweep_all_segments (char const *reason)
+scm_i_sweep_all_segments (char const *reason,
+ scm_t_sweep_statistics *sweep_stats)
{
- int i= 0;
+ unsigned i= 0;
+ scm_i_sweep_statistics_init (sweep_stats);
for (i = 0; i < scm_i_heap_segment_table_size; i++)
{
- scm_i_sweep_segment (scm_i_heap_segment_table[i]);
+ scm_t_sweep_statistics sweep;
+
+ scm_i_sweep_segment (scm_i_heap_segment_table[i], &sweep);
+ scm_i_sweep_statistics_sum (sweep_stats, sweep);
}
}
@@ -317,29 +321,35 @@ scm_i_insert_segment (scm_t_heap_segment * seg)
}
SCM
-scm_i_sweep_some_segments (scm_t_cell_type_statistics * fl)
+scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
+ scm_t_sweep_statistics *sweep_stats)
{
int i = fl->heap_segment_idx;
SCM collected = SCM_EOL;
-
+
+ scm_i_sweep_statistics_init (sweep_stats);
if (i == -1)
i++;
-
+
for (;
i < scm_i_heap_segment_table_size; i++)
{
+ scm_t_sweep_statistics sweep;
+
if (scm_i_heap_segment_table[i]->freelist != fl)
continue;
-
- collected = scm_i_sweep_some_cards (scm_i_heap_segment_table[i]);
+ collected = scm_i_sweep_some_cards (scm_i_heap_segment_table[i],
+ &sweep);
+
+ scm_i_sweep_statistics_sum (sweep_stats, sweep);
if (collected != SCM_EOL) /* Don't increment i */
break;
}
fl->heap_segment_idx = i;
-
+
return collected;
}
@@ -479,8 +489,7 @@ scm_i_get_new_heap_segment (scm_t_cell_type_statistics *freelist,
*/
float f = freelist->min_yield_fraction / 100.0;
float h = SCM_HEAP_SIZE;
- float min_cells
- = (f * h - scm_gc_cells_collected) / (1.0 - f);
+ float min_cells = (f * h - scm_gc_cells_collected) / (1.0 - f);
/* Make heap grow with factor 1.5 */
len = freelist->heap_size / 2;
diff --git a/libguile/gc.c b/libguile/gc.c
index 6141ff26c..1602be547 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -403,31 +403,32 @@ gc_start_stats (const char *what SCM_UNUSED)
{
t_before_gc = scm_c_get_internal_run_time ();
- scm_gc_cells_marked_acc += (double) scm_gc_cells_swept
- - (double) scm_gc_cells_collected;
- scm_gc_cells_swept_acc += (double) scm_gc_cells_swept;
-
- scm_gc_cell_yield_percentage = ( scm_gc_cells_collected * 100 ) / SCM_HEAP_SIZE;
-
- scm_gc_cells_swept = 0;
- scm_gc_cells_collected_1 = scm_gc_cells_collected;
-
- /*
- CELLS SWEPT is another word for the number of cells that were
- examined during GC. YIELD is the number that we cleaned
- out. MARKED is the number that weren't cleaned.
- */
- scm_gc_cells_collected = 0;
scm_gc_malloc_collected = 0;
scm_gc_ports_collected = 0;
}
static void
-gc_end_stats ()
+gc_end_stats (scm_t_sweep_statistics sweep_stats)
{
unsigned long t = scm_c_get_internal_run_time ();
scm_gc_time_taken += (t - t_before_gc);
+ /*
+ CELLS SWEPT is another word for the number of cells that were
+ examined during GC. YIELD is the number that we cleaned
+ out. MARKED is the number that weren't cleaned.
+ */
+ scm_gc_cells_marked_acc += (double) sweep_stats.swept
+ - (double) scm_gc_cells_collected;
+ scm_gc_cells_swept_acc += (double) sweep_stats.swept;
+
+ scm_gc_cell_yield_percentage = (sweep_stats.collected * 100) / SCM_HEAP_SIZE;
+
+ scm_gc_cells_swept = sweep_stats.swept;
+ scm_gc_cells_collected_1 = scm_gc_cells_collected;
+ scm_gc_cells_collected = sweep_stats.collected;
+ scm_cells_allocated -= sweep_stats.collected;
+
++scm_gc_times;
}
@@ -478,15 +479,19 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
{
SCM cell;
int did_gc = 0;
-
+ scm_t_sweep_statistics sweep_stats;
+
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
scm_gc_running_p = 1;
- *free_cells = scm_i_sweep_some_segments (freelist);
+ *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
+ scm_cells_allocated -= sweep_stats.collected;
+
if (*free_cells == SCM_EOL && scm_i_gc_grow_heap_p (freelist))
{
freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
- *free_cells = scm_i_sweep_some_segments (freelist);
+ *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
+ scm_cells_allocated -= sweep_stats.collected;
}
if (*free_cells == SCM_EOL)
@@ -495,7 +500,7 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
with the advent of lazy sweep, GC yield is only known just
before doing the GC.
*/
- scm_i_adjust_min_yield (freelist);
+ scm_i_adjust_min_yield (freelist, sweep_stats);
/*
out of fresh cells. Try to get some new ones.
@@ -504,7 +509,8 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
did_gc = 1;
scm_i_gc ("cells");
- *free_cells = scm_i_sweep_some_segments (freelist);
+ *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
+ scm_cells_allocated -= sweep_stats.collected;
}
if (*free_cells == SCM_EOL)
@@ -513,7 +519,8 @@ scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
failed getting new cells. Get new juice or die.
*/
freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
- *free_cells = scm_i_sweep_some_segments (freelist);
+ *free_cells = scm_i_sweep_some_segments (freelist, &sweep_stats);
+ scm_cells_allocated -= sweep_stats.collected;
}
if (*free_cells == SCM_EOL)
@@ -545,6 +552,8 @@ scm_t_c_hook scm_after_gc_c_hook;
void
scm_i_gc (const char *what)
{
+ scm_t_sweep_statistics sweep_stats;
+
scm_i_thread_put_to_sleep ();
scm_c_hook_run (&scm_before_gc_c_hook, 0);
@@ -571,7 +580,12 @@ scm_i_gc (const char *what)
Let's finish the sweep. The conservative GC might point into the
garbage, and marking that would create a mess.
*/
- scm_i_sweep_all_segments("GC");
+ scm_i_sweep_all_segments ("GC", &sweep_stats);
+
+ /* Invariant: the number of cells collected (i.e., freed) must always be
+ lower than or equal to the number of cells "swept" (i.e., visited). */
+ assert (sweep_stats.collected <= sweep_stats.swept);
+
if (scm_mallocated < scm_i_deprecated_memory_return)
{
/* The byte count of allocated objects has underflowed. This is
@@ -624,7 +638,7 @@ scm_i_gc (const char *what)
scm_gc_sweep ();
scm_c_hook_run (&scm_after_sweep_c_hook, 0);
- gc_end_stats ();
+ gc_end_stats (sweep_stats);
scm_i_thread_wake_up ();
@@ -635,6 +649,7 @@ scm_i_gc (const char *what)
*/
}
+
/* {GC Protection Helper Functions}
*/
diff --git a/libguile/private-gc.h b/libguile/private-gc.h
index 97ce63232..7cb1fbff4 100644
--- a/libguile/private-gc.h
+++ b/libguile/private-gc.h
@@ -118,11 +118,40 @@ typedef struct scm_t_cell_type_statistics {
} scm_t_cell_type_statistics;
+/* Sweep statistics. */
+typedef struct scm_sweep_statistics
+{
+ /* Number of cells "swept", i.e., visited during the sweep operation. */
+ unsigned swept;
+
+ /* Number of cells collected during the sweep operation. This number must
+ alsways be lower than or equal to SWEPT. */
+ unsigned collected;
+} scm_t_sweep_statistics;
+
+#define scm_i_sweep_statistics_init(_stats) \
+ do \
+ { \
+ (_stats)->swept = (_stats)->collected = 0; \
+ } \
+ while (0)
+
+#define scm_i_sweep_statistics_sum(_sum, _addition) \
+ do \
+ { \
+ (_sum)->swept += (_addition).swept; \
+ (_sum)->collected += (_addition).collected; \
+ } \
+ while (0)
+
+
+
extern scm_t_cell_type_statistics scm_i_master_freelist;
extern scm_t_cell_type_statistics scm_i_master_freelist2;
extern unsigned long scm_gc_cells_collected_1;
-void scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist);
+void scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
+ scm_t_sweep_statistics sweep_stats);
void scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist);
int scm_i_gc_grow_heap_p (scm_t_cell_type_statistics * freelist);
@@ -221,8 +250,10 @@ int scm_i_segment_cell_count (scm_t_heap_segment * seg);
void scm_i_clear_segment_mark_space (scm_t_heap_segment *seg);
scm_t_heap_segment * scm_i_make_empty_heap_segment (scm_t_cell_type_statistics*);
-SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg);
-void scm_i_sweep_segment (scm_t_heap_segment * seg);
+SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg,
+ scm_t_sweep_statistics *sweep_stats);
+void scm_i_sweep_segment (scm_t_heap_segment *seg,
+ scm_t_sweep_statistics *sweep_stats);
void scm_i_heap_segment_statistics (scm_t_heap_segment *seg, SCM tab);
@@ -232,9 +263,11 @@ long int scm_i_find_heap_segment_containing_object (SCM obj);
int scm_i_get_new_heap_segment (scm_t_cell_type_statistics *, policy_on_error);
void scm_i_clear_mark_space (void);
void scm_i_sweep_segments (void);
-SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics * fl);
+SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
+ scm_t_sweep_statistics *sweep_stats);
void scm_i_reset_segments (void);
-void scm_i_sweep_all_segments (char const *reason);
+void scm_i_sweep_all_segments (char const *reason,
+ scm_t_sweep_statistics *sweep_stats);
SCM scm_i_all_segments_statistics (SCM hashtab);
void scm_i_make_initial_segment (int init_heap_size, scm_t_cell_type_statistics *freelist);