summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src
diff options
context:
space:
mode:
authoravallee <avallee@chromium.org>2015-09-10 12:38:27 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-10 19:39:01 +0000
commit0266f40e73c10c35d47f7f7784a6e0599065593a (patch)
tree2d53bc8bc44accbcf3ef11abdf30702d7202ab70 /native_client_sdk/src
parent546b6d6881183ef83cc85048285ec29c839489bf (diff)
downloadchromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.zip
chromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.tar.gz
chromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.tar.bz2
NACL_IO: Split handle locks.
Under linux it is possile for a single fd to allow Thread A to block on reading from a fd while Thread B writes to the same fd. Read-like operations now use an input_lock_. Write-like operations under an output_lock_. Handle and attributes remain on the handle_lock_. Added the inverse of AUTO_LOCK; AUTO_UNLOCK which unlocks until end of scope and then re-locks. See https://android.googlesource.com/platform/system/core/+/master/adb/transport.cpp for an example use, specifically, the read and write threads use the same t->fd. BUG=516764 Review URL: https://codereview.chromium.org/1321883003 Cr-Commit-Position: refs/heads/master@{#348214}
Diffstat (limited to 'native_client_sdk/src')
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_handle.cc28
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_handle.h3
-rw-r--r--native_client_sdk/src/libraries/nacl_io/node.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/node.h1
4 files changed, 30 insertions, 6 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
index 4f88bbf..c3fb86f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
@@ -65,6 +65,9 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
off_t node_size;
AUTO_LOCK(handle_lock_);
+ if (!node_->IsSeekable())
+ return ESPIPE;
+
Error error = node_->GetSize(&node_size);
if (error)
return error;
@@ -101,9 +104,14 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
}
Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
- AUTO_LOCK(handle_lock_);
+ sdk_util::AutoLock read_lock(handle_lock_);
if (OpenMode() == O_WRONLY)
return EACCES;
+ if (!node_->IsSeekable()){
+ read_lock.Unlock();
+ AUTO_LOCK(input_lock_);
+ return node_->Read(handle_attr_, buf, nbytes, cnt);
+ }
Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
if (0 == error)
handle_attr_.offs += *cnt;
@@ -111,9 +119,14 @@ Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
}
Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
- AUTO_LOCK(handle_lock_);
+ sdk_util::AutoLock write_lock(handle_lock_);
if (OpenMode() == O_RDONLY)
return EACCES;
+ if (!node_->IsSeekable()){
+ write_lock.Unlock();
+ AUTO_LOCK(output_lock_);
+ return node_->Write(handle_attr_, buf, nbytes, cnt);
+ }
Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
if (0 == error)
handle_attr_.offs += *cnt;
@@ -139,6 +152,9 @@ Error KernelHandle::Fcntl(int request, int* result, ...) {
Error KernelHandle::VFcntl(int request, int* result, va_list args) {
switch (request) {
case F_GETFL: {
+ // Should not block, but could if blocked on Connect or Accept. This is
+ // acceptable.
+ AUTO_LOCK(handle_lock_);
*result = handle_attr_.flags;
return 0;
}
@@ -190,7 +206,7 @@ Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
if (OpenMode() == O_WRONLY)
return EACCES;
- AUTO_LOCK(handle_lock_);
+ AUTO_LOCK(input_lock_);
return sock->Recv(handle_attr_, buf, len, flags, out_len);
}
@@ -206,7 +222,7 @@ Error KernelHandle::RecvFrom(void* buf,
if (OpenMode() == O_WRONLY)
return EACCES;
- AUTO_LOCK(handle_lock_);
+ AUTO_LOCK(input_lock_);
return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
out_len);
}
@@ -218,7 +234,7 @@ Error KernelHandle::Send(const void* buf, size_t len, int flags, int* out_len) {
if (OpenMode() == O_RDONLY)
return EACCES;
- AUTO_LOCK(handle_lock_);
+ AUTO_LOCK(output_lock_);
return sock->Send(handle_attr_, buf, len, flags, out_len);
}
@@ -234,7 +250,7 @@ Error KernelHandle::SendTo(const void* buf,
if (OpenMode() == O_RDONLY)
return EACCES;
- AUTO_LOCK(handle_lock_);
+ AUTO_LOCK(output_lock_);
return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
out_len);
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
index e586c5d..54f455f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
@@ -84,6 +84,9 @@ class KernelHandle : public sdk_util::RefObject {
ScopedFilesystem filesystem_;
ScopedNode node_;
+ sdk_util::SimpleLock input_lock_;
+ sdk_util::SimpleLock output_lock_;
+ // Protects the handle and attributes.
sdk_util::SimpleLock handle_lock_;
HandleAttr handle_attr_;
diff --git a/native_client_sdk/src/libraries/nacl_io/node.cc b/native_client_sdk/src/libraries/nacl_io/node.cc
index 0c307a5..6ca1a20 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/node.cc
@@ -226,6 +226,10 @@ bool Node::IsaSock() {
return GetType() == S_IFSOCK;
}
+bool Node::IsSeekable() {
+ return !(IsaSock() || GetType() == S_IFIFO);
+}
+
Error Node::Isatty() {
return ENOTTY;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/node.h b/native_client_sdk/src/libraries/nacl_io/node.h
index f1ebdc3c..917aee4 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.h
+++ b/native_client_sdk/src/libraries/nacl_io/node.h
@@ -106,6 +106,7 @@ class Node : public sdk_util::RefObject {
virtual bool IsaDir();
virtual bool IsaFile();
virtual bool IsaSock();
+ virtual bool IsSeekable();
// Number of children for this node (directory)
virtual int ChildCount();