[plt-scheme] garbage collection questions

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed Feb 21 16:24:02 EST 2007

At Wed, 21 Feb 2007 10:13:59 -0000 (GMT), "Dave Griffiths" wrote:
> In a function extension, does the argv argument have to be protected from
> garbage collector in _every_ function which can result in a scheme
> allocation?

Yes. In

 Scheme_Object f(int argc, Scheme_object **argv) {
   ...
   scheme_do_something(...);
   ...
   ... argv[0] ...
 }

the caller of `f' may well have GC-registered a reference to the same
array as `argv', in which case the array referenced by `argv' won't get
collected during scheme_do_something(). But the array might get moved.
So, `argv' definitely needs to be registered with the GC; that way, if
scheme_do_something() causes the array to move, `argv' points to the
new location on return.

> Following on from this, is there documentation on which scheme api
> functions contain an allocation call? Is it safer to just protect all
> Scheme_Object pointers in every function extension regardless?

The latter. The documentation says

 Garbage collection can occur during any call into MzScheme or its
 allocator, on anytime that MzScheme has control, except during
 functions that are documented otherwise.

Very few functions are documented otherwise. I think the vast majority
of scheme_...() functions can, in fact, allocate.

You can assume that macros named using ALL_CAPS_AND_UNDERLINES()
do not allocate. For example, SCHEME_INTP() and SCHEME_INT_VAL()
do not allocate.

In "schemef.h", a number of functions are marked by XFORM_NON_GCING.
That's a compilation hint to the xform tool, and is not actually meant
as a part of the public API (i.e., don't rely on the annotations).

> And just to make sure - I'm assuming all memory allocated with the normal
> malloc/new (inside the extension code, or in library code) is ignored by
> the garbage collector.

Yes.

> Is there a way of running the garbage collector in a more deterministic
> manner - ie, make it run in a slow "debug" mode, freeing all availible
> memory at every opportunity (or is this what 3m does anyway) and then
> making it possible to check (with valgrind or similar) for strangeness, as
> a way of verifying extension code.

Configure with --enable-compact, and then change the #define of CHECKS
from 0 to 1 in "src/mzscheme/gc2/compact.c". This increases the number
of consistency checks, but it's a long way for GCing at every
opportunity (which would be prohibitively slow). You can change
GROW_FACTOR to something closer to 1 to trigger more frequent
collections.

> I also am having difficulty running tools like valgrind or gdb on recent
> SVN versions of mzscheme.

I don't know about Valgrind, but a common confusion with gdb under
Linux is that you get a seg fault from 3m almost immediately on
startup. That's because the GC uses page protection to implement write
barriers.

Tell gdb to ignore SIGSEGV:

 (gdb) handle SIGSEGV nostop noprint

and then continue. When there's a seg fault that doesn't look like a
write to a GC-protected page, the GC's signal handler will call
abort().

Under FreeBSD, it's SIGBUS instead of SIGSEGV.

(Under Mac OS X, the exception is handled at the Mach layer instead of
the BSD layer, so gdb doesn't stop at write barriers.)


Matthew



Posted on the users mailing list.