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 <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
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
ev := keventt{
ident: kqIdent,
filter: _EVFILT_USER,
- flags: _EV_ADD,
+ flags: _EV_ADD | _EV_CLEAR,
}
for {
n := kevent(kq, &ev, 1, nil, 0, nil)
ev := keventt{
ident: kqIdent,
filter: _EVFILT_USER,
- flags: _EV_ENABLE,
fflags: _NOTE_TRIGGER,
}
for {
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 {
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)))
}