diff options
| author | Jethro Beekman <jethro@fortanix.com> | 2019-04-10 19:47:10 -0700 |
|---|---|---|
| committer | Jethro Beekman <jethro@fortanix.com> | 2019-04-29 16:48:22 -0700 |
| commit | 09f4008da5ecee74fe06d8fd78ac39064e300512 (patch) | |
| tree | 48659169d808b9e5b7f8d95829466c790f46de68 | |
| parent | 7e624ce2c2f5196a94178ce7dd62173526ff6839 (diff) | |
| download | rust-09f4008da5ecee74fe06d8fd78ac39064e300512.tar.gz rust-09f4008da5ecee74fe06d8fd78ac39064e300512.zip | |
SGX target: implemented vectored I/O
| -rw-r--r-- | src/libstd/sys/sgx/abi/usercalls/mod.rs | 45 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/fd.rs | 14 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/net.rs | 4 |
3 files changed, 50 insertions, 13 deletions
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index 0abfc26bced..fca62e028de 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -1,4 +1,5 @@ -use crate::io::{Error as IoError, Result as IoResult}; +use crate::cmp; +use crate::io::{Error as IoError, Result as IoResult, IoSlice, IoSliceMut}; use crate::time::Duration; pub(crate) mod alloc; @@ -8,13 +9,27 @@ pub(crate) mod raw; use self::raw::*; /// Usercall `read`. See the ABI documentation for more information. +/// +/// This will do a single `read` usercall and scatter the read data among +/// `bufs`. To read to a single buffer, just pass a slice of length one. #[unstable(feature = "sgx_platform", issue = "56975")] -pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> { +pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> { unsafe { - let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len()); - let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?; - userbuf[..len].copy_to_enclave(&mut buf[..len]); - Ok(len) + let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len())); + let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len); + let ret_len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?; + let userbuf = &userbuf[..ret_len]; + let mut index = 0; + for buf in bufs { + let end = cmp::min(index + buf.len(), userbuf.len()); + if let Some(buflen) = end.checked_sub(index) { + userbuf[index..end].copy_to_enclave(&mut buf[..buflen]); + index += buf.len(); + } else { + break + } + } + Ok(userbuf.len()) } } @@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> { } /// Usercall `write`. See the ABI documentation for more information. +/// +/// This will do a single `write` usercall and gather the written data from +/// `bufs`. To write from a single buffer, just pass a slice of length one. #[unstable(feature = "sgx_platform", issue = "56975")] -pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> { +pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> { unsafe { - let userbuf = alloc::User::new_from_enclave(buf); + let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len())); + let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len); + let mut index = 0; + for buf in bufs { + let end = cmp::min(index + buf.len(), userbuf.len()); + if let Some(buflen) = end.checked_sub(index) { + userbuf[index..end].copy_from_enclave(&buf[..buflen]); + index += buf.len(); + } else { + break + } + } raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result() } } diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs index a9924f55f12..a1c4af81966 100644 --- a/src/libstd/sys/sgx/fd.rs +++ b/src/libstd/sys/sgx/fd.rs @@ -1,6 +1,6 @@ use fortanix_sgx_abi::Fd; -use crate::io; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem; use crate::sys::{AsInner, FromInner, IntoInner}; use super::abi::usercalls; @@ -25,11 +25,19 @@ impl FileDesc { } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - usercalls::read(self.fd, buf) + usercalls::read(self.fd, &mut [IoSliceMut::new(buf)]) + } + + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + usercalls::read(self.fd, bufs) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - usercalls::write(self.fd, buf) + usercalls::write(self.fd, &[IoSlice::new(buf)]) + } + + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + usercalls::write(self.fd, bufs) } pub fn flush(&self) -> io::Result<()> { diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index 76b0b81186a..f9eca9f4cb3 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -137,7 +137,7 @@ impl TcpStream { } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - io::default_read_vectored(|b| self.read(b), bufs) + self.inner.inner.read_vectored(bufs) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { @@ -145,7 +145,7 @@ impl TcpStream { } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - io::default_write_vectored(|b| self.write(b), bufs) + self.inner.inner.write_vectored(bufs) } pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
