Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying number of worker threads used to run an enclave #625

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions intel-sgx/aesm-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
html_root_url = "https://edp.fortanix.com/docs/api/")]
#![allow(non_local_definitions)] // Required by failure
#![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;
Expand Down
5 changes: 4 additions & 1 deletion intel-sgx/enclave-runner/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct Command {
usercall_ext: Option<Box<dyn UsercallExtension>>,
forward_panics: bool,
cmd_args: Vec<Vec<u8>>,
num_worker_threads: usize,
}

impl MappingInfo for Command {
Expand All @@ -45,6 +46,7 @@ impl Command {
usercall_ext: Option<Box<dyn UsercallExtension>>,
forward_panics: bool,
cmd_args: Vec<Vec<u8>>,
num_worker_threads: usize,
) -> Command {
let main = tcss.remove(0);
Command {
Expand All @@ -55,6 +57,7 @@ impl Command {
usercall_ext,
forward_panics,
cmd_args,
num_worker_threads,
}
}

Expand All @@ -63,6 +66,6 @@ impl Command {
}

pub fn run(self) -> Result<(), Error> {
EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.cmd_args)
EnclaveState::main_entry(self.main, self.threads, self.usercall_ext, self.forward_panics, self.cmd_args, self.num_worker_threads)
}
}
27 changes: 21 additions & 6 deletions intel-sgx/enclave-runner/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub struct EnclaveBuilder<'a> {
hash_enclave: Option<Box<dyn FnOnce(&mut EnclaveSource<'_>) -> Result<EnclaveHash, anyhow::Error>>>,
forward_panics: bool,
cmd_args: Option<Vec<Vec<u8>>>,
num_worker_threads: Option<usize>,
}

#[derive(Debug, ThisError)]
Expand Down Expand Up @@ -146,6 +147,7 @@ impl<'a> EnclaveBuilder<'a> {
hash_enclave: None,
forward_panics: false,
cmd_args: None,
num_worker_threads: None,
};

let _ = ret.coresident_signature();
Expand Down Expand Up @@ -298,14 +300,22 @@ 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<S: AsRef<[u8]>>(&mut self, arg: S) -> &mut Self {
let arg = arg.as_ref().to_owned();
self.initialized_args_mut().push(arg);
self
}

/// Sets the number of wroker threads used to run the enclave.
s-arash marked this conversation as resolved.
Show resolved Hide resolved
///
/// **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<T: Load>(
mut self,
loader: &mut T,
Expand All @@ -332,21 +342,26 @@ impl<'a> EnclaveBuilder<'a> {
}

pub fn build<T: Load>(mut self, loader: &mut T) -> Result<Command, anyhow::Error> {
let num_cpus = num_cpus::get();
let num_worker_threads = self.num_worker_threads.unwrap_or(num_cpus);
anyhow::ensure!(num_worker_threads > 0, "`num_worker_threads` cannot be zero");
anyhow::ensure!(num_worker_threads <= num_cpus, "`num_worker_threads` cannot exceed number of logical cores (`num_cpus::get()`)");
s-arash marked this conversation as resolved.
Show resolved Hide resolved

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)| Command::internal_new(t, a, s, c, fp, args))
.map(|(t, a, s, fp)| Command::internal_new(t, a, s, c, fp, 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`].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With so many parameters that aren't shared between Command and Library enclaves, does it maybe make sense to have separate builders for Command and Library enclaves? That way, each type of builder could only have the parameters that make sense for the type of enclave it builds.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. But that would be a breaking change. I think it's better to release a sem-ver compatible version with this change, and leave this kind of refactoring to a future sem-ver breaking version.

///
/// [`arg`]: struct.EnclaveBuilder.html#method.arg
/// [`args`]: struct.EnclaveBuilder.html#method.args
/// [`num_worker_threads`]: Self::num_worker_threads()
pub fn build_library<T: Load>(mut self, loader: &mut T) -> Result<Library, anyhow::Error> {
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)| Library::internal_new(t, a, s, c, fp))
Expand Down
4 changes: 2 additions & 2 deletions intel-sgx/enclave-runner/src/usercalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,9 @@ impl EnclaveState {
usercall_ext: Option<Box<dyn UsercallExtension>>,
forward_panics: bool,
cmd_args: Vec<Vec<u8>>,
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);
Expand All @@ -1109,8 +1111,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,
Expand Down
2 changes: 2 additions & 0 deletions ipc-queue/src/fifo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
3 changes: 3 additions & 0 deletions ipc-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,13 @@ pub trait AsyncSynchronizer: Clone {
fn notify(&self, event: QueueEvent);
}

#[allow(dead_code)]
pub struct AsyncSender<T: 'static, S> {
inner: Fifo<T>,
synchronizer: S,
}

#[allow(dead_code)]
pub struct AsyncReceiver<T: 'static, S> {
inner: Fifo<T>,
synchronizer: S,
Expand All @@ -159,6 +161,7 @@ pub struct AsyncReceiver<T: 'static, S> {

/// `DescriptorGuard<T>` can produce a `FifoDescriptor<T>` that is guaranteed
/// to remain valid as long as the DescriptorGuard is not dropped.
#[allow(dead_code)]
pub struct DescriptorGuard<T> {
descriptor: FifoDescriptor<T>,
#[cfg(not(target_env = "sgx"))]
Expand Down
4 changes: 4 additions & 0 deletions ipc-queue/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: 'static> {
read_epoch: Arc<AtomicU64>,
fifo: Fifo<T>,
}

/// 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<T> PositionMonitor<T> {
#[allow(dead_code)]
pub (crate) fn new(read_epoch: Arc<AtomicU64>,fifo: Fifo<T>) -> PositionMonitor<T> {
PositionMonitor {
read_epoch,
Expand Down
Loading