[MLton-devel] calling SML from C; reentrance
Stephen Weeks
MLton@mlton.org
Fri, 16 May 2003 13:47:38 -0700
> However, I was also thinking about the fact
> MLton.FFI.handleCallFromC isn't reentrant (and I don't see how to
> make it so from the client side) -- in the sense that the callFromC
> handler can't call a C function that calls back into SML.
Good point.
> Interestingly, though, here is how the code fails:
...
> Out of memory: 1,073,854,960 bytes live.
>
> I have no idea why the runtime looking for a gig (and clearly a gig is not
> live, as this machine has 512Meg RAM + 128Meg Swap).
Once you get into segfault land, all bets are off. I don't see that
error -- I just get a segfault. Who knows why, or cares (unless you
want to try to figure out the appropriate type system to catch such
bugs).
> In a "single threaded" main program, there will really only ever be
> one stack of execution, just chained together through C functions.
I'm not quite sure what you mean by "one stack of execution". With
your code, each C call causes a call to install, whic creates a new
SML thread with a new stack.
> Interestingly, this is precisely what happens on the C side, where
> the same stack is used for all the C functions, just peppered with
> returns to MLton_callFromC that side-track the execution into ML
> before returning.
Actually, it would be nice if the SML side only had one stack,
peppered with calls to Thread_returnToC. But I couldn't figure out an
easy way to make that work.
> In a "multi threaded" main program, this should be more robust,
> since while handling a call from C to SML in one thread, we might
> switch to another ML thread that also calls C that calls SML.
Yes, handling reentrancy and multi-threading is nice.
> It also seems that we could further simplify setCallFromCHandler as
> follows:
...
That makes sense too.
How about the following, based on the idea of creating one thread per
C call, but requiring only one call in total to
Prim.setCallFromCHandler and requiring no thread creation when making
additional calls to setCallFromCHandler. It seems cleaner to me.
val setCallFromCHandler =
let
val r: (unit -> unit) ref =
ref (fn () => raise Fail "no handler for C calls")
val _ =
Prim.setCallFromCHandler
(toPrimitive
(new (let
fun loop (): unit =
let
val t = Prim.saved ()
val _ =
Prim.switchTo
(toPrimitive
(new (fn () => (!r ()
; Prim.setSaved t
; Prim.returnToC ()))))
in
loop ()
end
in
loop
end)))
in
fn f => r := f
end
Hmm. It occurs to me that with this code may lead to a way execute on
top of the existing SML stack that called the C function. Maybe we
need to add a primtive for executing a function call on top of a
stack?
-------------------------------------------------------
This SF.net email is sponsored by: If flattening out C++ or Java
code to make your application fit in a relational database is painful,
don't do it! Check out ObjectStore. Now part of Progress Software.
http://www.objectstore.net/sourceforge
_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel