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") }
// so it emits the test and keeps the call, giving the desired
// escape analysis result. The test is cheaper than the call.
var cgoAlwaysFalse bool
var cgo_yield = &_cgo_yield
......@@ -141,15 +141,15 @@ func notesleep(n *note) {
throw("notesleep not on g0")
}
ns := int64(-1)
if _cgo_yield != nil {
if *cgo_yield != nil {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
ns = 10e6
}
for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
gp.m.blocked = false
}
......@@ -164,15 +164,15 @@ func notetsleep_internal(n *note, ns int64) bool {
gp := getg()
if ns < 0 {
if _cgo_yield != nil {
if *cgo_yield != nil {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
ns = 10e6
}
for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
gp.m.blocked = false
}
......@@ -185,13 +185,13 @@ func notetsleep_internal(n *note, ns int64) bool {
deadline := nanotime() + ns
for {
if _cgo_yield != nil && ns > 10e6 {
if *cgo_yield != nil && ns > 10e6 {
ns = 10e6
}
gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns)
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
gp.m.blocked = false
if atomic.Load(key32(&n.key)) != 0 {
......
......@@ -163,14 +163,14 @@ func notesleep(n *note) {
}
// Queued. Sleep.
gp.m.blocked = true
if _cgo_yield == nil {
if *cgo_yield == nil {
semasleep(-1)
} else {
// Sleep for an arbitrary-but-moderate interval to poll libc interceptors.
const ns = 10e6
for atomic.Loaduintptr(&n.key) == 0 {
semasleep(ns)
asmcgocall(_cgo_yield, nil)
asmcgocall(*cgo_yield, nil)
}
}
gp.m.blocked = false
......@@ -195,13 +195,13 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
if ns < 0 {
// Queued. Sleep.
gp.m.blocked = true
if _cgo_yield == nil {
if *cgo_yield == nil {
semasleep(-1)
} else {
// Sleep in arbitrary-but-moderate intervals to poll libc interceptors.
const ns = 10e6
for semasleep(ns) < 0 {
asmcgocall(_cgo_yield, nil)
asmcgocall(*cgo_yield, nil)
}
}
gp.m.blocked = false
......@@ -212,7 +212,7 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
for {
// Registered. Sleep.
gp.m.blocked = true
if _cgo_yield != nil && ns > 10e6 {
if *cgo_yield != nil && ns > 10e6 {
ns = 10e6
}
if semasleep(ns) >= 0 {
......@@ -221,8 +221,8 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
// Done.
return true
}
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
gp.m.blocked = false
// Interrupted or timed out. Still registered. Semaphore not acquired.
......
......@@ -1903,8 +1903,8 @@ top:
ready(gp, 0, true)
}
}
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
// local runq
......@@ -3760,8 +3760,8 @@ func sysmon() {
unlock(&sched.lock)
}
// trigger libc interceptors if needed
if _cgo_yield != nil {
asmcgocall(_cgo_yield, nil)
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
// poll network if not polled for more than 10ms
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