[PATCH 1/2] Add ftxwakeall and waitgrps to libthread.
[Thread Prev] | [Thread Next]
- Subject: [PATCH 1/2] Add ftxwakeall and waitgrps to libthread.
- From: iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Mon, 23 Jul 2018 23:19:11 -0700
- To: "myrddin-dev" <myrddin-dev@xxxxxxxxxxxxxx>
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. --- lib/thread/bld.sub | 2 ++ lib/thread/futex+freebsd.myr | 5 ++++ lib/thread/futex+linux.myr | 5 ++++ lib/thread/futex+openbsd:6.2.myr | 5 ++++ lib/thread/futex+osx.myr | 5 ++++ lib/thread/mutex+futex.myr | 2 -- lib/thread/sem+futex.myr | 2 -- lib/thread/test/waitgrp.myr | 19 ++++++++++++ lib/thread/waitgrp+futex.myr | 37 +++++++++++++++++++++++ lib/thread/waitgrp.myr | 50 ++++++++++++++++++++++++++++++++ 10 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 lib/thread/test/waitgrp.myr create mode 100644 lib/thread/waitgrp+futex.myr create mode 100644 lib/thread/waitgrp.myr diff --git a/lib/thread/bld.sub b/lib/thread/bld.sub index 72cda980..a0c1a745 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 f659b3a1..ea5f28d8 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 32a652d1..c5dbf062 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 8283fe18..e3c9c413 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 7c74f56d..17478703 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 1a17c60d..5878755a 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 76fb285d..d79bd41b 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 00000000..3331825c --- /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 00000000..7fbd5eb6 --- /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 00000000..5da902d3 --- /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") +} -- 2.18.0
Re: [PATCH 1/2] Add ftxwakeall and waitgrps to libthread. | Ori Bernstein <ori@xxxxxxxxxxxxxx> |
- Prev by Date: Re: [PATCH] Add zeroed env pointer when a const fn is passed as an argument.
- Next by Date: Subject: [PATCH 2/2] Add/fix condvar implementations.
- Previous by thread: Re: [PATCH] Add zeroed env pointer when a const fn is passed as an argument.
- Next by thread: Re: [PATCH 1/2] Add ftxwakeall and waitgrps to libthread.
- Index(es):