*** empty log message ***
[bpt/guile.git] / libguile / gc-freelist.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
57 SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
58 (SCM flag),
59 "DEPRECATED.\n")
60 #define FUNC_NAME s_scm_gc_set_debug_check_freelist_x
61 {
62 scm_c_issue_deprecation_warning ("gc-set-debug-check-freelist! has been removed from GUILE. Doing nothing\n");
63 return SCM_UNSPECIFIED;
64 }
65 #undef FUNC_NAME
66
67
68 #endif /* defined (GUILE_DEBUG) */
69 #endif /* deprecated */
70
71
72
73
74 /*
75 This adjust FREELIST variables to decide wether or not to allocate
76 more heap in the next GC run. It uses scm_gc_cells_collected and scm_gc_cells_collected1
77 */
78
79 void
80 scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist)
81 {
82 /* min yield is adjusted upwards so that next predicted total yield
83 * (allocated cells actually freed by GC) becomes
84 * `min_yield_fraction' of total heap size. Note, however, that
85 * the absolute value of min_yield will correspond to `collected'
86 * on one master (the one which currently is triggering GC).
87 *
88 * The reason why we look at total yield instead of cells collected
89 * on one list is that we want to take other freelists into account.
90 * On this freelist, we know that (local) yield = collected cells,
91 * but that's probably not the case on the other lists.
92 *
93 * (We might consider computing a better prediction, for example
94 * by computing an average over multiple GC:s.)
95 */
96 if (freelist->min_yield_fraction)
97 {
98 /* Pick largest of last two yields. */
99 long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100)
100 - (long) SCM_MAX (scm_gc_cells_collected_1, scm_gc_cells_collected));
101 #ifdef DEBUGINFO
102 fprintf (stderr, " after GC = %lu, delta = %ld\n",
103 (unsigned long) scm_cells_allocated,
104 (long) delta);
105 #endif
106 if (delta > 0)
107 freelist->min_yield += delta;
108 }
109 }
110
111
112 static void
113 scm_init_freelist (scm_t_cell_type_statistics *freelist,
114 int span,
115 int min_yield)
116 {
117 if (min_yield < 1)
118 min_yield = 1;
119 if (min_yield > 99)
120 min_yield = 99;
121
122 freelist->heap_segment_idx = -1;
123 freelist->min_yield = 0;
124 freelist->min_yield_fraction = min_yield;
125 freelist->span = span;
126 freelist->collected = 0;
127 freelist->collected_1 = 0;
128 freelist->heap_size = 0;
129 }
130
131 #if (SCM_ENABLE_DEPRECATED == 1)
132 size_t scm_default_init_heap_size_1;
133 int scm_default_min_yield_1;
134 size_t scm_default_init_heap_size_2;
135 int scm_default_min_yield_2;
136 size_t scm_default_max_segment_size;
137 #endif
138
139 void
140 scm_gc_init_freelist (void)
141 {
142 int init_heap_size_1
143 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_1", SCM_DEFAULT_INIT_HEAP_SIZE_1);
144 int init_heap_size_2
145 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_2", SCM_DEFAULT_INIT_HEAP_SIZE_2);
146
147 /* These are the thread-local freelists. */
148 scm_key_create (&scm_i_freelist, free);
149 scm_key_create (&scm_i_freelist2, free);
150 SCM_FREELIST_CREATE (scm_i_freelist);
151 SCM_FREELIST_CREATE (scm_i_freelist2);
152
153 scm_init_freelist (&scm_i_master_freelist2, 2,
154 scm_getenv_int ("GUILE_MIN_YIELD_2", SCM_DEFAULT_MIN_YIELD_2));
155 scm_init_freelist (&scm_i_master_freelist, 1,
156 scm_getenv_int ("GUILE_MIN_YIELD_1", SCM_DEFAULT_MIN_YIELD_1));
157
158 scm_max_segment_size = scm_getenv_int ("GUILE_MAX_SEGMENT_SIZE", SCM_DEFAULT_MAX_SEGMENT_SIZE);
159
160 if (scm_max_segment_size <= 0)
161 scm_max_segment_size = SCM_DEFAULT_MAX_SEGMENT_SIZE;
162
163
164 scm_i_make_initial_segment (init_heap_size_1, &scm_i_master_freelist);
165 scm_i_make_initial_segment (init_heap_size_2, &scm_i_master_freelist2);
166
167 #if (SCM_ENABLE_DEPRECATED == 1)
168 if ( scm_default_init_heap_size_1 ||
169 scm_default_min_yield_1||
170 scm_default_init_heap_size_2||
171 scm_default_min_yield_2||
172 scm_default_max_segment_size)
173 {
174 scm_c_issue_deprecation_warning ("Tuning heap parameters with C variables is deprecated. Use environment variables instead.");
175 }
176 #endif
177 }
178
179
180 void
181 scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist)
182 {
183 freelist->collected_1 = freelist->collected;
184 freelist->collected = 0;
185
186 /*
187 at the end we simply start with the lowest segment again.
188 */
189 freelist->heap_segment_idx = -1;
190 }
191
192 int
193 scm_i_gc_grow_heap_p (scm_t_cell_type_statistics * freelist)
194 {
195 return SCM_MAX (freelist->collected,freelist->collected_1) < freelist->min_yield;
196 }