[MLton] interrupted system call

Matthew Fluet fluet@cs.cornell.edu
Fri, 26 Mar 2004 19:40:02 -0500 (EST)


> Also, from what I can tell, your use of wrapAtomic is just an
> optimization.  That is {wrapAtomic = false} is used to tell syscall
> that there is no state that needs connecting.  It doesn't seem like
> there would be any harm caused by forcing {wrapAtomic = true}.

It is an optimization, but critical sections are doing more work as a
consequence of this discussion.  In particular, if atomicEnd necessitates
a GC_gc in the CFG, then we'll be forcing more SSA variables onto the
stack.  That's an expense.

Of course, its probably a moot point.  I'm going to point out below that
accessing errno needs to be in the critical region.

> val syscall: (unit -> int * (unit -> 'a)) * {restart: bool} -> 'a
> fun mlF (x, {a, b}) =
>    syscall (fn () => (F_Foo_setA a
> 		        ; F_Foo_setB b
> 		        ; (MLton_F x,
> 		  	   fn () => {y = F_Bar_getY (),
> 			  	     z = F_Bar_getZ ()})),
> 	      {restart = true})

I understand that this is equivalent to my signature.  I find it
harder to read at a glance to pick out the distinct portions of the code;
I've got to unwind where thunks begin and end.  And I'm going to be
spending a lot more time looking at code that calls syscall than I am
looking at its signature.  I prefer to see the names.  (Of course, Stephen
would insist on ordering the record alphabetically:
  {call = ...,
   restart = ...,
   post = ...,
   pre = ...}
rendering it utterly unreadable. ;-)

>       fun call (err: int -> 'a): 'a =
>          let
> 	    val () = atomicBegin ()
>             val (n, post) = f ()
>          in
>             if n = ~1
> 	       then (atomicEnd (); err (getErrno ()))
> 	    else (post () before atomicEnd ())
>          end

atomicEnd will invoke the signal handler; so, errno could be bogus when we
continue executing here.  So, we need to getErrno before atomicEnd.

Note also that this is a situation where atomicBegin/End is simpler (and
obviously correct) than MLton.Thread.atomically.  You can do it with with
atomically, but it's just more CPS thunking.

>       fun err (e: int): 'a =
>          if restart andalso (e = Signal.intr orelse e = Signal.restart)

Don't forget !MLton.Signal.restart.