aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-16 16:42:53 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-16 16:42:53 +0000
commitc3ab26e8bb0c5bf1c20358d036f987a20734c9ad (patch)
treed5ba10b1e7a7066a1d806d7a74159a141f9f53b8
parent3943b161342a68ec90a7b977cf6a8e451671e25d (diff)
downloadgcc-c3ab26e8bb0c5bf1c20358d036f987a20734c9ad.zip
gcc-c3ab26e8bb0c5bf1c20358d036f987a20734c9ad.tar.gz
gcc-c3ab26e8bb0c5bf1c20358d036f987a20734c9ad.tar.bz2
runtime: add some more preemption checks
In particular this lets BenchmarkPingPongHog in runtime/proc_test.go complete. Reviewed-on: https://go-review.googlesource.com/94735 From-SVN: r257743
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/go/runtime/chan.go10
-rw-r--r--libgo/go/runtime/hashmap.go25
-rw-r--r--libgo/go/runtime/malloc.go1
-rw-r--r--libgo/go/runtime/proc.go5
-rw-r--r--libgo/go/runtime/select.go7
6 files changed, 47 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index baf77e3..cb7dffd 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-5d5ea2fd05dbf369ccc53c93d4846623cdea0c47
+cef3934fbc63f5e121abb8f88d3799961ac95b59
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
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 @@ func chansend1(c *hchan, elem unsafe.Pointer) {
* 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 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
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 @@ func makemap(t *maptype, hint int, h *hmap) *hmap {
// 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 mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
}
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 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
// 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 @@ func mapaccess2_fat(t *maptype, h *hmap, key, zero unsafe.Pointer) (unsafe.Point
// 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 mapiterinit(t *maptype, h *hmap, it *hiter) {
}
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 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
}
}
+ // 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 @@ func preemptone(_p_ *p) bool {
// 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 @@ retc:
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: