runtime: correct semaphore implementation on netbsd

NetBSD's semaphores use the underlying lighweight process mechanism
(LWP) on NetBSD, rather than pthreads. This means the m.prodcid needs
to be set to the LWP ID rather than the pthread ID in order for unpark
notifications to get sent to the right place.

Introduce a new getProcID() method that selects the correct ID for the
platform.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/261742
This commit is contained in:
Nikhil Benesch 2020-10-13 07:17:55 +00:00 committed by Ian Lance Taylor
parent 61a43de58c
commit ca56d57624
7 changed files with 30 additions and 8 deletions

View File

@ -1,4 +1,4 @@
6cb7b9e924d84125f21f4a2a96aa0d59466056fe
c5505c4e626fa4217911443b4db8b065855a0206
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -21,6 +21,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
func getProcID() uint64 {
return uint64(gettid())
}
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer

View File

@ -27,8 +27,7 @@ func mpreinit(mp *m) {
func minit() {
minitSignals()
// FIXME: only works on linux for now.
getg().m.procid = uint64(gettid())
getg().m.procid = getProcID()
}
// Called from dropm to undo the effect of an minit.

View File

@ -18,6 +18,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
func getProcID() uint64 {
return uint64(gettid())
}
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer

View File

@ -13,6 +13,10 @@ type mOS struct {
unused byte
}
func getProcID() uint64 {
return uint64(gettid())
}
func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 {
return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
}

View File

@ -14,12 +14,19 @@ type mOS struct {
waitsemacount uint32
}
func getProcID() uint64 {
return uint64(lwp_self())
}
//extern _lwp_self
func lwp_self() int32
//go:noescape
//extern lwp_park
//extern _lwp_park
func lwp_park(ts int32, rel int32, abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
//go:noescape
//extern lwp_unpark
//extern _lwp_unpark
func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
//go:noescape
@ -88,7 +95,7 @@ func semasleep(ns int64) int32 {
tsp = &ts
}
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
if ret == _ETIMEDOUT {
if ret != 0 && errno() == _ETIMEDOUT {
return -1
}
}
@ -101,10 +108,10 @@ func semawakeup(mp *m) {
// "If the target LWP is not currently waiting, it will return
// immediately upon the next call to _lwp_park()."
ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
if ret != 0 && ret != _ESRCH {
if ret != 0 && errno() != _ESRCH {
// semawakeup can be called on signal stack.
systemstack(func() {
print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " errno=", errno(), "\n")
})
}
}

View File

@ -10,6 +10,10 @@ type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
func getProcID() uint64 {
return uint64(gettid())
}
//extern malloc
func libc_malloc(uintptr) unsafe.Pointer