]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use gList in netpoll
authorAustin Clements <austin@google.com>
Fri, 10 Aug 2018 04:09:00 +0000 (00:09 -0400)
committerAustin Clements <austin@google.com>
Mon, 20 Aug 2018 18:19:25 +0000 (18:19 +0000)
netpoll is perhaps one of the most confusing uses of G lists currently
since it passes around many lists as bare *g values right now.
Switching to gList makes it much clearer what's an individual g and
what's a list.

Change-Id: I8d8993c4967c5bae049c7a094aad3a657928ba6c
Reviewed-on: https://go-review.googlesource.com/129397
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
src/runtime/netpoll.go
src/runtime/netpoll_epoll.go
src/runtime/netpoll_fake.go
src/runtime/netpoll_kqueue.go
src/runtime/netpoll_solaris.go
src/runtime/netpoll_stub.go
src/runtime/netpoll_windows.go
src/runtime/proc.go

index c8fb95d3aaf5db07fa440ba835ee49e194fed6a8..f9c422650a16414c34bef90d6f0cbbc269fb23e7 100644 (file)
@@ -289,24 +289,22 @@ func poll_runtime_pollUnblock(pd *pollDesc) {
        }
 }
 
-// make pd ready, newly runnable goroutines (if any) are returned in rg/wg
+// make pd ready, newly runnable goroutines (if any) are added to toRun.
 // May run during STW, so write barriers are not allowed.
 //go:nowritebarrier
