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