shithub: mc

ref: 58a13c39b7f3e6ab0bf950908e98b9f0dfb7c951
dir: /lib/thread/condvar+openbsd:6.2.myr/

View raw version
use std
use sys

use "atomic"
use "common"
use "futex"
use "mutex"

pkg thread =
	type cond = struct
		_mtx	: mutex#
		_seq	: ftxtag
	;;

	const mkcond	: (mtx : mutex# -> cond)
	const condwait	: (cond : cond# -> void)
	const condsignal	: (cond : cond# -> void)
	const condbroadcast	: (cond : cond# -> void)
;;

const mkcond = {mtx
	-> [._mtx = mtx, ._seq = 0]
}

const condwait = {cond
	var mtx = cond._mtx
	var seq = xget(&cond._seq)

	mtxunlock(mtx)
	ftxwait(&cond._seq, seq, -1)

	/*
	In the event of a broadcast, we need to atomically set the mutex to
	contended. This allows us to pass responsibility for waking up the
	potential other waiters from the requeue operation on to the unlocker
	of the mutex.
	*/
	mtxcontended(mtx)
}

const condsignal = {cond : cond#
	xadd(&cond._seq, 1)
	ftxwake(&cond._seq)
}

const condbroadcast = {cond : cond#
	xadd(&cond._seq, 1)
	sys.futex((&cond._seq : uint32#), sys.Futexrequeue, 1,
		(0x7fffffff : sys.timespec#),
		(&cond._mtx._state : uint32#))
}