Skip to content

Commit c8d7fa0

Browse files
committed
feat(port_std): check context on method entry
1 parent ff5c815 commit c8d7fa0

File tree

1 file changed

+88
-41
lines changed
  • src/constance_port_std/src

1 file changed

+88
-41
lines changed

src/constance_port_std/src/lib.rs

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ enum Tsm {
103103
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104104
enum ThreadRole {
105105
Unknown,
106+
Boot,
106107
/// The backing thread for an interrupt context.
107108
Interrupt,
108109
/// The backing thread for a task.
@@ -131,7 +132,7 @@ impl TaskState {
131132
assert_eq!(ums::current_thread(), Some(expected_thread_id));
132133
}
133134

134-
unsafe fn exit_and_dispatch(&self, state: &'static State) -> ! {
135+
unsafe fn exit_and_dispatch<System: PortInstance>(&self, state: &'static State) -> ! {
135136
log::trace!("exit_and_dispatch({:p}) enter", self);
136137
self.assert_current_thread();
137138

@@ -157,7 +158,7 @@ impl TaskState {
157158
drop(lock);
158159

159160
// Invoke the dispatcher
160-
unsafe { state.yield_cpu() };
161+
unsafe { state.yield_cpu::<System>() };
161162

162163
log::trace!("exit_and_dispatch({:p}) calling exit_thread", self);
163164
unsafe { ums::exit_thread() };
@@ -188,6 +189,8 @@ impl State {
188189
// kernel runs
189190
let mut lock = self.thread_group.get().unwrap().lock();
190191
let thread_id = lock.spawn(|_| {
192+
THREAD_ROLE.with(|role| role.set(ThreadRole::Boot));
193+
191194
// Safety: We are a port, so it's okay to call this
192195
unsafe {
193196
<System as PortToKernel>::boot();
@@ -212,7 +215,8 @@ impl State {
212215
System::TaskReadyQueue: std::borrow::BorrowMut<[StaticListHead<TaskCb<System>>]>,
213216
{
214217
log::trace!("dispatch_first_task");
215-
assert!(self.is_cpu_lock_active());
218+
assert_eq!(expect_worker_thread::<System>(), ThreadRole::Boot);
219+
assert!(self.is_cpu_lock_active::<System>());
216220

217221
// Create a UMS worker thread for the dispatcher
218222
let mut lock = self.thread_group.get().unwrap().lock();
@@ -255,9 +259,11 @@ impl State {
255259
// FIXME: Work-around for <https://github.com/rust-lang/rust/issues/43475>
256260
System::TaskReadyQueue: std::borrow::BorrowMut<[StaticListHead<TaskCb<System>>]>,
257261
{
258-
unsafe { self.enter_cpu_lock() };
262+
assert_eq!(expect_worker_thread::<System>(), ThreadRole::Interrupt);
263+
264+
unsafe { self.enter_cpu_lock::<System>() };
259265
unsafe { System::choose_running_task() };
260-
unsafe { self.leave_cpu_lock() };
266+
unsafe { self.leave_cpu_lock::<System>() };
261267

262268
let mut lock = self.thread_group.get().unwrap().lock();
263269

@@ -271,10 +277,10 @@ impl State {
271277
Tsm::Dormant => {
272278
// Spawn a UMS worker thread for this task
273279
let thread = lock.spawn(move |_| {
274-
assert!(!self.is_cpu_lock_active());
275-
log::debug!("task {:p} is now running", task);
276-
277280
THREAD_ROLE.with(|role| role.set(ThreadRole::Task));
281+
assert!(!self.is_cpu_lock_active::<System>());
282+
283+
log::debug!("task {:p} is now running", task);
278284

279285
// Safety: The port can call this
280286
unsafe {
@@ -303,35 +309,40 @@ impl State {
303309
};
304310
}
305311

306-
pub unsafe fn yield_cpu(&'static self) {
312+
pub unsafe fn yield_cpu<System: PortInstance>(&'static self) {
307313
log::trace!("yield_cpu");
308-
assert!(!self.is_cpu_lock_active());
314+
expect_worker_thread::<System>();
315+
assert!(!self.is_cpu_lock_active::<System>());
309316

310-
self.pend_interrupt_line(INTERRUPT_LINE_DISPATCH).unwrap();
317+
self.pend_interrupt_line::<System>(INTERRUPT_LINE_DISPATCH)
318+
.unwrap();
311319
}
312320

313321
pub unsafe fn exit_and_dispatch<System: PortInstance>(
314322
&'static self,
315323
task: &'static TaskCb<System>,
316324
) -> ! {
317325
log::trace!("exit_and_dispatch");
318-
assert!(self.is_cpu_lock_active());
326+
assert_eq!(expect_worker_thread::<System>(), ThreadRole::Task);
327+
assert!(self.is_cpu_lock_active::<System>());
319328

320329
unsafe {
321-
task.port_task_state.exit_and_dispatch(self);
330+
task.port_task_state.exit_and_dispatch::<System>(self);
322331
}
323332
}
324333

325-
pub unsafe fn enter_cpu_lock(&self) {
334+
pub unsafe fn enter_cpu_lock<System: PortInstance>(&self) {
326335
log::trace!("enter_cpu_lock");
336+
expect_worker_thread::<System>();
327337

328338
let mut lock = self.thread_group.get().unwrap().lock();
329339
assert!(!lock.scheduler().cpu_lock);
330340
lock.scheduler().cpu_lock = true;
331341
}
332342

333-
pub unsafe fn leave_cpu_lock(&'static self) {
343+
pub unsafe fn leave_cpu_lock<System: PortInstance>(&'static self) {
334344
log::trace!("leave_cpu_lock");
345+
expect_worker_thread::<System>();
335346

336347
let mut lock = self.thread_group.get().unwrap().lock();
337348
assert!(lock.scheduler().cpu_lock);
@@ -348,6 +359,8 @@ impl State {
348359
task: &'static TaskCb<System>,
349360
) {
350361
log::trace!("initialize_task_state {:p}", task);
362+
expect_worker_thread::<System>();
363+
assert!(self.is_cpu_lock_active::<System>());
351364

352365
let pts = &task.port_task_state;
353366
let mut tsm = pts.tsm.lock();
@@ -362,26 +375,34 @@ impl State {
362375
}
363376
}
364377

365-
pub fn is_cpu_lock_active(&self) -> bool {
378+
pub fn is_cpu_lock_active<System: PortInstance>(&self) -> bool {
379+
expect_worker_thread::<System>();
380+
366381
(self.thread_group.get().unwrap().lock())
367382
.scheduler()
368383
.cpu_lock
369384
}
370385

371-
pub fn is_interrupt_context(&self) -> bool {
386+
pub fn is_interrupt_context<System: PortInstance>(&self) -> bool {
387+
expect_worker_thread::<System>();
388+
372389
THREAD_ROLE.with(|role| match role.get() {
373390
ThreadRole::Interrupt => true,
374391
ThreadRole::Task => false,
375392
_ => panic!("`is_interrupt_context` was called from an unknown thread"),
376393
})
377394
}
378395

379-
pub fn set_interrupt_line_priority<System: Kernel>(
396+
pub fn set_interrupt_line_priority<System: PortInstance>(
380397
&'static self,
381398
num: InterruptNum,
382399
priority: InterruptPriority,
383400
) -> Result<(), SetInterruptLinePriorityError> {
384401
log::trace!("set_interrupt_line_priority{:?}", (num, priority));
402+
assert!(matches!(
403+
expect_worker_thread::<System>(),
404+
ThreadRole::Boot | ThreadRole::Task
405+
));
385406

386407
let mut lock = self.thread_group.get().unwrap().lock();
387408
lock.scheduler()
@@ -396,11 +417,12 @@ impl State {
396417
Ok(())
397418
}
398419

399-
pub fn enable_interrupt_line<System: Kernel>(
420+
pub fn enable_interrupt_line<System: PortInstance>(
400421
&'static self,
401422
num: InterruptNum,
402423
) -> Result<(), EnableInterruptLineError> {
403424
log::trace!("enable_interrupt_line{:?}", (num,));
425+
expect_worker_thread::<System>();
404426

405427
let mut lock = self.thread_group.get().unwrap().lock();
406428
lock.scheduler()
@@ -415,23 +437,25 @@ impl State {
415437
Ok(())
416438
}
417439

418-
pub fn disable_interrupt_line(
440+
pub fn disable_interrupt_line<System: PortInstance>(
419441
&self,
420442
num: InterruptNum,
421443
) -> Result<(), EnableInterruptLineError> {
422444
log::trace!("disable_interrupt_line{:?}", (num,));
445+
expect_worker_thread::<System>();
423446

424447
(self.thread_group.get().unwrap().lock())
425448
.scheduler()
426449
.update_line(num, |line| line.enable = false)
427450
.map_err(|sched::BadIntLineError| EnableInterruptLineError::BadParam)
428451
}
429452

430-
pub fn pend_interrupt_line(
453+
pub fn pend_interrupt_line<System: PortInstance>(
431454
&'static self,
432455
num: InterruptNum,
433456
) -> Result<(), PendInterruptLineError> {
434457
log::trace!("pend_interrupt_line{:?}", (num,));
458+
expect_worker_thread::<System>();
435459

436460
let mut lock = self.thread_group.get().unwrap().lock();
437461
lock.scheduler()
@@ -446,19 +470,25 @@ impl State {
446470
Ok(())
447471
}
448472

449-
pub fn clear_interrupt_line(&self, num: InterruptNum) -> Result<(), ClearInterruptLineError> {
473+
pub fn clear_interrupt_line<System: PortInstance>(
474+
&self,
475+
num: InterruptNum,
476+
) -> Result<(), ClearInterruptLineError> {
450477
log::trace!("clear_interrupt_line{:?}", (num,));
478+
expect_worker_thread::<System>();
451479

452480
(self.thread_group.get().unwrap().lock())
453481
.scheduler()
454482
.update_line(num, |line| line.pended = false)
455483
.map_err(|sched::BadIntLineError| ClearInterruptLineError::BadParam)
456484
}
457485

458-
pub fn is_interrupt_line_pending(
486+
pub fn is_interrupt_line_pending<System: PortInstance>(
459487
&self,
460488
num: InterruptNum,
461489
) -> Result<bool, QueryInterruptLineError> {
490+
expect_worker_thread::<System>();
491+
462492
(self.thread_group.get().unwrap().lock())
463493
.scheduler()
464494
.is_line_pended(num)
@@ -469,7 +499,9 @@ impl State {
469499
pub const MAX_TICK_COUNT: UTicks = UTicks::MAX;
470500
pub const MAX_TIMEOUT: UTicks = UTicks::MAX / 2;
471501

472-
pub fn tick_count(&self) -> UTicks {
502+
pub fn tick_count<System: PortInstance>(&self) -> UTicks {
503+
expect_worker_thread::<System>();
504+
473505
let origin = if let Some(x) = self.origin.load(Ordering::Acquire) {
474506
x
475507
} else {
@@ -516,15 +548,26 @@ impl State {
516548
(micros as UTicks).wrapping_add(get_random_number())
517549
}
518550

519-
pub fn pend_tick_after(&self, tick_count_delta: UTicks) {
551+
pub fn pend_tick_after<System: PortInstance>(&self, tick_count_delta: UTicks) {
552+
expect_worker_thread::<System>();
520553
// TODO
521554
}
522555

523-
pub fn pend_tick(&self) {
556+
pub fn pend_tick<System: PortInstance>(&self) {
557+
expect_worker_thread::<System>();
524558
// TODO
525559
}
526560
}
527561

562+
/// Assert that the current thread is a worker thread of `System`.
563+
fn expect_worker_thread<System: PortInstance>() -> ThreadRole {
564+
// TODO: Check that the current worker thread belongs to
565+
// `System::port_state().thread_group`
566+
let role = THREAD_ROLE.with(|r| r.get());
567+
assert_ne!(role, ThreadRole::Unknown);
568+
role
569+
}
570+
528571
/// Initiate graceful shutdown.
529572
///
530573
/// The shutdown completes when all threads complete execution. Usually, the
@@ -551,7 +594,11 @@ pub fn pend_interrupt_line<System: PortInstance>(
551594
) -> Result<(), PendInterruptLineError> {
552595
log::trace!("external-pend_interrupt_line{:?}", (num,));
553596

554-
assert_eq!(THREAD_ROLE.with(|r| r.get()), ThreadRole::Unknown);
597+
assert_eq!(
598+
THREAD_ROLE.with(|r| r.get()),
599+
ThreadRole::Unknown,
600+
"this method cannot be called from a port-managed thread"
601+
);
555602

556603
let state = System::port_state();
557604
let mut lock = state.thread_group.get().unwrap().lock();
@@ -600,31 +647,31 @@ macro_rules! use_port {
600647
}
601648

602649
unsafe fn yield_cpu() {
603-
PORT_STATE.yield_cpu()
650+
PORT_STATE.yield_cpu::<Self>()
604651
}
605652

606653
unsafe fn exit_and_dispatch(task: &'static TaskCb<Self>) -> ! {
607-
PORT_STATE.exit_and_dispatch(task);
654+
PORT_STATE.exit_and_dispatch::<Self>(task);
608655
}
609656

610657
unsafe fn enter_cpu_lock() {
611-
PORT_STATE.enter_cpu_lock()
658+
PORT_STATE.enter_cpu_lock::<Self>()
612659
}
613660

614661
unsafe fn leave_cpu_lock() {
615-
PORT_STATE.leave_cpu_lock()
662+
PORT_STATE.leave_cpu_lock::<Self>()
616663
}
617664

618665
unsafe fn initialize_task_state(task: &'static TaskCb<Self>) {
619-
PORT_STATE.initialize_task_state(task)
666+
PORT_STATE.initialize_task_state::<Self>(task)
620667
}
621668

622669
fn is_cpu_lock_active() -> bool {
623-
PORT_STATE.is_cpu_lock_active()
670+
PORT_STATE.is_cpu_lock_active::<Self>()
624671
}
625672

626673
fn is_interrupt_context() -> bool {
627-
PORT_STATE.is_interrupt_context()
674+
PORT_STATE.is_interrupt_context::<Self>()
628675
}
629676
}
630677

@@ -644,21 +691,21 @@ macro_rules! use_port {
644691
}
645692

646693
unsafe fn disable_interrupt_line(line: InterruptNum) -> Result<(), EnableInterruptLineError> {
647-
PORT_STATE.disable_interrupt_line(line)
694+
PORT_STATE.disable_interrupt_line::<Self>(line)
648695
}
649696

650697
unsafe fn pend_interrupt_line(line: InterruptNum) -> Result<(), PendInterruptLineError> {
651-
PORT_STATE.pend_interrupt_line(line)
698+
PORT_STATE.pend_interrupt_line::<Self>(line)
652699
}
653700

654701
unsafe fn clear_interrupt_line(line: InterruptNum) -> Result<(), ClearInterruptLineError> {
655-
PORT_STATE.clear_interrupt_line(line)
702+
PORT_STATE.clear_interrupt_line::<Self>(line)
656703
}
657704

658705
unsafe fn is_interrupt_line_pending(
659706
line: InterruptNum,
660707
) -> Result<bool, QueryInterruptLineError> {
661-
PORT_STATE.is_interrupt_line_pending(line)
708+
PORT_STATE.is_interrupt_line_pending::<Self>(line)
662709
}
663710
}
664711

@@ -667,15 +714,15 @@ macro_rules! use_port {
667714
const MAX_TIMEOUT: UTicks = State::MAX_TIMEOUT;
668715

669716
unsafe fn tick_count() -> UTicks {
670-
PORT_STATE.tick_count()
717+
PORT_STATE.tick_count::<Self>()
671718
}
672719

673720
unsafe fn pend_tick_after(tick_count_delta: UTicks) {
674-
PORT_STATE.pend_tick_after(tick_count_delta)
721+
PORT_STATE.pend_tick_after::<Self>(tick_count_delta)
675722
}
676723

677724
unsafe fn pend_tick() {
678-
PORT_STATE.pend_tick()
725+
PORT_STATE.pend_tick::<Self>()
679726
}
680727
}
681728
}

0 commit comments

Comments
 (0)