Skip to content

Commit 09f4008

Browse files
author
Jethro Beekman
committed
SGX target: implemented vectored I/O
1 parent 7e624ce commit 09f4008

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

src/libstd/sys/sgx/abi/usercalls/mod.rs

+37-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::io::{Error as IoError, Result as IoResult};
1+
use crate::cmp;
2+
use crate::io::{Error as IoError, Result as IoResult, IoSlice, IoSliceMut};
23
use crate::time::Duration;
34

45
pub(crate) mod alloc;
@@ -8,13 +9,27 @@ pub(crate) mod raw;
89
use self::raw::*;
910

1011
/// Usercall `read`. See the ABI documentation for more information.
12+
///
13+
/// This will do a single `read` usercall and scatter the read data among
14+
/// `bufs`. To read to a single buffer, just pass a slice of length one.
1115
#[unstable(feature = "sgx_platform", issue = "56975")]
12-
pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
16+
pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
1317
unsafe {
14-
let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
15-
let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
16-
userbuf[..len].copy_to_enclave(&mut buf[..len]);
17-
Ok(len)
18+
let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
19+
let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
20+
let ret_len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
21+
let userbuf = &userbuf[..ret_len];
22+
let mut index = 0;
23+
for buf in bufs {
24+
let end = cmp::min(index + buf.len(), userbuf.len());
25+
if let Some(buflen) = end.checked_sub(index) {
26+
userbuf[index..end].copy_to_enclave(&mut buf[..buflen]);
27+
index += buf.len();
28+
} else {
29+
break
30+
}
31+
}
32+
Ok(userbuf.len())
1833
}
1934
}
2035

@@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
3045
}
3146

3247
/// Usercall `write`. See the ABI documentation for more information.
48+
///
49+
/// This will do a single `write` usercall and gather the written data from
50+
/// `bufs`. To write from a single buffer, just pass a slice of length one.
3351
#[unstable(feature = "sgx_platform", issue = "56975")]
34-
pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
52+
pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
3553
unsafe {
36-
let userbuf = alloc::User::new_from_enclave(buf);
54+
let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
55+
let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
56+
let mut index = 0;
57+
for buf in bufs {
58+
let end = cmp::min(index + buf.len(), userbuf.len());
59+
if let Some(buflen) = end.checked_sub(index) {
60+
userbuf[index..end].copy_from_enclave(&buf[..buflen]);
61+
index += buf.len();
62+
} else {
63+
break
64+
}
65+
}
3766
raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
3867
}
3968
}

src/libstd/sys/sgx/fd.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use fortanix_sgx_abi::Fd;
22

3-
use crate::io;
3+
use crate::io::{self, IoSlice, IoSliceMut};
44
use crate::mem;
55
use crate::sys::{AsInner, FromInner, IntoInner};
66
use super::abi::usercalls;
@@ -25,11 +25,19 @@ impl FileDesc {
2525
}
2626

2727
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
28-
usercalls::read(self.fd, buf)
28+
usercalls::read(self.fd, &mut [IoSliceMut::new(buf)])
29+
}
30+
31+
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
32+
usercalls::read(self.fd, bufs)
2933
}
3034

3135
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
32-
usercalls::write(self.fd, buf)
36+
usercalls::write(self.fd, &[IoSlice::new(buf)])
37+
}
38+
39+
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
40+
usercalls::write(self.fd, bufs)
3341
}
3442

3543
pub fn flush(&self) -> io::Result<()> {

src/libstd/sys/sgx/net.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ impl TcpStream {
137137
}
138138

139139
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
140-
io::default_read_vectored(|b| self.read(b), bufs)
140+
self.inner.inner.read_vectored(bufs)
141141
}
142142

143143
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
144144
self.inner.inner.write(buf)
145145
}
146146

147147
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
148-
io::default_write_vectored(|b| self.write(b), bufs)
148+
self.inner.inner.write_vectored(bufs)
149149
}
150150

151151
pub fn peer_addr(&self) -> io::Result<SocketAddr> {

0 commit comments

Comments
 (0)