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