Skip to content

Commit 2617b05

Browse files
committed
feat(port_std): do the boot phase in a UMS worker thread
This change has the following benefits: - Unmanaged interrupts can be taken during the boot phase like real hardware. - Graceful shutdown can be implemented without resorting to panicking.
1 parent aa58bdf commit 2617b05

File tree

3 files changed

+32
-23
lines changed

3 files changed

+32
-23
lines changed

src/constance_port_std/src/lib.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,36 @@ impl State {
174174
}
175175
}
176176

177-
pub fn init<System: Kernel>(&self) {
177+
/// Initialize the user-mode scheduling system and boot the kernel.
178+
pub fn port_boot<System: Kernel>(&self) -> ! {
178179
// Create a UMS thread group.
179180
let (thread_group, join_handle) = ums::ThreadGroup::new(sched::SchedState::new::<System>());
180181

181182
self.thread_group.set(thread_group).ok().unwrap();
182183
*self.join_handle.lock() = Some(join_handle);
184+
185+
// Create the initial UMS worker thread, where the boot phase of the
186+
// kernel runs
187+
let mut lock = self.thread_group.get().unwrap().lock();
188+
let thread_id = lock.spawn(|_| {
189+
// Safety: We are a port, so it's okay to call this
190+
unsafe {
191+
<System as PortToKernel>::boot();
192+
}
193+
});
194+
log::trace!("startup thread = {:?}", thread_id);
195+
lock.scheduler().task_thread = Some(thread_id);
196+
lock.scheduler().recycle_thread(thread_id);
197+
lock.preempt();
198+
drop(lock);
199+
200+
// Wait until the thread group shuts down
201+
let join_handle = self.join_handle.lock().take().unwrap();
202+
if let Err(e) = join_handle.join() {
203+
std::panic::resume_unwind(e);
204+
}
205+
206+
panic!("the system has been shut down")
183207
}
184208

185209
pub unsafe fn dispatch_first_task<System: PortInstance>(&'static self) -> !
@@ -211,17 +235,11 @@ impl State {
211235
self.thread_group.get().unwrap(),
212236
&mut lock
213237
));
214-
lock.preempt();
215238
drop(lock);
216239

217-
// Wait until the thread group shuts down
218-
let join_handle = self.join_handle.lock().take().unwrap();
219-
if let Err(e) = join_handle.join() {
220-
std::panic::resume_unwind(e);
221-
}
222-
223-
// TODO: Expose a function to shut down the system
224-
panic!("the system has been shut down");
240+
// Safety: The requirement of `dispatch_first_task` explicitly allows
241+
// discarding the context.
242+
unsafe { ums::exit_thread() };
225243
}
226244

227245
extern "C" fn dispatch_handler<System: PortInstance>()
@@ -637,12 +655,7 @@ macro_rules! use_port {
637655

638656
$crate::env_logger::init();
639657

640-
port_std_impl::PORT_STATE.init::<$sys>();
641-
642-
// Safety: We are a port, so it's okay to call these
643-
unsafe {
644-
<$sys as PortToKernel>::boot();
645-
}
658+
port_std_impl::PORT_STATE.port_boot::<$sys>();
646659
}
647660
};
648661
}

src/constance_port_std/src/sched.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ impl ums::Scheduler for SchedState {
134134
/// Check for any pending interrupts that can be activated under the current
135135
/// condition. If there are one or more of them, activate them and return
136136
/// `true`, in which case the caller should call
137-
/// [`ums::ThreadGroupLockGuard::preempt`] or [`ums::yield_now`].
137+
/// [`ums::ThreadGroupLockGuard::preempt`], [`ums::yield_now`],
138+
/// [`ums::exit_thread`].
138139
///
139140
/// This should be called after changing some properties of `SchedState` in a
140141
/// way that might cause interrupt handlers to activate, such as disabling

src/constance_port_std/tests/test_suite.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,7 @@ macro_rules! instantiate_kernel_tests {
8383
#[test]
8484
fn run() {
8585
TEST_UTIL.run(|| {
86-
port_std_impl::PORT_STATE.init::<System>();
87-
88-
// Safety: We are a port, so it's okay to call this
89-
unsafe {
90-
<System as constance::kernel::PortToKernel>::boot();
91-
}
86+
port_std_impl::PORT_STATE.port_boot::<System>();
9287
});
9388
}
9489
}

0 commit comments

Comments
 (0)