guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: removing scm_gc_mark_conservatively()


From: Dirk Herrmann
Subject: Re: removing scm_gc_mark_conservatively()
Date: Tue, 25 Sep 2001 00:05:20 +0200 (MEST)

On 22 Sep 2001, Marius Vollmer wrote:

> [ Sorry for coming so late. ]
> 
> Dirk Herrmann <address@hidden> writes:
> 
> > On Sun, 16 Sep 2001, Chris Cramer wrote:
> > 
> > > This patch (for stable) removes scm_gc_mark_conservatively().
> > > It fixes all the segfault problems I've been having.
> > 
> > Applied (with two minor changes) to stable and development.  Thanks for
> > your patch and the bug hunting!
> 
> Shouldn't you also always set the cell type to scm_tc16_allocated in
> SCM_NEWCELL?  Else you might miss references during code like
> 
>     SCM_NEWCELL (z);
>     SCM_SET_CELL_OBJECT_1 (z, x);
>     scm_gc ();  // is not scanned here and x might no longer be living.
>     SCM_SET_CELL_WORD_0 (z, scm_tc16_whatever);
> 
> I'm not sure whether we have such code, but we might.

First some clarification:  scm_tc16_allocated is provided for the cell
access debugging mode.  In this mode, _every_ access to a cell is
exhaustively checked.  In particular, it is checked whether a free cell is
accessed.  The reason is to find out about cells that the garbage
collector has freed accidentally - if such cells are used after gc, they
will be of the type 'free cell'.  However, a freshly obtained cell is
necessarily of the type 'free cell' until you overwrite its header - but
in cell access debugging mode even the overwriting of the header of a cell
checks first if the cell is a free cell.  Thus, for this special debugging
mode, the type scm_tc16_allocated is introduced, which is only used by the
heap administration logic:  before a fresh cell is passed to the user, it
is changed from 'free cell' to 'allocated cell'.  This change is done
using some special functions, which circumvent the regular cell access
checks.

Now, in non-cell-debugging mode it is not necessary to mark an allocated
cell as such.  Doing so would mean to add a memory-write access to every
freshly obtained cell.  Some time ago guile had used this scheme (for a
few months) due to other reasons, but IIRC we were quite happy to remove
the additional accesses as the problems that were making them necessary
could be solved.

Now, what about the code in your example?  I had a similar situation in
mind when I introduced scm_gc_mark_conservatively.  However, I suspected
that the garbage collection might happen unexpectedly due to a thread
switch.  In the above code, the correct solution would be to use
scm_remember_upto_here_1(x) after the call to the gc.  This will also work
in the case of multiple preemptive threads.  I knew of this alternative
when I introduced scm_gc_mark_conservatively, but I thought the extra
function calls to scm_remember_upto_here_1 could be avoided when each
freshly allocated cell was scanned conservatively...

Note:  There are other alternative solutions which can be used to avoid
the problem with an unexpected intermediate gc:

    SCM_NEWCELL (z);
    SCM_SET_CELL_OBJECT_1 (z, SCM_BOOL_F);
    scm_gc ();  // is not scanned here and x might no longer be living.
    SCM_SET_CELL_WORD_0 (z, scm_tc16_whatever);
    SCM_SET_CELL_OBJECT_1 (z, x);  (*)

The trick is to initialize z with some valid object (valid from the
perspective of the gc), and postpone the real initialization to the
end.  Then you know that x will live up to line (*).

Another solution is to block gc during the initialization phase.  If
threads are stopped by gc, and this stopping is done using signals, then
the blocking of gc can be done by blocking signals during the
initialization.

Best regards
Dirk Herrmann





reply via email to

[Prev in Thread] Current Thread [Next in Thread]