[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.