Merge commit 'f30e1bdf97ae8b2b2918da585f887a4d3a23a347' into boehm-demers-weiser-gc
[bpt/guile.git] / libguile / gc.c
CommitLineData
2b829bbb 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006 Free Software Foundation, Inc.
a00c95d9 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.
a00c95d9 7 *
73be1d9e 8 * This library is distributed in the hope that it will be useful,
0f2d19dd 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.
a00c95d9 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 */
1bbd0b84 17
9de87eea 18#define _GNU_SOURCE
1bbd0b84 19
37ddcaf6
MD
20/* #define DEBUGINFO */
21
aa54a9b0
RB
22#if HAVE_CONFIG_H
23# include <config.h>
24#endif
56495472 25
e7bca227
LC
26#include "libguile/gen-scmconfig.h"
27
0f2d19dd 28#include <stdio.h>
e6e2e95a 29#include <errno.h>
783e7774 30#include <string.h>
c8a1bdc4 31#include <assert.h>
e6e2e95a 32
a0599745 33#include "libguile/_scm.h"
0a7a7445 34#include "libguile/eval.h"
a0599745
MD
35#include "libguile/stime.h"
36#include "libguile/stackchk.h"
37#include "libguile/struct.h"
a0599745
MD
38#include "libguile/smob.h"
39#include "libguile/unif.h"
40#include "libguile/async.h"
41#include "libguile/ports.h"
42#include "libguile/root.h"
43#include "libguile/strings.h"
44#include "libguile/vectors.h"
801cb5e7 45#include "libguile/weaks.h"
686765af 46#include "libguile/hashtab.h"
ecf470a2 47#include "libguile/tags.h"
a0599745 48
c8a1bdc4 49#include "libguile/private-gc.h"
a0599745 50#include "libguile/validate.h"
1be6b49c 51#include "libguile/deprecation.h"
a0599745 52#include "libguile/gc.h"
9de87eea 53#include "libguile/dynwind.h"
fce59c93 54
e7bca227 55#include "libguile/boehm-gc.h"
a82e7953 56
bc9d9bb2 57#ifdef GUILE_DEBUG_MALLOC
a0599745 58#include "libguile/debug-malloc.h"
bc9d9bb2
MD
59#endif
60
0f2d19dd 61#ifdef HAVE_MALLOC_H
95b88819 62#include <malloc.h>
0f2d19dd
JB
63#endif
64
65#ifdef HAVE_UNISTD_H
95b88819 66#include <unistd.h>
0f2d19dd
JB
67#endif
68
fb50ef08
MD
69/* Lock this mutex before doing lazy sweeping.
70 */
b17e0ac3 71scm_i_pthread_mutex_t scm_i_sweep_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
fb50ef08 72
eae33935 73/* Set this to != 0 if every cell that is accessed shall be checked:
61045190 74 */
eab1b259
HWN
75int scm_debug_cell_accesses_p = 0;
76int scm_expensive_debug_cell_accesses_p = 0;
406c7d90 77
e81d98ec
DH
78/* Set this to 0 if no additional gc's shall be performed, otherwise set it to
79 * the number of cell accesses after which a gc shall be called.
80 */
eab1b259 81int scm_debug_cells_gc_interval = 0;
e81d98ec 82
eab1b259
HWN
83/*
84 Global variable, so you can switch it off at runtime by setting
85 scm_i_cell_validation_already_running.
406c7d90 86 */
eab1b259
HWN
87int scm_i_cell_validation_already_running ;
88
89#if (SCM_DEBUG_CELL_ACCESSES == 1)
90
91
92/*
93
94 Assert that the given object is a valid reference to a valid cell. This
95 test involves to determine whether the object is a cell pointer, whether
96 this pointer actually points into a heap segment and whether the cell
97 pointed to is not a free cell. Further, additional garbage collections may
98 get executed after a user defined number of cell accesses. This helps to
99 find places in the C code where references are dropped for extremely short
100 periods.
101
102*/
406c7d90 103void
eab1b259 104scm_i_expensive_validation_check (SCM cell)
406c7d90 105{
eab1b259
HWN
106 if (!scm_in_heap_p (cell))
107 {
108 fprintf (stderr, "scm_assert_cell_valid: this object does not live in the heap: %lux\n",
109 (unsigned long) SCM_UNPACK (cell));
110 abort ();
111 }
112
113 /* If desired, perform additional garbage collections after a user
114 * defined number of cell accesses.
115 */
116 if (scm_debug_cells_gc_interval)
117 {
118 static unsigned int counter = 0;
61045190 119
eab1b259
HWN
120 if (counter != 0)
121 {
122 --counter;
123 }
124 else
125 {
126 counter = scm_debug_cells_gc_interval;
b17e0ac3 127 scm_gc ();
eab1b259
HWN
128 }
129 }
130}
131
132void
133scm_assert_cell_valid (SCM cell)
134{
135 if (!scm_i_cell_validation_already_running && scm_debug_cell_accesses_p)
406c7d90 136 {
eab1b259 137 scm_i_cell_validation_already_running = 1; /* set to avoid recursion */
406c7d90 138
c8a1bdc4 139 /*
eab1b259
HWN
140 During GC, no user-code should be run, and the guile core
141 should use non-protected accessors.
142 */
c8a1bdc4 143 if (scm_gc_running_p)
eab1b259 144 return;
c8a1bdc4
HWN
145
146 /*
eab1b259
HWN
147 Only scm_in_heap_p and rescanning the heap is wildly
148 expensive.
149 */
150 if (scm_expensive_debug_cell_accesses_p)
151 scm_i_expensive_validation_check (cell);
c8a1bdc4
HWN
152
153 if (!SCM_GC_MARK_P (cell))
406c7d90 154 {
c8a1bdc4
HWN
155 fprintf (stderr,
156 "scm_assert_cell_valid: this object is unmarked. \n"
157 "It has been garbage-collected in the last GC run: "
158 "%lux\n",
1be6b49c 159 (unsigned long) SCM_UNPACK (cell));
406c7d90
DH
160 abort ();
161 }
c8a1bdc4 162
eab1b259 163 scm_i_cell_validation_already_running = 0; /* re-enable */
406c7d90
DH
164 }
165}
166
167
eab1b259 168
406c7d90
DH
169SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
170 (SCM flag),
1e6808ea 171 "If @var{flag} is @code{#f}, cell access checking is disabled.\n"
eab1b259 172 "If @var{flag} is @code{#t}, cheap cell access checking is enabled,\n"
e81d98ec 173 "but no additional calls to garbage collection are issued.\n"
eab1b259 174 "If @var{flag} is a number, strict cell access checking is enabled,\n"
e81d98ec
DH
175 "with an additional garbage collection after the given\n"
176 "number of cell accesses.\n"
1e6808ea
MG
177 "This procedure only exists when the compile-time flag\n"
178 "@code{SCM_DEBUG_CELL_ACCESSES} was set to 1.")
406c7d90
DH
179#define FUNC_NAME s_scm_set_debug_cell_accesses_x
180{
7888309b 181 if (scm_is_false (flag))
eab1b259
HWN
182 {
183 scm_debug_cell_accesses_p = 0;
184 }
bc36d050 185 else if (scm_is_eq (flag, SCM_BOOL_T))
eab1b259
HWN
186 {
187 scm_debug_cells_gc_interval = 0;
188 scm_debug_cell_accesses_p = 1;
189 scm_expensive_debug_cell_accesses_p = 0;
190 }
e11e83f3 191 else
eab1b259 192 {
e11e83f3 193 scm_debug_cells_gc_interval = scm_to_signed_integer (flag, 0, INT_MAX);
eab1b259
HWN
194 scm_debug_cell_accesses_p = 1;
195 scm_expensive_debug_cell_accesses_p = 1;
196 }
406c7d90
DH
197 return SCM_UNSPECIFIED;
198}
199#undef FUNC_NAME
0f2d19dd 200
ecf470a2 201
c8a1bdc4 202#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
0f2d19dd
JB
203
204\f
26224b3f
LC
205/* Hooks. */
206scm_t_c_hook scm_before_gc_c_hook;
207scm_t_c_hook scm_before_mark_c_hook;
208scm_t_c_hook scm_before_sweep_c_hook;
209scm_t_c_hook scm_after_sweep_c_hook;
210scm_t_c_hook scm_after_gc_c_hook;
945fec60 211
0f2d19dd
JB
212
213/* scm_mtrigger
539b08a4 214 * is the number of bytes of malloc allocation needed to trigger gc.
0f2d19dd 215 */
c014a02e 216unsigned long scm_mtrigger;
0f2d19dd 217
0f2d19dd
JB
218/* GC Statistics Keeping
219 */
f2893a25 220unsigned long scm_cells_allocated = 0;
c014a02e 221unsigned long scm_mallocated = 0;
d9f71a07
LC
222
223/* Global GC sweep statistics since the last full GC. */
224static scm_t_sweep_statistics scm_i_gc_sweep_stats = { 0, 0 };
225static scm_t_sweep_statistics scm_i_gc_sweep_stats_1 = { 0, 0 };
226
227/* Total count of cells marked/swept. */
228static double scm_gc_cells_marked_acc = 0.;
229static double scm_gc_cells_swept_acc = 0.;
230
231static unsigned long scm_gc_time_taken = 0;
c014a02e 232static unsigned long t_before_gc;
d9f71a07
LC
233static unsigned long scm_gc_mark_time_taken = 0;
234
235static unsigned long scm_gc_times = 0;
236
237static int scm_gc_cell_yield_percentage = 0;
238static unsigned long protected_obj_count = 0;
239
240/* The following are accessed from `gc-malloc.c' and `gc-card.c'. */
c2cbcc57 241int scm_gc_malloc_yield_percentage = 0;
915b3f9f
LC
242
243static unsigned long protected_obj_count = 0;
c2cbcc57 244
0f2d19dd
JB
245
246SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
915b3f9f
LC
247SCM_SYMBOL (sym_heap_size, "heap-size");
248SCM_SYMBOL (sym_heap_free_size, "heap-free-size");
249SCM_SYMBOL (sym_heap_total_allocated, "heap-total-allocated");
0f2d19dd
JB
250SCM_SYMBOL (sym_mallocated, "bytes-malloced");
251SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
252SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
253SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
c9b0d4b0 254SCM_SYMBOL (sym_gc_mark_time_taken, "gc-mark-time-taken");
c9b0d4b0
ML
255SCM_SYMBOL (sym_times, "gc-times");
256SCM_SYMBOL (sym_cells_marked, "cells-marked");
257SCM_SYMBOL (sym_cells_swept, "cells-swept");
c2cbcc57
HWN
258SCM_SYMBOL (sym_malloc_yield, "malloc-yield");
259SCM_SYMBOL (sym_cell_yield, "cell-yield");
7eec4c37 260SCM_SYMBOL (sym_protected_objects, "protected-objects");
0f2d19dd 261
bb2c57fa 262
cf2d30f6 263
d3dd80ab 264
cf2d30f6 265/* Number of calls to SCM_NEWCELL since startup. */
c8a1bdc4
HWN
266unsigned scm_newcell_count;
267unsigned scm_newcell2_count;
b37fe1c5 268
b37fe1c5 269
0f2d19dd
JB
270/* {Scheme Interface to GC}
271 */
1367aa5e
HWN
272static SCM
273tag_table_to_type_alist (void *closure, SCM key, SCM val, SCM acc)
274{
8fecbb19 275 if (scm_is_integer (key))
8a00ba71 276 {
3e2073bd 277 int c_tag = scm_to_int (key);
8fecbb19
HWN
278
279 char const * name = scm_i_tag_name (c_tag);
280 if (name != NULL)
281 {
282 key = scm_from_locale_string (name);
283 }
284 else
285 {
286 char s[100];
287 sprintf (s, "tag %d", c_tag);
288 key = scm_from_locale_string (s);
289 }
8a00ba71 290 }
8fecbb19 291
1367aa5e
HWN
292 return scm_cons (scm_cons (key, val), acc);
293}
294
295SCM_DEFINE (scm_gc_live_object_stats, "gc-live-object-stats", 0, 0, 0,
296 (),
297 "Return an alist of statistics of the current live objects. ")
298#define FUNC_NAME s_scm_gc_live_object_stats
299{
300 SCM tab = scm_make_hash_table (scm_from_int (57));
b01532af
NJ
301 SCM alist;
302
b01532af 303 alist
1367aa5e
HWN
304 = scm_internal_hash_fold (&tag_table_to_type_alist, NULL, SCM_EOL, tab);
305
306 return alist;
307}
308#undef FUNC_NAME
309
c2cbcc57 310extern int scm_gc_malloc_yield_percentage;
a00c95d9 311SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
1bbd0b84 312 (),
1e6808ea 313 "Return an association list of statistics about Guile's current\n"
c8a1bdc4 314 "use of storage.\n")
1bbd0b84 315#define FUNC_NAME s_scm_gc_stats
0f2d19dd 316{
0f2d19dd 317 SCM answer;
915b3f9f
LC
318 size_t heap_size, free_bytes, bytes_since_gc, total_bytes;
319 size_t gc_times;
4c9419ac 320
915b3f9f
LC
321 heap_size = GC_get_heap_size ();
322 free_bytes = GC_get_free_bytes ();
323 bytes_since_gc = GC_get_bytes_since_gc ();
324 total_bytes = GC_get_total_bytes ();
325 gc_times = GC_gc_no;
fca43887 326
33b320ae
NJ
327 /* njrev: can any of these scm_cons's or scm_list_n signal a memory
328 error? If so we need a frame here. */
b9bd8526 329 answer =
915b3f9f
LC
330 scm_list_n (scm_cons (sym_gc_time_taken, SCM_INUM0),
331#if 0
b9bd8526
MV
332 scm_cons (sym_cells_allocated,
333 scm_from_ulong (local_scm_cells_allocated)),
b9bd8526
MV
334 scm_cons (sym_mallocated,
335 scm_from_ulong (local_scm_mallocated)),
336 scm_cons (sym_mtrigger,
337 scm_from_ulong (local_scm_mtrigger)),
b9bd8526
MV
338 scm_cons (sym_gc_mark_time_taken,
339 scm_from_ulong (local_scm_gc_mark_time_taken)),
340 scm_cons (sym_cells_marked,
341 scm_from_double (local_scm_gc_cells_marked)),
342 scm_cons (sym_cells_swept,
343 scm_from_double (local_scm_gc_cells_swept)),
344 scm_cons (sym_malloc_yield,
345 scm_from_long(local_scm_gc_malloc_yield_percentage)),
346 scm_cons (sym_cell_yield,
347 scm_from_long (local_scm_gc_cell_yield_percentage)),
b9bd8526 348 scm_cons (sym_heap_segments, heap_segs),
915b3f9f
LC
349#endif
350 scm_cons (sym_heap_size, scm_from_size_t (heap_size)),
351 scm_cons (sym_heap_free_size, scm_from_size_t (free_bytes)),
352 scm_cons (sym_heap_total_allocated,
353 scm_from_size_t (total_bytes)),
354 scm_cons (sym_protected_objects,
355 scm_from_ulong (protected_obj_count)),
356 scm_cons (sym_times, scm_from_size_t (gc_times)),
b9bd8526 357 SCM_UNDEFINED);
fca43887 358
c8a1bdc4 359 return answer;
0f2d19dd 360}
c8a1bdc4 361#undef FUNC_NAME
0f2d19dd 362
539b08a4 363
acf4331f 364
0f2d19dd 365
c8a1bdc4
HWN
366SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
367 (SCM obj),
368 "Return an integer that for the lifetime of @var{obj} is uniquely\n"
369 "returned by this function for @var{obj}")
370#define FUNC_NAME s_scm_object_address
c68296f8 371{
b9bd8526 372 return scm_from_ulong (SCM_UNPACK (obj));
c68296f8 373}
c8a1bdc4 374#undef FUNC_NAME
c68296f8 375
1be6b49c 376
915b3f9f
LC
377SCM_DEFINE (scm_gc_disable, "gc-disable", 0, 0, 0,
378 (),
379 "Disables the garbage collector. Nested calls are permitted. "
380 "GC is re-enabled once @code{gc-enable} has been called the "
381 "same number of times @code{gc-disable} was called.")
382#define FUNC_NAME s_scm_gc_disable
383{
384 GC_disable ();
385 return SCM_UNSPECIFIED;
386}
387#undef FUNC_NAME
388
389SCM_DEFINE (scm_gc_enable, "gc-enable", 0, 0, 0,
390 (),
391 "Enables the garbage collector.")
392#define FUNC_NAME s_scm_gc_enable
393{
394 GC_enable ();
395 return SCM_UNSPECIFIED;
396}
397#undef FUNC_NAME
398
399
c8a1bdc4
HWN
400SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
401 (),
402 "Scans all of SCM objects and reclaims for further use those that are\n"
403 "no longer accessible.")
404#define FUNC_NAME s_scm_gc
405{
b17e0ac3
MV
406 scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
407 scm_gc_running_p = 1;
408 scm_i_gc ("call");
33b320ae
NJ
409 /* njrev: It looks as though other places, e.g. scm_realloc,
410 can call scm_i_gc without acquiring the sweep mutex. Does this
411 matter? Also scm_i_gc (or its descendants) touch the
412 scm_sys_protects, which are protected in some cases
413 (e.g. scm_permobjs above in scm_gc_stats) by a critical section,
414 not by the sweep mutex. Shouldn't all the GC-relevant objects be
415 protected in the same way? */
b17e0ac3
MV
416 scm_gc_running_p = 0;
417 scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
418 scm_c_hook_run (&scm_after_gc_c_hook, 0);
c8a1bdc4 419 return SCM_UNSPECIFIED;
9d47a1e6 420}
c8a1bdc4 421#undef FUNC_NAME
9d47a1e6 422
c8a1bdc4 423void
b17e0ac3 424scm_i_gc (const char *what)
c8a1bdc4 425{
26224b3f 426 GC_gcollect ();
eab1b259 427}
0f2d19dd 428
4c7016dc 429
0f2d19dd
JB
430\f
431/* {GC Protection Helper Functions}
432 */
433
434
5d2b97cd
DH
435/*
436 * If within a function you need to protect one or more scheme objects from
437 * garbage collection, pass them as parameters to one of the
438 * scm_remember_upto_here* functions below. These functions don't do
439 * anything, but since the compiler does not know that they are actually
440 * no-ops, it will generate code that calls these functions with the given
441 * parameters. Therefore, you can be sure that the compiler will keep those
442 * scheme values alive (on the stack or in a register) up to the point where
443 * scm_remember_upto_here* is called. In other words, place the call to
592996c9 444 * scm_remember_upto_here* _behind_ the last code in your function, that
5d2b97cd
DH
445 * depends on the scheme object to exist.
446 *
8c494e99
DH
447 * Example: We want to make sure that the string object str does not get
448 * garbage collected during the execution of 'some_function' in the code
449 * below, because otherwise the characters belonging to str would be freed and
5d2b97cd
DH
450 * 'some_function' might access freed memory. To make sure that the compiler
451 * keeps str alive on the stack or in a register such that it is visible to
452 * the conservative gc we add the call to scm_remember_upto_here_1 _after_ the
453 * call to 'some_function'. Note that this would not be necessary if str was
454 * used anyway after the call to 'some_function'.
eb01cb64 455 * char *chars = scm_i_string_chars (str);
5d2b97cd
DH
456 * some_function (chars);
457 * scm_remember_upto_here_1 (str); // str will be alive up to this point.
458 */
459
9e1569bd
KR
460/* Remove any macro versions of these while defining the functions.
461 Functions are always included in the library, for upward binary
462 compatibility and in case combinations of GCC and non-GCC are used. */
463#undef scm_remember_upto_here_1
464#undef scm_remember_upto_here_2
465
5d2b97cd 466void
e81d98ec 467scm_remember_upto_here_1 (SCM obj SCM_UNUSED)
5d2b97cd
DH
468{
469 /* Empty. Protects a single object from garbage collection. */
470}
471
472void
e81d98ec 473scm_remember_upto_here_2 (SCM obj1 SCM_UNUSED, SCM obj2 SCM_UNUSED)
5d2b97cd
DH
474{
475 /* Empty. Protects two objects from garbage collection. */
476}
477
478void
e81d98ec 479scm_remember_upto_here (SCM obj SCM_UNUSED, ...)
5d2b97cd
DH
480{
481 /* Empty. Protects any number of objects from garbage collection. */
482}
483
c209c88e 484/*
41b0806d
GB
485 These crazy functions prevent garbage collection
486 of arguments after the first argument by
487 ensuring they remain live throughout the
488 function because they are used in the last
489 line of the code block.
490 It'd be better to have a nice compiler hint to
491 aid the conservative stack-scanning GC. --03/09/00 gjb */
0f2d19dd
JB
492SCM
493scm_return_first (SCM elt, ...)
0f2d19dd
JB
494{
495 return elt;
496}
497
41b0806d
GB
498int
499scm_return_first_int (int i, ...)
500{
501 return i;
502}
503
0f2d19dd 504
0f2d19dd 505SCM
6e8d25a6 506scm_permanent_object (SCM obj)
0f2d19dd 507{
8e7b3e98 508 return (scm_gc_protect_object (obj));
0f2d19dd
JB
509}
510
511
7bd4fbe2
MD
512/* Protect OBJ from the garbage collector. OBJ will not be freed, even if all
513 other references are dropped, until the object is unprotected by calling
6b1b030e 514 scm_gc_unprotect_object (OBJ). Calls to scm_gc_protect/unprotect_object nest,
7bd4fbe2
MD
515 i. e. it is possible to protect the same object several times, but it is
516 necessary to unprotect the object the same number of times to actually get
517 the object unprotected. It is an error to unprotect an object more often
518 than it has been protected before. The function scm_protect_object returns
519 OBJ.
520*/
521
522/* Implementation note: For every object X, there is a counter which
6b1b030e 523 scm_gc_protect_object(X) increments and scm_gc_unprotect_object(X) decrements.
7bd4fbe2 524*/
686765af 525
7eec4c37
HWN
526
527
ef290276 528SCM
6b1b030e 529scm_gc_protect_object (SCM obj)
ef290276 530{
686765af 531 SCM handle;
9d47a1e6 532
686765af 533 /* This critical section barrier will be replaced by a mutex. */
33b320ae
NJ
534 /* njrev: Indeed; if my comment above is correct, there is the same
535 critsec/mutex inconsistency here. */
9de87eea 536 SCM_CRITICAL_SECTION_START;
9d47a1e6 537
e11e83f3
MV
538 handle = scm_hashq_create_handle_x (scm_protects, obj, scm_from_int (0));
539 SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), scm_from_int (1)));
9d47a1e6 540
7eec4c37
HWN
541 protected_obj_count ++;
542
9de87eea 543 SCM_CRITICAL_SECTION_END;
9d47a1e6 544
ef290276
JB
545 return obj;
546}
547
548
549/* Remove any protection for OBJ established by a prior call to
dab7f566 550 scm_protect_object. This function returns OBJ.
ef290276 551
dab7f566 552 See scm_protect_object for more information. */
ef290276 553SCM
6b1b030e 554scm_gc_unprotect_object (SCM obj)
ef290276 555{
686765af 556 SCM handle;
9d47a1e6 557
686765af 558 /* This critical section barrier will be replaced by a mutex. */
33b320ae 559 /* njrev: and again. */
9de87eea 560 SCM_CRITICAL_SECTION_START;
9d47a1e6 561
0ff7e3ff
HWN
562 if (scm_gc_running_p)
563 {
564 fprintf (stderr, "scm_unprotect_object called during GC.\n");
565 abort ();
566 }
b17e0ac3 567
686765af 568 handle = scm_hashq_get_handle (scm_protects, obj);
9d47a1e6 569
7888309b 570 if (scm_is_false (handle))
686765af 571 {
0f0f0899
MD
572 fprintf (stderr, "scm_unprotect_object called on unprotected object\n");
573 abort ();
686765af 574 }
6a199940
DH
575 else
576 {
e11e83f3 577 SCM count = scm_difference (SCM_CDR (handle), scm_from_int (1));
bc36d050 578 if (scm_is_eq (count, scm_from_int (0)))
6a199940
DH
579 scm_hashq_remove_x (scm_protects, obj);
580 else
1be6b49c 581 SCM_SETCDR (handle, count);
6a199940 582 }
7eec4c37 583 protected_obj_count --;
686765af 584
9de87eea 585 SCM_CRITICAL_SECTION_END;
ef290276
JB
586
587 return obj;
588}
589
6b1b030e
ML
590void
591scm_gc_register_root (SCM *p)
592{
8e7b3e98 593 /* Nothing. */
6b1b030e
ML
594}
595
596void
597scm_gc_unregister_root (SCM *p)
598{
8e7b3e98 599 /* Nothing. */
6b1b030e
ML
600}
601
602void
603scm_gc_register_roots (SCM *b, unsigned long n)
604{
605 SCM *p = b;
606 for (; p < b + n; ++p)
607 scm_gc_register_root (p);
608}
609
610void
611scm_gc_unregister_roots (SCM *b, unsigned long n)
612{
613 SCM *p = b;
614 for (; p < b + n; ++p)
615 scm_gc_unregister_root (p);
616}
617
04a98cff 618int scm_i_terminating;
c45acc34 619
0f2d19dd 620\f
a00c95d9 621
4c48ba06 622
c8a1bdc4
HWN
623/*
624 MOVE THIS FUNCTION. IT DOES NOT HAVE ANYTHING TODO WITH GC.
625 */
85db4a2c
DH
626
627/* Get an integer from an environment variable. */
c8a1bdc4
HWN
628int
629scm_getenv_int (const char *var, int def)
85db4a2c 630{
c8a1bdc4
HWN
631 char *end = 0;
632 char *val = getenv (var);
633 long res = def;
85db4a2c
DH
634 if (!val)
635 return def;
636 res = strtol (val, &end, 10);
637 if (end == val)
638 return def;
639 return res;
640}
641
c35738c1
MD
642void
643scm_storage_prehistory ()
644{
184327a6
LC
645 GC_all_interior_pointers = 0;
646
a82e7953 647 GC_INIT ();
e7bca227
LC
648
649#ifdef SCM_I_GSC_USE_PTHREAD_THREADS
650 /* When using GC 6.8, this call is required to initialize thread-local
651 freelists (shouldn't be necessary with GC 7.0). */
652 GC_init ();
653#endif
654
fdab75a1 655 GC_expand_hp (SCM_DEFAULT_INIT_HEAP_SIZE_2);
915b3f9f 656
184327a6
LC
657 /* We only need to register a displacement for those types for which the
658 higher bits of the type tag are used to store a pointer (that is, a
659 pointer to an 8-octet aligned region). For `scm_tc3_struct', this is
660 handled in `scm_alloc_struct ()'. */
661 GC_REGISTER_DISPLACEMENT (scm_tc3_cons);
662 GC_REGISTER_DISPLACEMENT (scm_tc3_closure);
663
915b3f9f
LC
664 /* Sanity check. */
665 if (!GC_is_visible (scm_sys_protects))
666 abort ();
a82e7953 667
c35738c1
MD
668 scm_c_hook_init (&scm_before_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
669 scm_c_hook_init (&scm_before_mark_c_hook, 0, SCM_C_HOOK_NORMAL);
670 scm_c_hook_init (&scm_before_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
671 scm_c_hook_init (&scm_after_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
672 scm_c_hook_init (&scm_after_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
673}
85db4a2c 674
9de87eea 675scm_i_pthread_mutex_t scm_i_gc_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
eb01cb64 676
4a4c9785 677int
85db4a2c 678scm_init_storage ()
0f2d19dd 679{
1be6b49c 680 size_t j;
0f2d19dd
JB
681
682 j = SCM_NUM_PROTECTS;
683 while (j)
684 scm_sys_protects[--j] = SCM_BOOL_F;
4a4c9785 685
0f2d19dd 686 j = SCM_HEAP_SEG_SIZE;
d6884e63 687
9de87eea
MV
688#if 0
689 /* We can't have a cleanup handler since we have no thread to run it
690 in. */
691
a18bcd0e 692#ifdef HAVE_ATEXIT
c45acc34 693 atexit (cleanup);
e52ceaac
MD
694#else
695#ifdef HAVE_ON_EXIT
696 on_exit (cleanup, 0);
697#endif
9de87eea
MV
698#endif
699
a18bcd0e 700#endif
0f2d19dd 701
e4da0740 702 scm_stand_in_procs = scm_make_weak_key_hash_table (scm_from_int (257));
00ffa0e7 703 scm_protects = scm_c_make_hash_table (31);
d6884e63 704
0f2d19dd
JB
705 return 0;
706}
939794ce 707
0f2d19dd
JB
708\f
709
939794ce
DH
710SCM scm_after_gc_hook;
711
939794ce
DH
712static SCM gc_async;
713
939794ce
DH
714/* The function gc_async_thunk causes the execution of the after-gc-hook. It
715 * is run after the gc, as soon as the asynchronous events are handled by the
716 * evaluator.
717 */
718static SCM
719gc_async_thunk (void)
720{
721 scm_c_run_hook (scm_after_gc_hook, SCM_EOL);
939794ce
DH
722 return SCM_UNSPECIFIED;
723}
724
725
726/* The function mark_gc_async is run by the scm_after_gc_c_hook at the end of
727 * the garbage collection. The only purpose of this function is to mark the
728 * gc_async (which will eventually lead to the execution of the
729 * gc_async_thunk).
730 */
731static void *
e81d98ec
DH
732mark_gc_async (void * hook_data SCM_UNUSED,
733 void *func_data SCM_UNUSED,
734 void *data SCM_UNUSED)
735{
736 /* If cell access debugging is enabled, the user may choose to perform
737 * additional garbage collections after an arbitrary number of cell
738 * accesses. We don't want the scheme level after-gc-hook to be performed
739 * for each of these garbage collections for the following reason: The
740 * execution of the after-gc-hook causes cell accesses itself. Thus, if the
741 * after-gc-hook was performed with every gc, and if the gc was performed
742 * after a very small number of cell accesses, then the number of cell
743 * accesses during the execution of the after-gc-hook will suffice to cause
744 * the execution of the next gc. Then, guile would keep executing the
745 * after-gc-hook over and over again, and would never come to do other
746 * things.
eae33935 747 *
e81d98ec
DH
748 * To overcome this problem, if cell access debugging with additional
749 * garbage collections is enabled, the after-gc-hook is never run by the
750 * garbage collecter. When running guile with cell access debugging and the
751 * execution of the after-gc-hook is desired, then it is necessary to run
752 * the hook explicitly from the user code. This has the effect, that from
753 * the scheme level point of view it seems that garbage collection is
754 * performed with a much lower frequency than it actually is. Obviously,
755 * this will not work for code that depends on a fixed one to one
756 * relationship between the execution counts of the C level garbage
757 * collection hooks and the execution count of the scheme level
758 * after-gc-hook.
759 */
9de87eea 760
e81d98ec 761#if (SCM_DEBUG_CELL_ACCESSES == 1)
eab1b259 762 if (scm_debug_cells_gc_interval == 0)
e81d98ec
DH
763 scm_system_async_mark (gc_async);
764#else
939794ce 765 scm_system_async_mark (gc_async);
e81d98ec
DH
766#endif
767
939794ce
DH
768 return NULL;
769}
770
26224b3f
LC
771char const *
772scm_i_tag_name (scm_t_bits tag)
773{
774 if (tag >= 255)
775 {
776 if (tag == scm_tc_free_cell)
777 return "free cell";
778
779 {
780 int k = 0xff & (tag >> 8);
781 return (scm_smobs[k].name);
782 }
783 }
784
785 switch (tag) /* 7 bits */
786 {
787 case scm_tcs_struct:
788 return "struct";
789 case scm_tcs_cons_imcar:
790 return "cons (immediate car)";
791 case scm_tcs_cons_nimcar:
792 return "cons (non-immediate car)";
793 case scm_tcs_closures:
794 return "closures";
795 case scm_tc7_pws:
796 return "pws";
797 case scm_tc7_wvect:
798 return "weak vector";
799 case scm_tc7_vector:
800 return "vector";
801#ifdef CCLO
802 case scm_tc7_cclo:
803 return "compiled closure";
804#endif
805 case scm_tc7_number:
806 switch (tag)
807 {
808 case scm_tc16_real:
809 return "real";
810 break;
811 case scm_tc16_big:
812 return "bignum";
813 break;
814 case scm_tc16_complex:
815 return "complex number";
816 break;
817 case scm_tc16_fraction:
818 return "fraction";
819 break;
820 }
821 break;
822 case scm_tc7_string:
823 return "string";
824 break;
825 case scm_tc7_stringbuf:
826 return "string buffer";
827 break;
828 case scm_tc7_symbol:
829 return "symbol";
830 break;
831 case scm_tc7_variable:
832 return "variable";
833 break;
834 case scm_tcs_subrs:
835 return "subrs";
836 break;
837 case scm_tc7_port:
838 return "port";
839 break;
840 case scm_tc7_smob:
841 return "smob"; /* should not occur. */
842 break;
843 }
844
845 return NULL;
846}
847
848
26224b3f
LC
849
850\f
0f2d19dd
JB
851void
852scm_init_gc ()
0f2d19dd 853{
a82e7953 854 /* `GC_INIT ()' was invoked in `scm_storage_prehistory ()'. */
d678e25c 855
fde50407
ML
856 scm_after_gc_hook = scm_permanent_object (scm_make_hook (SCM_INUM0));
857 scm_c_define ("after-gc-hook", scm_after_gc_hook);
939794ce 858
2592c4c7
MV
859 gc_async = scm_c_make_subr ("%gc-thunk", scm_tc7_subr_0,
860 gc_async_thunk);
939794ce
DH
861
862 scm_c_hook_add (&scm_after_gc_c_hook, mark_gc_async, NULL, 0);
863
a0599745 864#include "libguile/gc.x"
0f2d19dd 865}
89e00824 866
9a5fa6e9
NJ
867#ifdef __ia64__
868# ifdef __hpux
869# include <sys/param.h>
870# include <sys/pstat.h>
871void *
872scm_ia64_register_backing_store_base (void)
873{
874 struct pst_vm_status vm_status;
875 int i = 0;
876 while (pstat_getprocvm (&vm_status, sizeof (vm_status), 0, i++) == 1)
877 if (vm_status.pst_type == PS_RSESTACK)
878 return (void *) vm_status.pst_vaddr;
879 abort ();
880}
881void *
882scm_ia64_ar_bsp (const void *ctx)
883{
884 uint64_t bsp;
885 __uc_get_ar_bsp(ctx, &bsp);
886 return (void *) bsp;
887}
888# endif /* hpux */
889# ifdef linux
890# include <ucontext.h>
891void *
892scm_ia64_register_backing_store_base (void)
893{
894 extern void *__libc_ia64_register_backing_store_base;
895 return __libc_ia64_register_backing_store_base;
896}
897void *
898scm_ia64_ar_bsp (const void *opaque)
899{
900 ucontext_t *ctx = opaque;
901 return (void *) ctx->uc_mcontext.sc_ar_bsp;
902}
903# endif /* linux */
904#endif /* __ia64__ */
c8a1bdc4
HWN
905
906void
907scm_gc_sweep (void)
908#define FUNC_NAME "scm_gc_sweep"
909{
26224b3f
LC
910 /* FIXME */
911 fprintf (stderr, "%s: doing nothing\n", __FUNCTION__);
c8a1bdc4
HWN
912}
913
914#undef FUNC_NAME
915
916
56495472 917
89e00824
ML
918/*
919 Local Variables:
920 c-file-style: "gnu"
921 End:
922*/