From 8dd1d5b75a95100e747b1a88e9e557d5d2c30b64 Mon Sep 17 00:00:00 2001
From: Jamie Liu <jamieliu@google.com>
Date: Tue, 12 May 2020 12:24:23 -0700
Subject: Don't call kernel.Task.Block() from
 netstack.SocketOperations.Write().

kernel.Task.Block() requires that the caller is running on the task goroutine.
netstack.SocketOperations.Write() uses kernel.TaskFromContext() to call
kernel.Task.Block() even if it's not running on the task goroutine. Stop doing
that.

PiperOrigin-RevId: 311178335
---
 pkg/amutex/BUILD     |  1 +
 pkg/amutex/amutex.go | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)

(limited to 'pkg/amutex')

diff --git a/pkg/amutex/BUILD b/pkg/amutex/BUILD
index 9612f072e..ffc918846 100644
--- a/pkg/amutex/BUILD
+++ b/pkg/amutex/BUILD
@@ -6,6 +6,7 @@ go_library(
     name = "amutex",
     srcs = ["amutex.go"],
     visibility = ["//:sandbox"],
+    deps = ["//pkg/syserror"],
 )
 
 go_test(
diff --git a/pkg/amutex/amutex.go b/pkg/amutex/amutex.go
index 1c4fd1784..a078a31db 100644
--- a/pkg/amutex/amutex.go
+++ b/pkg/amutex/amutex.go
@@ -18,6 +18,8 @@ package amutex
 
 import (
 	"sync/atomic"
+
+	"gvisor.dev/gvisor/pkg/syserror"
 )
 
 // Sleeper must be implemented by users of the abortable mutex to allow for
@@ -53,6 +55,21 @@ func (NoopSleeper) SleepFinish(success bool) {}
 // Interrupted implements Sleeper.Interrupted.
 func (NoopSleeper) Interrupted() bool { return false }
 
+// Block blocks until either receiving from ch succeeds (in which case it
+// returns nil) or sleeper is interrupted (in which case it returns
+// syserror.ErrInterrupted).
+func Block(sleeper Sleeper, ch <-chan struct{}) error {
+	cancel := sleeper.SleepStart()
+	select {
+	case <-ch:
+		sleeper.SleepFinish(true)
+		return nil
+	case <-cancel:
+		sleeper.SleepFinish(false)
+		return syserror.ErrInterrupted
+	}
+}
+
 // AbortableMutex is an abortable mutex. It allows Lock() to be aborted while it
 // waits to acquire the mutex.
 type AbortableMutex struct {
-- 
cgit v1.2.3