Garbage collection cleanup.
[bpt/guile.git] / libguile / gc-freelist.c
CommitLineData
2b829bbb 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2006 Free Software Foundation, Inc.
c7743d02 2 *
73be1d9e
MV
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.
c7743d02 7 *
73be1d9e 8 * This library is distributed in the hope that it will be useful,
c7743d02 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
c7743d02 12 *
73be1d9e
MV
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
92205699 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 16 */
c7743d02
HWN
17
18#include <assert.h>
5bd4a949 19#include <stdio.h>
c7743d02
HWN
20
21#include "libguile/private-gc.h"
22#include "libguile/gc.h"
23#include "libguile/deprecation.h"
24#include "libguile/private-gc.h"
25
26scm_t_cell_type_statistics scm_i_master_freelist;
27scm_t_cell_type_statistics scm_i_master_freelist2;
28
c7743d02
HWN
29/*
30
31In older versions of GUILE GC there was extensive support for
32debugging freelists. This was useful, since the freelist was kept
33inside the heap, and writing to an object that was GC'd would mangle
34the list. Mark bits are now separate, and checking for sane cell
35access can be done much more easily by simply checking if the mark bit
36is unset before allocation. --hwn
37
c7743d02
HWN
38*/
39
40#if (SCM_ENABLE_DEPRECATED == 1)
41#if defined(GUILE_DEBUG_FREELIST)
42
43SCM_DEFINE (scm_map_free_list, "map-free-list", 0, 0, 0,
44 (),
45 "DEPRECATED\n")
2e945bcc 46#define FUNC_NAME "s_scm_map_free_list"
c7743d02
HWN
47{
48 scm_c_issue_deprecation_warning ("map-free-list has been removed from GUILE. Doing nothing\n");
49 return SCM_UNSPECIFIED;
50}
2e945bcc 51#undef FUNC_NAME
c7743d02
HWN
52
53SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
54 (SCM flag),
55 "DEPRECATED.\n")
2e945bcc 56#define FUNC_NAME "s_scm_gc_set_debug_check_freelist_x"
c7743d02
HWN
57{
58 scm_c_issue_deprecation_warning ("gc-set-debug-check-freelist! has been removed from GUILE. Doing nothing\n");
59 return SCM_UNSPECIFIED;
60}
61#undef FUNC_NAME
62
63
64#endif /* defined (GUILE_DEBUG) */
65#endif /* deprecated */
66
c7743d02
HWN
67static void
68scm_init_freelist (scm_t_cell_type_statistics *freelist,
82ae1b8e
HWN
69 int span,
70 int min_yield_percentage)
c7743d02 71{
82ae1b8e
HWN
72 if (min_yield_percentage < 1)
73 min_yield_percentage = 1;
74 if (min_yield_percentage > 99)
75 min_yield_percentage = 99;
dac04e9f 76
c7743d02 77 freelist->heap_segment_idx = -1;
82ae1b8e 78 freelist->min_yield_fraction = min_yield_percentage / 100.0;
c7743d02 79 freelist->span = span;
82ae1b8e 80 freelist->swept = 0;
c7743d02 81 freelist->collected = 0;
82ae1b8e 82 freelist->heap_total_cells = 0;
c7743d02
HWN
83}
84
85#if (SCM_ENABLE_DEPRECATED == 1)
82ae1b8e
HWN
86size_t scm_default_init_heap_size_1;
87int scm_default_min_yield_1;
88size_t scm_default_init_heap_size_2;
89int scm_default_min_yield_2;
90size_t scm_default_max_segment_size;
91
92static void
93check_deprecated_heap_vars (void) {
94 if (scm_default_init_heap_size_1 ||
95 scm_default_min_yield_1||
96 scm_default_init_heap_size_2||
97 scm_default_min_yield_2||
98 scm_default_max_segment_size)
99 {
100 scm_c_issue_deprecation_warning ("Tuning heap parameters with C variables is deprecated. Use environment variables instead.");
101 }
102}
103#else
104static void check_deprecated_heap_vars (void) { }
c7743d02
HWN
105#endif
106
107void
108scm_gc_init_freelist (void)
109{
82ae1b8e
HWN
110 const char *error_message =
111 "Could not allocate initial heap of %uld.\n"
112 "Try adjusting GUILE_INIT_SEGMENT_SIZE_%d\n";
113
dac04e9f 114 int init_heap_size_1
c7743d02 115 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_1", SCM_DEFAULT_INIT_HEAP_SIZE_1);
dac04e9f 116 int init_heap_size_2
c7743d02
HWN
117 = scm_getenv_int ("GUILE_INIT_SEGMENT_SIZE_2", SCM_DEFAULT_INIT_HEAP_SIZE_2);
118
c7743d02
HWN
119 scm_init_freelist (&scm_i_master_freelist2, 2,
120 scm_getenv_int ("GUILE_MIN_YIELD_2", SCM_DEFAULT_MIN_YIELD_2));
121 scm_init_freelist (&scm_i_master_freelist, 1,
122 scm_getenv_int ("GUILE_MIN_YIELD_1", SCM_DEFAULT_MIN_YIELD_1));
123
c7743d02 124 scm_max_segment_size = scm_getenv_int ("GUILE_MAX_SEGMENT_SIZE", SCM_DEFAULT_MAX_SEGMENT_SIZE);
dac04e9f
HWN
125
126 if (scm_max_segment_size <= 0)
127 scm_max_segment_size = SCM_DEFAULT_MAX_SEGMENT_SIZE;
82ae1b8e
HWN
128
129 if (scm_i_get_new_heap_segment (&scm_i_master_freelist,
130 init_heap_size_1, return_on_error) == -1) {
131 fprintf (stderr, error_message, init_heap_size_1, 1);
132 abort();
133 }
134 if (scm_i_get_new_heap_segment (&scm_i_master_freelist2,
135 init_heap_size_2, return_on_error) == -1) {
136 fprintf (stderr, error_message, init_heap_size_2, 2);
137 abort();
138 }
139
140 check_deprecated_heap_vars();
c7743d02
HWN
141}
142
143
82ae1b8e 144
c7743d02
HWN
145void
146scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist)
147{
c7743d02 148 freelist->collected = 0;
82ae1b8e 149 freelist->swept = 0;
c7743d02
HWN
150 /*
151 at the end we simply start with the lowest segment again.
152 */
153 freelist->heap_segment_idx = -1;
154}
155
82ae1b8e
HWN
156
157/*
158 Returns how many more cells we should allocate according to our
159 policy. May return negative if we don't need to allocate more.
160
161
162 The new yield should at least equal gc fraction of new heap size, i.e.
163
164 c + dh > f * (h + dh)
165
166 c : collected
167 f : min yield fraction
168 h : heap size
169 dh : size of new heap segment
170
171 this gives dh > (f * h - c) / (1 - f).
172*/
173float
174scm_i_gc_heap_size_delta (scm_t_cell_type_statistics * freelist)
c7743d02 175{
82ae1b8e
HWN
176 float f = freelist->min_yield_fraction;
177 float collected = freelist->collected;
178 float swept = freelist->swept;
179 float delta = ((f * swept - collected) / (1.0 - f));
180
181 assert(freelist->heap_total_cells >= freelist->collected);
182 assert(freelist->swept == freelist->heap_total_cells);
183 assert(swept >= collected);
184
185 return delta;
c7743d02 186}