runtime: add some more preemption checks
In particular this lets BenchmarkPingPongHog in runtime/proc_test.go
complete.
Change-Id: I99dfec5b83abf158865cd4a709eeddb5b7842b6e
Reviewed-on: https://go-review.googlesource.com/94735
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/libgo/go/runtime/chan.go b/libgo/go/runtime/chan.go
index bf708ae..87f7879 100644
--- a/libgo/go/runtime/chan.go
+++ b/libgo/go/runtime/chan.go
@@ -148,6 +148,11 @@
* the operation; we'll see that it's now closed.
*/
func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if c == nil {
if !block {
return false
@@ -430,6 +435,11 @@
print("chanrecv: chan=", c, "\n")
}
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if c == nil {
if !block {
return
diff --git a/libgo/go/runtime/hashmap.go b/libgo/go/runtime/hashmap.go
index a1fe49e..aba9abd 100644
--- a/libgo/go/runtime/hashmap.go
+++ b/libgo/go/runtime/hashmap.go
@@ -356,6 +356,11 @@
// NOTE: The returned pointer may keep the whole map live, so don't
// hold onto it for very long.
func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if raceenabled && h != nil {
callerpc := getcallerpc()
pc := funcPC(mapaccess1)
@@ -409,6 +414,11 @@
}
func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if raceenabled && h != nil {
callerpc := getcallerpc()
pc := funcPC(mapaccess2)
@@ -463,6 +473,11 @@
// returns both key and value. Used by map iterator
func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe.Pointer) {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if h == nil || h.count == 0 {
return nil, nil
}
@@ -521,6 +536,11 @@
// Like mapaccess, but allocates a slot for the key if it is not present in the map.
func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
if h == nil {
panic(plainError("assignment to entry in nil map"))
}
@@ -772,6 +792,11 @@
}
func mapiternext(it *hiter) {
+ // Check preemption, since unlike gc we don't check on every call.
+ if getg().preempt {
+ checkPreempt()
+ }
+
h := it.h
if raceenabled {
callerpc := getcallerpc()
diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go
index 88e4ba3..c27aa48 100644
--- a/libgo/go/runtime/malloc.go
+++ b/libgo/go/runtime/malloc.go
@@ -826,6 +826,7 @@
}
}
+ // Check preemption, since unlike gc we don't check on every call.
if getg().preempt {
checkPreempt()
}
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index edf4140..1d95109 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -4084,8 +4084,9 @@
// setting a global variable and figuring out a way to efficiently
// check that global variable.
//
- // For now we check gp.preempt in schedule and mallocgc,
- // which is at least better than doing nothing at all.
+ // For now we check gp.preempt in schedule, mallocgc, selectgo,
+ // and a few other places, which is at least better than doing
+ // nothing at all.
return true
}
diff --git a/libgo/go/runtime/select.go b/libgo/go/runtime/select.go
index 096af52..1c5124b 100644
--- a/libgo/go/runtime/select.go
+++ b/libgo/go/runtime/select.go
@@ -584,6 +584,13 @@
if cas.releasetime > 0 {
blockevent(cas.releasetime-t0, 1)
}
+
+ // Check preemption, since unlike gc we don't check on every call.
+ // A test case for this one is BenchmarkPingPongHog in proc_test.go.
+ if dfl != nil && getg().preempt {
+ checkPreempt()
+ }
+
return casi
sclose: