Change Notify() to use unix.RawSyscall.

eventfd.Notify() uses unix.Write which will eventually
call unix.Syscall which will yield the current go processor
resulting in the Go scheduler parking the current goroutine
till the syscall returns.

But in most cases where Notify() is called there is no reason
to yield as the caller probably wants to continue doing something
right afterwards. Like in the case of the sharedmem endpoint
which may still have more packets to write.

PiperOrigin-RevId: 405693801
This commit is contained in:
Bhasker Hariharan 2021-10-26 11:27:57 -07:00 committed by gVisor bot
parent c8d8354700
commit 2d384f761c
3 changed files with 38 additions and 1 deletions

View File

@ -6,6 +6,7 @@ go_library(
name = "eventfd",
srcs = [
"eventfd.go",
"eventfd_unsafe.go",
],
visibility = ["//:sandbox"],
deps = [

View File

@ -74,7 +74,7 @@ func (ev Eventfd) Write(val uint64) error {
var buf [sizeofUint64]byte
hostarch.ByteOrder.PutUint64(buf[:], val)
for {
n, err := unix.Write(ev.fd, buf[:])
n, err := nonBlockingWrite(ev.fd, buf[:])
if err == unix.EINTR {
continue
}

View File

@ -0,0 +1,36 @@
// Copyright 2021 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package eventfd
import (
"unsafe"
"golang.org/x/sys/unix"
)
// nonBlockingWrite writes the given buffer to a file descriptor. It fails if
// partial data is written.
func nonBlockingWrite(fd int, buf []byte) (int, error) {
var ptr unsafe.Pointer
if len(buf) > 0 {
ptr = unsafe.Pointer(&buf[0])
}
nwritten, _, errno := unix.RawSyscall(unix.SYS_WRITE, uintptr(fd), uintptr(ptr), uintptr(len(buf)))
if errno != 0 {
return int(nwritten), errno
}
return int(nwritten), nil
}