[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