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: