diff --git a/Cargo.lock b/Cargo.lock index 988cabc..4f56f52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2705,6 +2705,7 @@ version = "0.2.0" dependencies = [ "anyhow", "argh", + "critical-section", "embassy-futures", "embassy-sync 0.5.0", "embedded-io-adapters", diff --git a/async/Cargo.toml b/async/Cargo.toml index cd3b20e..e0743e7 100644 --- a/async/Cargo.toml +++ b/async/Cargo.toml @@ -50,3 +50,6 @@ embedded-io-adapters = { version = "0.6", features = ["tokio-1"] } simplelog = "0.12" # for simplelog time = { version = "0.3", features = ["local-offset"] } + +sunset-embassy = { version = "0.2", path = "../embassy", features = ["multi-thread"] } +critical-section = { version = "1.1", features = ["std"] } diff --git a/async/examples/sunsetc.rs b/async/examples/sunsetc.rs index e7f8bf4..ca6939d 100644 --- a/async/examples/sunsetc.rs +++ b/async/examples/sunsetc.rs @@ -26,14 +26,7 @@ use time::UtcOffset; #[tokio::main] async fn real_main(tz: UtcOffset) -> Result<()> { let args = parse_args(tz)?; - - // TODO: currently we just run it all on a single thread. - // Running with tokio's normal multiple threads works fine - // if we change SunsetRawMutex to a CriticalSectionMutex - // (or something wrapping std::sync::Mutex). - // Need to figure how to make it configurable. - let local = tokio::task::LocalSet::new(); - let exit_code = local.run_until(run(args)).await?; + let exit_code = run(args).await?; std::process::exit(exit_code) } @@ -73,11 +66,16 @@ async fn run(args: Args) -> Result { want_pty = false } - let ssh_task = spawn_local(async move { + // Sunset will work fine on a non-threaded executor (such as Tokio LocalSet). + // sunset-embassy's "multi-thread" feature is not required in that case. + // sunsetc example here uses the normal threaded scheduler in order to test the + // "multi-thread" feature (and as a more "default" example). + let ssh_task = tokio::task::spawn(async move { let mut rxbuf = Zeroizing::new(vec![0; 3000]); let mut txbuf = Zeroizing::new(vec![0; 3000]); let ssh = SSHClient::new(&mut rxbuf, &mut txbuf)?; + // CmdlineClient implements the session logic for a commandline SSH client. let mut app = CmdlineClient::new( args.username.as_ref().unwrap(), &args.host, diff --git a/async/src/cmdline_client.rs b/async/src/cmdline_client.rs index 5214892..9c2b7ad 100644 --- a/async/src/cmdline_client.rs +++ b/async/src/cmdline_client.rs @@ -372,6 +372,7 @@ enum EscapeAction { Suspend, } +/// Handles ~. escape sequences in an interactive shell. #[derive(Debug)] enum Escaper { Idle, diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index 02d3534..d87cc13 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -19,6 +19,12 @@ sunset = { version = "0.2.0", path = "../", features = ["embedded-io"] } log = { version = "0.4" } [features] +# Use a critical-section mutex to lock state. This feature must be enabled +# to run on executors that require futures to be Send (such as default Tokio). +# The application should depend on critical-section "std" feature. +# When multi-thread is disabled locking overhead is avoided. +multi-thread = [] + # Remove any use of `unsafe`. This currently requires # nightly and -Zpolonius (not ready yet) try-polonius = [] diff --git a/embassy/src/embassy_sunset.rs b/embassy/src/embassy_sunset.rs index f63cc31..4572ab8 100644 --- a/embassy/src/embassy_sunset.rs +++ b/embassy/src/embassy_sunset.rs @@ -7,7 +7,8 @@ use core::sync::atomic::AtomicBool; use core::sync::atomic::Ordering::{Relaxed, SeqCst}; use embassy_sync::waitqueue::WakerRegistration; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; +#[allow(unused_imports)] +use embassy_sync::blocking_mutex::raw::{NoopRawMutex,CriticalSectionRawMutex}; use embassy_sync::mutex::{Mutex, MutexGuard}; use embassy_sync::signal::Signal; use embassy_futures::select::select; @@ -23,11 +24,10 @@ use sunset::{error, ChanData, ChanHandle, ChanNum, Error, Result, Runner}; use sunset::config::MAX_CHANNELS; use sunset::event::Event; -// For now we only support single-threaded executors. -// In future this could be behind a cfg to allow different -// RawMutex for std executors or other situations. +#[cfg(feature = "multi-thread")] +pub type SunsetRawMutex = CriticalSectionRawMutex; +#[cfg(not(feature = "multi-thread"))] pub type SunsetRawMutex = NoopRawMutex; -// pub type SunsetRawMutex = CriticalSectionRawMutex; pub type SunsetMutex = Mutex;