Skip to content

Commit 0cb5a90

Browse files
committed
feat(port_std): add lock_scheduler to suspend preemption
1 parent c8d7fa0 commit 0cb5a90

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/constance_port_std/src/lib.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,35 @@ Based on the internal user-mode scheduling (UMS) framework, we treat interrupt h
5757
The interrupt line [`INTERRUPT_LINE_DISPATCH`] is reserved for the dispatcher.
5858

5959
[`INTERRUPT_LINE_DISPATCH`]: crate::INTERRUPT_LINE_DISPATCH
60+
61+
# Preemption and Host Environment
62+
63+
The user-mode scheduling scheme may interact poorly with other components or the host operating system. Preemption is implemented by signals on POSIX platforms and can cause system calls to fail with an error code that `libstd` is not prepared to deal with. Also, sharing an external resource between threads is prone to a deadlock. Here's an example: Suppose an application uses an allocator whose internal structure is protected by a host mutex. Task A acquires a lock, but then gets preempted by task B, which also attempts to acquire a lock. The guest operating system is unaware of the existence of such resources and keeps scheduling task B (not knowing that completing task A would unblock task B), leading to a deadlock.
64+
65+
**This means that even using the default (system) global allocator inside a guest environment can cause a deadlock.**
66+
67+
There are several ways to tackle these problems:
68+
69+
- Lock the scheduler structure by calling [`lock_scheduler`].
70+
71+
**Con:** You need to be careful not to call any guest operating services while the lock is being held.
72+
73+
- Activate [CPU Lock] while accessing external resources.
74+
75+
**Con:** CPU Lock doesn't affect unmanaged interrupt handlers. Many guest operating services are unavailable while CPU Lock is being held.
76+
77+
- Activate [Priority Boost] while accessing external resources.
78+
79+
**Con:** Priority Boost doesn't affect and can't be used in interrupt handlers.
80+
81+
- Create a mutex using the guest operating system's feature and use it to ensure only one task can access a particular external resource at a time.
82+
83+
**Con:** Interrupt handlers can't perform a blocking operation. Interrupts can still preempt host system calls.
84+
85+
- Create an asynchronous RPC channel.
86+
87+
**Con:** Complicated and requires allocation of system-global resources such as an interrupt line for inbound signaling.
88+
89+
[`lock_scheduler`]: crate::lock_scheduler
90+
[CPU Lock]: constance::kernel::Kernel::acquire_cpu_lock
91+
[Priority Boost]: constance::kernel::Kernel::boost_priority

src/constance_port_std/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,15 @@ pub fn pend_interrupt_line<System: PortInstance>(
614614
Ok(())
615615
}
616616

617+
/// Temporarily lock the scheduler, disabling preemption.
618+
///
619+
/// *All* operating system and port functions will be unavailable until the lock
620+
/// is relinquished.
621+
pub fn lock_scheduler<System: PortInstance>() -> impl Sized {
622+
let state = System::port_state();
623+
state.thread_group.get().unwrap().lock()
624+
}
625+
617626
#[macro_export]
618627
macro_rules! use_port {
619628
(unsafe $vis:vis struct $sys:ident) => {

0 commit comments

Comments
 (0)