summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoririri <iri@konnichiwastevenspielbergde.su>2018-07-23 23:19:11 -0700
committerOri Bernstein <ori@eigenstate.org>2018-07-25 21:45:24 -0700
commit03220ea343818819d6c155bd83e609ca2282a6e4 (patch)
treecaa698cb67b5a7be69d35f20714b8f39b9e69133
parent3dca3385472541f62ef9455814a5599a8e97c03a (diff)
downloadmc-03220ea343818819d6c155bd83e609ca2282a6e4.tar.gz
Add ftxwakeall and waitgrps to libthread.
A waitgrp provides more or less the same functionality as a pthread_barrier_t or a sync.WaitGroup from Go. Since "barrier" sounds similar to a memory barrier/fence, I went with the latter name.
-rw-r--r--lib/thread/bld.sub2
-rw-r--r--lib/thread/futex+freebsd.myr5
-rw-r--r--lib/thread/futex+linux.myr5
-rw-r--r--lib/thread/futex+openbsd:6.2.myr5
-rw-r--r--lib/thread/futex+osx.myr5
-rw-r--r--lib/thread/mutex+futex.myr2
-rw-r--r--lib/thread/sem+futex.myr2
-rw-r--r--lib/thread/test/waitgrp.myr19
-rw-r--r--lib/thread/waitgrp+futex.myr37
-rw-r--r--lib/thread/waitgrp.myr50
10 files changed, 128 insertions, 4 deletions
diff --git a/lib/thread/bld.sub b/lib/thread/bld.sub
index 72cda98..a0c1a74 100644
--- a/lib/thread/bld.sub
+++ b/lib/thread/bld.sub
@@ -3,8 +3,10 @@ lib thread =
hookstd.myr # install thread hooks
mutex+futex.myr
sem+futex.myr
+ waitgrp+futex.myr
mutex.myr # fallback, for unimplemented platforms
sem.myr # fallback, for unimplemented platforms
+ waitgrp.myr # fallback, for unimplemented platforms
#generic fallbacks
ncpu.myr
diff --git a/lib/thread/futex+freebsd.myr b/lib/thread/futex+freebsd.myr
index f659b3a..ea5f28d 100644
--- a/lib/thread/futex+freebsd.myr
+++ b/lib/thread/futex+freebsd.myr
@@ -9,6 +9,7 @@ pkg thread =
const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
const ftxwake : (uaddr : ftxtag# -> int)
+ const ftxwakeall : (uaddr : ftxtag# -> int)
;;
const ftxwait = {uaddr, val, timeout
@@ -32,6 +33,10 @@ const ftxwake = {uaddr
-> sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 1, Zptr, Zptr)
}
+const ftxwakeall = {uaddr
+ -> sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 0x7fffffff, Zptr, Zptr)
+}
+
impl atomic ftxtag =
xget = {p; -> (xget32((p : uint32#)) : ftxtag)}
xset = {p, v; xset32((p : uint32#), (v : uint32))}
diff --git a/lib/thread/futex+linux.myr b/lib/thread/futex+linux.myr
index 32a652d..c5dbf06 100644
--- a/lib/thread/futex+linux.myr
+++ b/lib/thread/futex+linux.myr
@@ -9,6 +9,7 @@ pkg thread =
const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
const ftxwake : (uaddr : ftxtag# -> int)
+ const ftxwakeall : (uaddr : ftxtag# -> int)
;;
const ftxwait = {uaddr, val, timeout
@@ -24,6 +25,10 @@ const ftxwake = {uaddr
-> (sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 1, Zptr, Zptr, 0) : int)
}
+const ftxwakeall = {uaddr
+ -> (sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 0x7fffffff, Zptr, Zptr, 0) : int)
+}
+
impl atomic ftxtag =
xget = {p; -> (xget32((p : uint32#)) : ftxtag)}
xset = {p, v; xset32((p : uint32#), (v : uint32))}
diff --git a/lib/thread/futex+openbsd:6.2.myr b/lib/thread/futex+openbsd:6.2.myr
index 8283fe1..e3c9c41 100644
--- a/lib/thread/futex+openbsd:6.2.myr
+++ b/lib/thread/futex+openbsd:6.2.myr
@@ -9,6 +9,7 @@ pkg thread =
const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
const ftxwake : (uaddr : ftxtag# -> int)
+ const ftxwakeall : (uaddr : ftxtag# -> int)
;;
const ftxwait = {uaddr, val, timeout
@@ -19,6 +20,10 @@ const ftxwake = {uaddr
-> sys.futex((uaddr : uint32#), sys.Futexwake, 1, Zptr, Zptr)
}
+const ftxwakeall = {uaddr
+ -> sys.futex((uaddr : uint32#), sys.Futexwake, 0x7fffffff, Zptr, Zptr)
+}
+
impl atomic ftxtag =
xget = {p; -> (xget32((p : uint32#)) : ftxtag)}
xset = {p, v; xset32((p : uint32#), (v : uint32))}
diff --git a/lib/thread/futex+osx.myr b/lib/thread/futex+osx.myr
index 7c74f56..1747870 100644
--- a/lib/thread/futex+osx.myr
+++ b/lib/thread/futex+osx.myr
@@ -10,6 +10,7 @@ pkg thread =
const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
const ftxwake : (uaddr : ftxtag# -> int)
+ const ftxwakeall : (uaddr : ftxtag# -> int)
;;
/*
@@ -48,6 +49,10 @@ const ftxwake = {uaddr
-> sys.ulock_wake(sys.Ulockcompareandwait, (uaddr : uint64#), 0)
}
+const ftxwakeall = {uaddr
+ -> sys.ulock_wake(sys.Ulockcompareandwait | sys.Ulockulfwakeall, (uaddr : uint64#), 0)
+}
+
impl atomic ftxtag =
xget = {p; -> (xget64((p : uint64#)) : ftxtag)}
xset = {p, v; xset64((p : uint64#), (v : uint64))}
diff --git a/lib/thread/mutex+futex.myr b/lib/thread/mutex+futex.myr
index 1a17c60..5878755 100644
--- a/lib/thread/mutex+futex.myr
+++ b/lib/thread/mutex+futex.myr
@@ -1,5 +1,3 @@
-use sys
-
use "atomic"
use "common"
use "futex"
diff --git a/lib/thread/sem+futex.myr b/lib/thread/sem+futex.myr
index 76fb285..d79bd41 100644
--- a/lib/thread/sem+futex.myr
+++ b/lib/thread/sem+futex.myr
@@ -1,5 +1,4 @@
use std
-use sys
use "atomic"
use "common"
@@ -31,7 +30,6 @@ const semwait = {s
;;
ftxwait(&s._val, v, Zptr)
;;
- -> void /* Unreachable */
}
const semtrywait = {s
diff --git a/lib/thread/test/waitgrp.myr b/lib/thread/test/waitgrp.myr
new file mode 100644
index 0000000..3331825
--- /dev/null
+++ b/lib/thread/test/waitgrp.myr
@@ -0,0 +1,19 @@
+use std
+use thread
+
+const Threadc = 8
+
+var wg
+
+const main = {
+ wg = thread.mkwg(Threadc)
+
+ for var i = 0; i < Threadc; i++
+ thread.spawn({
+ std.usleep(3_000_000)
+ thread.wgpost(&wg)
+ thread.wgwait(&wg)
+ })
+ ;;
+ thread.wgwait(&wg)
+}
diff --git a/lib/thread/waitgrp+futex.myr b/lib/thread/waitgrp+futex.myr
new file mode 100644
index 0000000..7fbd5eb
--- /dev/null
+++ b/lib/thread/waitgrp+futex.myr
@@ -0,0 +1,37 @@
+use std
+
+use "atomic"
+use "common"
+use "futex"
+
+pkg thread =
+ type waitgrp = struct
+ _val : ftxtag
+ ;;
+
+ const mkwg : (v : uint32 -> waitgrp)
+ const wgwait : (w : waitgrp# -> void)
+ const wgpost : (w : waitgrp# -> void)
+;;
+
+const mkwg = {v
+ -> [._val = (v : ftxtag)]
+}
+
+const wgwait = {w
+ var v = 0
+
+ while (v = xget(&w._val)) != 0
+ ftxwait(&w._val, v, Zptr)
+ ;;
+}
+
+const wgpost = {w
+ var v = xadd(&w._val, -1)
+
+ if v == 1
+ ftxwakeall(&w._val)
+ -> void
+ ;;
+ std.assert(v > 0, "error: waitgroup underflowed\n")
+}
diff --git a/lib/thread/waitgrp.myr b/lib/thread/waitgrp.myr
new file mode 100644
index 0000000..5da902d
--- /dev/null
+++ b/lib/thread/waitgrp.myr
@@ -0,0 +1,50 @@
+use std
+
+use "atomic"
+
+pkg thread =
+ type waitgrp = struct
+ _val : uint32
+ ;;
+
+ const mkwg : (v : uint32 -> waitgrp)
+ const wgwait : (w : waitgrp# -> void)
+ const wgpost : (w : waitgrp# -> void)
+;;
+
+const mkwg = {v
+ -> [._val = v]
+}
+
+const wgwait = {w
+ for var i = 0; i < 1000; i++
+ if xget(&w._val) == 0
+ -> void
+ ;;
+ ;;
+
+ for var i = 0; i < 1000; i++
+ if xget(&w._val) == 0
+ -> void
+ ;;
+ std.nanosleep(10_000)
+ ;;
+
+ for var i = 0; i < 1000; i++
+ if xget(&w._val) == 0
+ -> void
+ ;;
+ std.nanosleep(100_000)
+ ;;
+
+ for ; ;
+ if xget(&w._val) == 0
+ -> void
+ ;;
+ std.nanosleep(1_000_000)
+ ;;
+}
+
+const wgpost = {w
+ std.assert(xadd(&w._val, -1) > 0, "error: waitgroup underflowed\n")
+}