]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: disallow write barriers in handoffp and callees
authorAustin Clements <austin@google.com>
Thu, 26 Mar 2015 19:50:22 +0000 (15:50 -0400)
committerAustin Clements <austin@google.com>
Thu, 26 Mar 2015 20:38:59 +0000 (20:38 +0000)
handoffp by definition runs without a P, so it's not allowed to have
write barriers. It doesn't have any right now, but mark it
nowritebarrier to disallow any creeping in in the future. handoffp in
turns calls startm, newm, and newosproc, all of which are "below Go"
and make sense to run without a P, so disallow write barriers in these
as well.

For most functions, we've done this because they may race with
stoptheworld() and hence must not have write barriers. For these
functions, it's a little different: the world can't stop while we're
in handoffp, so this race isn't present. But we implement this
restriction with a somewhat broader rule that you can't have a write
barrier without a P. We like this rule because it's simple and means
that our write barriers can depend on there being a P, even though
this rule is actually a little broader than necessary. Hence, even
though there's no danger of the race in these functions, we want to
adhere to the broader rule.

Change-Id: Ie22319c30eea37d703eb52f5c7ca5da872030b88
Reviewed-on: https://go-review.googlesource.com/8130
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Minux Ma <minux@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
src/runtime/os1_darwin.go
src/runtime/os1_dragonfly.go
src/runtime/os1_freebsd.go
src/runtime/os1_linux.go
src/runtime/os1_nacl.go
src/runtime/os1_netbsd.go
src/runtime/os1_openbsd.go
src/runtime/os1_plan9.go
src/runtime/os1_windows.go
src/runtime/os3_solaris.go
src/runtime/proc1.go

index 6a60314494287de00c55c48a0ef32e58d4c9201f..f6eb557b81ae0738ae2e2374a01c6cfd4578b3c5 100644 (file)
@@ -71,6 +71,8 @@ func goenvs() {
        }
 }
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
        if false {
index c94b1411b089f2fe9a0e9705955fdde017634f62..33d87ebdd984dd2b625a72b66ef8f40fc5555910 100644 (file)
@@ -71,6 +71,8 @@ func futexwakeup(addr *uint32, cnt uint32) {
 
 func lwp_start(uintptr)
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        if false {
                print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
index ae9f78c27b304788bb935c58e8859ac221e6fce3..10c72d1d7ee831307f5888cb6daf3b6fb41512c4 100644 (file)
@@ -67,6 +67,8 @@ func futexwakeup(addr *uint32, cnt uint32) {
 
 func thr_start()
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        if false {
                print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
index 44da57ab0b6cf0ac8b52c3afabfd410ce226456f..190206dcb6499e99f5e0874289127f2f97c49a58 100644 (file)
@@ -113,6 +113,8 @@ const (
        _CLONE_NEWIPC         = 0x8000000
 )
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        /*
         * note: strace gets confused if we use CLONE_PTRACE here.
index b3759c140815b349f5b7f5afbb5a0050cbf3fffb..238de5b441da18ef696167f3eeee562102a81c82 100644 (file)
@@ -67,6 +67,7 @@ func usleep(us uint32) {
 
 func mstart_nacl()
 
+// May run without a P, so write barriers are not allowed.
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        mp.tls[0] = uintptr(unsafe.Pointer(mp.g0))
index f2e6ef682e28ca914a8cd33dae3618ffe75c7f15..9a401550baba0756eecd3b42bb949992ce15f336 100644 (file)
@@ -89,6 +89,8 @@ func semawakeup(mp *m) {
        }
 }
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        if false {
                print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
index 92a19fe31b4550fb0a1d57bbc54c929b1d04129d..1f5ac4aa31a1f670577cac52661286d7b278eddc 100644 (file)
@@ -98,6 +98,8 @@ func semawakeup(mp *m) {
        }
 }
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        if false {
                print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
index bba1f17e328dc7f92f981643f555468a6caa6721..30621ad56128c62e3aec2790653d1b484be2eca6 100644 (file)
@@ -183,6 +183,8 @@ func exit(e int) {
        exits(&status[0])
 }
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        if false {
                print("newosproc mp=", mp, " ostk=", &mp, "\n")
index 4ae1a8411b6512ef7402ae9dc63bbfe2ab86c7c0..609e4307113b9068b8e7bbf40928b2118d7b9cd8 100644 (file)
@@ -282,6 +282,8 @@ func semacreate() uintptr {
        return stdcall4(_CreateEventA, 0, 0, 0, 0)
 }
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
        const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
        thandle := stdcall6(_CreateThread, 0, 0x20000,
index 8c65567b8374c0939d5e370782975c511ec6c67b..ddec87e7e2a2a5e059ca8d6d41f024a8a8755df5 100644 (file)
@@ -131,6 +131,8 @@ func osinit() {
 
 func tstart_sysvicall()
 
+// May run without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func newosproc(mp *m, _ unsafe.Pointer) {
        var (
                attr pthreadattr
index 4459802b158226626fd3b484a8ea44af3d78c35d..690a97891930fa849c41e1bd1c00d27d82004f2c 100644 (file)
@@ -973,7 +973,7 @@ func unlockextra(mp *m) {
 
 // Create a new m.  It will start off with a call to fn, or else the scheduler.
 // fn needs to be static and not a heap allocated closure.
-// May run during STW, so write barriers are not allowed.
+// May run without a P, so write barriers are not allowed.
 //go:nowritebarrier
 func newm(fn func(), _p_ *p) {
        mp := allocm(_p_)
@@ -1035,7 +1035,7 @@ func mspinning() {
 
 // Schedules some M to run the p (creates an M if necessary).
 // If p==nil, tries to get an idle P, if no idle P's does nothing.
-// May run during STW, so write barriers are not allowed.
+// May run without a P, so write barriers are not allowed.
 //go:nowritebarrier
 func startm(_p_ *p, spinning bool) {
        lock(&sched.lock)
@@ -1072,6 +1072,8 @@ func startm(_p_ *p, spinning bool) {
 }
 
 // Hands off P from syscall or locked M.
+// Always runs without a P, so write barriers are not allowed.
+//go:nowritebarrier
 func handoffp(_p_ *p) {
        // if it has local work, start it straight away
        if _p_.runqhead != _p_.runqtail || sched.runqsize != 0 {