runtime: add some more preemption checks
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 16 Feb 2018 16:42:53 +0000 (16:42 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 16 Feb 2018 16:42:53 +0000 (16:42 +0000)
    In particular this lets BenchmarkPingPongHog in runtime/proc_test.go
    complete.

    Reviewed-on: https://go-review.googlesource.com/94735

From-SVN: r257743

gcc/go/gofrontend/MERGE
libgo/go/runtime/chan.go
libgo/go/runtime/hashmap.go
libgo/go/runtime/malloc.go
libgo/go/runtime/proc.go
libgo/go/runtime/select.go

index baf77e31e70cd3772ed1fd1e0ed9d49844e3fa89..cb7dffd7905c34d604856ace43f1139826536fec 100644 (file)
@@ -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.
index bf708aec5c439faab1230a334a802339c9151245..87f7879e6f5e368dbc61fce1d0ddd2926c5df74b 100644 (file)
@@ -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
index a1fe49e9305427805d350c8864cb2b6e9837a97e..aba9abd7aab7d1983710ab07e0b44b692f382e2c 100644 (file)
@@ -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()
index 88e4ba3657b8a2ed7d78ac101437239577ac178b..c27aa487df3f7eca24ae9118eb9075c6c731c803 100644 (file)
@@ -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()
        }
index edf41405c1c11103f9ab116e5d207c6f4a060eef..1d95109d7c0cbc388800e94d820f324510c3c895 100644 (file)
@@ -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
 }
index 096af52be353bd5f7bd68b65913a5ae72a38097c..1c5124b4704b82b7f453651bf1710a1c4784b7c0 100644 (file)
@@ -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: