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

Re: no constants please

This page is part of the web mail archives of SRFI 50 from before July 7th, 2015. The new archives for SRFI 50 contain all messages, not just those from before July 7th, 2015.




    > From: Richard Kelsey <kelsey@xxxxxxx>


    >    But the problems with the current FFI include issues with
    >    single-threaded, no-async-issue Scheme implementations including:

    >    ~ don't handle read/write barriers properly
    >    ~ don't handle transient root set members properly

    > You haven't convinced me on these points.  You have given examples
    > of misuses of the FFI, in which values are left in unprotected
    > locations during a call to a possibly-GCing procedure.  

Sorry for the confusion.  I did indeed miss that the SRFI requires:

	Note that the C function, if it allocates Scheme heap storage,
	must register its parameters with the garbage collector.

which undermines the specific examples I gave.   Here is an example
of a read/write barrier problem that I believe is based on code that
is "correct" under the draft specification:


	{
          SCHEME_DECLARE_GC_PROTECT(2);
          scheme_value x = SCHEME_UNSPECIFIC;
          scheme_value y = SCHEME_UNSPECIFIC;

          SCHEME_GC_PROTECT_2 (x, y);

          [.... set y to some heap-allocated value ....];

          [.... do some possibly-GC-causing stuff ....];

          /*A*/

          x = y;

          [.... do some possibly-GC-causing stuff ....];

          /*B*/

          SCHEME_<any> (x);

          SCHEME_GC_UNPROTECT ();
        }


The error occurs in an incremental copying collector which believes 
at point /*A*/ that it has updated `x' but not yet 'y' and at point
/*B*/ that it has reached the end of a copy cycle.

The old (pre-copying) reference to the value of `y' has been copied to
`x' -- too late for `x' to be updated.   When `SCHEME_<any>' is
called, it is passed a bogus value.

Reading or writing to or from root values (or any other Scheme
location) in an incremental, copying collector requires a read or
write barrier in order to preserve the tri-color invarient -- but the
naked C assignment `x = y' affords no such barrier (hence, permits the
invariant to be violated).

In order to preserve the invariant in the face of C's assignment
operator, at least all GC_PROTECT_GLOBAL locations and all GC_PROTECT
automatic variables must be, whenever such an assignment is possible,
the same color.   Unless the draft is modified to prohibit assignments
of the form `x = *z' where `z' is a `scheme_value *' that may point to
a GCPROtected automatic in some caller's frame -- then _all_
GCPROtected locations must be of the same GC color whenever a foreign
function is executing code between GC points.

Either way, the FFI is basically incompatible with incremental garbage
collection.

A "philosophical" way to look at this might be:  with
SCHEME_DECLARE_GC_PROTECT and SCHEME_GC_PROTECT_<n> and
SCHEME_GC_PROTECT_GLOBAL you are letting FFI-using code extend the
Scheme heap, extend the GC's working storage, _and_ giving the C
compiler license to read and write the Scheme heap directly.  In
fairness, you're trying hard to limit what the C compiler can do while
reading and writing the Scheme heap by taking advantage of sequence
points and declaring that some legal C code over these types is an
illegal use -- but examples like the above show that those limitations
are insufficient.

In contrast, with Pika-style conventions, you are letting FFI-using
code extend the Scheme heap, extend the GC's working storage -- but
_not_ giving the C compiler license to read and write the scheme heap
at all, nor sanctioning any FFI-using C code which does so.

Given the kinds of restrictions you are imposing on what counts as
correct FFI-using code, plus the restriction that parameters must be
GCPROtected in functions that may cause GC, I have serious doubts that
Pika-conventions have any real overhead compared to what you are
envisioning.  The number of stores and loads comes out the same
(Pika might even come out ahead).  Pika is simply less error
prone and more general.


-t

(You also talk about threads and interruption points related to them
but, of course, that doesn't address truly concurrent threads.)