-func netpollready(gpp *guintptr, pd *pollDesc, mode int32) {
-       var rg, wg guintptr
+func netpollready(toRun *gList, pd *pollDesc, mode int32) {
+       var rg, wg *g
        if mode == 'r' || mode == 'r'+'w' {
-               rg.set(netpollunblock(pd, 'r', true))
+               rg = netpollunblock(pd, 'r', true)
        }
        if mode == 'w' || mode == 'r'+'w' {
-               wg.set(netpollunblock(pd, 'w', true))
+               wg = netpollunblock(pd, 'w', true)
        }
-       if rg != 0 {
-               rg.ptr().schedlink = *gpp
-               *gpp = rg
+       if rg != nil {
+               toRun.push(rg)
        }
-       if wg != 0 {
-               wg.ptr().schedlink = *gpp
-               *gpp = wg
+       if wg != nil {
+               toRun.push(wg)
        }
 }
 
index 1908220ebbd9b297c140cccb342ef467e9a4d881..f764d6ff7c886021e51288cef844a5ba718266e4 100644 (file)
@@ -58,9 +58,9 @@ func netpollarm(pd *pollDesc, mode int) {
 
 // polls for ready network connections
 // returns list of goroutines that become runnable
-func netpoll(block bool) *g {
+func netpoll(block bool) gList {
        if epfd == -1 {
-               return nil
+               return gList{}
        }
        waitms := int32(-1)
        if !block {
@@ -76,7 +76,7 @@ retry:
                }
                goto retry
        }
-       var gp guintptr
+       var toRun gList
        for i := int32(0); i < n; i++ {
                ev := &events[i]
                if ev.events == 0 {
@@ -92,11 +92,11 @@ retry:
                if mode != 0 {
                        pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
 
-                       netpollready(&gp, pd, mode)
+                       netpollready(&toRun, pd, mode)
                }
        }
-       if block && gp == 0 {
+       if block && toRun.empty() {
                goto retry
        }
-       return gp.ptr()
+       return toRun
 }
index aab18dc8468cd5e4345f3e5be5d3e5a781617672..5b1a63a8787d023d5a94f86a98eb7186d23300a6 100644 (file)
@@ -27,6 +27,6 @@ func netpollclose(fd uintptr) int32 {
 func netpollarm(pd *pollDesc, mode int) {
 }
 
-func netpoll(block bool) *g {
-       return nil
+func netpoll(block bool) gList {
+       return gList{}
 }
index 0f73bf385e48de6bf0fff12ce143a76f20061460..fdaa1cd80debd23dad16865646b2fbd4fbe58731 100644 (file)
@@ -59,9 +59,9 @@ func netpollarm(pd *pollDesc, mode int) {
 
 // Polls for ready network connections.
 // Returns list of goroutines that become runnable.
-func netpoll(block bool) *g {
+func netpoll(block bool) gList {
        if kq == -1 {
-               return nil
+               return gList{}
        }
        var tp *timespec
        var ts timespec
@@ -78,7 +78,7 @@ retry:
                }
                goto retry
        }
-       var gp guintptr
+       var toRun gList
        for i := 0; i < int(n); i++ {
                ev := &events[i]
                var mode int32
@@ -102,11 +102,11 @@ retry:
                        mode += 'w'
                }
                if mode != 0 {
-                       netpollready(&gp, (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
+                       netpollready(&toRun, (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
                }
        }
-       if block && gp == 0 {
+       if block && toRun.empty() {
                goto retry
        }
-       return gp.ptr()
+       return toRun
 }
index 853e5f63e3bedcfbcd51db93864c3bc086a360ec..6bd484afaaec8dca228f3476769652b636f3e5c2 100644 (file)
@@ -180,9 +180,9 @@ func netpollarm(pd *pollDesc, mode int) {
 
 // polls for ready network connections
 // returns list of goroutines that become runnable
-func netpoll(block bool) *g {
+func netpoll(block bool) gList {
        if portfd == -1 {
-               return nil
+               return gList{}
        }
 
        var wait *timespec
@@ -202,7 +202,7 @@ retry:
                goto retry
        }
 
-       var gp guintptr
+       var toRun gList
        for i := 0; i < int(n); i++ {
                ev := &events[i]
 
@@ -233,12 +233,12 @@ retry:
                }
 
                if mode != 0 {
-                       netpollready(&gp, pd, mode)
+                       netpollready(&toRun, pd, mode)
                }
        }
 
-       if block && gp == 0 {
+       if block && toRun.empty() {
                goto retry
        }
-       return gp.ptr()
+       return toRun
 }
index a4d6b4608ac63916fd7286dc86cf47c1d20dd466..f585333579dabf79476ff0294a1e806bccdf550b 100644 (file)
@@ -10,10 +10,10 @@ var netpollWaiters uint32
 
 // Polls for ready network connections.
 // Returns list of goroutines that become runnable.
-func netpoll(block bool) (gp *g) {
+func netpoll(block bool) gList {
        // Implementation for platforms that do not support
        // integrated network poller.
-       return
+       return gList{}
 }
 
 func netpollinited() bool {
index 134071f5e3ca178728d8ec9314c98f1509872552..07ef15ce2f3898654e56c666eb2c200dd65dbaab 100644 (file)
@@ -63,17 +63,17 @@ func netpollarm(pd *pollDesc, mode int) {
 
 // Polls for completed network IO.
 // Returns list of goroutines that become runnable.
-func netpoll(block bool) *g {
+func netpoll(block bool) gList {
        var entries [64]overlappedEntry
        var wait, qty, key, flags, n, i uint32
        var errno int32
        var op *net_op
-       var gp guintptr
+       var toRun gList
 
        mp := getg().m
 
        if iocphandle == _INVALID_HANDLE_VALUE {
-               return nil
+               return gList{}
        }
        wait = 0
        if block {
@@ -92,7 +92,7 @@ retry:
                        mp.blocked = false
                        errno = int32(getlasterror())
                        if !block && errno == _WAIT_TIMEOUT {
-                               return nil
+                               return gList{}
                        }
                        println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
                        throw("runtime: netpoll failed")
@@ -105,7 +105,7 @@ retry:
                        if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
                                errno = int32(getlasterror())
                        }
-                       handlecompletion(&gp, op, errno, qty)
+                       handlecompletion(&toRun, op, errno, qty)
                }
        } else {
                op = nil
@@ -118,7 +118,7 @@ retry:
                        mp.blocked = false
                        errno = int32(getlasterror())
                        if !block && errno == _WAIT_TIMEOUT {
-                               return nil
+                               return gList{}
                        }
                        if op == nil {
                                println("runtime: GetQueuedCompletionStatus failed (errno=", errno, ")")
@@ -127,15 +127,15 @@ retry:
                        // dequeued failed IO packet, so report that
                }
                mp.blocked = false
-               handlecompletion(&gp, op, errno, qty)
+               handlecompletion(&toRun, op, errno, qty)
        }
-       if block && gp == 0 {
+       if block && toRun.empty() {
                goto retry
        }
-       return gp.ptr()
+       return toRun
 }
 
-func handlecompletion(gpp *guintptr, op *net_op, errno int32, qty uint32) {
+func handlecompletion(toRun *gList, op *net_op, errno int32, qty uint32) {
        if op == nil {
                println("runtime: GetQueuedCompletionStatus returned op == nil")
                throw("runtime: netpoll failed")
@@ -147,5 +147,5 @@ func handlecompletion(gpp *guintptr, op *net_op, errno int32, qty uint32) {
        }
        op.errno = errno
        op.qty = qty
-       netpollready(gpp, op.pd, mode)
+       netpollready(toRun, op.pd, mode)
 }
index fbb1ce17506986392adbf30ead1f700de835571d..2a780e49ee021f8f221963dafb4c50dc89126422 100644 (file)
@@ -1148,8 +1148,8 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
 
        _g_.m.locks++ // disable preemption because it can be holding p in a local var
        if netpollinited() {
-               gp := netpoll(false) // non-blocking
-               injectglist(gp)
+               list := netpoll(false) // non-blocking
+               injectglist(list.head.ptr())
        }
        add := needaddgcproc()
        lock(&sched.lock)
@@ -2312,9 +2312,9 @@ top:
        // not set lastpoll yet), this thread will do blocking netpoll below
        // anyway.
        if netpollinited() && atomic.Load(&netpollWaiters) > 0 && atomic.Load64(&sched.lastpoll) != 0 {
-               if gp := netpoll(false); gp != nil { // non-blocking
-                       // netpoll returns list of goroutines linked by schedlink.
-                       injectglist(gp.schedlink.ptr())
+               if list := netpoll(false); !list.empty() { // non-blocking
+                       gp := list.pop()
+                       injectglist(list.head.ptr())
                        casgstatus(gp, _Gwaiting, _Grunnable)
                        if trace.enabled {
                                traceGoUnpark(gp, 0)
@@ -2466,22 +2466,23 @@ stop:
                if _g_.m.spinning {
                        throw("findrunnable: netpoll with spinning")
                }
-               gp := netpoll(true) // block until new work is available
+               list := netpoll(true) // block until new work is available
                atomic.Store64(&sched.lastpoll, uint64(nanotime()))
-               if gp != nil {
+               if !list.empty() {
                        lock(&sched.lock)
                        _p_ = pidleget()
                        unlock(&sched.lock)
                        if _p_ != nil {
                                acquirep(_p_)
-                               injectglist(gp.schedlink.ptr())
+                               gp := list.pop()
+                               injectglist(list.head.ptr())
                                casgstatus(gp, _Gwaiting, _Grunnable)
                                if trace.enabled {
                                        traceGoUnpark(gp, 0)
                                }
                                return gp, false
                        }
-                       injectglist(gp)
+                       injectglist(list.head.ptr())
                }
        }
        stopm()
@@ -2501,8 +2502,8 @@ func pollWork() bool {
                return true
        }
        if netpollinited() && atomic.Load(&netpollWaiters) > 0 && sched.lastpoll != 0 {
-               if gp := netpoll(false); gp != nil {
-                       injectglist(gp)
+               if list := netpoll(false); !list.empty() {
+                       injectglist(list.head.ptr())
                        return true
                }
        }
@@ -4387,8 +4388,8 @@ func sysmon() {
                now := nanotime()
                if netpollinited() && lastpoll != 0 && lastpoll+10*1000*1000 < now {
                        atomic.Cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
-                       gp := netpoll(false) // non-blocking - returns list of goroutines
-                       if gp != nil {
+                       list := netpoll(false) // non-blocking - returns list of goroutines
+                       if !list.empty() {
                                // Need to decrement number of idle locked M's
                                // (pretending that one more is running) before injectglist.
                                // Otherwise it can lead to the following situation:
@@ -4397,7 +4398,7 @@ func sysmon() {
                                // observes that there is no work to do and no other running M's
                                // and reports deadlock.
                                incidlelocked(-1)
-                               injectglist(gp)
+                               injectglist(list.head.ptr())
                                incidlelocked(1)
                        }
                }