summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBhasker Hariharan <bhaskerh@google.com>2021-10-26 11:27:57 -0700
committergVisor bot <gvisor-bot@google.com>2021-10-26 11:30:21 -0700
commit2d384f761c42ef9efb7ffdbd1a4f1ca328e60eab (patch)
treede166e929bcc48ed011a3a09e6959d864ffef87b
parentc8d835470037be9efcad13091fb6d173c68cc0ca (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/BUILD1
-rw-r--r--pkg/eventfd/eventfd.go2
-rw-r--r--pkg/eventfd/eventfd_unsafe.go36
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
+}