diff options
author | Bhasker Hariharan <bhaskerh@google.com> | 2021-10-26 11:27:57 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-10-26 11:30:21 -0700 |
commit | 2d384f761c42ef9efb7ffdbd1a4f1ca328e60eab (patch) | |
tree | de166e929bcc48ed011a3a09e6959d864ffef87b | |
parent | c8d835470037be9efcad13091fb6d173c68cc0ca (diff) |
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
-rw-r--r-- | pkg/eventfd/BUILD | 1 | ||||
-rw-r--r-- | pkg/eventfd/eventfd.go | 2 | ||||
-rw-r--r-- | pkg/eventfd/eventfd_unsafe.go | 36 |
3 files changed, 38 insertions, 1 deletions
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 +} |