Skip to content

Commit d068c2c

Browse files
panjf2000gopherbot
authored andcommitted
runtime: use eventfd as the event wait/notify mechanism for epoll
Fixes #65443 Change-Id: I9ad4689b36e87ee930d35a38322a8797896483b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/560615 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Jorropo <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent c4d55ab commit d068c2c

13 files changed

+58
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package syscall
6+
7+
const (
8+
EFD_CLOEXEC = 0x80000
9+
)

src/runtime/internal/syscall/defs_linux_386.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 319
1111
SYS_EPOLL_CREATE1 = 329
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 328
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_amd64.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 281
1111
SYS_EPOLL_CREATE1 = 291
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 290
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_arm.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 346
1111
SYS_EPOLL_CREATE1 = 357
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 356
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_arm64.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 22
1111
SYS_FCNTL = 25
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 19
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_loong64.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 22
1111
SYS_FCNTL = 25
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 19
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_mips64x.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const (
1212
SYS_EPOLL_PWAIT = 5272
1313
SYS_EPOLL_CREATE1 = 5285
1414
SYS_EPOLL_PWAIT2 = 5441
15+
SYS_EVENTFD2 = 5284
1516

1617
EPOLLIN = 0x1
1718
EPOLLOUT = 0x4
@@ -23,6 +24,7 @@ const (
2324
EPOLL_CTL_ADD = 0x1
2425
EPOLL_CTL_DEL = 0x2
2526
EPOLL_CTL_MOD = 0x3
27+
EFD_NONBLOCK = 0x80
2628
)
2729

2830
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_mipsx.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const (
1212
SYS_EPOLL_PWAIT = 4313
1313
SYS_EPOLL_CREATE1 = 4326
1414
SYS_EPOLL_PWAIT2 = 4441
15+
SYS_EVENTFD2 = 4325
1516

1617
EPOLLIN = 0x1
1718
EPOLLOUT = 0x4
@@ -23,6 +24,7 @@ const (
2324
EPOLL_CTL_ADD = 0x1
2425
EPOLL_CTL_DEL = 0x2
2526
EPOLL_CTL_MOD = 0x3
27+
EFD_NONBLOCK = 0x80
2628
)
2729

2830
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_ppc64x.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const (
1212
SYS_EPOLL_PWAIT = 303
1313
SYS_EPOLL_CREATE1 = 315
1414
SYS_EPOLL_PWAIT2 = 441
15+
SYS_EVENTFD2 = 314
1516

1617
EPOLLIN = 0x1
1718
EPOLLOUT = 0x4
@@ -23,6 +24,7 @@ const (
2324
EPOLL_CTL_ADD = 0x1
2425
EPOLL_CTL_DEL = 0x2
2526
EPOLL_CTL_MOD = 0x3
27+
EFD_NONBLOCK = 0x800
2628
)
2729

2830
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_riscv64.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 22
1111
SYS_FCNTL = 25
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 19
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/defs_linux_s390x.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
SYS_EPOLL_PWAIT = 312
1111
SYS_EPOLL_CREATE1 = 327
1212
SYS_EPOLL_PWAIT2 = 441
13+
SYS_EVENTFD2 = 323
1314

1415
EPOLLIN = 0x1
1516
EPOLLOUT = 0x4
@@ -21,6 +22,7 @@ const (
2122
EPOLL_CTL_ADD = 0x1
2223
EPOLL_CTL_DEL = 0x2
2324
EPOLL_CTL_MOD = 0x3
25+
EFD_NONBLOCK = 0x800
2426
)
2527

2628
type EpollEvent struct {

src/runtime/internal/syscall/syscall_linux.go

+5
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ func EpollCtl(epfd, op, fd int32, event *EpollEvent) (errno uintptr) {
6060
_, _, e := Syscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
6161
return e
6262
}
63+
64+
func Eventfd(initval, flags int32) (fd int32, errno uintptr) {
65+
r1, _, e := Syscall6(SYS_EVENTFD2, uintptr(initval), uintptr(flags), 0, 0, 0, 0)
66+
return int32(r1), e
67+
}

src/runtime/netpoll_epoll.go

+24-24
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import (
1313
)
1414

1515
var (
16-
epfd int32 = -1 // epoll descriptor
17-
18-
netpollBreakRd, netpollBreakWr uintptr // for netpollBreak
19-
20-
netpollWakeSig atomic.Uint32 // used to avoid duplicate calls of netpollBreak
16+
epfd int32 = -1 // epoll descriptor
17+
netpollEventFd uintptr // eventfd for netpollBreak
18+
netpollWakeSig atomic.Uint32 // used to avoid duplicate calls of netpollBreak
2119
)
2220

2321
func netpollinit() {
@@ -27,26 +25,25 @@ func netpollinit() {
2725
println("runtime: epollcreate failed with", errno)
2826
throw("runtime: netpollinit failed")
2927
}
30-
r, w, errpipe := nonblockingPipe()
31-
if errpipe != 0 {
32-
println("runtime: pipe failed with", -errpipe)
33-
throw("runtime: pipe failed")
28+
efd, errno := syscall.Eventfd(0, syscall.EFD_CLOEXEC|syscall.EFD_NONBLOCK)
29+
if errno != 0 {
30+
println("runtime: eventfd failed with", -errno)
31+
throw("runtime: eventfd failed")
3432
}
3533
ev := syscall.EpollEvent{
3634
Events: syscall.EPOLLIN,
3735
}
38-
*(**uintptr)(unsafe.Pointer(&ev.Data)) = &netpollBreakRd
39-
errno = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, r, &ev)
36+
*(**uintptr)(unsafe.Pointer(&ev.Data)) = &netpollEventFd
37+
errno = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, efd, &ev)
4038
if errno != 0 {
4139
println("runtime: epollctl failed with", errno)
4240
throw("runtime: epollctl failed")
4341
}
44-
netpollBreakRd = uintptr(r)
45-
netpollBreakWr = uintptr(w)
42+
netpollEventFd = uintptr(efd)
4643
}
4744

4845
func netpollIsPollDescriptor(fd uintptr) bool {
49-
return fd == uintptr(epfd) || fd == netpollBreakRd || fd == netpollBreakWr
46+
return fd == uintptr(epfd) || fd == netpollEventFd
5047
}
5148

5249
func netpollopen(fd uintptr, pd *pollDesc) uintptr {
@@ -73,10 +70,11 @@ func netpollBreak() {
7370
return
7471
}
7572

73+
var one uint64 = 1
74+
oneSize := int32(unsafe.Sizeof(one))
7675
for {
77-
var b byte
78-
n := write(netpollBreakWr, unsafe.Pointer(&b), 1)
79-
if n == 1 {
76+
n := write(netpollEventFd, noescape(unsafe.Pointer(&one)), oneSize)
77+
if n == oneSize {
8078
break
8179
}
8280
if n == -_EINTR {
@@ -136,17 +134,19 @@ retry:
136134
continue
137135
}
138136

139-
if *(**uintptr)(unsafe.Pointer(&ev.Data)) == &netpollBreakRd {
137+
if *(**uintptr)(unsafe.Pointer(&ev.Data)) == &netpollEventFd {
140138
if ev.Events != syscall.EPOLLIN {
141-
println("runtime: netpoll: break fd ready for", ev.Events)
142-
throw("runtime: netpoll: break fd ready for something unexpected")
139+
println("runtime: netpoll: eventfd ready for", ev.Events)
140+
throw("runtime: netpoll: eventfd ready for something unexpected")
143141
}
144142
if delay != 0 {
145143
// netpollBreak could be picked up by a
146-
// nonblocking poll. Only read the byte
147-
// if blocking.
148-
var tmp [16]byte
149-
read(int32(netpollBreakRd), noescape(unsafe.Pointer(&tmp[0])), int32(len(tmp)))
144+
// nonblocking poll. Only read the 8-byte
145+
// integer if blocking.
146+
// Since EFD_SEMAPHORE was not specified,
147+
// the eventfd counter will be reset to 0.
148+
var one uint64
149+
read(int32(netpollEventFd), noescape(unsafe.Pointer(&one)), int32(unsafe.Sizeof(one)))
150150
netpollWakeSig.Store(0)
151151
}
152152
continue

0 commit comments

Comments
 (0)