summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-09-23 08:31:57 -0700
committerOri Bernstein <ori@eigenstate.org>2017-09-23 08:31:57 -0700
commit61fc99f4d1bb75a6ac88cf5395f37f735589b4ce (patch)
treed184b4dadc534fdeaa053078255af6a7e82c5426 /lib
parent466e33d95d9da9d218952c836d99c75ac2142b05 (diff)
downloadmc-61fc99f4d1bb75a6ac88cf5395f37f735589b4ce.tar.gz
Implement OpenBSD 6.2 futex mutexes.
Diffstat (limited to 'lib')
-rw-r--r--lib/sys/bld.sub1
-rw-r--r--lib/sys/sys+openbsd:6.2-x64.myr4
-rw-r--r--lib/thread/bld.sub1
-rw-r--r--lib/thread/mutex+openbsd:6.2.myr76
4 files changed, 82 insertions, 0 deletions
diff --git a/lib/sys/bld.sub b/lib/sys/bld.sub
index 7ffb6c8..abf90f5 100644
--- a/lib/sys/bld.sub
+++ b/lib/sys/bld.sub
@@ -7,6 +7,7 @@ lib sys =
sys+osx-x64.myr
sys+openbsd-x64.myr
sys+openbsd:6.1-x64.myr
+ sys+openbsd:6.2-x64.myr
sys+plan9-x64.myr
syscall+freebsd-x64.s
diff --git a/lib/sys/sys+openbsd:6.2-x64.myr b/lib/sys/sys+openbsd:6.2-x64.myr
index ca0ed6a..4a1f0e5 100644
--- a/lib/sys/sys+openbsd:6.2-x64.myr
+++ b/lib/sys/sys+openbsd:6.2-x64.myr
@@ -597,6 +597,10 @@ pkg sys =
;;
+ const Futexwait : int = 1
+ const Futexwake : int = 2
+ const Futexrequeue : int = 3
+
const Sysexit : scno = 1
const Sysfork : scno = 2
const Sysread : scno = 3
diff --git a/lib/thread/bld.sub b/lib/thread/bld.sub
index c5df621..4318db3 100644
--- a/lib/thread/bld.sub
+++ b/lib/thread/bld.sub
@@ -42,6 +42,7 @@ lib thread =
# openbsd impl of thread primitives
exit+openbsd-x64.s
spawn+openbsd.myr
+ mutex+openbsd:6.2.myr
atomic-impl+x64.s
atomic.myr
diff --git a/lib/thread/mutex+openbsd:6.2.myr b/lib/thread/mutex+openbsd:6.2.myr
new file mode 100644
index 0000000..f2648f5
--- /dev/null
+++ b/lib/thread/mutex+openbsd:6.2.myr
@@ -0,0 +1,76 @@
+use std
+use sys
+
+use "atomic"
+use "common"
+
+pkg thread =
+ type mutex = struct
+ _state : uint32
+ ;;
+
+ const mkmtx : (-> mutex)
+ const mtxlock : (mtx : mutex# -> void)
+ const mtxtrylock : (mtx : mutex# -> bool)
+ const mtxunlock : (mtx : mutex# -> void)
+
+ pkglocal const Unlocked : uint32 = 0
+ pkglocal const Locked : uint32 = 1
+ pkglocal const Contended : uint32 = 2
+;;
+
+var nspin = 10 /* FIXME: pick a sane number, based on CPU count */
+
+const mkmtx = {
+ -> [._state = Unlocked]
+}
+
+const mtxlock = {mtx
+ var c
+
+ /*
+ Uncontended case: we get an unlocked mutex, and we lock it.
+ */
+ c = Locked
+ for var i = 0; i < nspin; i++
+ c = xcas(&mtx._state, Unlocked, Locked)
+ if c == Unlocked
+ -> void
+ ;;
+ ;;
+
+ /*
+ Contended case: we set the lock state to Contended. This indicates that there
+ the lock is locked, and we potentially have threads waiting on it, which means
+ that we will need to wake them up.
+ */
+ if c == Locked
+ c = xchg(&mtx._state, Contended)
+ ;;
+
+ while c != Unlocked
+ sys.futex(&mtx._state, sys.Futexwait, (Contended : int), Zptr, Zptr)
+ c = xchg(&mtx._state, Contended)
+ ;;
+}
+
+const mtxtrylock = {mtx
+ -> xcas(&mtx._state, Unlocked, Locked) == Unlocked
+}
+
+const mtxunlock = {mtx
+ /*
+ Uncontended case: If the mutex state is not contended, and we still
+ are uncontended by the xchg() call, then it's safe to simply return;
+ nobody was waiting for us.
+ */
+ if mtx._state == Contended
+ mtx._state = Unlocked
+ elif xchg(&mtx._state, Unlocked) == Locked
+ -> void
+ ;;
+
+ /* wake one thread */
+ sys.futex(&mtx._state, sys.Futexwake, 1, Zptr, Zptr)
+}
+