more code
[bpt/guile.git] / libguile / gc-malloc.c
CommitLineData
c7743d02
HWN
1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42
43\f
44#include <stdio.h>
45#include <errno.h>
46#include <string.h>
47
48#ifdef __ia64__
49#include <ucontext.h>
50extern unsigned long * __libc_ia64_register_backing_store_base;
51#endif
52
53#include "libguile/_scm.h"
54#include "libguile/eval.h"
55#include "libguile/stime.h"
56#include "libguile/stackchk.h"
57#include "libguile/struct.h"
58#include "libguile/smob.h"
59#include "libguile/unif.h"
60#include "libguile/async.h"
61#include "libguile/ports.h"
62#include "libguile/root.h"
63#include "libguile/strings.h"
64#include "libguile/vectors.h"
65#include "libguile/weaks.h"
66#include "libguile/hashtab.h"
67#include "libguile/tags.h"
68
69#include "libguile/validate.h"
70#include "libguile/deprecation.h"
71#include "libguile/gc.h"
72
73#include "libguile/private-gc.h"
74
75#ifdef GUILE_DEBUG_MALLOC
76#include "libguile/debug-malloc.h"
77#endif
78
79#ifdef HAVE_MALLOC_H
80#include <malloc.h>
81#endif
82
83#ifdef HAVE_UNISTD_H
84#include <unistd.h>
85#endif
86
87/*
88 INIT_MALLOC_LIMIT is the initial amount of malloc usage which will
89 trigger a GC.
90
91 After startup (at the guile> prompt), we have approximately 100k of
92 alloced memory, which won't go away on GC. Let's set the init such
93 that we get a nice yield on the next allocation:
94*/
95#define SCM_DEFAULT_INIT_MALLOC_LIMIT 200000
96#define SCM_DEFAULT_MALLOC_MINYIELD 40
97
98
99static int scm_i_minyield_malloc;
100
101void
102scm_gc_init_malloc (void)
103{
104 scm_mtrigger = scm_getenv_int ("GUILE_INIT_MALLOC_LIMIT",
105 SCM_DEFAULT_INIT_MALLOC_LIMIT);
106 scm_i_minyield_malloc = scm_getenv_int ("GUILE_MIN_YIELD_MALLOC",
107 SCM_DEFAULT_MALLOC_MINYIELD);
108}
109
110
111\f
112/* Function for non-cell memory management.
113 */
114
115void *
116scm_malloc (size_t size)
117{
118 void *ptr;
119
120 if (size == 0)
121 return NULL;
122
123 SCM_SYSCALL (ptr = malloc (size));
124 if (ptr)
125 return ptr;
126
127 scm_i_sweep_all_segments ("malloc");
128 SCM_SYSCALL (ptr = malloc (size));
129 if (ptr)
130 return ptr;
131
132 scm_igc ("malloc");
133 scm_i_sweep_all_segments ("malloc/gc");
134
135 SCM_SYSCALL (ptr = malloc (size));
136 if (ptr)
137 return ptr;
138
139 scm_memory_error ("malloc");
140}
141
142void *
143scm_realloc (void *mem, size_t size)
144{
145 void *ptr;
146
147 SCM_SYSCALL (ptr = realloc (mem, size));
148 if (ptr)
149 return ptr;
150
151 scm_i_sweep_all_segments ("realloc");
152
153 SCM_SYSCALL (ptr = realloc (mem, size));
154 if (ptr)
155 return ptr;
156
157 scm_igc ("realloc");
158 scm_i_sweep_all_segments ("realloc");
159
160 SCM_SYSCALL (ptr = realloc (mem, size));
161 if (ptr)
162 return ptr;
163
164 scm_memory_error ("realloc");
165}
166
167char *
168scm_strndup (const char *str, size_t n)
169{
170 char *dst = scm_malloc (n+1);
171 memcpy (dst, str, n);
172 dst[n] = 0;
173 return dst;
174}
175
176char *
177scm_strdup (const char *str)
178{
179 return scm_strndup (str, strlen (str));
180}
181
182void
183scm_gc_register_collectable_memory (void *mem, size_t size, const char *what)
184{
185 scm_mallocated += size;
186
187 /*
188 we could finish the full sweep (without mark) here, but in
189 practice this turns out to be ineffective.
190 */
191
192 /*
193 A program that uses a lot of malloced collectable memory (vectors,
194 strings), will use a lot of memory off the cell-heap; it needs to
195 do GC more often (before cells are exhausted), otherwise swapping
196 and malloc management will tie it down.
197 */
198 if (scm_mallocated > scm_mtrigger)
199 {
200 long prev_alloced = scm_mallocated;
201 float yield;
202
203 scm_igc (what);
204 scm_i_sweep_all_segments("mtrigger");
205
206 yield = (prev_alloced - scm_mallocated) / (float) prev_alloced;
207
208 /*
209 fprintf (stderr, "prev %lud , now %lud, yield %4.2lf, want %d",
210 prev_alloced, scm_mallocated, 100.0*yield, scm_i_minyield_malloc);
211 */
212
213 if (yield < scm_i_minyield_malloc / 100.0)
214 {
215 /*
216 We make the trigger a little larger, even; If you have a
217 program that builds up a lot of data in strings, then the
218 desired yield will never be satisfied.
219
220 Instead of getting bogged down, we let the mtrigger grow
221 strongly with it.
222 */
223 scm_mtrigger = (scm_mallocated * 110) / (100 - scm_i_minyield_malloc);
224
225 /*
226 fprintf (stderr, "Mtrigger sweep: ineffective. New trigger %d\n", scm_mtrigger);
227 */
228
229
230 }
231 }
232
233#ifdef GUILE_DEBUG_MALLOC
234 if (mem)
235 scm_malloc_register (mem, what);
236#endif
237}
238
239void
240scm_gc_unregister_collectable_memory (void *mem, size_t size, const char *what)
241{
242 scm_mallocated -= size;
243 scm_gc_malloc_collected += size;
244
245#ifdef GUILE_DEBUG_MALLOC
246 if (mem)
247 scm_malloc_unregister (mem);
248#endif
249}
250
251void *
252scm_gc_malloc (size_t size, const char *what)
253{
254 /*
255 The straightforward implementation below has the problem
256 that it might call the GC twice, once in scm_malloc and then
257 again in scm_gc_register_collectable_memory. We don't really
258 want the second GC since it will not find new garbage.
259
260
261 Note: this is a theoretical peeve. In reality, malloc() never
262 returns NULL. Usually, memory is overcommitted, and when you try
263 to write it the program is killed with signal 11. --hwn
264 */
265
266 void *ptr = scm_malloc (size);
267 scm_gc_register_collectable_memory (ptr, size, what);
268 return ptr;
269}
270
271void *
272scm_gc_realloc (void *mem, size_t old_size, size_t new_size, const char *what)
273{
274 /* XXX - see scm_gc_malloc. */
275
276 void *ptr = scm_realloc (mem, new_size);
277 scm_gc_unregister_collectable_memory (mem, old_size, what);
278 scm_gc_register_collectable_memory (ptr, new_size, what);
279 return ptr;
280}
281
282void
283scm_gc_free (void *mem, size_t size, const char *what)
284{
285 scm_gc_unregister_collectable_memory (mem, size, what);
286 free (mem);
287}
288
289char *
290scm_gc_strndup (const char *str, size_t n, const char *what)
291{
292 char *dst = scm_gc_malloc (n+1, what);
293 memcpy (dst, str, n);
294 dst[n] = 0;
295 return dst;
296}
297
298char *
299scm_gc_strdup (const char *str, const char *what)
300{
301 return scm_gc_strndup (str, strlen (str), what);
302}
303
304#if SCM_ENABLE_DEPRECATED == 1
305
306/* {Deprecated front end to malloc}
307 *
308 * scm_must_malloc, scm_must_realloc, scm_must_free, scm_done_malloc,
309 * scm_done_free
310 *
311 * These functions provide services comparable to malloc, realloc, and
312 * free. They should be used when allocating memory that will be under
313 * control of the garbage collector, i.e., if the memory may be freed
314 * during garbage collection.
315 *
316 * They are deprecated because they weren't really used the way
317 * outlined above, and making sure to return the right amount from
318 * smob free routines was sometimes difficult when dealing with nested
319 * data structures. We basically want everybody to review their code
320 * and use the more symmetrical scm_gc_malloc/scm_gc_free functions
321 * instead. In some cases, where scm_must_malloc has been used
322 * incorrectly (i.e. for non-GC-able memory), use scm_malloc/free.
323 */
324
325void *
326scm_must_malloc (size_t size, const char *what)
327{
328 scm_c_issue_deprecation_warning
329 ("scm_must_malloc is deprecated. "
330 "Use scm_gc_malloc and scm_gc_free instead.");
331
332 return scm_gc_malloc (size, what);
333}
334
335void *
336scm_must_realloc (void *where,
337 size_t old_size,
338 size_t size,
339 const char *what)
340{
341 scm_c_issue_deprecation_warning
342 ("scm_must_realloc is deprecated. "
343 "Use scm_gc_realloc and scm_gc_free instead.");
344
345 return scm_gc_realloc (where, old_size, size, what);
346}
347
348char *
349scm_must_strndup (const char *str, size_t length)
350{
351 scm_c_issue_deprecation_warning
352 ("scm_must_strndup is deprecated. "
353 "Use scm_gc_strndup and scm_gc_free instead.");
354
355 return scm_gc_strndup (str, length, "string");
356}
357
358char *
359scm_must_strdup (const char *str)
360{
361 scm_c_issue_deprecation_warning
362 ("scm_must_strdup is deprecated. "
363 "Use scm_gc_strdup and scm_gc_free instead.");
364
365 return scm_gc_strdup (str, "string");
366}
367
368void
369scm_must_free (void *obj)
370#define FUNC_NAME "scm_must_free"
371{
372 scm_c_issue_deprecation_warning
373 ("scm_must_free is deprecated. "
374 "Use scm_gc_malloc and scm_gc_free instead.");
375
376#ifdef GUILE_DEBUG_MALLOC
377 scm_malloc_unregister (obj);
378#endif
379 if (obj)
380 free (obj);
381 else
382 SCM_MISC_ERROR ("freeing NULL pointer", SCM_EOL);
383}
384#undef FUNC_NAME
385
386
387void
388scm_done_malloc (long size)
389{
390 scm_c_issue_deprecation_warning
391 ("scm_done_malloc is deprecated. "
392 "Use scm_gc_register_collectable_memory instead.");
393
394 scm_gc_register_collectable_memory (NULL, size, "foreign mallocs");
395}
396
397void
398scm_done_free (long size)
399{
400 scm_c_issue_deprecation_warning
401 ("scm_done_free is deprecated. "
402 "Use scm_gc_unregister_collectable_memory instead.");
403
404 scm_gc_unregister_collectable_memory (NULL, size, "foreign mallocs");
405}
406
407#endif /* SCM_ENABLE_DEPRECATED == 1 */