diff --git a/intel-sgx/aesm-client/src/lib.rs b/intel-sgx/aesm-client/src/lib.rs index 6b5164fd2..19445bd1d 100644 --- a/intel-sgx/aesm-client/src/lib.rs +++ b/intel-sgx/aesm-client/src/lib.rs @@ -17,6 +17,9 @@ * In order to avoid CI failures, allow the below lint. */ #![allow(renamed_and_removed_lints)] #![deny(warnings)] +// To fix this error, which appears in generated code: +// "lint `box_pointers` has been removed: it does not detect other kinds of allocations, and existed only for historical reasons." +#![allow(renamed_and_removed_lints)] extern crate byteorder; pub extern crate anyhow; diff --git a/intel-sgx/enclave-runner/src/command.rs b/intel-sgx/enclave-runner/src/command.rs index 00f9717c3..ffaefd205 100644 --- a/intel-sgx/enclave-runner/src/command.rs +++ b/intel-sgx/enclave-runner/src/command.rs @@ -24,6 +24,7 @@ pub struct Command { forward_panics: bool, force_time_usercalls: bool, cmd_args: Vec>, + num_worker_threads: usize, } impl MappingInfo for Command { @@ -47,6 +48,7 @@ impl Command { forward_panics: bool, force_time_usercalls: bool, cmd_args: Vec>, + num_worker_threads: usize, ) -> Command { let main = tcss.remove(0); Command { @@ -58,6 +60,7 @@ impl Command { forward_panics, force_time_usercalls, cmd_args, + num_worker_threads, } } @@ -66,6 +69,6 @@ impl Command { } pub fn run(self) -> Result<(), Error> { - EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.force_time_usercalls, self.cmd_args) + EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.force_time_usercalls, self.cmd_args, self.num_worker_threads) } } diff --git a/intel-sgx/enclave-runner/src/loader.rs b/intel-sgx/enclave-runner/src/loader.rs index 88aa0016a..6da6079f2 100644 --- a/intel-sgx/enclave-runner/src/loader.rs +++ b/intel-sgx/enclave-runner/src/loader.rs @@ -6,6 +6,7 @@ use std::fs::File; use std::io::{Error as IoError, ErrorKind, Read, Result as IoResult}; +use std::ops::RangeInclusive; use std::os::raw::c_void; use std::path::Path; use std::{arch, str}; @@ -70,6 +71,7 @@ pub struct EnclaveBuilder<'a> { forward_panics: bool, force_time_usercalls: bool, cmd_args: Option>>, + num_worker_threads: Option, } #[derive(Debug, ThisError)] @@ -148,6 +150,7 @@ impl<'a> EnclaveBuilder<'a> { forward_panics: false, force_time_usercalls: true, // By default, keep the old behavior of always doing a usercall on an insecure_time call cmd_args: None, + num_worker_threads: None, }; let _ = ret.coresident_signature(); @@ -310,7 +313,6 @@ impl<'a> EnclaveBuilder<'a> { /// Adding command arguments and then calling [`build_library`] will cause /// a panic. /// - /// [`Command`]: struct.Command.html /// [`build_library`]: struct.EnclaveBuilder.html#method.build_library pub fn arg>(&mut self, arg: S) -> &mut Self { let arg = arg.as_ref().to_owned(); @@ -318,6 +320,15 @@ impl<'a> EnclaveBuilder<'a> { self } + /// Sets the number of worker threads used to run the enclave. + /// + /// **NOTE:** This is only applicable to [`Command`] enclaves. + /// Setting this and then calling [`build_library`](Self::build_library) will cause a panic. + pub fn num_worker_threads(&mut self, num_worker_threads: usize) -> &mut Self { + self.num_worker_threads = Some(num_worker_threads); + self + } + fn load( mut self, loader: &mut T, @@ -346,21 +357,30 @@ impl<'a> EnclaveBuilder<'a> { } pub fn build(mut self, loader: &mut T) -> Result { + if let Some(num_worker_threads) = self.num_worker_threads { + const NUM_WORKER_THREADS_RANGE: RangeInclusive = 1..=65536; + anyhow::ensure!( + NUM_WORKER_THREADS_RANGE.contains(&num_worker_threads), + "`num_worker_threads` must be in range {NUM_WORKER_THREADS_RANGE:?}" + ); + } + let num_worker_threads = self.num_worker_threads.unwrap_or_else(num_cpus::get); + self.initialized_args_mut(); let args = self.cmd_args.take().unwrap_or_default(); let c = self.usercall_ext.take(); self.load(loader) - .map(|(t, a, s, fp, dti)| Command::internal_new(t, a, s, c, fp, dti, args)) + .map(|(t, a, s, fp, dti)| Command::internal_new(t, a, s, c, fp, dti, args, num_worker_threads)) } - /// Panics if you have previously called [`arg`] or [`args`]. + /// Panics if you have previously called [`arg`], [`args`], or [`num_worker_threads`]. /// /// [`arg`]: struct.EnclaveBuilder.html#method.arg /// [`args`]: struct.EnclaveBuilder.html#method.args + /// [`num_worker_threads`]: Self::num_worker_threads() pub fn build_library(mut self, loader: &mut T) -> Result { - if self.cmd_args.is_some() { - panic!("Command arguments do not apply to Library enclaves."); - } + assert!(self.cmd_args.is_none(), "Command arguments do not apply to Library enclaves."); + assert!(self.num_worker_threads.is_none(), "`num_worker_threads` cannot be specified for Library enclaves."); let c = self.usercall_ext.take(); self.load(loader) .map(|(t, a, s, fp, dti)| Library::internal_new(t, a, s, c, fp, dti)) diff --git a/intel-sgx/enclave-runner/src/usercalls/mod.rs b/intel-sgx/enclave-runner/src/usercalls/mod.rs index 7eced57e4..bb7e51a2f 100644 --- a/intel-sgx/enclave-runner/src/usercalls/mod.rs +++ b/intel-sgx/enclave-runner/src/usercalls/mod.rs @@ -1106,7 +1106,9 @@ impl EnclaveState { forward_panics: bool, force_time_usercalls: bool, cmd_args: Vec>, + num_of_worker_threads: usize, ) -> StdResult<(), anyhow::Error> { + assert!(num_of_worker_threads > 0, "worker_threads cannot be zero"); let mut event_queues = FnvHashMap::with_capacity_and_hasher(threads.len() + 1, Default::default()); let main = Self::event_queue_add_tcs(&mut event_queues, main); @@ -1129,8 +1131,6 @@ impl EnclaveState { entry: CoEntry::Initial(main.tcs, argv as _, argc as _, 0, 0, 0), }; - let num_of_worker_threads = num_cpus::get(); - let kind = EnclaveKind::Command(Command { panic_reason: Mutex::new(PanicReason { primary_panic_reason: None, diff --git a/ipc-queue/src/fifo.rs b/ipc-queue/src/fifo.rs index 847904aca..7541ef4bb 100644 --- a/ipc-queue/src/fifo.rs +++ b/ipc-queue/src/fifo.rs @@ -356,10 +356,12 @@ impl Offsets { } } + #[allow(unused)] pub(crate) fn read_high_bit(&self) -> bool { self.read & self.len == self.len } + #[allow(unused)] pub(crate) fn write_high_bit(&self) -> bool { self.write & self.len == self.len } diff --git a/ipc-queue/src/lib.rs b/ipc-queue/src/lib.rs index 279b78001..53fca1e98 100644 --- a/ipc-queue/src/lib.rs +++ b/ipc-queue/src/lib.rs @@ -146,11 +146,13 @@ pub trait AsyncSynchronizer: Clone { fn notify(&self, event: QueueEvent); } +#[allow(dead_code)] pub struct AsyncSender { inner: Fifo, synchronizer: S, } +#[allow(dead_code)] pub struct AsyncReceiver { inner: Fifo, synchronizer: S, @@ -159,6 +161,7 @@ pub struct AsyncReceiver { /// `DescriptorGuard` can produce a `FifoDescriptor` that is guaranteed /// to remain valid as long as the DescriptorGuard is not dropped. +#[allow(dead_code)] pub struct DescriptorGuard { descriptor: FifoDescriptor, #[cfg(not(target_env = "sgx"))] diff --git a/ipc-queue/src/position.rs b/ipc-queue/src/position.rs index a986ed1bf..9f28f8124 100644 --- a/ipc-queue/src/position.rs +++ b/ipc-queue/src/position.rs @@ -19,18 +19,22 @@ use std::sync::atomic::Ordering; /// arranged as a ring buffer, we can assign a position to each value written/ /// read to/from the queue. This is useful in case we want to know whether or /// not a particular value written to the queue has been read. +#[allow(dead_code)] pub struct PositionMonitor { read_epoch: Arc, fifo: Fifo, } /// A read position in a queue. +#[allow(dead_code)] pub struct ReadPosition(u64); /// A write position in a queue. +#[allow(dead_code)] pub struct WritePosition(u64); impl PositionMonitor { + #[allow(dead_code)] pub (crate) fn new(read_epoch: Arc,fifo: Fifo) -> PositionMonitor { PositionMonitor { read_epoch,