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

Re: continuations and threads

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

>>>>> "Jim" == Jim Blandy <jimb@xxxxxxxxxxxx> writes:

>> > I think this is pretty gross, but it does allow a natural
>> > correspondence between C function calls and Scheme function calls:
>> > continuations preserve active calls to C functions, as well as Scheme
>> > functions.  If it's important to your users to be able to write C
>> > functions that can call and be called by Scheme functions, I think
>> > this is a plausible implementation choice.  I'm not aware of any other
>> > implementation that does this while requiring so little distortion of
>> > your C code.  (But if you know of one, I'd love to hear about it!)
>> There is another way (I have not implemented it yet though)... but it
>> is too complex to describe at this hour of the night!

Jim> :)

Jim> Now that you mention it, there is something I remember Roland McGrath
Jim> implementing for SMLNJ, while working for Olin Shivers.

Jim> I think the basic idea was that frames (activation records) for ML
Jim> functions were kept on the heap (as normal), while frames for C
Jim> functions were kept on a C stack.  You let the ML frames behave like
Jim> the first-class objects they are --- you can call/cc to your heart's
Jim> content --- but if you try to return to a C frame in a non-stacklike
Jim> order, the ML/C boundary code detects this and throws an exception.

Jim> I think he even arranged it so that if you returned early to an older
Jim> C frame, the younger frames would be popped appropriately (via
Jim> longjmp), and any references to younger C frames would be marked
Jim> invalid, so you'd get an error if you tried to use them.

The C FFI Richard Kelsey and I implemented for Scheme 48 does this as
well.  Here's the relevant blurb from the documentation:

There are some complications that occur when mixing calls from C to  
   Scheme with continuations and threads. C only supports downward
   continuations (via longjmp()). Scheme continuations that capture a
   portion of the C stack have to follow the same restriction. For
   example, suppose Scheme procedure s0 captures continuation a and then
   calls C procedure c0, which in turn calls Scheme procedure s1.
   Procedure s1 can safely call the continuation a, because that is a
   downward use. When a is called Scheme 48 will remove the portion of
   the C stack used by the call to c0. On the other hand, if s1 captures
   a continuation, that continuation cannot be used from s0, because by
   the time control returns to s0 the C stack used by c0 will no longer
   be valid. An attempt to invoke an upward continuation that is closed
   over a portion of the C stack will raise an exception.
   In Scheme 48 threads are implemented using continuations, so the
   downward restriction applies to them as well. An attempt to return
   from Scheme to C at a time when the appropriate C frame is not on top
   of the C stack will cause the current thread to block until the frame
   is available. For example, suppose thread t0 calls a C procedure which
   calls back to Scheme, at which point control switches to thread t1,
   which also calls C and then back to Scheme. At this point both t0 and
   t1 have active calls to C on the C stack, with t1's C frame above
   t0's. If thread t0 attempts to return from Scheme to C it will block,
   as its frame is not accessable. Once t1 has returned to C and from
   there to Scheme, t0 will be able to resume. The return to Scheme is
   required because context switches can only occur while C code is 
   running. T0 will also be able to resume if t1 uses a continuation to
   throw past its call to C.
Cheers =8-} Mike
Friede, Völkerverständigung und überhaupt blabla