diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go index ebf786f0af..d39b010cf0 100644 --- a/src/runtime/lock_sema.go +++ b/src/runtime/lock_sema.go @@ -13,18 +13,16 @@ import ( // This implementation depends on OS-specific implementations of // -// uintptr runtime·semacreate(void) -// Create a semaphore, which will be assigned to m->waitsema. -// The zero value is treated as absence of any semaphore, -// so be sure to return a non-zero value. +// func semacreate(mp *m) +// Create a semaphore for mp, if it does not already have one. // -// int32 runtime·semasleep(int64 ns) -// If ns < 0, acquire m->waitsema and return 0. -// If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds. +// func semasleep(ns int64) int32 +// If ns < 0, acquire m's semaphore and return 0. +// If ns >= 0, try to acquire m's semaphore for at most ns nanoseconds. // Return 0 if the semaphore was acquired, -1 if interrupted or timed out. // -// int32 runtime·semawakeup(M *mp) -// Wake up mp, which is or will soon be sleeping on mp->waitsema. +// func semawakeup(mp *m) +// Wake up mp, which is or will soon be sleeping on its semaphore. // const ( locked uintptr = 1 @@ -45,9 +43,7 @@ func lock(l *mutex) { if atomic.Casuintptr(&l.key, 0, locked) { return } - if gp.m.waitsema == 0 { - gp.m.waitsema = semacreate() - } + semacreate(gp.m) // On uniprocessor's, no point spinning. // On multiprocessors, spin for ACTIVE_SPIN attempts. @@ -157,9 +153,7 @@ func notesleep(n *note) { if gp != gp.m.g0 { throw("notesleep not on g0") } - if gp.m.waitsema == 0 { - gp.m.waitsema = semacreate() - } + semacreate(gp.m) if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) { // Must be locked (got wakeup). if n.key != locked { @@ -248,9 +242,7 @@ func notetsleep(n *note, ns int64) bool { if gp != gp.m.g0 && gp.m.preemptoff != "" { throw("notetsleep not on g0") } - if gp.m.waitsema == 0 { - gp.m.waitsema = semacreate() - } + semacreate(gp.m) return notetsleep_internal(n, ns, nil, 0) } @@ -261,9 +253,7 @@ func notetsleepg(n *note, ns int64) bool { if gp == gp.m.g0 { throw("notetsleepg on g0") } - if gp.m.waitsema == 0 { - gp.m.waitsema = semacreate() - } + semacreate(gp.m) entersyscallblock(0) ok := notetsleep_internal(n, ns, nil, 0) exitsyscall(0) diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go index be710599df..ba38a78ed1 100644 --- a/src/runtime/os1_darwin.go +++ b/src/runtime/os1_darwin.go @@ -17,16 +17,17 @@ func unimplemented(name string) { //go:nosplit func semawakeup(mp *m) { - mach_semrelease(uint32(mp.waitsema)) + mach_semrelease(mp.waitsema) } //go:nosplit -func semacreate() uintptr { - var x uintptr +func semacreate(mp *m) { + if mp.waitsema != 0 { + return + } systemstack(func() { - x = uintptr(mach_semcreate()) + mp.waitsema = mach_semcreate() }) - return x } // BSD interface for threading. @@ -370,7 +371,7 @@ func semasleep1(ns int64) int32 { if ns >= 0 { var nsecs int32 secs := timediv(ns, 1000000000, &nsecs) - r := mach_semaphore_timedwait(uint32(_g_.m.waitsema), uint32(secs), uint32(nsecs)) + r := mach_semaphore_timedwait(_g_.m.waitsema, uint32(secs), uint32(nsecs)) if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT { return -1 } @@ -381,7 +382,7 @@ func semasleep1(ns int64) int32 { } for { - r := mach_semaphore_wait(uint32(_g_.m.waitsema)) + r := mach_semaphore_wait(_g_.m.waitsema) if r == 0 { break } diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go index 143752ada8..ad4329cecd 100644 --- a/src/runtime/os1_nacl.go +++ b/src/runtime/os1_nacl.go @@ -83,8 +83,10 @@ func newosproc(mp *m, stk unsafe.Pointer) { } //go:nosplit -func semacreate() uintptr { - var cond uintptr +func semacreate(mp *m) { + if mp.waitsema != 0 { + return + } systemstack(func() { mu := nacl_mutex_create(0) if mu < 0 { @@ -93,14 +95,12 @@ func semacreate() uintptr { } c := nacl_cond_create(0) if c < 0 { - print("nacl_cond_create: error ", -cond, "\n") + print("nacl_cond_create: error ", -c, "\n") throw("semacreate") } - cond = uintptr(c) - _g_ := getg() - _g_.m.waitsemalock = uint32(mu) + mp.waitsema = c + mp.waitsemalock = mu }) - return cond } //go:nosplit @@ -109,13 +109,13 @@ func semasleep(ns int64) int32 { systemstack(func() { _g_ := getg() - if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 { + if nacl_mutex_lock(_g_.m.waitsemalock) < 0 { throw("semasleep") } for _g_.m.waitsemacount == 0 { if ns < 0 { - if nacl_cond_wait(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock)) < 0 { + if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 { throw("semasleep") } } else { @@ -123,9 +123,9 @@ func semasleep(ns int64) int32 { end := ns + nanotime() ts.tv_sec = end / 1e9 ts.tv_nsec = int32(end % 1e9) - r := nacl_cond_timed_wait_abs(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock), &ts) + r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts) if r == -_ETIMEDOUT { - nacl_mutex_unlock(int32(_g_.m.waitsemalock)) + nacl_mutex_unlock(_g_.m.waitsemalock) ret = -1 return } @@ -136,7 +136,7 @@ func semasleep(ns int64) int32 { } _g_.m.waitsemacount = 0 - nacl_mutex_unlock(int32(_g_.m.waitsemalock)) + nacl_mutex_unlock(_g_.m.waitsemalock) ret = 0 }) return ret @@ -145,15 +145,15 @@ func semasleep(ns int64) int32 { //go:nosplit func semawakeup(mp *m) { systemstack(func() { - if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 { + if nacl_mutex_lock(mp.waitsemalock) < 0 { throw("semawakeup") } if mp.waitsemacount != 0 { throw("semawakeup") } mp.waitsemacount = 1 - nacl_cond_signal(int32(mp.waitsema)) - nacl_mutex_unlock(int32(mp.waitsemalock)) + nacl_cond_signal(mp.waitsema) + nacl_mutex_unlock(mp.waitsemalock) }) } diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go index b127c64ff4..3e77d248f7 100644 --- a/src/runtime/os1_netbsd.go +++ b/src/runtime/os1_netbsd.go @@ -40,8 +40,7 @@ func getncpu() int32 { } //go:nosplit -func semacreate() uintptr { - return 1 +func semacreate(mp *m) { } //go:nosplit diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go index beda59789c..11034a64f6 100644 --- a/src/runtime/os1_openbsd.go +++ b/src/runtime/os1_openbsd.go @@ -47,8 +47,7 @@ func getncpu() int32 { } //go:nosplit -func semacreate() uintptr { - return 1 +func semacreate(mp *m) { } //go:nosplit diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go index 07ad498fbc..bc7ce65daf 100644 --- a/src/runtime/os1_plan9.go +++ b/src/runtime/os1_plan9.go @@ -205,8 +205,7 @@ func newosproc(mp *m, stk unsafe.Pointer) { } //go:nosplit -func semacreate() uintptr { - return 1 +func semacreate(mp *m) { } //go:nosplit diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go index bd514724f1..8134543578 100644 --- a/src/runtime/os1_windows.go +++ b/src/runtime/os1_windows.go @@ -365,8 +365,11 @@ func semawakeup(mp *m) { } //go:nosplit -func semacreate() uintptr { - return stdcall4(_CreateEventA, 0, 0, 0, 0) +func semacreate(mp *m) { + if mp.waitsema != 0 { + return + } + mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0) } // May run with m.p==nil, so write barriers are not allowed. diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 792188fea6..3ac121a7b8 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -314,7 +314,11 @@ func unblocksig(sig int32) { } //go:nosplit -func semacreate() uintptr { +func semacreate(mp *m) { + if mp.waitsema != 0 { + return + } + var sem *semt _g_ := getg() @@ -331,7 +335,7 @@ func semacreate() uintptr { if sem_init(sem, 0, 0) != 0 { throw("sem_init") } - return uintptr(unsafe.Pointer(sem)) + mp.waitsema = uintptr(unsafe.Pointer(sem)) } //go:nosplit diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 0fedb707e9..7a70639b02 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -6,7 +6,9 @@ package runtime import "unsafe" -type mOS struct{} +type mOS struct { + waitsema uint32 // semaphore for parking on locks +} func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 func bsdthread_register() int32 diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go index 58330d2810..69eaf4c14e 100644 --- a/src/runtime/os_nacl.go +++ b/src/runtime/os_nacl.go @@ -6,7 +6,11 @@ package runtime import "unsafe" -type mOS struct{} +type mOS struct { + waitsema int32 // semaphore for parking on locks + waitsemacount int32 + waitsemalock int32 +} func nacl_exception_stack(p uintptr, size int32) int32 func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32 diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 659ec2d65a..988374120d 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -6,7 +6,9 @@ package runtime import "unsafe" -type mOS struct{} +type mOS struct { + waitsemacount uint32 +} //go:noescape func setitimer(mode int32, new, old *itimerval) diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go index 74a838fa41..12f4cd1a24 100644 --- a/src/runtime/os_openbsd.go +++ b/src/runtime/os_openbsd.go @@ -4,7 +4,9 @@ package runtime -type mOS struct{} +type mOS struct { + waitsemacount uint32 +} //go:noescape func setitimer(mode int32, new, old *itimerval) diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 3b3e940cbc..6e6a55e636 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -7,8 +7,9 @@ package runtime import "unsafe" type mOS struct { - notesig *int8 - errstr *byte + waitsemacount uint32 + notesig *int8 + errstr *byte } func closefd(fd int32) int32 diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go index 129653ef19..9dbe38a32a 100644 --- a/src/runtime/os_solaris.go +++ b/src/runtime/os_solaris.go @@ -16,7 +16,8 @@ type mscratch struct { } type mOS struct { - perrno *int32 // pointer to tls errno + waitsema uintptr // semaphore for parking on locks + perrno *int32 // pointer to tls errno // these are here because they are too large to be on the stack // of low-level NOSPLIT functions. //LibCall libcall; diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 22f7daad51..5dab1dec16 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -6,7 +6,9 @@ package runtime import "unsafe" -type mOS struct{} +type mOS struct { + waitsema uintptr // semaphore for parking on locks +} type stdFunction *byte diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 9ec0d1545e..1dbd3d2094 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -308,9 +308,6 @@ type m struct { fflag uint32 // floating point compare flags locked uint32 // tracking for lockosthread nextwaitm uintptr // next m waiting for lock - waitsema uintptr // semaphore for parking on locks - waitsemacount uint32 - waitsemalock uint32 gcstats gcstats needextram bool traceback uint8