Commit ec9aae77 authored by Matthew Dempsky's avatar Matthew Dempsky

runtime: move m's OS-specific semaphore fields into mOS

Allows removing fields that aren't relevant to a particular OS or
changing their types to match the underlying OS system calls they'll
be used for.

Change-Id: I5cea89ee77b4e7b985bff41337e561887c3272ff
Reviewed-on: https://go-review.googlesource.com/16176Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
parent d42cc102
...@@ -13,18 +13,16 @@ import ( ...@@ -13,18 +13,16 @@ import (
// This implementation depends on OS-specific implementations of // This implementation depends on OS-specific implementations of
// //
// uintptr runtime·semacreate(void) // func semacreate(mp *m)
// Create a semaphore, which will be assigned to m->waitsema. // Create a semaphore for mp, if it does not already have one.
// The zero value is treated as absence of any semaphore,
// so be sure to return a non-zero value.
// //
// int32 runtime·semasleep(int64 ns) // func semasleep(ns int64) int32
// If ns < 0, acquire m->waitsema and return 0. // If ns < 0, acquire m's semaphore and return 0.
// If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds. // 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. // Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
// //
// int32 runtime·semawakeup(M *mp) // func semawakeup(mp *m)
// Wake up mp, which is or will soon be sleeping on mp->waitsema. // Wake up mp, which is or will soon be sleeping on its semaphore.
// //
const ( const (
locked uintptr = 1 locked uintptr = 1
...@@ -45,9 +43,7 @@ func lock(l *mutex) { ...@@ -45,9 +43,7 @@ func lock(l *mutex) {
if atomic.Casuintptr(&l.key, 0, locked) { if atomic.Casuintptr(&l.key, 0, locked) {
return return
} }
if gp.m.waitsema == 0 { semacreate(gp.m)
gp.m.waitsema = semacreate()
}
// On uniprocessor's, no point spinning. // On uniprocessor's, no point spinning.
// On multiprocessors, spin for ACTIVE_SPIN attempts. // On multiprocessors, spin for ACTIVE_SPIN attempts.
...@@ -157,9 +153,7 @@ func notesleep(n *note) { ...@@ -157,9 +153,7 @@ func notesleep(n *note) {
if gp != gp.m.g0 { if gp != gp.m.g0 {
throw("notesleep not on g0") throw("notesleep not on g0")
} }
if gp.m.waitsema == 0 { semacreate(gp.m)
gp.m.waitsema = semacreate()
}
if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) { if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
// Must be locked (got wakeup). // Must be locked (got wakeup).
if n.key != locked { if n.key != locked {
...@@ -248,9 +242,7 @@ func notetsleep(n *note, ns int64) bool { ...@@ -248,9 +242,7 @@ func notetsleep(n *note, ns int64) bool {
if gp != gp.m.g0 && gp.m.preemptoff != "" { if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0") throw("notetsleep not on g0")
} }
if gp.m.waitsema == 0 { semacreate(gp.m)
gp.m.waitsema = semacreate()
}
return notetsleep_internal(n, ns, nil, 0) return notetsleep_internal(n, ns, nil, 0)
} }
...@@ -261,9 +253,7 @@ func notetsleepg(n *note, ns int64) bool { ...@@ -261,9 +253,7 @@ func notetsleepg(n *note, ns int64) bool {
if gp == gp.m.g0 { if gp == gp.m.g0 {
throw("notetsleepg on g0") throw("notetsleepg on g0")
} }
if gp.m.waitsema == 0 { semacreate(gp.m)
gp.m.waitsema = semacreate()
}
entersyscallblock(0) entersyscallblock(0)
ok := notetsleep_internal(n, ns, nil, 0) ok := notetsleep_internal(n, ns, nil, 0)
exitsyscall(0) exitsyscall(0)
......
...@@ -17,16 +17,17 @@ func unimplemented(name string) { ...@@ -17,16 +17,17 @@ func unimplemented(name string) {
//go:nosplit //go:nosplit
func semawakeup(mp *m) { func semawakeup(mp *m) {
mach_semrelease(uint32(mp.waitsema)) mach_semrelease(mp.waitsema)
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
var x uintptr if mp.waitsema != 0 {
return
}
systemstack(func() { systemstack(func() {
x = uintptr(mach_semcreate()) mp.waitsema = mach_semcreate()
}) })
return x
} }
// BSD interface for threading. // BSD interface for threading.
...@@ -370,7 +371,7 @@ func semasleep1(ns int64) int32 { ...@@ -370,7 +371,7 @@ func semasleep1(ns int64) int32 {
if ns >= 0 { if ns >= 0 {
var nsecs int32 var nsecs int32
secs := timediv(ns, 1000000000, &nsecs) 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 { if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT {
return -1 return -1
} }
...@@ -381,7 +382,7 @@ func semasleep1(ns int64) int32 { ...@@ -381,7 +382,7 @@ func semasleep1(ns int64) int32 {
} }
for { for {
r := mach_semaphore_wait(uint32(_g_.m.waitsema)) r := mach_semaphore_wait(_g_.m.waitsema)
if r == 0 { if r == 0 {
break break
} }
......
...@@ -83,8 +83,10 @@ func newosproc(mp *m, stk unsafe.Pointer) { ...@@ -83,8 +83,10 @@ func newosproc(mp *m, stk unsafe.Pointer) {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
var cond uintptr if mp.waitsema != 0 {
return
}
systemstack(func() { systemstack(func() {
mu := nacl_mutex_create(0) mu := nacl_mutex_create(0)
if mu < 0 { if mu < 0 {
...@@ -93,14 +95,12 @@ func semacreate() uintptr { ...@@ -93,14 +95,12 @@ func semacreate() uintptr {
} }
c := nacl_cond_create(0) c := nacl_cond_create(0)
if c < 0 { if c < 0 {
print("nacl_cond_create: error ", -cond, "\n") print("nacl_cond_create: error ", -c, "\n")
throw("semacreate") throw("semacreate")
} }
cond = uintptr(c) mp.waitsema = c
_g_ := getg() mp.waitsemalock = mu
_g_.m.waitsemalock = uint32(mu)
}) })
return cond
} }
//go:nosplit //go:nosplit
...@@ -109,13 +109,13 @@ func semasleep(ns int64) int32 { ...@@ -109,13 +109,13 @@ func semasleep(ns int64) int32 {
systemstack(func() { systemstack(func() {
_g_ := getg() _g_ := getg()
if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 { if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
throw("semasleep") throw("semasleep")
} }
for _g_.m.waitsemacount == 0 { for _g_.m.waitsemacount == 0 {
if ns < 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") throw("semasleep")
} }
} else { } else {
...@@ -123,9 +123,9 @@ func semasleep(ns int64) int32 { ...@@ -123,9 +123,9 @@ func semasleep(ns int64) int32 {
end := ns + nanotime() end := ns + nanotime()
ts.tv_sec = end / 1e9 ts.tv_sec = end / 1e9
ts.tv_nsec = int32(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 { if r == -_ETIMEDOUT {
nacl_mutex_unlock(int32(_g_.m.waitsemalock)) nacl_mutex_unlock(_g_.m.waitsemalock)
ret = -1 ret = -1
return return
} }
...@@ -136,7 +136,7 @@ func semasleep(ns int64) int32 { ...@@ -136,7 +136,7 @@ func semasleep(ns int64) int32 {
} }
_g_.m.waitsemacount = 0 _g_.m.waitsemacount = 0
nacl_mutex_unlock(int32(_g_.m.waitsemalock)) nacl_mutex_unlock(_g_.m.waitsemalock)
ret = 0 ret = 0
}) })
return ret return ret
...@@ -145,15 +145,15 @@ func semasleep(ns int64) int32 { ...@@ -145,15 +145,15 @@ func semasleep(ns int64) int32 {
//go:nosplit //go:nosplit
func semawakeup(mp *m) { func semawakeup(mp *m) {
systemstack(func() { systemstack(func() {
if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 { if nacl_mutex_lock(mp.waitsemalock) < 0 {
throw("semawakeup") throw("semawakeup")
} }
if mp.waitsemacount != 0 { if mp.waitsemacount != 0 {
throw("semawakeup") throw("semawakeup")
} }
mp.waitsemacount = 1 mp.waitsemacount = 1
nacl_cond_signal(int32(mp.waitsema)) nacl_cond_signal(mp.waitsema)
nacl_mutex_unlock(int32(mp.waitsemalock)) nacl_mutex_unlock(mp.waitsemalock)
}) })
} }
......
...@@ -40,8 +40,7 @@ func getncpu() int32 { ...@@ -40,8 +40,7 @@ func getncpu() int32 {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
return 1
} }
//go:nosplit //go:nosplit
......
...@@ -47,8 +47,7 @@ func getncpu() int32 { ...@@ -47,8 +47,7 @@ func getncpu() int32 {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
return 1
} }
//go:nosplit //go:nosplit
......
...@@ -205,8 +205,7 @@ func newosproc(mp *m, stk unsafe.Pointer) { ...@@ -205,8 +205,7 @@ func newosproc(mp *m, stk unsafe.Pointer) {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
return 1
} }
//go:nosplit //go:nosplit
......
...@@ -365,8 +365,11 @@ func semawakeup(mp *m) { ...@@ -365,8 +365,11 @@ func semawakeup(mp *m) {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
return stdcall4(_CreateEventA, 0, 0, 0, 0) 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. // May run with m.p==nil, so write barriers are not allowed.
......
...@@ -314,7 +314,11 @@ func unblocksig(sig int32) { ...@@ -314,7 +314,11 @@ func unblocksig(sig int32) {
} }
//go:nosplit //go:nosplit
func semacreate() uintptr { func semacreate(mp *m) {
if mp.waitsema != 0 {
return
}
var sem *semt var sem *semt
_g_ := getg() _g_ := getg()
...@@ -331,7 +335,7 @@ func semacreate() uintptr { ...@@ -331,7 +335,7 @@ func semacreate() uintptr {
if sem_init(sem, 0, 0) != 0 { if sem_init(sem, 0, 0) != 0 {
throw("sem_init") throw("sem_init")
} }
return uintptr(unsafe.Pointer(sem)) mp.waitsema = uintptr(unsafe.Pointer(sem))
} }
//go:nosplit //go:nosplit
......
...@@ -6,7 +6,9 @@ package runtime ...@@ -6,7 +6,9 @@ package runtime
import "unsafe" 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_create(stk, arg unsafe.Pointer, fn uintptr) int32
func bsdthread_register() int32 func bsdthread_register() int32
......
...@@ -6,7 +6,11 @@ package runtime ...@@ -6,7 +6,11 @@ package runtime
import "unsafe" 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_stack(p uintptr, size int32) int32
func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32 func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
......
...@@ -6,7 +6,9 @@ package runtime ...@@ -6,7 +6,9 @@ package runtime
import "unsafe" import "unsafe"
type mOS struct{} type mOS struct {
waitsemacount uint32
}
//go:noescape //go:noescape
func setitimer(mode int32, new, old *itimerval) func setitimer(mode int32, new, old *itimerval)
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
package runtime package runtime
type mOS struct{} type mOS struct {
waitsemacount uint32
}
//go:noescape //go:noescape
func setitimer(mode int32, new, old *itimerval) func setitimer(mode int32, new, old *itimerval)
......
...@@ -7,8 +7,9 @@ package runtime ...@@ -7,8 +7,9 @@ package runtime
import "unsafe" import "unsafe"
type mOS struct { type mOS struct {
notesig *int8 waitsemacount uint32
errstr *byte notesig *int8
errstr *byte
} }
func closefd(fd int32) int32 func closefd(fd int32) int32
......
...@@ -16,7 +16,8 @@ type mscratch struct { ...@@ -16,7 +16,8 @@ type mscratch struct {
} }
type mOS 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 // these are here because they are too large to be on the stack
// of low-level NOSPLIT functions. // of low-level NOSPLIT functions.
//LibCall libcall; //LibCall libcall;
......
...@@ -6,7 +6,9 @@ package runtime ...@@ -6,7 +6,9 @@ package runtime
import "unsafe" import "unsafe"
type mOS struct{} type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
type stdFunction *byte type stdFunction *byte
......
...@@ -308,9 +308,6 @@ type m struct { ...@@ -308,9 +308,6 @@ type m struct {
fflag uint32 // floating point compare flags fflag uint32 // floating point compare flags
locked uint32 // tracking for lockosthread locked uint32 // tracking for lockosthread
nextwaitm uintptr // next m waiting for lock nextwaitm uintptr // next m waiting for lock
waitsema uintptr // semaphore for parking on locks
waitsemacount uint32
waitsemalock uint32
gcstats gcstats gcstats gcstats
needextram bool needextram bool
traceback uint8 traceback uint8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment