Commit a7383fc4 authored by Elias Naur's avatar Elias Naur Committed by Russ Cox

runtime: use a proper type, sigset, for m.sigmask

Replace the cross platform but unsafe [4]uintptr type with a OS
specific type, sigset. Most OSes already define sigset, and this
change defines a suitable sigset for the OSes that don't (darwin,
openbsd). The OSes that don't use m.sigmask (windows, plan9, nacl)
now defines sigset as the empty type, struct{}.

The gain is strongly typed access to m.sigmask, saving a dynamic
size sanity check and unsafe.Pointer casting. Also, some storage is
saved for each M, since [4]uinptr was conservative for most OSes.

The cost is that OSes that don't need m.sigmask has to define sigset.

completes ./all.bash with GOOS linux, on amd64
completes ./make.bash with GOOSes openbsd, android, plan9, windows,
darwin, solaris, netbsd, freebsd, dragonfly, all amd64.

With GOOS=nacl ./make.bash failed with a seemingly unrelated error.

[Replay of CL 16942 by Elias Naur.]

Change-Id: I98f144d626033ae5318576115ed635415ac71b2c
Reviewed-on: https://go-review.googlesource.com/17033Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
parent 0ae57c3b
...@@ -8,7 +8,9 @@ import "unsafe" ...@@ -8,7 +8,9 @@ import "unsafe"
//extern SigTabTT runtime·sigtab[]; //extern SigTabTT runtime·sigtab[];
var sigset_all = ^uint32(0) type sigset uint32
var sigset_all = ^sigset(0)
func unimplemented(name string) { func unimplemented(name string) {
println(name, "not implemented") println(name, "not implemented")
...@@ -83,7 +85,7 @@ func newosproc(mp *m, stk unsafe.Pointer) { ...@@ -83,7 +85,7 @@ func newosproc(mp *m, stk unsafe.Pointer) {
print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
} }
var oset uint32 var oset sigset
sigprocmask(_SIG_SETMASK, &sigset_all, &oset) sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
errno := bsdthread_create(stk, unsafe.Pointer(mp), funcPC(mstart)) errno := bsdthread_create(stk, unsafe.Pointer(mp), funcPC(mstart))
sigprocmask(_SIG_SETMASK, &oset, nil) sigprocmask(_SIG_SETMASK, &oset, nil)
...@@ -109,7 +111,7 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg uintptr) { ...@@ -109,7 +111,7 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg uintptr) {
} }
stk := unsafe.Pointer(uintptr(stack) + stacksize) stk := unsafe.Pointer(uintptr(stack) + stacksize)
var oset uint32 var oset sigset
sigprocmask(_SIG_SETMASK, &sigset_all, &oset) sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
errno := bsdthread_create(stk, fn, fnarg) errno := bsdthread_create(stk, fn, fnarg)
sigprocmask(_SIG_SETMASK, &oset, nil) sigprocmask(_SIG_SETMASK, &oset, nil)
...@@ -132,17 +134,12 @@ func mpreinit(mp *m) { ...@@ -132,17 +134,12 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*uint32)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
sigprocmask(_SIG_SETMASK, nil, smask)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*uint32)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
sigprocmask(_SIG_SETMASK, smask, nil)
} }
//go:nosplit //go:nosplit
...@@ -158,7 +155,7 @@ func minit() { ...@@ -158,7 +155,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask &^= 1 << (uint32(i) - 1) nmask &^= 1 << (uint32(i) - 1)
...@@ -483,10 +480,11 @@ func signalstack(s *stack) { ...@@ -483,10 +480,11 @@ func signalstack(s *stack) {
} }
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
sigprocmask(_SIG_SETMASK, &m[0], nil) s := sigset(m[0])
sigprocmask(_SIG_SETMASK, &s, nil)
} }
func unblocksig(sig int32) { func unblocksig(sig int32) {
mask := uint32(1) << (uint32(sig) - 1) mask := sigset(1) << (uint32(sig) - 1)
sigprocmask(_SIG_UNBLOCK, &mask, nil) sigprocmask(_SIG_UNBLOCK, &mask, nil)
} }
...@@ -119,17 +119,12 @@ func mpreinit(mp *m) { ...@@ -119,17 +119,12 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
sigprocmask(_SIG_SETMASK, nil, smask)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
sigprocmask(_SIG_SETMASK, smask, nil)
} }
//go:nosplit //go:nosplit
...@@ -149,7 +144,7 @@ func minit() { ...@@ -149,7 +144,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
......
...@@ -122,17 +122,12 @@ func mpreinit(mp *m) { ...@@ -122,17 +122,12 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
sigprocmask(_SIG_SETMASK, nil, smask)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
sigprocmask(_SIG_SETMASK, smask, nil)
} }
//go:nosplit //go:nosplit
...@@ -155,7 +150,7 @@ func minit() { ...@@ -155,7 +150,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
......
...@@ -199,16 +199,13 @@ func mpreinit(mp *m) { ...@@ -199,16 +199,13 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) smask := &mp.sigmask
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask))) rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask)))
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) smask := &mp.sigmask
rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask))) rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
} }
...@@ -230,7 +227,7 @@ func minit() { ...@@ -230,7 +227,7 @@ func minit() {
_g_.m.procid = uint64(gettid()) _g_.m.procid = uint64(gettid())
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
sigdelset(&nmask, i) sigdelset(&nmask, i)
......
...@@ -6,6 +6,8 @@ package runtime ...@@ -6,6 +6,8 @@ package runtime
import "unsafe" import "unsafe"
type sigset struct{}
// Called to initialize a new m (including the bootstrap m). // Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory. // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) { func mpreinit(mp *m) {
......
...@@ -140,17 +140,12 @@ func mpreinit(mp *m) { ...@@ -140,17 +140,12 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
sigprocmask(_SIG_SETMASK, nil, smask)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
sigprocmask(_SIG_SETMASK, smask, nil)
} }
//go:nosplit //go:nosplit
...@@ -168,7 +163,7 @@ func minit() { ...@@ -168,7 +163,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
......
...@@ -22,9 +22,11 @@ const ( ...@@ -22,9 +22,11 @@ const (
_CLOCK_MONOTONIC = 3 _CLOCK_MONOTONIC = 3
) )
type sigset uint32
const ( const (
sigset_none = uint32(0) sigset_none = sigset(0)
sigset_all = ^uint32(0) sigset_all = ^sigset(0)
) )
// From OpenBSD's <sys/sysctl.h> // From OpenBSD's <sys/sysctl.h>
...@@ -150,17 +152,12 @@ func mpreinit(mp *m) { ...@@ -150,17 +152,12 @@ func mpreinit(mp *m) {
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*uint32)(unsafe.Pointer(&mp.sigmask)) mp.sigmask = sigprocmask(_SIG_BLOCK, 0)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
*smask = sigprocmask(_SIG_BLOCK, 0)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := *(*uint32)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, mp.sigmask)
sigprocmask(_SIG_SETMASK, smask)
} }
//go:nosplit //go:nosplit
...@@ -180,7 +177,7 @@ func minit() { ...@@ -180,7 +177,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask &^= 1 << (uint32(i) - 1) nmask &^= 1 << (uint32(i) - 1)
...@@ -213,7 +210,7 @@ func setsig(i int32, fn uintptr, restart bool) { ...@@ -213,7 +210,7 @@ func setsig(i int32, fn uintptr, restart bool) {
if restart { if restart {
sa.sa_flags |= _SA_RESTART sa.sa_flags |= _SA_RESTART
} }
sa.sa_mask = sigset_all sa.sa_mask = uint32(sigset_all)
if fn == funcPC(sighandler) { if fn == funcPC(sighandler) {
fn = funcPC(sigtramp) fn = funcPC(sigtramp)
} }
...@@ -248,10 +245,10 @@ func signalstack(s *stack) { ...@@ -248,10 +245,10 @@ func signalstack(s *stack) {
} }
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
sigprocmask(_SIG_SETMASK, m[0]) sigprocmask(_SIG_SETMASK, sigset(m[0]))
} }
func unblocksig(sig int32) { func unblocksig(sig int32) {
mask := uint32(1) << (uint32(sig) - 1) mask := sigset(1) << (uint32(sig) - 1)
sigprocmask(_SIG_UNBLOCK, mask) sigprocmask(_SIG_UNBLOCK, mask)
} }
...@@ -9,6 +9,8 @@ import ( ...@@ -9,6 +9,8 @@ import (
"unsafe" "unsafe"
) )
type sigset struct{}
// Called to initialize a new m (including the bootstrap m). // Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory. // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) { func mpreinit(mp *m) {
......
...@@ -97,6 +97,8 @@ var ( ...@@ -97,6 +97,8 @@ var (
_GetQueuedCompletionStatusEx stdFunction _GetQueuedCompletionStatusEx stdFunction
) )
type sigset struct{}
// Call a Windows function with stdcall conventions, // Call a Windows function with stdcall conventions,
// and switch to os stack during the call. // and switch to os stack during the call.
func asmstdcall(fn unsafe.Pointer) func asmstdcall(fn unsafe.Pointer)
......
...@@ -194,17 +194,12 @@ func miniterrno() ...@@ -194,17 +194,12 @@ func miniterrno()
//go:nosplit //go:nosplit
func msigsave(mp *m) { func msigsave(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
throw("insufficient storage for signal mask")
}
sigprocmask(_SIG_SETMASK, nil, smask)
} }
//go:nosplit //go:nosplit
func msigrestore(mp *m) { func msigrestore(mp *m) {
smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
sigprocmask(_SIG_SETMASK, smask, nil)
} }
//go:nosplit //go:nosplit
...@@ -221,7 +216,7 @@ func minit() { ...@@ -221,7 +216,7 @@ func minit() {
signalstack(&_g_.m.gsignal.stack) signalstack(&_g_.m.gsignal.stack)
// restore signal mask from m.sigmask and unblock essential signals // restore signal mask from m.sigmask and unblock essential signals
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) nmask := _g_.m.sigmask
for i := range sigtable { for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 { if sigtable[i].flags&_SigUnblock != 0 {
nmask.__sigbits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) nmask.__sigbits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
......
...@@ -24,7 +24,7 @@ func mach_thread_self() uint32 ...@@ -24,7 +24,7 @@ func mach_thread_self() uint32
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
//go:noescape //go:noescape
func sigprocmask(how uint32, new, old *uint32) func sigprocmask(how uint32, new, old *sigset)
//go:noescape //go:noescape
func sigaction(mode uint32, new, old *sigactiont) func sigaction(mode uint32, new, old *sigactiont)
......
...@@ -18,7 +18,7 @@ func sigaction(sig int32, new, old *sigactiont) ...@@ -18,7 +18,7 @@ func sigaction(sig int32, new, old *sigactiont)
func sigaltstack(new, old *stackt) func sigaltstack(new, old *stackt)
//go:noescape //go:noescape
func sigprocmask(mode int32, new uint32) uint32 func sigprocmask(mode int32, new sigset) sigset
//go:noescape //go:noescape
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
......
...@@ -284,7 +284,7 @@ type m struct { ...@@ -284,7 +284,7 @@ type m struct {
// Fields not known to debuggers. // Fields not known to debuggers.
procid uint64 // for debuggers, but offset not hard-coded procid uint64 // for debuggers, but offset not hard-coded
gsignal *g // signal-handling g gsignal *g // signal-handling g
sigmask [4]uintptr // storage for saved signal mask sigmask sigset // storage for saved signal mask
tls [6]uintptr // thread-local storage (for x86 extern register) tls [6]uintptr // thread-local storage (for x86 extern register)
mstartfn func() mstartfn func()
curg *g // current running goroutine curg *g // current running goroutine
......
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