Commit 3a1ce108 authored by Cherry Zhang's avatar Cherry Zhang

runtime: access _cgo_yield indirectly

The darwin linker for ARM does not allow PC-relative relocation
of external symbol in text section. Work around it by accessing
it indirectly: putting its address in a global variable (which is
not external), and accessing through that variable.

Fixes #19684.

Change-Id: I41361bbb281b5dbdda0d100ae49d32c69ed85a81
Reviewed-on: https://go-review.googlesource.com/38596
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Reviewed-by: 's avatarElias Naur <elias.naur@gmail.com>
parent 48de5a85
...@@ -50,3 +50,5 @@ func cgoUse(interface{}) { throw("cgoUse should not be called") } ...@@ -50,3 +50,5 @@ func cgoUse(interface{}) { throw("cgoUse should not be called") }
// so it emits the test and keeps the call, giving the desired // so it emits the test and keeps the call, giving the desired
// escape analysis result. The test is cheaper than the call. // escape analysis result. The test is cheaper than the call.
var cgoAlwaysFalse bool var cgoAlwaysFalse bool
var cgo_yield = &_cgo_yield
...@@ -141,15 +141,15 @@ func notesleep(n *note) { ...@@ -141,15 +141,15 @@ func notesleep(n *note) {
throw("notesleep not on g0") throw("notesleep not on g0")
} }
ns := int64(-1) ns := int64(-1)
if _cgo_yield != nil { if *cgo_yield != nil {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors. // Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
ns = 10e6 ns = 10e6
} }
for atomic.Load(key32(&n.key)) == 0 { for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns) futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
gp.m.blocked = false gp.m.blocked = false
} }
...@@ -164,15 +164,15 @@ func notetsleep_internal(n *note, ns int64) bool { ...@@ -164,15 +164,15 @@ func notetsleep_internal(n *note, ns int64) bool {
gp := getg() gp := getg()
if ns < 0 { if ns < 0 {
if _cgo_yield != nil { if *cgo_yield != nil {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors. // Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
ns = 10e6 ns = 10e6
} }
for atomic.Load(key32(&n.key)) == 0 { for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns) futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
gp.m.blocked = false gp.m.blocked = false
} }
...@@ -185,13 +185,13 @@ func notetsleep_internal(n *note, ns int64) bool { ...@@ -185,13 +185,13 @@ func notetsleep_internal(n *note, ns int64) bool {
deadline := nanotime() + ns deadline := nanotime() + ns
for { for {
if _cgo_yield != nil && ns > 10e6 { if *cgo_yield != nil && ns > 10e6 {
ns = 10e6 ns = 10e6
} }
gp.m.blocked = true gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns) futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
gp.m.blocked = false gp.m.blocked = false
if atomic.Load(key32(&n.key)) != 0 { if atomic.Load(key32(&n.key)) != 0 {
......
...@@ -163,14 +163,14 @@ func notesleep(n *note) { ...@@ -163,14 +163,14 @@ func notesleep(n *note) {
} }
// Queued. Sleep. // Queued. Sleep.
gp.m.blocked = true gp.m.blocked = true
if _cgo_yield == nil { if *cgo_yield == nil {
semasleep(-1) semasleep(-1)
} else { } else {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors. // Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
const ns = 10e6 const ns = 10e6
for atomic.Loaduintptr(&n.key) == 0 { for atomic.Loaduintptr(&n.key) == 0 {
semasleep(ns) semasleep(ns)
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
} }
gp.m.blocked = false gp.m.blocked = false
...@@ -195,13 +195,13 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool { ...@@ -195,13 +195,13 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
if ns < 0 { if ns < 0 {
// Queued. Sleep. // Queued. Sleep.
gp.m.blocked = true gp.m.blocked = true
if _cgo_yield == nil { if *cgo_yield == nil {
semasleep(-1) semasleep(-1)
} else { } else {
// Sleep in arbitrary-but-moderate intervals to poll libc interceptors. // Sleep in arbitrary-but-moderate intervals to poll libc interceptors.
const ns = 10e6 const ns = 10e6
for semasleep(ns) < 0 { for semasleep(ns) < 0 {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
} }
gp.m.blocked = false gp.m.blocked = false
...@@ -212,7 +212,7 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool { ...@@ -212,7 +212,7 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
for { for {
// Registered. Sleep. // Registered. Sleep.
gp.m.blocked = true gp.m.blocked = true
if _cgo_yield != nil && ns > 10e6 { if *cgo_yield != nil && ns > 10e6 {
ns = 10e6 ns = 10e6
} }
if semasleep(ns) >= 0 { if semasleep(ns) >= 0 {
...@@ -221,8 +221,8 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool { ...@@ -221,8 +221,8 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
// Done. // Done.
return true return true
} }
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
gp.m.blocked = false gp.m.blocked = false
// Interrupted or timed out. Still registered. Semaphore not acquired. // Interrupted or timed out. Still registered. Semaphore not acquired.
......
...@@ -1903,8 +1903,8 @@ top: ...@@ -1903,8 +1903,8 @@ top:
ready(gp, 0, true) ready(gp, 0, true)
} }
} }
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
// local runq // local runq
...@@ -3760,8 +3760,8 @@ func sysmon() { ...@@ -3760,8 +3760,8 @@ func sysmon() {
unlock(&sched.lock) unlock(&sched.lock)
} }
// trigger libc interceptors if needed // trigger libc interceptors if needed
if _cgo_yield != nil { if *cgo_yield != nil {
asmcgocall(_cgo_yield, nil) asmcgocall(*cgo_yield, nil)
} }
// poll network if not polled for more than 10ms // poll network if not polled for more than 10ms
lastpoll := int64(atomic.Load64(&sched.lastpoll)) lastpoll := int64(atomic.Load64(&sched.lastpoll))
......
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