On 2011-03-28, at 2:04 AM, Mikael wrote:
Dear Marc,
Below A B C D are Scheme procedures and f g h are C procedures.
In case of nested Scheme->C calls, i.e. if A calls f which calls B which calls g which calls C which calls h which calls D etc., then for the application not to enter an undefined state, returning the C calls _MUST_ be done in the exact reverse order in order, right? I.e., D must return to h which must return to C which must return to g which must return to B which must return to f which must return to A. If any mixing of this order is done - i.e. D returns to g, or B returns to h, etc., then the application enters an undefined state, right, or how is it?
Mikael, have you read the section "Continuations and the C-interface" in the Gambit manual? Note that Gambit implements threads using continuation captures/invocations. Because the thread system is preemptive, it is possible for the context switching between threads to happen at any time, and you have to design your program to tolerate this. This is an issue when more than one Scheme thread calls a C function which calls a Scheme function. For example, assume two Scheme threads T1 and T2 performing these (non-tail) calls
T1: A -> f -> B T2: X -> g -> Y
If there was a context switch to T2 while T1 was executing B, and T2 which was in X then did its call to g, the C stack will contain the stack frame for f and on top of that the stack frame for g.
If T2 completes the call to Y without a context switch, then it will pop g's frame from the C stack, leaving only the frame for f. If there is now a context switch to T1 (say when T2 is back in X) then execution will resume in B, and the return to f can proceed normally. All is good.
However... If T2 is in Y when there is a context switch back to T1, the execution will resume in B, and the return to f will be done by *removing the frame for g* from the C stack (using a longjump). When T2 wakes up and tries to return to g there will be a run time error because g's frame no longer exists.
This is a consequence of interleaving the C stack frames of multiple Scheme threads on a single C stack.
The "solution" is to have at most one Scheme thread which has call chains interleaving Scheme and C calls. It is OK for other Scheme threads to call C code, but they should not call back to Scheme.
Is this clear?
Marc