Changes from arch/CVS synchronization
[bpt/guile.git] / libguile / gc-freelist.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2006 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include <assert.h>
19 #include <stdio.h>
20
21 #include "libguile/private-gc.h"
22 #include "libguile/gc.h"
23 #include "libguile/deprecation.h"
24 #include "libguile/private-gc.h"
25
26 scm_t_cell_type_statistics scm_i_master_freelist;
27 scm_t_cell_type_statistics scm_i_master_freelist2;
28
29
30
31
32 /*
33
34 In older versions of GUILE GC there was extensive support for
35 debugging freelists. This was useful, since the freelist was kept
36 inside the heap, and writing to an object that was GC'd would mangle
37 the list. Mark bits are now separate, and checking for sane cell
38 access can be done much more easily by simply checking if the mark bit
39 is unset before allocation. --hwn
40
41
42
43 */
44
45 #if (SCM_ENABLE_DEPRECATED == 1)
46 #if defined(GUILE_DEBUG_FREELIST)
47
48 SCM_DEFINE (scm_map_free_list, "map-free-list", 0, 0, 0,
49 (),
50 "DEPRECATED\n")
51 #define FUNC_NAME "s_scm_map_free_list"
52 {
53 scm_c_issue_deprecation_warning ("map-free-list has been removed from GUILE. Doing nothing\n");
54 return SCM_UNSPECIFIED;
55 }
56 #undef FUNC_NAME
57
58 SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
59 (SCM flag),
60 "DEPRECATED.\n")
61 #define FUNC_NAME "s_scm_gc_set_debug_check_freelist_x"
62 {
63 scm_c_issue_deprecation_warning ("gc-set-debug-check-freelist! has been removed from GUILE. Doing nothing\n");
64 return SCM_UNSPECIFIED;
65 }
66 #undef FUNC_NAME
67
68
69 #endif /* defined (GUILE_DEBUG) */
70 #endif /* deprecated */
71
72
73
74
75 /* Adjust FREELIST variables to decide wether or not to allocate more heap in
76 the next GC run based on SWEEP_STATS on SWEEP_STATS_1 (statistics
77 collected after the two last full GC). */
78 void
79 scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
80 scm_t_sweep_statistics sweep_stats,
81 scm_t_sweep_statistics sweep_stats_1)
82 {
83 /* min yield is adjusted upwards so that next predicted total yield
84 * (allocated cells actually freed by GC) becomes
85 * `min_yield_fraction' of total heap size. Note, however, that
86 * the absolute value of min_yield will correspond to `collected'
87 * on one master (the one which currently is triggering GC).
88 *
89 * The reason why we look at total yield instead of cells collected
90 * on one list is that we want to take other freelists into account.
91 * On this freelist, we know that (local) yield = collected cells,
92 * but that's probably not the case on the other lists.
93 *
94 * (We might consider computing a better prediction, for example
95 * by computing an average over multiple GC:s.)
96 */
97 if (freelist->min_yield_fraction)
98 {
99 /* Pick largest of last two yields. */
100 long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100)
101 - (long) SCM_MAX (sweep_stats.collected,
102 sweep_stats_1.collected));
103 #ifdef DEBUGINFO
104 fprintf (stderr, " after GC = %lu, delta = %ld\n",
105 (unsigned long) scm_cells_allocated,
106 (long) delta);
107 #endif
108 if (delta > 0)
109 freelist->min_yield += delta;
110 }
111 }
112
113
114 static void
115 scm_init_freelist (scm_t_cell_type_statistics *freelist,
116 int span,
117 int min_yield)
118 {
119 if (min_yield < 1)
120 min_yield = 1;
121 if (min_yield > 99)
122 min_yield = 99;
123
124 freelist->heap_segment_idx = -1;
125 freelist->min_yield = 0;
126 freelist->min_yield_fraction = min_yield;
127 freelist->span = span;
128 freelist->collected = 0;
129 freelist->collected_1 = 0;
130 freelist->heap_size = 0;
131 }
132
133 #if (SCM_ENABLE_DEPRECATED == 1)
134 size_t scm_default_init_heap_size_1;
135 int scm_default_min_yield_1;
136 size_t scm_default_init_heap_size_2;
137 int scm_default_min_yield_2;
138 size_t scm_default_max_segment_size;
139 #endif
140
141 void
142 scm_gc_init_freelist (void)
143 {
144 int init_heap_size_1
145 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_1", SCM_DEFAULT_INIT_HEAP_SIZE_1);
146 int init_heap_size_2
147 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_2", SCM_DEFAULT_INIT_HEAP_SIZE_2);
148
149 scm_init_freelist (&scm_i_master_freelist2, 2,
150 scm_getenv_int ("GUILE_MIN_YIELD_2", SCM_DEFAULT_MIN_YIELD_2));
151 scm_init_freelist (&scm_i_master_freelist, 1,
152 scm_getenv_int ("GUILE_MIN_YIELD_1", SCM_DEFAULT_MIN_YIELD_1));
153
154 scm_max_segment_size = scm_getenv_int ("GUILE_MAX_SEGMENT_SIZE", SCM_DEFAULT_MAX_SEGMENT_SIZE);
155
156 if (scm_max_segment_size <= 0)
157 scm_max_segment_size = SCM_DEFAULT_MAX_SEGMENT_SIZE;
158
159
160 scm_i_make_initial_segment (init_heap_size_1, &scm_i_master_freelist);
161 scm_i_make_initial_segment (init_heap_size_2, &scm_i_master_freelist2);
162
163 #if (SCM_ENABLE_DEPRECATED == 1)
164 if ( scm_default_init_heap_size_1 ||
165 scm_default_min_yield_1||
166 scm_default_init_heap_size_2||
167 scm_default_min_yield_2||
168 scm_default_max_segment_size)
169 {
170 scm_c_issue_deprecation_warning ("Tuning heap parameters with C variables is deprecated. Use environment variables instead.");
171 }
172 #endif
173 }
174
175
176 void
177 scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist)
178 {
179 freelist->collected_1 = freelist->collected;
180 freelist->collected = 0;
181
182 /*
183 at the end we simply start with the lowest segment again.
184 */
185 freelist->heap_segment_idx = -1;
186 }
187
188 int
189 scm_i_gc_grow_heap_p (scm_t_cell_type_statistics * freelist)
190 {
191 return SCM_MAX (freelist->collected,freelist->collected_1) < freelist->min_yield;
192 }