aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/netpoll_solaris.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-04-05 15:53:12 -0700
committerIan Lance Taylor <iant@golang.org>2019-10-21 16:37:45 +0000
commit50f4896b72d16b6538178c8ca851b20655075b7f (patch)
treeac9868bddb566d8895e541450bf7059f7f006098 /src/runtime/netpoll_solaris.go
parent33425ab8dbb03c355b2263b8250a1829e260d66f (diff)
downloadgo-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.go46
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
}