*** empty log message ***
[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*/
c2cbcc57 95#define SCM_DEFAULT_INIT_MALLOC_LIMIT 200*1024
c7743d02
HWN
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
c7743d02
HWN
115void *
116scm_realloc (void *mem, size_t size)
117{
118 void *ptr;
119
120 SCM_SYSCALL (ptr = realloc (mem, size));
121 if (ptr)
122 return ptr;
123
124 scm_i_sweep_all_segments ("realloc");
125
126 SCM_SYSCALL (ptr = realloc (mem, size));
127 if (ptr)
128 return ptr;
129
130 scm_igc ("realloc");
131 scm_i_sweep_all_segments ("realloc");
132
133 SCM_SYSCALL (ptr = realloc (mem, size));
134 if (ptr)
135 return ptr;
136
137 scm_memory_error ("realloc");
138}
139
39e8f371
HWN
140void *
141scm_malloc (size_t sz)
142{
143 return scm_realloc (NULL, sz);
144}
ba1b2226
HWN
145
146/*
147 Hmm. Should we use the C convention for arguments (i.e. N_ELTS,
148 SIZEOF_ELT)? --hwn
149 */
150void *
151scm_calloc (size_t sz)
152{
1383773b
HWN
153 void * ptr;
154
155 /*
156 By default, try to use calloc, as it is likely more efficient than
157 calling memset by hand.
158 */
159 SCM_SYSCALL(ptr= calloc (sz, 1));
160 if (ptr)
161 return ptr;
162
163 ptr = scm_realloc (NULL, sz);
ba1b2226
HWN
164 memset (ptr, 0x0, sz);
165 return ptr;
166}
167
39e8f371 168
c7743d02
HWN
169char *
170scm_strndup (const char *str, size_t n)
171{
172 char *dst = scm_malloc (n+1);
173 memcpy (dst, str, n);
174 dst[n] = 0;
175 return dst;
176}
177
178char *
179scm_strdup (const char *str)
180{
181 return scm_strndup (str, strlen (str));
182}
183
184void
185scm_gc_register_collectable_memory (void *mem, size_t size, const char *what)
186{
187 scm_mallocated += size;
188
189 /*
190 we could finish the full sweep (without mark) here, but in
191 practice this turns out to be ineffective.
192 */
193
194 /*
195 A program that uses a lot of malloced collectable memory (vectors,
196 strings), will use a lot of memory off the cell-heap; it needs to
197 do GC more often (before cells are exhausted), otherwise swapping
198 and malloc management will tie it down.
199 */
200 if (scm_mallocated > scm_mtrigger)
201 {
202 long prev_alloced = scm_mallocated;
203 float yield;
204
205 scm_igc (what);
206 scm_i_sweep_all_segments("mtrigger");
207
c2cbcc57
HWN
208 yield = (prev_alloced - scm_mallocated) / (float) prev_alloced;
209 scm_gc_malloc_yield_percentage = (int) (100 * yield);
c7743d02
HWN
210 /*
211 fprintf (stderr, "prev %lud , now %lud, yield %4.2lf, want %d",
212 prev_alloced, scm_mallocated, 100.0*yield, scm_i_minyield_malloc);
213 */
214
215 if (yield < scm_i_minyield_malloc / 100.0)
216 {
217 /*
218 We make the trigger a little larger, even; If you have a
219 program that builds up a lot of data in strings, then the
220 desired yield will never be satisfied.
221
222 Instead of getting bogged down, we let the mtrigger grow
223 strongly with it.
224 */
225 scm_mtrigger = (scm_mallocated * 110) / (100 - scm_i_minyield_malloc);
226
227 /*
228 fprintf (stderr, "Mtrigger sweep: ineffective. New trigger %d\n", scm_mtrigger);
229 */
c7743d02 230 }
c2cbcc57
HWN
231
232
c7743d02
HWN
233 }
234
235#ifdef GUILE_DEBUG_MALLOC
236 if (mem)
237 scm_malloc_register (mem, what);
238#endif
239}
240
241void
242scm_gc_unregister_collectable_memory (void *mem, size_t size, const char *what)
243{
244 scm_mallocated -= size;
245 scm_gc_malloc_collected += size;
246
247#ifdef GUILE_DEBUG_MALLOC
248 if (mem)
249 scm_malloc_unregister (mem);
250#endif
251}
252
253void *
254scm_gc_malloc (size_t size, const char *what)
255{
256 /*
257 The straightforward implementation below has the problem
258 that it might call the GC twice, once in scm_malloc and then
259 again in scm_gc_register_collectable_memory. We don't really
260 want the second GC since it will not find new garbage.
261
262
263 Note: this is a theoretical peeve. In reality, malloc() never
264 returns NULL. Usually, memory is overcommitted, and when you try
265 to write it the program is killed with signal 11. --hwn
266 */
267
268 void *ptr = scm_malloc (size);
269 scm_gc_register_collectable_memory (ptr, size, what);
270 return ptr;
271}
272
39e8f371
HWN
273void *
274scm_gc_calloc (size_t size, const char *what)
275{
276 void *ptr = scm_gc_malloc (size, what);
277 memset (ptr, 0x0, size);
278 return ptr;
279}
280
281
c7743d02
HWN
282void *
283scm_gc_realloc (void *mem, size_t old_size, size_t new_size, const char *what)
284{
285 /* XXX - see scm_gc_malloc. */
286
287 void *ptr = scm_realloc (mem, new_size);
288 scm_gc_unregister_collectable_memory (mem, old_size, what);
289 scm_gc_register_collectable_memory (ptr, new_size, what);
290 return ptr;
291}
292
293void
294scm_gc_free (void *mem, size_t size, const char *what)
295{
296 scm_gc_unregister_collectable_memory (mem, size, what);
297 free (mem);
298}
299
300char *
301scm_gc_strndup (const char *str, size_t n, const char *what)
302{
303 char *dst = scm_gc_malloc (n+1, what);
304 memcpy (dst, str, n);
305 dst[n] = 0;
306 return dst;
307}
308
309char *
310scm_gc_strdup (const char *str, const char *what)
311{
312 return scm_gc_strndup (str, strlen (str), what);
313}
314
315#if SCM_ENABLE_DEPRECATED == 1
316
317/* {Deprecated front end to malloc}
318 *
319 * scm_must_malloc, scm_must_realloc, scm_must_free, scm_done_malloc,
320 * scm_done_free
321 *
322 * These functions provide services comparable to malloc, realloc, and
323 * free. They should be used when allocating memory that will be under
324 * control of the garbage collector, i.e., if the memory may be freed
325 * during garbage collection.
326 *
327 * They are deprecated because they weren't really used the way
328 * outlined above, and making sure to return the right amount from
329 * smob free routines was sometimes difficult when dealing with nested
330 * data structures. We basically want everybody to review their code
331 * and use the more symmetrical scm_gc_malloc/scm_gc_free functions
332 * instead. In some cases, where scm_must_malloc has been used
333 * incorrectly (i.e. for non-GC-able memory), use scm_malloc/free.
334 */
335
336void *
337scm_must_malloc (size_t size, const char *what)
338{
339 scm_c_issue_deprecation_warning
340 ("scm_must_malloc is deprecated. "
341 "Use scm_gc_malloc and scm_gc_free instead.");
342
343 return scm_gc_malloc (size, what);
344}
345
346void *
347scm_must_realloc (void *where,
348 size_t old_size,
349 size_t size,
350 const char *what)
351{
352 scm_c_issue_deprecation_warning
353 ("scm_must_realloc is deprecated. "
354 "Use scm_gc_realloc and scm_gc_free instead.");
355
356 return scm_gc_realloc (where, old_size, size, what);
357}
358
359char *
360scm_must_strndup (const char *str, size_t length)
361{
362 scm_c_issue_deprecation_warning
363 ("scm_must_strndup is deprecated. "
364 "Use scm_gc_strndup and scm_gc_free instead.");
365
366 return scm_gc_strndup (str, length, "string");
367}
368
369char *
370scm_must_strdup (const char *str)
371{
372 scm_c_issue_deprecation_warning
373 ("scm_must_strdup is deprecated. "
374 "Use scm_gc_strdup and scm_gc_free instead.");
375
376 return scm_gc_strdup (str, "string");
377}
378
379void
380scm_must_free (void *obj)
381#define FUNC_NAME "scm_must_free"
382{
383 scm_c_issue_deprecation_warning
384 ("scm_must_free is deprecated. "
385 "Use scm_gc_malloc and scm_gc_free instead.");
386
387#ifdef GUILE_DEBUG_MALLOC
388 scm_malloc_unregister (obj);
389#endif
390 if (obj)
391 free (obj);
392 else
be3ff021
HWN
393 {
394 fprintf (stderr,"freeing NULL pointer");
395 abort ();
396 }
c7743d02
HWN
397}
398#undef FUNC_NAME
399
400
401void
402scm_done_malloc (long size)
403{
404 scm_c_issue_deprecation_warning
405 ("scm_done_malloc is deprecated. "
406 "Use scm_gc_register_collectable_memory instead.");
407
408 scm_gc_register_collectable_memory (NULL, size, "foreign mallocs");
409}
410
411void
412scm_done_free (long size)
413{
414 scm_c_issue_deprecation_warning
415 ("scm_done_free is deprecated. "
416 "Use scm_gc_unregister_collectable_memory instead.");
417
418 scm_gc_unregister_collectable_memory (NULL, size, "foreign mallocs");
419}
420
421#endif /* SCM_ENABLE_DEPRECATED == 1 */