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