mirror of
https://github.com/golang/go
synced 2024-11-18 04:04:49 -07:00
runtime: simplify OpenBSD semaphores
OpenBSD's thrsleep system call includes an "abort" parameter, which specifies a memory address to be tested after being registered on the sleep channel (i.e., capable of being woken up by thrwakeup). By passing a pointer to waitsemacount for this parameter, we avoid race conditions without needing a lock. Instead we just need to use atomicload, cas, and xadd to mutate the semaphore count. Change-Id: If9f2ab7cfd682da217f9912783cadea7e72283a8 Reviewed-on: https://go-review.googlesource.com/5563 Reviewed-by: Dmitry Vyukov <dvyukov@google.com> Reviewed-by: Joel Sing <jsing@google.com>
This commit is contained in:
parent
1fda57ba72
commit
9f926e81c2
@ -62,25 +62,22 @@ func semasleep(ns int64) int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// spin-mutex lock
|
v := atomicload(&_g_.m.waitsemacount)
|
||||||
for {
|
if v > 0 {
|
||||||
if xchg(&_g_.m.waitsemalock, 1) == 0 {
|
if cas(&_g_.m.waitsemacount, v, v-1) {
|
||||||
break
|
return 0 // semaphore acquired
|
||||||
}
|
}
|
||||||
osyield()
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if _g_.m.waitsemacount != 0 {
|
// Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
|
||||||
// semaphore is available.
|
//
|
||||||
_g_.m.waitsemacount--
|
// From OpenBSD's __thrsleep(2) manual:
|
||||||
// spin-mutex unlock
|
// "The abort argument, if not NULL, points to an int that will
|
||||||
atomicstore(&_g_.m.waitsemalock, 0)
|
// be examined [...] immediately before blocking. If that int
|
||||||
return 0 // semaphore acquired
|
// is non-zero then __thrsleep() will immediately return EINTR
|
||||||
}
|
// without blocking."
|
||||||
|
ret := thrsleep(uintptr(unsafe.Pointer(&_g_.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &_g_.m.waitsemacount)
|
||||||
// sleep until semaphore != 0 or timeout.
|
|
||||||
// thrsleep unlocks m.waitsemalock.
|
|
||||||
ret := thrsleep(uintptr(unsafe.Pointer(&_g_.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, uintptr(unsafe.Pointer(&_g_.m.waitsemalock)), (*int32)(unsafe.Pointer(&_g_.m.waitsemacount)))
|
|
||||||
if ret == _EWOULDBLOCK {
|
if ret == _EWOULDBLOCK {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -89,14 +86,7 @@ func semasleep(ns int64) int32 {
|
|||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func semawakeup(mp *m) {
|
func semawakeup(mp *m) {
|
||||||
// spin-mutex lock
|
xadd(&mp.waitsemacount, 1)
|
||||||
for {
|
|
||||||
if xchg(&mp.waitsemalock, 1) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
osyield()
|
|
||||||
}
|
|
||||||
mp.waitsemacount++
|
|
||||||
ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
|
ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
|
||||||
if ret != 0 && ret != _ESRCH {
|
if ret != 0 && ret != _ESRCH {
|
||||||
// semawakeup can be called on signal stack.
|
// semawakeup can be called on signal stack.
|
||||||
@ -104,8 +94,6 @@ func semawakeup(mp *m) {
|
|||||||
print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
|
print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// spin-mutex unlock
|
|
||||||
atomicstore(&mp.waitsemalock, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newosproc(mp *m, stk unsafe.Pointer) {
|
func newosproc(mp *m, stk unsafe.Pointer) {
|
||||||
|
@ -26,7 +26,7 @@ func raiseproc(sig int32)
|
|||||||
func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
|
func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *int32) int32
|
func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func thrwakeup(ident uintptr, n int32) int32
|
func thrwakeup(ident uintptr, n int32) int32
|
||||||
|
Loading…
Reference in New Issue
Block a user