-
Notifications
You must be signed in to change notification settings - Fork 107
Support alarm and SIGALRM #693
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
base: weiteng/ctrl_c
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -95,6 +95,61 @@ pub trait ThreadProvider: RawPointerProvider { | |
| /// [`EnterShim`]: crate::shim::EnterShim | ||
| /// [`EnterShim::interrupt`]: crate::shim::EnterShim::interrupt | ||
| fn interrupt_thread(&self, thread: &Self::ThreadHandle); | ||
|
|
||
| /// Runs `f` on the current thread after performing any platform-specific | ||
| /// thread registration needed for [`current_thread`](Self::current_thread) | ||
| /// and related functionality to work. | ||
| /// | ||
| /// This is intended for test threads that do not go through the normal | ||
| /// [`spawn_thread`](Self::spawn_thread) / guest entry path. The platform | ||
| /// sets up thread state before calling `f` and tears it down afterward. | ||
| /// | ||
| /// The default implementation simply calls `f()` with no additional setup. | ||
| /// Platforms that require explicit thread registration should override this. | ||
| #[cfg(debug_assertions)] | ||
| fn run_test_thread<R>(f: impl FnOnce() -> R) -> R { | ||
| f() | ||
| } | ||
| } | ||
|
|
||
| /// Timer support for proactive signal delivery. | ||
| /// | ||
| /// Platforms that support this should set [`SUPPORTS_TIMER`](Self::SUPPORTS_TIMER) | ||
| /// to `true`. | ||
| pub trait TimerProvider { | ||
| /// The platform-specific timer handle type. | ||
| type TimerHandle: TimerHandle; | ||
|
|
||
| /// Whether this platform supports [`TimerProvider`] for proactive timer delivery. | ||
| const SUPPORTS_TIMER: bool = false; | ||
|
|
||
| /// Create a new one-shot timer that delivers `signal` when it fires. | ||
| fn create_timer(&self, signal: crate::shim::Signal) -> Self::TimerHandle; | ||
| } | ||
|
|
||
| /// A handle to a platform timer created by [`TimerProvider::create_timer`]. | ||
| /// | ||
| /// Dropping the handle **must** cancel any pending timer and ensure that the | ||
| /// associated callback will not fire after the drop returns. | ||
|
Comment on lines
+132
to
+133
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "associated callback"? It is unclear what this refers to. Also who is in charge of cancelling? As I understand it, it is saying that the platform cancels pending timers, yes? If so, the writing style should just be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re "associated callback", I think (if I understand correctly) this is making a long-range assumption that connects to the signals provider stuff. That should be documented if that's the design you want to go for. Ideally however, we do not use a long-range assumption like that and just literally have a callback registration right here? |
||
| pub trait TimerHandle { | ||
| /// Arm (or re-arm) the timer to fire after `duration` elapses. | ||
| /// | ||
| /// If the timer is already armed, the previous deadline is replaced. | ||
| /// A zero duration cancels the timer without firing. | ||
| fn set_timer(&self, duration: core::time::Duration); | ||
| } | ||
|
|
||
| /// Provider for consuming platform-originating signals. | ||
| /// | ||
| /// Platforms can record signals (e.g., `SIGINT`) and the shim should call | ||
| /// [`SignalProvider::take_pending_signals`] to consume them. | ||
| pub trait SignalProvider { | ||
| /// Atomically take all pending asynchronous signals (e.g., SIGINT and SIGALRM) | ||
| /// for the current thread, passing each one to `f`. | ||
| /// | ||
| /// Platforms that support asynchronous signals should override this method. | ||
| #[allow(unused_variables, reason = "no-op by default")] | ||
| fn take_pending_signals(&self, f: impl FnMut(crate::shim::Signal)) {} | ||
| } | ||
|
|
||
| /// Punch through any functionality for a particular platform that is not explicitly part of the | ||
|
|
@@ -220,6 +275,25 @@ where | |
| /// A provider of raw mutexes | ||
| pub trait RawMutexProvider { | ||
| type RawMutex: RawMutex; | ||
|
|
||
| /// Called when a thread enters an interruptible wait. | ||
| /// | ||
| /// The passed `waker` should live at least until the thread leaves the interruptible | ||
| /// wait (i.e., [`on_interruptible_wait_end`](Self::on_interruptible_wait_end) is called). | ||
| /// The platform can use the `waker` to wake up the thread while it is in the interruptible wait. | ||
| /// | ||
| /// This is a no-op by default. | ||
| #[allow(unused_variables)] | ||
| fn on_interruptible_wait_start(&self, waker: &crate::event::wait::Waker<Self>) | ||
| where | ||
| Self: crate::sync::RawSyncPrimitivesProvider + Sized, | ||
| { | ||
| } | ||
|
|
||
| /// Called when a thread leaves an interruptible wait. | ||
| /// | ||
| /// This is a no-op by default. | ||
| fn on_interruptible_wait_end(&self) {} | ||
| } | ||
|
|
||
| /// A raw mutex/lock API; expected to roughly match (or even be implemented using) a Linux futex. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,18 @@ | |
|
|
||
| use super::{ | ||
| Punchthrough, PunchthroughError, PunchthroughProvider, PunchthroughToken, RawConstPointer, | ||
| RawMutPointer, | ||
| RawMutPointer, TimerHandle, | ||
| }; | ||
|
|
||
| /// A [`TimerHandle`] stub for platforms that have not yet implemented | ||
| /// [`super::TimerProvider`]. All methods panic with `todo!()`. | ||
| pub struct StubTimerHandle(()); | ||
|
Comment on lines
+14
to
+16
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mentioned elsewhere, define this as a |
||
|
|
||
| impl TimerHandle for StubTimerHandle { | ||
| fn set_timer(&self, _duration: core::time::Duration) { | ||
| todo!("TimerProvider not yet implemented for this platform") | ||
| } | ||
| } | ||
| use zerocopy::{FromBytes, IntoBytes}; | ||
|
|
||
| /// A trivial provider, useful when no punchthrough is necessary. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor:
I'm not sure
SUPPORTS_TIMERis the ideal move, a possible alternative is to doUnsupportedTimerHandleshould be defined aspub enum UnsupportedTimerHandle {}which is equivalent to Rust!, which means that it can never actually be created; that way you are guaranteeing it via the type system.