From 2d384f761c42ef9efb7ffdbd1a4f1ca328e60eab Mon Sep 17 00:00:00 2001 From: Bhasker Hariharan Date: Tue, 26 Oct 2021 11:27:57 -0700 Subject: 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 --- pkg/eventfd/BUILD | 1 + pkg/eventfd/eventfd.go | 2 +- pkg/eventfd/eventfd_unsafe.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 pkg/eventfd/eventfd_unsafe.go diff --git a/pkg/eventfd/BUILD b/pkg/eventfd/BUILD index 02407cb99..f0bed8e49 100644 --- a/pkg/eventfd/BUILD +++ b/pkg/eventfd/BUILD @@ -6,6 +6,7 @@ go_library( name = "eventfd", srcs = [ "eventfd.go", + "eventfd_unsafe.go", ], visibility = ["//:sandbox"], deps = [ diff --git a/pkg/eventfd/eventfd.go b/pkg/eventfd/eventfd.go index acdac01b8..99ebad34d 100644 --- a/pkg/eventfd/eventfd.go +++ b/pkg/eventfd/eventfd.go @@ -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 } diff --git a/pkg/eventfd/eventfd_unsafe.go b/pkg/eventfd/eventfd_unsafe.go new file mode 100644 index 000000000..bb9698f95 --- /dev/null +++ b/pkg/eventfd/eventfd_unsafe.go @@ -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 +} -- cgit v1.2.3