Re: Comparing Pika-syle and JNI-style Jim Blandy 14 Jan 2004 23:54 UTC

Tom Lord <xxxxxx@emf.net> writes:
> About the following: one of us is confused.  Not sure which.
>
>
>     > >     >     mn_ref *
>     > >     >     mn_to_car (mn_call *call, mn_ref *ref)
>     > >     >     {
>     > >     >       mn__begin_incoherent (call);
>     > >     >       {
>     > >     >         ref->obj = check_pair (ref)->car;
>     > >     >       }
>     > >     >       mn__end_incoherent (call);
>     > >     >
>     > >     >       return ref;
>     > >     >     }
>
>     > > Isn't that code incorrect in a threaded system?   While `ref' is,
>     > > indeed, about to be freed, the pair that it refers to is live.
>     > > Assuming that the `incoherent' calls exclude only GC but not other
>     > > mutators (which is the benefit you seem to be claiming), then the
>     > > `->car' risks producing garbage.
>
>     > This is what that comment is going on about.  References are
>     > immutable: there is no operation that changes a reference's referent.
>     > mn_to_car looks like a counter-example, but it isn't: officially, it
>     > frees REF, so it would be incorrect to call it if any other thread
>     > were referring to it.  But since it's freeing a reference and then
>     > immediately allocating a new one, it might as well just reuse the
>     > reference.
>
> That's not what I mean by "incorrect in a threaded system".
>
> Am I correct that `check_pair (ref)' returns a pointer to something
> like:
>
> 	struct pair
>         {
>           scheme_value car;
>           scheme_value cdr;
>         }
>
> ?

Yes.

> And am I correct that mn__begin_incoherent excludes GC but not other
> mutators?

Yes.

> If both assumptions are true then the code is incorrect because
> `->car' is not necessarily going to return a legitimate scheme value
> (it may return a "half written" one).

That's right, in theory.

(Just to be clear: we're now talking about details of the Minor
implementation, here, not whether the Minor API can be implemented
properly.  I think we agree that the Minor interface gives
implementations the hooks they need to do whatever synchronization is
needed.)

I just assume things will work out here:

- The Minor implementation is not intended to be portable to all ISO C
  / POSIX platforms.  I'm much more interested in the native code JIT
  than in the interpreter, so the Minor implementation will generally
  make machine-specific assumptions where doing so makes a big
  difference.  And since I'm interested in clean interoperation with
  the C and C++ toolchains, I plan to generate native .o files, so
  Minor will be ABI-specific, too.

- Java requires that pointers not be corrupted, even in the absence of
  proper synchronization.  As far as I can see, the gcj front end for
  GCC doesn't do anything special to ensure that pointers are read and
  written with single instructions.  So I think C code should be able
  to make the same assumption.

- GCC must not generate split stores for sig_atomic_t, and the GNU C
  library simply defines that as 'int' on every platform.  So on those
  platforms where int can hold a pointer, I'm fine.  This is true on
  every platform I intend to care about, except the x86-64.

- Of course, the instructions the compiler generates don't dictate how
  the inter-processor cache interactions work, so in theory they could
  chop up the pointer, too.  But Java already requires that writes to
  words appear atomic, so this is apparently not a problem.