diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-04-05 15:53:12 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2019-10-21 16:37:45 +0000 |
commit | 50f4896b72d16b6538178c8ca851b20655075b7f (patch) | |
tree | ac9868bddb566d8895e541450bf7059f7f006098 /src/runtime/netpoll_solaris.go | |
parent | 33425ab8dbb03c355b2263b8250a1829e260d66f (diff) | |
download | go-50f4896b72d16b6538178c8ca851b20655075b7f.tar.gz go-50f4896b72d16b6538178c8ca851b20655075b7f.zip |
runtime: add netpollBreak
The new netpollBreak function can be used to interrupt a blocking netpoll.
This function is not currently used; it will be used by later CLs.
Updates #27707
Change-Id: I5cb936609ba13c3c127ea1368a49194fc58c9f4d
Reviewed-on: https://go-review.googlesource.com/c/go/+/171824
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime/netpoll_solaris.go')
-rw-r--r-- | src/runtime/netpoll_solaris.go | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/src/runtime/netpoll_solaris.go b/src/runtime/netpoll_solaris.go index ad41ab5af2..fac4829ed1 100644 --- a/src/runtime/netpoll_solaris.go +++ b/src/runtime/netpoll_solaris.go @@ -71,17 +71,20 @@ import "unsafe" //go:cgo_import_dynamic libc_port_associate port_associate "libc.so" //go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" //go:cgo_import_dynamic libc_port_getn port_getn "libc.so" +//go:cgo_import_dynamic libc_port_alert port_alert "libc.so" //go:linkname libc_port_create libc_port_create //go:linkname libc_port_associate libc_port_associate //go:linkname libc_port_dissociate libc_port_dissociate //go:linkname libc_port_getn libc_port_getn +//go:linkname libc_port_alert libc_port_alert var ( libc_port_create, libc_port_associate, libc_port_dissociate, - libc_port_getn libcFunc + libc_port_getn, + libc_port_alert libcFunc ) func errno() int32 { @@ -108,6 +111,10 @@ func port_getn(port int32, evs *portevent, max uint32, nget *uint32, timeout *ti return int32(sysvicall5(&libc_port_getn, uintptr(port), uintptr(unsafe.Pointer(evs)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout)))) } +func port_alert(port int32, flags, events uint32, user uintptr) int32 { + return int32(sysvicall4(&libc_port_alert, uintptr(port), uintptr(flags), uintptr(events), user)) +} + var portfd int32 = -1 func netpollinit() { @@ -121,8 +128,8 @@ func netpollinit() { throw("runtime: netpollinit failed") } -func netpolldescriptor() uintptr { - return uintptr(portfd) +func netpollIsPollDescriptor(fd uintptr) bool { + return fd == uintptr(portfd) } func netpollopen(fd uintptr, pd *pollDesc) int32 { @@ -178,6 +185,21 @@ func netpollarm(pd *pollDesc, mode int) { unlock(&pd.lock) } +// netpollBreak interrupts a port_getn wait. +func netpollBreak() { + // Use port_alert to put portfd into alert mode. + // This will wake up all threads sleeping in port_getn on portfd, + // and cause their calls to port_getn to return immediately. + // Further, until portfd is taken out of alert mode, + // all calls to port_getn will return immediately. + if port_alert(portfd, _PORT_ALERT_UPDATE, _POLLHUP, uintptr(unsafe.Pointer(&portfd))) < 0 { + if e := errno(); e != _EBUSY { + println("runtime: port_alert failed with", e) + throw("runtime: netpoll: port_alert failed") + } + } +} + // netpoll checks for ready network connections. // Returns list of goroutines that become runnable. // delay < 0: blocks indefinitely @@ -224,6 +246,24 @@ retry: for i := 0; i < int(n); i++ { ev := &events[i] + if ev.portev_source == _PORT_SOURCE_ALERT { + if ev.portev_events != _POLLHUP || unsafe.Pointer(ev.portev_user) != unsafe.Pointer(&portfd) { + throw("runtime: netpoll: bad port_alert wakeup") + } + if delay != 0 { + // Now that a blocking call to netpoll + // has seen the alert, take portfd + // back out of alert mode. + // See the comment in netpollBreak. + if port_alert(portfd, 0, 0, 0) < 0 { + e := errno() + println("runtime: port_alert failed with", e) + throw("runtime: netpoll: port_alert failed") + } + } + continue + } + if ev.portev_events == 0 { continue } |