// 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
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.
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 {
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)
}
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)
//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.
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
}
}
for {
- r := mach_semaphore_wait(uint32(_g_.m.waitsema))
+ r := mach_semaphore_wait(_g_.m.waitsema)
if r == 0 {
break
}
}
//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 {
}
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
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 {
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
}
}
_g_.m.waitsemacount = 0
- nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+ nacl_mutex_unlock(_g_.m.waitsemalock)
ret = 0
})
return ret
//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)
})
}
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
}
//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.
}
//go:nosplit
-func semacreate() uintptr {
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
+
var sem *semt
_g_ := getg()
if sem_init(sem, 0, 0) != 0 {
throw("sem_init")
}
- return uintptr(unsafe.Pointer(sem))
+ mp.waitsema = uintptr(unsafe.Pointer(sem))
}
//go:nosplit
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
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
import "unsafe"
-type mOS struct{}
+type mOS struct {
+ waitsemacount uint32
+}
//go:noescape
func setitimer(mode int32, new, old *itimerval)
package runtime
-type mOS struct{}
+type mOS struct {
+ waitsemacount uint32
+}
//go:noescape
func setitimer(mode int32, new, old *itimerval)
import "unsafe"
type mOS struct {
- notesig *int8
- errstr *byte
+ waitsemacount uint32
+ notesig *int8
+ errstr *byte
}
func closefd(fd int32) int32
}
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;
import "unsafe"
-type mOS struct{}
+type mOS struct {
+ waitsema uintptr // semaphore for parking on locks
+}
type stdFunction *byte
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