[MLton-commit] r6455
spoons at mlton.org
spoons at mlton.org
Mon Mar 3 07:42:42 PST 2008
Make thread operations safe for true concurrency.
Use per-processor state (rather than global state) along with the
primitive thread operations to implement MLTON_THREAD.
----------------------------------------------------------------------
U mlton/branches/shared-heap-multicore/basis-library/mlton/thread.sml
----------------------------------------------------------------------
Modified: mlton/branches/shared-heap-multicore/basis-library/mlton/thread.sml
===================================================================
--- mlton/branches/shared-heap-multicore/basis-library/mlton/thread.sml 2008-03-03 15:41:17 UTC (rev 6454)
+++ mlton/branches/shared-heap-multicore/basis-library/mlton/thread.sml 2008-03-03 15:42:41 UTC (rev 6455)
@@ -70,19 +70,25 @@
fun new f = T (ref (New f))
local
+ val numProcessors = MLtonParallelInternal.numberOfProcessors
+ val procNum = MLtonParallelInternal.processorNumber
local
- val func: (unit -> unit) option ref = ref NONE
+ (* create one reference per processor *)
+ val func: (unit -> unit) option Array.array =
+ Array.tabulate (numProcessors, fn _ => NONE)
val base: Prim.preThread =
let
val () = Prim.copyCurrent ()
+ (* Call to procNum *must* come after copy *)
+ val proc = procNum ()
in
- case !func of
+ case Array.unsafeSub (func, proc) of
NONE => Prim.savedPre gcState
| SOME x =>
(* This branch never returns. *)
let
(* Atomic 1 *)
- val () = func := NONE
+ val () = Array.update (func, proc, NONE)
val () = atomicEnd ()
(* Atomic 0 *)
in
@@ -94,16 +100,17 @@
fun newThread (f: unit -> unit) : Prim.thread =
let
(* Atomic 2 *)
- val () = func := SOME f
+ val () = Array.update (func, procNum (), SOME f)
in
Prim.copy base
end
end
- val switching = ref false
+ val switching = Array.tabulate (numProcessors, fn _ => false)
in
fun 'a atomicSwitch (f: 'a t -> Runnable.t): 'a =
+ let val proc = procNum () in
(* Atomic 1 *)
- if !switching
+ if Array.unsafeSub (switching, proc)
then let
val () = atomicEnd ()
(* Atomic 0 *)
@@ -112,13 +119,13 @@
end
else
let
- val _ = switching := true
+ val _ = Array.update (switching, proc, true)
val r : (unit -> 'a) ref =
ref (fn () => die "Thread.atomicSwitch didn't set r.\n")
val t: 'a thread ref =
ref (Paused (fn x => r := x, Prim.current gcState))
fun fail e = (t := Dead
- ; switching := false
+ ; Array.update (switching, proc, false)
; atomicEnd ()
; raise e)
val (T t': Runnable.t) = f (T t) handle e => fail e
@@ -128,13 +135,19 @@
| Interrupted t => t
| New g => (atomicBegin (); newThread g)
| Paused (f, t) => (f (fn () => ()); t)
- val _ = switching := false
+
+ val _ = if not (Array.unsafeSub (switching, proc))
+ then raise Fail "switching switched?"
+ else ()
+
+ val _ = Array.update (switching, proc, false)
(* Atomic 1 when Paused/Interrupted, Atomic 2 when New *)
val _ = Prim.switchTo primThread (* implicit atomicEnd() *)
(* Atomic 0 when resuming *)
in
!r ()
end
+ end
fun switch f =
(atomicBegin ()
@@ -166,6 +179,8 @@
local
+ (* XXX spoons global state in signal handlers (but that's not the
+ only problem...) *)
val signalHandler: Prim.thread option ref = ref NONE
datatype state = Normal | InHandler
val state: state ref = ref Normal
More information about the MLton-commit
mailing list