From: Maksym Sobolyev Date: Wed, 20 Nov 2024 19:27:40 +0000 (+0000) Subject: runtime: utilize EVFILT_USER more effectively X-Git-Tag: go1.24rc1~145 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=21b5f2637a37fe2fece7e6bf3d5f97a9520693ba;p=gostls13.git runtime: utilize EVFILT_USER more effectively Re-work kqueue_event wakeup logic to use one-shot events. In an event of waking up a wrong thread, simply re-post the event. This saves close to 1 system call per wakeup on average, since chances of non-blocking poller picking it up is pretty low. Change-Id: I202d0d57a31d91ac5354ea075215f647c65790d3 GitHub-Last-Rev: e707d4732683702bd2989f07230a2f34354c288b GitHub-Pull-Request: golang/go#70408 Reviewed-on: https://go-review.googlesource.com/c/go/+/628975 Auto-Submit: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go index ca7898205e..db4dddc2fe 100644 --- a/src/runtime/netpoll_kqueue.go +++ b/src/runtime/netpoll_kqueue.go @@ -129,10 +129,11 @@ retry: ev := &events[i] if isWakeup(ev) { - if delay != 0 { + isBlocking := delay != 0 + processWakeupEvent(kq, isBlocking) + if isBlocking { // netpollBreak could be picked up by a nonblocking poll. - // Only call drainWakeupEvent and reset the netpollWakeSig if blocking. - drainWakeupEvent(kq) + // Only reset the netpollWakeSig if blocking. netpollWakeSig.Store(0) } continue diff --git a/src/runtime/netpoll_kqueue_event.go b/src/runtime/netpoll_kqueue_event.go index d5f783e607..852a00a5d8 100644 --- a/src/runtime/netpoll_kqueue_event.go +++ b/src/runtime/netpoll_kqueue_event.go @@ -16,7 +16,7 @@ func addWakeupEvent(kq int32) { ev := keventt{ ident: kqIdent, filter: _EVFILT_USER, - flags: _EV_ADD, + flags: _EV_ADD | _EV_CLEAR, } for { n := kevent(kq, &ev, 1, nil, 0, nil) @@ -38,7 +38,6 @@ func wakeNetpoll(kq int32) { ev := keventt{ ident: kqIdent, filter: _EVFILT_USER, - flags: _EV_ENABLE, fflags: _NOTE_TRIGGER, } for { @@ -66,13 +65,11 @@ func isWakeup(ev *keventt) bool { return false } -func drainWakeupEvent(kq int32) { - ev := keventt{ - ident: kqIdent, - filter: _EVFILT_USER, - flags: _EV_DISABLE, +func processWakeupEvent(kq int32, isBlocking bool) { + if !isBlocking { + // Got a wrong thread, relay + wakeNetpoll(kq) } - kevent(kq, &ev, 1, nil, 0, nil) } func netpollIsPollDescriptor(fd uintptr) bool { diff --git a/src/runtime/netpoll_kqueue_pipe.go b/src/runtime/netpoll_kqueue_pipe.go index 98f73e84d2..cf1e2afa83 100644 --- a/src/runtime/netpoll_kqueue_pipe.go +++ b/src/runtime/netpoll_kqueue_pipe.go @@ -63,7 +63,11 @@ func isWakeup(ev *keventt) bool { return false } -func drainWakeupEvent(_ int32) { +func processWakeupEvent(_ int32, isBlocking bool) { + // Only drain if blocking. + if !isBlocking { + return + } var buf [16]byte read(int32(netpollBreakRd), noescape(unsafe.Pointer(&buf[0])), int32(len(buf))) }