more code
[bpt/guile.git] / libguile / gc.c
CommitLineData
c709de7f 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
a00c95d9 2 *
0f2d19dd
JB
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.
a00c95d9 7 *
0f2d19dd
JB
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.
a00c95d9 12 *
0f2d19dd
JB
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
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
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.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84 41
1bbd0b84 42
37ddcaf6
MD
43/* #define DEBUGINFO */
44
56495472 45
0f2d19dd 46#include <stdio.h>
e6e2e95a 47#include <errno.h>
783e7774 48#include <string.h>
c8a1bdc4 49#include <assert.h>
e6e2e95a 50
d9189652
RB
51#ifdef __ia64__
52#include <ucontext.h>
bb1180ef 53extern unsigned long * __libc_ia64_register_backing_store_base;
d9189652
RB
54#endif
55
a0599745 56#include "libguile/_scm.h"
0a7a7445 57#include "libguile/eval.h"
a0599745
MD
58#include "libguile/stime.h"
59#include "libguile/stackchk.h"
60#include "libguile/struct.h"
a0599745
MD
61#include "libguile/smob.h"
62#include "libguile/unif.h"
63#include "libguile/async.h"
64#include "libguile/ports.h"
65#include "libguile/root.h"
66#include "libguile/strings.h"
67#include "libguile/vectors.h"
801cb5e7 68#include "libguile/weaks.h"
686765af 69#include "libguile/hashtab.h"
ecf470a2 70#include "libguile/tags.h"
a0599745 71
c8a1bdc4 72#include "libguile/private-gc.h"
a0599745 73#include "libguile/validate.h"
1be6b49c 74#include "libguile/deprecation.h"
a0599745 75#include "libguile/gc.h"
fce59c93 76
bc9d9bb2 77#ifdef GUILE_DEBUG_MALLOC
a0599745 78#include "libguile/debug-malloc.h"
bc9d9bb2
MD
79#endif
80
0f2d19dd 81#ifdef HAVE_MALLOC_H
95b88819 82#include <malloc.h>
0f2d19dd
JB
83#endif
84
85#ifdef HAVE_UNISTD_H
95b88819 86#include <unistd.h>
0f2d19dd
JB
87#endif
88
406c7d90 89
8c494e99 90
406c7d90
DH
91unsigned int scm_gc_running_p = 0;
92
406c7d90
DH
93#if (SCM_DEBUG_CELL_ACCESSES == 1)
94
eae33935 95/* Set this to != 0 if every cell that is accessed shall be checked:
61045190
DH
96 */
97unsigned int scm_debug_cell_accesses_p = 1;
406c7d90 98
e81d98ec
DH
99/* Set this to 0 if no additional gc's shall be performed, otherwise set it to
100 * the number of cell accesses after which a gc shall be called.
101 */
102static unsigned int debug_cells_gc_interval = 0;
103
406c7d90
DH
104
105/* Assert that the given object is a valid reference to a valid cell. This
106 * test involves to determine whether the object is a cell pointer, whether
107 * this pointer actually points into a heap segment and whether the cell
e81d98ec
DH
108 * pointed to is not a free cell. Further, additional garbage collections may
109 * get executed after a user defined number of cell accesses. This helps to
110 * find places in the C code where references are dropped for extremely short
111 * periods.
406c7d90 112 */
c8a1bdc4 113
406c7d90
DH
114void
115scm_assert_cell_valid (SCM cell)
116{
61045190
DH
117 static unsigned int already_running = 0;
118
c8a1bdc4 119 if (!already_running)
406c7d90 120 {
61045190 121 already_running = 1; /* set to avoid recursion */
406c7d90 122
c8a1bdc4
HWN
123 /*
124 During GC, no user-code should be run, and the guile core should
125 use non-protected accessors.
126 */
127 if (scm_gc_running_p)
128 abort();
129
130 /*
131 Only scm_in_heap_p is wildly expensive.
132 */
133 if (scm_debug_cell_accesses_p)
134 if (!scm_in_heap_p (cell))
135 {
136 fprintf (stderr, "scm_assert_cell_valid: this object does not live in the heap: %lux\n",
137 (unsigned long) SCM_UNPACK (cell));
138 abort ();
139 }
140
141 if (!SCM_GC_MARK_P (cell))
406c7d90 142 {
c8a1bdc4
HWN
143 fprintf (stderr,
144 "scm_assert_cell_valid: this object is unmarked. \n"
145 "It has been garbage-collected in the last GC run: "
146 "%lux\n",
1be6b49c 147 (unsigned long) SCM_UNPACK (cell));
406c7d90
DH
148 abort ();
149 }
c8a1bdc4
HWN
150
151
152 /* If desired, perform additional garbage collections after a user
153 * defined number of cell accesses.
154 */
155 if (scm_debug_cell_accesses_p && debug_cells_gc_interval)
406c7d90 156 {
c8a1bdc4
HWN
157 static unsigned int counter = 0;
158
159 if (counter != 0)
406c7d90 160 {
c8a1bdc4 161 --counter;
406c7d90 162 }
c8a1bdc4 163 else
e81d98ec 164 {
c8a1bdc4
HWN
165 counter = debug_cells_gc_interval;
166 scm_igc ("scm_assert_cell_valid");
e81d98ec 167 }
406c7d90 168 }
61045190 169 already_running = 0; /* re-enable */
406c7d90
DH
170 }
171}
172
173
174SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
175 (SCM flag),
1e6808ea 176 "If @var{flag} is @code{#f}, cell access checking is disabled.\n"
e81d98ec
DH
177 "If @var{flag} is @code{#t}, cell access checking is enabled,\n"
178 "but no additional calls to garbage collection are issued.\n"
179 "If @var{flag} is a number, cell access checking is enabled,\n"
180 "with an additional garbage collection after the given\n"
181 "number of cell accesses.\n"
1e6808ea
MG
182 "This procedure only exists when the compile-time flag\n"
183 "@code{SCM_DEBUG_CELL_ACCESSES} was set to 1.")
406c7d90
DH
184#define FUNC_NAME s_scm_set_debug_cell_accesses_x
185{
186 if (SCM_FALSEP (flag)) {
187 scm_debug_cell_accesses_p = 0;
188 } else if (SCM_EQ_P (flag, SCM_BOOL_T)) {
e81d98ec
DH
189 debug_cells_gc_interval = 0;
190 scm_debug_cell_accesses_p = 1;
191 } else if (SCM_INUMP (flag)) {
192 long int f = SCM_INUM (flag);
193 if (f <= 0) SCM_OUT_OF_RANGE (1, flag);
194 debug_cells_gc_interval = f;
406c7d90
DH
195 scm_debug_cell_accesses_p = 1;
196 } else {
197 SCM_WRONG_TYPE_ARG (1, flag);
198 }
199 return SCM_UNSPECIFIED;
200}
201#undef FUNC_NAME
c8a1bdc4 202#else
0f2d19dd 203
8fef55a8 204/*
c8a1bdc4
HWN
205 Provide a stub, so people can use their Scheme code on non-debug
206 versions of GUILE as well.
4c48ba06 207 */
c8a1bdc4
HWN
208SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
209 (SCM flag),
210 "This function is used to turn on checking for a debug version of GUILE. This version does not support this functionality\n")
211#define FUNC_NAME s_scm_set_debug_cell_accesses_x
212{
213
214 /*
215 do nothing
216 */
0f2d19dd 217
c8a1bdc4
HWN
218 scm_remember_upto_here (flag);
219 return SCM_UNSPECIFIED;
220}
221#undef FUNC_NAME
ecf470a2 222
c8a1bdc4 223#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
0f2d19dd
JB
224
225\f
945fec60 226
c8a1bdc4
HWN
227SCM scm_i_freelist = SCM_EOL;
228SCM scm_i_freelist2 = SCM_EOL;
229
0f2d19dd
JB
230
231/* scm_mtrigger
539b08a4 232 * is the number of bytes of malloc allocation needed to trigger gc.
0f2d19dd 233 */
c014a02e 234unsigned long scm_mtrigger;
0f2d19dd 235
0f2d19dd
JB
236/* scm_gc_heap_lock
237 * If set, don't expand the heap. Set only during gc, during which no allocation
238 * is supposed to take place anyway.
239 */
240int scm_gc_heap_lock = 0;
241
242/* GC Blocking
243 * Don't pause for collection if this is set -- just
244 * expand the heap.
245 */
0f2d19dd
JB
246int scm_block_gc = 1;
247
0f2d19dd
JB
248/* During collection, this accumulates objects holding
249 * weak references.
250 */
ab4bef85 251SCM scm_weak_vectors;
0f2d19dd 252
7445e0e8
MD
253/* During collection, this accumulates structures which are to be freed.
254 */
255SCM scm_structs_to_free;
256
0f2d19dd
JB
257/* GC Statistics Keeping
258 */
c014a02e
ML
259unsigned long scm_cells_allocated = 0;
260unsigned long scm_mallocated = 0;
261unsigned long scm_gc_cells_collected;
c8a1bdc4 262unsigned long scm_gc_cells_collected_1 = 0; /* previous GC yield */
c014a02e
ML
263unsigned long scm_gc_malloc_collected;
264unsigned long scm_gc_ports_collected;
0f2d19dd 265unsigned long scm_gc_time_taken = 0;
c014a02e
ML
266static unsigned long t_before_gc;
267static unsigned long t_before_sweep;
c9b0d4b0 268unsigned long scm_gc_mark_time_taken = 0;
c014a02e
ML
269unsigned long scm_gc_times = 0;
270unsigned long scm_gc_cells_swept = 0;
c9b0d4b0
ML
271double scm_gc_cells_marked_acc = 0.;
272double scm_gc_cells_swept_acc = 0.;
0f2d19dd
JB
273
274SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
275SCM_SYMBOL (sym_heap_size, "cell-heap-size");
276SCM_SYMBOL (sym_mallocated, "bytes-malloced");
277SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
278SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
279SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
c9b0d4b0 280SCM_SYMBOL (sym_gc_mark_time_taken, "gc-mark-time-taken");
c9b0d4b0
ML
281SCM_SYMBOL (sym_times, "gc-times");
282SCM_SYMBOL (sym_cells_marked, "cells-marked");
283SCM_SYMBOL (sym_cells_swept, "cells-swept");
0f2d19dd 284
bb2c57fa 285
cf2d30f6 286
d3dd80ab 287
cf2d30f6 288/* Number of calls to SCM_NEWCELL since startup. */
c8a1bdc4
HWN
289unsigned scm_newcell_count;
290unsigned scm_newcell2_count;
b37fe1c5 291
b37fe1c5 292
0f2d19dd
JB
293/* {Scheme Interface to GC}
294 */
295
a00c95d9 296SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
1bbd0b84 297 (),
1e6808ea 298 "Return an association list of statistics about Guile's current\n"
c8a1bdc4 299 "use of storage.\n")
1bbd0b84 300#define FUNC_NAME s_scm_gc_stats
0f2d19dd 301{
c8a1bdc4
HWN
302 long i = 0;
303 SCM heap_segs = SCM_EOL ;
c014a02e
ML
304 unsigned long int local_scm_mtrigger;
305 unsigned long int local_scm_mallocated;
306 unsigned long int local_scm_heap_size;
307 unsigned long int local_scm_cells_allocated;
308 unsigned long int local_scm_gc_time_taken;
309 unsigned long int local_scm_gc_times;
310 unsigned long int local_scm_gc_mark_time_taken;
c9b0d4b0
ML
311 double local_scm_gc_cells_swept;
312 double local_scm_gc_cells_marked;
0f2d19dd 313 SCM answer;
c8a1bdc4
HWN
314 unsigned long *bounds = 0;
315 int table_size = scm_i_heap_segment_table_size;
0f2d19dd 316 SCM_DEFER_INTS;
939794ce 317
c8a1bdc4
HWN
318 /*
319 temporarily store the numbers, so as not to cause GC.
7febb4a2 320 */
c8a1bdc4
HWN
321
322 bounds = malloc (sizeof (int) * table_size * 2);
323 if (!bounds)
324 abort();
325 for (i = table_size; i--; )
326 {
327 bounds[2*i] = (unsigned long)scm_i_heap_segment_table[i]->bounds[0];
328 bounds[2*i+1] = (unsigned long)scm_i_heap_segment_table[i]->bounds[1];
329 }
0f2d19dd 330
4c9419ac 331
c8a1bdc4
HWN
332 /* Below, we cons to produce the resulting list. We want a snapshot of
333 * the heap situation before consing.
334 */
335 local_scm_mtrigger = scm_mtrigger;
336 local_scm_mallocated = scm_mallocated;
337 local_scm_heap_size = SCM_HEAP_SIZE;
539b08a4 338
c8a1bdc4
HWN
339 local_scm_cells_allocated = scm_cells_allocated;
340
341 local_scm_gc_time_taken = scm_gc_time_taken;
342 local_scm_gc_mark_time_taken = scm_gc_mark_time_taken;
343 local_scm_gc_times = scm_gc_times;
539b08a4 344
1be6b49c 345
c8a1bdc4
HWN
346 local_scm_gc_cells_swept = scm_gc_cells_swept_acc + scm_gc_cells_swept;
347 local_scm_gc_cells_marked = scm_gc_cells_marked_acc
348 +(double) scm_gc_cells_swept
349 -(double) scm_gc_cells_collected;
0f2d19dd 350
e4ef2330 351
c8a1bdc4
HWN
352 for (i = table_size; i--;)
353 {
354 heap_segs = scm_cons (scm_cons (scm_ulong2num (bounds[2*i]),
355 scm_ulong2num (bounds[2*i+1])),
356 heap_segs);
357 }
358
359 answer = scm_list_n (scm_cons (sym_gc_time_taken, scm_ulong2num (local_scm_gc_time_taken)),
360 scm_cons (sym_cells_allocated, scm_ulong2num (local_scm_cells_allocated)),
361 scm_cons (sym_heap_size, scm_ulong2num (local_scm_heap_size)),
362 scm_cons (sym_mallocated, scm_ulong2num (local_scm_mallocated)),
363 scm_cons (sym_mtrigger, scm_ulong2num (local_scm_mtrigger)),
364 scm_cons (sym_times, scm_ulong2num (local_scm_gc_times)),
365 scm_cons (sym_gc_mark_time_taken, scm_ulong2num (local_scm_gc_mark_time_taken)),
366 scm_cons (sym_cells_marked, scm_i_dbl2big (local_scm_gc_cells_marked)),
367 scm_cons (sym_cells_swept, scm_i_dbl2big (local_scm_gc_cells_swept)),
368 scm_cons (sym_heap_segments, heap_segs),
369 SCM_UNDEFINED);
370 SCM_ALLOW_INTS;
371
372 free (bounds);
373 return answer;
0f2d19dd 374}
c8a1bdc4 375#undef FUNC_NAME
0f2d19dd 376
c8a1bdc4
HWN
377static void
378gc_start_stats (const char *what SCM_UNUSED)
e4a7824f 379{
c8a1bdc4 380 t_before_gc = scm_c_get_internal_run_time ();
539b08a4 381
c8a1bdc4
HWN
382 scm_gc_cells_marked_acc += (double) scm_gc_cells_swept
383 - (double) scm_gc_cells_collected;
384 scm_gc_cells_swept_acc += scm_gc_cells_swept;
e4a7824f 385
c8a1bdc4
HWN
386 scm_gc_cells_swept = 0;
387 scm_gc_cells_collected_1 = scm_gc_cells_collected;
539b08a4 388
c8a1bdc4
HWN
389 /*
390 CELLS SWEPT is another word for the number of cells that were
391 examined during GC. YIELD is the number that we cleaned
392 out. MARKED is the number that weren't cleaned.
393 */
394 scm_gc_cells_collected = 0;
395 scm_gc_malloc_collected = 0;
396 scm_gc_ports_collected = 0;
e4a7824f 397}
acf4331f 398
c8a1bdc4
HWN
399static void
400gc_end_stats ()
0f2d19dd 401{
c8a1bdc4
HWN
402 unsigned long t = scm_c_get_internal_run_time ();
403 scm_gc_time_taken += (t - t_before_gc);
539b08a4 404
c8a1bdc4 405 ++scm_gc_times;
0f2d19dd 406}
acf4331f 407
0f2d19dd 408
c8a1bdc4
HWN
409SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
410 (SCM obj),
411 "Return an integer that for the lifetime of @var{obj} is uniquely\n"
412 "returned by this function for @var{obj}")
413#define FUNC_NAME s_scm_object_address
c68296f8 414{
c8a1bdc4 415 return scm_ulong2num ((unsigned long) SCM_UNPACK (obj));
c68296f8 416}
c8a1bdc4 417#undef FUNC_NAME
c68296f8 418
1be6b49c 419
c8a1bdc4
HWN
420SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
421 (),
422 "Scans all of SCM objects and reclaims for further use those that are\n"
423 "no longer accessible.")
424#define FUNC_NAME s_scm_gc
425{
426 SCM_DEFER_INTS;
427 scm_igc ("call");
428 SCM_ALLOW_INTS;
429 return SCM_UNSPECIFIED;
9d47a1e6 430}
c8a1bdc4 431#undef FUNC_NAME
9d47a1e6 432
c68296f8
MV
433
434\f
0f2d19dd 435
c8a1bdc4
HWN
436/* When we get POSIX threads support, the master will be global and
437 * common while the freelist will be individual for each thread.
0f2d19dd
JB
438 */
439
c8a1bdc4
HWN
440SCM
441scm_gc_for_newcell (scm_t_cell_type_statistics *freelist, SCM *free_cells)
0f2d19dd 442{
c8a1bdc4
HWN
443 SCM cell;
444
445 ++scm_ints_disabled;
0f2d19dd 446
c8a1bdc4
HWN
447 *free_cells = scm_i_sweep_some_segments (freelist);
448 if (*free_cells == SCM_EOL && scm_i_gc_grow_heap_p (freelist))
449 {
450 freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
451 *free_cells = scm_i_sweep_some_segments (freelist);
452 }
acb0a19c 453
c8a1bdc4
HWN
454 if (*free_cells == SCM_EOL && !scm_block_gc)
455 {
456 /*
457 with the advent of lazy sweep, GC yield is only know just
458 before doing the GC.
459 */
460 scm_i_adjust_min_yield (freelist);
461
462 /*
463 out of fresh cells. Try to get some new ones.
464 */
0f2d19dd 465
c8a1bdc4 466 scm_igc ("cells");
a00c95d9 467
c8a1bdc4
HWN
468 *free_cells = scm_i_sweep_some_segments (freelist);
469 }
470
471 if (*free_cells == SCM_EOL)
472 {
473 /*
474 failed getting new cells. Get new juice or die.
475 */
476 freelist->heap_segment_idx = scm_i_get_new_heap_segment (freelist, abort_on_error);
477 *free_cells = scm_i_sweep_some_segments (freelist);
478 }
479
480 if (*free_cells == SCM_EOL)
481 abort ();
0f2d19dd 482
c8a1bdc4 483 cell = *free_cells;
0f2d19dd 484
c8a1bdc4 485 --scm_ints_disabled;
0f2d19dd 486
c8a1bdc4
HWN
487 *free_cells = SCM_FREE_CELL_CDR (cell);
488 return cell;
489}
4a4c9785 490
4a4c9785 491
c8a1bdc4
HWN
492scm_t_c_hook scm_before_gc_c_hook;
493scm_t_c_hook scm_before_mark_c_hook;
494scm_t_c_hook scm_before_sweep_c_hook;
495scm_t_c_hook scm_after_sweep_c_hook;
496scm_t_c_hook scm_after_gc_c_hook;
4a4c9785 497
c8a1bdc4
HWN
498void
499scm_igc (const char *what)
500{
501 ++scm_gc_running_p;
502 scm_c_hook_run (&scm_before_gc_c_hook, 0);
a00c95d9 503
c8a1bdc4
HWN
504#ifdef DEBUGINFO
505 fprintf (stderr,"gc reason %s\n", what);
506
507 fprintf (stderr,
508 SCM_NULLP (scm_i_freelist)
509 ? "*"
510 : (SCM_NULLP (scm_i_freelist2) ? "o" : "m"));
511#endif
4c48ba06 512
c8a1bdc4
HWN
513 /* During the critical section, only the current thread may run. */
514 SCM_CRITICAL_SECTION_START;
a00c95d9 515
c8a1bdc4 516 if (!scm_stack_base || scm_block_gc)
d6884e63 517 {
c8a1bdc4
HWN
518 --scm_gc_running_p;
519 return;
d6884e63
ML
520 }
521
c8a1bdc4 522 gc_start_stats (what);
a00c95d9 523
c8a1bdc4
HWN
524 if (scm_gc_heap_lock)
525 /* We've invoked the collector while a GC is already in progress.
526 That should never happen. */
527 abort ();
a00c95d9 528
c8a1bdc4 529 ++scm_gc_heap_lock;
a00c95d9 530
c8a1bdc4
HWN
531 /*
532 Let's finish the sweep. The conservative GC might point into the
533 garbage, and marking that would create a mess.
534 */
535 scm_i_sweep_all_segments("GC");
536 if (scm_mallocated < scm_i_deprecated_memory_return)
b6efc951 537 {
c8a1bdc4
HWN
538 /* The byte count of allocated objects has underflowed. This is
539 probably because you forgot to report the sizes of objects you
540 have allocated, by calling scm_done_malloc or some such. When
541 the GC freed them, it subtracted their size from
542 scm_mallocated, which underflowed. */
543 fprintf (stderr,
544 "scm_gc_sweep: Byte count of allocated objects has underflowed.\n"
545 "This is probably because the GC hasn't been correctly informed\n"
546 "about object sizes\n");
b6efc951
DH
547 abort ();
548 }
c8a1bdc4 549 scm_mallocated -= scm_i_deprecated_memory_return;
0f2d19dd 550
c8a1bdc4
HWN
551
552
553 scm_c_hook_run (&scm_before_mark_c_hook, 0);
b6efc951 554
c8a1bdc4
HWN
555 scm_mark_all ();
556
557 t_before_sweep = scm_c_get_internal_run_time ();
558 scm_gc_mark_time_taken += (t_before_sweep - t_before_gc);
559
560 scm_c_hook_run (&scm_before_sweep_c_hook, 0);
561
562 /*
563 Moved this lock upwards so that we can alloc new heap at the end of a sweep.
0f2d19dd 564
c8a1bdc4 565 DOCME: why should the heap be locked anyway?
0f2d19dd 566 */
c8a1bdc4 567 --scm_gc_heap_lock;
a00c95d9 568
c8a1bdc4 569 scm_gc_sweep ();
0f2d19dd 570
c8a1bdc4
HWN
571 scm_c_hook_run (&scm_after_sweep_c_hook, 0);
572 gc_end_stats ();
573
574 SCM_CRITICAL_SECTION_END;
575 scm_c_hook_run (&scm_after_gc_c_hook, 0);
576 --scm_gc_running_p;
577}
578
579\f
0f2d19dd 580
a00c95d9 581
0f2d19dd 582
0f2d19dd 583
c8a1bdc4
HWN
584
585\f
0f2d19dd 586
0f2d19dd
JB
587\f
588/* {GC Protection Helper Functions}
589 */
590
591
5d2b97cd
DH
592/*
593 * If within a function you need to protect one or more scheme objects from
594 * garbage collection, pass them as parameters to one of the
595 * scm_remember_upto_here* functions below. These functions don't do
596 * anything, but since the compiler does not know that they are actually
597 * no-ops, it will generate code that calls these functions with the given
598 * parameters. Therefore, you can be sure that the compiler will keep those
599 * scheme values alive (on the stack or in a register) up to the point where
600 * scm_remember_upto_here* is called. In other words, place the call to
592996c9 601 * scm_remember_upto_here* _behind_ the last code in your function, that
5d2b97cd
DH
602 * depends on the scheme object to exist.
603 *
8c494e99
DH
604 * Example: We want to make sure that the string object str does not get
605 * garbage collected during the execution of 'some_function' in the code
606 * below, because otherwise the characters belonging to str would be freed and
5d2b97cd
DH
607 * 'some_function' might access freed memory. To make sure that the compiler
608 * keeps str alive on the stack or in a register such that it is visible to
609 * the conservative gc we add the call to scm_remember_upto_here_1 _after_ the
610 * call to 'some_function'. Note that this would not be necessary if str was
611 * used anyway after the call to 'some_function'.
612 * char *chars = SCM_STRING_CHARS (str);
613 * some_function (chars);
614 * scm_remember_upto_here_1 (str); // str will be alive up to this point.
615 */
616
617void
e81d98ec 618scm_remember_upto_here_1 (SCM obj SCM_UNUSED)
5d2b97cd
DH
619{
620 /* Empty. Protects a single object from garbage collection. */
621}
622
623void
e81d98ec 624scm_remember_upto_here_2 (SCM obj1 SCM_UNUSED, SCM obj2 SCM_UNUSED)
5d2b97cd
DH
625{
626 /* Empty. Protects two objects from garbage collection. */
627}
628
629void
e81d98ec 630scm_remember_upto_here (SCM obj SCM_UNUSED, ...)
5d2b97cd
DH
631{
632 /* Empty. Protects any number of objects from garbage collection. */
633}
634
c209c88e 635/*
41b0806d
GB
636 These crazy functions prevent garbage collection
637 of arguments after the first argument by
638 ensuring they remain live throughout the
639 function because they are used in the last
640 line of the code block.
641 It'd be better to have a nice compiler hint to
642 aid the conservative stack-scanning GC. --03/09/00 gjb */
0f2d19dd
JB
643SCM
644scm_return_first (SCM elt, ...)
0f2d19dd
JB
645{
646 return elt;
647}
648
41b0806d
GB
649int
650scm_return_first_int (int i, ...)
651{
652 return i;
653}
654
0f2d19dd 655
0f2d19dd 656SCM
6e8d25a6 657scm_permanent_object (SCM obj)
0f2d19dd
JB
658{
659 SCM_REDEFER_INTS;
660 scm_permobjs = scm_cons (obj, scm_permobjs);
661 SCM_REALLOW_INTS;
662 return obj;
663}
664
665
7bd4fbe2
MD
666/* Protect OBJ from the garbage collector. OBJ will not be freed, even if all
667 other references are dropped, until the object is unprotected by calling
6b1b030e 668 scm_gc_unprotect_object (OBJ). Calls to scm_gc_protect/unprotect_object nest,
7bd4fbe2
MD
669 i. e. it is possible to protect the same object several times, but it is
670 necessary to unprotect the object the same number of times to actually get
671 the object unprotected. It is an error to unprotect an object more often
672 than it has been protected before. The function scm_protect_object returns
673 OBJ.
674*/
675
676/* Implementation note: For every object X, there is a counter which
6b1b030e 677 scm_gc_protect_object(X) increments and scm_gc_unprotect_object(X) decrements.
7bd4fbe2 678*/
686765af 679
ef290276 680SCM
6b1b030e 681scm_gc_protect_object (SCM obj)
ef290276 682{
686765af 683 SCM handle;
9d47a1e6 684
686765af 685 /* This critical section barrier will be replaced by a mutex. */
2dd6a83a 686 SCM_REDEFER_INTS;
9d47a1e6 687
0f0f0899 688 handle = scm_hashq_create_handle_x (scm_protects, obj, SCM_MAKINUM (0));
1be6b49c 689 SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), SCM_MAKINUM (1)));
9d47a1e6 690
2dd6a83a 691 SCM_REALLOW_INTS;
9d47a1e6 692
ef290276
JB
693 return obj;
694}
695
696
697/* Remove any protection for OBJ established by a prior call to
dab7f566 698 scm_protect_object. This function returns OBJ.
ef290276 699
dab7f566 700 See scm_protect_object for more information. */
ef290276 701SCM
6b1b030e 702scm_gc_unprotect_object (SCM obj)
ef290276 703{
686765af 704 SCM handle;
9d47a1e6 705
686765af 706 /* This critical section barrier will be replaced by a mutex. */
2dd6a83a 707 SCM_REDEFER_INTS;
9d47a1e6 708
686765af 709 handle = scm_hashq_get_handle (scm_protects, obj);
9d47a1e6 710
22a52da1 711 if (SCM_FALSEP (handle))
686765af 712 {
0f0f0899
MD
713 fprintf (stderr, "scm_unprotect_object called on unprotected object\n");
714 abort ();
686765af 715 }
6a199940
DH
716 else
717 {
1be6b49c
ML
718 SCM count = scm_difference (SCM_CDR (handle), SCM_MAKINUM (1));
719 if (SCM_EQ_P (count, SCM_MAKINUM (0)))
6a199940
DH
720 scm_hashq_remove_x (scm_protects, obj);
721 else
1be6b49c 722 SCM_SETCDR (handle, count);
6a199940 723 }
686765af 724
2dd6a83a 725 SCM_REALLOW_INTS;
ef290276
JB
726
727 return obj;
728}
729
6b1b030e
ML
730void
731scm_gc_register_root (SCM *p)
732{
733 SCM handle;
734 SCM key = scm_long2num ((long) p);
eae33935 735
6b1b030e
ML
736 /* This critical section barrier will be replaced by a mutex. */
737 SCM_REDEFER_INTS;
738
739 handle = scm_hashv_create_handle_x (scm_gc_registered_roots, key, SCM_MAKINUM (0));
740 SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), SCM_MAKINUM (1)));
741
742 SCM_REALLOW_INTS;
743}
744
745void
746scm_gc_unregister_root (SCM *p)
747{
748 SCM handle;
749 SCM key = scm_long2num ((long) p);
750
751 /* This critical section barrier will be replaced by a mutex. */
752 SCM_REDEFER_INTS;
753
754 handle = scm_hashv_get_handle (scm_gc_registered_roots, key);
755
756 if (SCM_FALSEP (handle))
757 {
758 fprintf (stderr, "scm_gc_unregister_root called on unregistered root\n");
759 abort ();
760 }
761 else
762 {
763 SCM count = scm_difference (SCM_CDR (handle), SCM_MAKINUM (1));
764 if (SCM_EQ_P (count, SCM_MAKINUM (0)))
765 scm_hashv_remove_x (scm_gc_registered_roots, key);
766 else
767 SCM_SETCDR (handle, count);
768 }
769
770 SCM_REALLOW_INTS;
771}
772
773void
774scm_gc_register_roots (SCM *b, unsigned long n)
775{
776 SCM *p = b;
777 for (; p < b + n; ++p)
778 scm_gc_register_root (p);
779}
780
781void
782scm_gc_unregister_roots (SCM *b, unsigned long n)
783{
784 SCM *p = b;
785 for (; p < b + n; ++p)
786 scm_gc_unregister_root (p);
787}
788
04a98cff 789int scm_i_terminating;
c45acc34
JB
790
791/* called on process termination. */
e52ceaac
MD
792#ifdef HAVE_ATEXIT
793static void
794cleanup (void)
795#else
796#ifdef HAVE_ON_EXIT
51157deb
MD
797extern int on_exit (void (*procp) (), int arg);
798
e52ceaac
MD
799static void
800cleanup (int status, void *arg)
801#else
802#error Dont know how to setup a cleanup handler on your system.
803#endif
804#endif
c45acc34 805{
04a98cff 806 scm_i_terminating = 1;
c45acc34
JB
807 scm_flush_all_ports ();
808}
ef290276 809
0f2d19dd 810\f
a00c95d9 811
4c48ba06 812
c8a1bdc4
HWN
813/*
814 MOVE THIS FUNCTION. IT DOES NOT HAVE ANYTHING TODO WITH GC.
815 */
85db4a2c
DH
816
817/* Get an integer from an environment variable. */
c8a1bdc4
HWN
818int
819scm_getenv_int (const char *var, int def)
85db4a2c 820{
c8a1bdc4
HWN
821 char *end = 0;
822 char *val = getenv (var);
823 long res = def;
85db4a2c
DH
824 if (!val)
825 return def;
826 res = strtol (val, &end, 10);
827 if (end == val)
828 return def;
829 return res;
830}
831
832
4a4c9785 833int
85db4a2c 834scm_init_storage ()
0f2d19dd 835{
1be6b49c 836 size_t j;
0f2d19dd
JB
837
838 j = SCM_NUM_PROTECTS;
839 while (j)
840 scm_sys_protects[--j] = SCM_BOOL_F;
841 scm_block_gc = 1;
4a4c9785 842
c8a1bdc4
HWN
843 scm_gc_init_freelist();
844 scm_gc_init_malloc ();
0f2d19dd
JB
845
846 j = SCM_HEAP_SEG_SIZE;
d6884e63 847
c8a1bdc4 848
acb0a19c 849
801cb5e7
MD
850 scm_c_hook_init (&scm_before_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
851 scm_c_hook_init (&scm_before_mark_c_hook, 0, SCM_C_HOOK_NORMAL);
852 scm_c_hook_init (&scm_before_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
853 scm_c_hook_init (&scm_after_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
854 scm_c_hook_init (&scm_after_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
0f2d19dd
JB
855
856 /* Initialise the list of ports. */
f5fd8aa2
MV
857 scm_port_table = (scm_t_port **)
858 malloc (sizeof (scm_t_port *) * scm_port_table_room);
859 if (!scm_port_table)
0f2d19dd
JB
860 return 1;
861
a18bcd0e 862#ifdef HAVE_ATEXIT
c45acc34 863 atexit (cleanup);
e52ceaac
MD
864#else
865#ifdef HAVE_ON_EXIT
866 on_exit (cleanup, 0);
867#endif
a18bcd0e 868#endif
0f2d19dd 869
8960e0a0 870 scm_stand_in_procs = SCM_EOL;
0f2d19dd 871 scm_permobjs = SCM_EOL;
00ffa0e7 872 scm_protects = scm_c_make_hash_table (31);
6b1b030e 873 scm_gc_registered_roots = scm_c_make_hash_table (31);
d6884e63 874
0f2d19dd
JB
875 return 0;
876}
939794ce 877
0f2d19dd
JB
878\f
879
939794ce
DH
880SCM scm_after_gc_hook;
881
939794ce
DH
882static SCM gc_async;
883
939794ce
DH
884/* The function gc_async_thunk causes the execution of the after-gc-hook. It
885 * is run after the gc, as soon as the asynchronous events are handled by the
886 * evaluator.
887 */
888static SCM
889gc_async_thunk (void)
890{
891 scm_c_run_hook (scm_after_gc_hook, SCM_EOL);
939794ce
DH
892 return SCM_UNSPECIFIED;
893}
894
895
896/* The function mark_gc_async is run by the scm_after_gc_c_hook at the end of
897 * the garbage collection. The only purpose of this function is to mark the
898 * gc_async (which will eventually lead to the execution of the
899 * gc_async_thunk).
900 */
901static void *
e81d98ec
DH
902mark_gc_async (void * hook_data SCM_UNUSED,
903 void *func_data SCM_UNUSED,
904 void *data SCM_UNUSED)
905{
906 /* If cell access debugging is enabled, the user may choose to perform
907 * additional garbage collections after an arbitrary number of cell
908 * accesses. We don't want the scheme level after-gc-hook to be performed
909 * for each of these garbage collections for the following reason: The
910 * execution of the after-gc-hook causes cell accesses itself. Thus, if the
911 * after-gc-hook was performed with every gc, and if the gc was performed
912 * after a very small number of cell accesses, then the number of cell
913 * accesses during the execution of the after-gc-hook will suffice to cause
914 * the execution of the next gc. Then, guile would keep executing the
915 * after-gc-hook over and over again, and would never come to do other
916 * things.
eae33935 917 *
e81d98ec
DH
918 * To overcome this problem, if cell access debugging with additional
919 * garbage collections is enabled, the after-gc-hook is never run by the
920 * garbage collecter. When running guile with cell access debugging and the
921 * execution of the after-gc-hook is desired, then it is necessary to run
922 * the hook explicitly from the user code. This has the effect, that from
923 * the scheme level point of view it seems that garbage collection is
924 * performed with a much lower frequency than it actually is. Obviously,
925 * this will not work for code that depends on a fixed one to one
926 * relationship between the execution counts of the C level garbage
927 * collection hooks and the execution count of the scheme level
928 * after-gc-hook.
929 */
930#if (SCM_DEBUG_CELL_ACCESSES == 1)
931 if (debug_cells_gc_interval == 0)
932 scm_system_async_mark (gc_async);
933#else
939794ce 934 scm_system_async_mark (gc_async);
e81d98ec
DH
935#endif
936
939794ce
DH
937 return NULL;
938}
939
0f2d19dd
JB
940void
941scm_init_gc ()
0f2d19dd 942{
939794ce
DH
943 SCM after_gc_thunk;
944
c8a1bdc4
HWN
945
946 scm_gc_init_mark ();
d678e25c 947
fde50407
ML
948 scm_after_gc_hook = scm_permanent_object (scm_make_hook (SCM_INUM0));
949 scm_c_define ("after-gc-hook", scm_after_gc_hook);
939794ce 950
9a441ddb
MV
951 after_gc_thunk = scm_c_make_subr ("%gc-thunk", scm_tc7_subr_0,
952 gc_async_thunk);
23670993 953 gc_async = scm_system_async (after_gc_thunk); /* protected via scm_asyncs */
939794ce
DH
954
955 scm_c_hook_add (&scm_after_gc_c_hook, mark_gc_async, NULL, 0);
956
a0599745 957#include "libguile/gc.x"
0f2d19dd 958}
89e00824 959
c8a1bdc4
HWN
960
961void
962scm_gc_sweep (void)
963#define FUNC_NAME "scm_gc_sweep"
964{
965 scm_i_deprecated_memory_return = 0;
966
967 scm_i_gc_sweep_freelist_reset (&scm_i_master_freelist);
968 scm_i_gc_sweep_freelist_reset (&scm_i_master_freelist2);
969
970 /*
971 NOTHING HERE: LAZY SWEEPING !
972 */
973 scm_i_reset_segments ();
974
975 /* When we move to POSIX threads private freelists should probably
976 be GC-protected instead. */
977 scm_i_freelist = SCM_EOL;
978 scm_i_freelist2 = SCM_EOL;
979}
980
981#undef FUNC_NAME
982
983
56495472 984
89e00824
ML
985/*
986 Local Variables:
987 c-file-style: "gnu"
988 End:
989*/