Skip to content

Commit c762883

Browse files
committed
perf(kernel): add PortThreading::try_enter_cpu_lock
This operation can be optimized into a single CSR read-modify-write instruction on RISC-V.
1 parent 6704f0d commit c762883

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

src/constance/src/kernel.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,12 @@ pub trait Kernel: Port + KernelCfg2 + Sized + 'static {
268268

269269
impl<T: Port + KernelCfg2 + 'static> Kernel for T {
270270
fn acquire_cpu_lock() -> Result<(), CpuLockError> {
271-
if Self::is_cpu_lock_active() {
272-
Err(CpuLockError::BadContext)
273-
} else {
274-
// Safety: CPU Lock inactive
275-
unsafe { Self::enter_cpu_lock() };
271+
// Safety: `try_enter_cpu_lock` is only meant to be called by
272+
// the kernel
273+
if unsafe { Self::try_enter_cpu_lock() } {
276274
Ok(())
275+
} else {
276+
Err(CpuLockError::BadContext)
277277
}
278278
}
279279

@@ -441,6 +441,18 @@ pub unsafe trait PortThreading: KernelCfg1 {
441441
/// Precondition: CPU Lock active
442442
unsafe fn leave_cpu_lock();
443443

444+
/// Activate CPU Lock. Return `true` iff CPU Lock was inactive before the
445+
/// call.
446+
unsafe fn try_enter_cpu_lock() -> bool {
447+
if Self::is_cpu_lock_active() {
448+
false
449+
} else {
450+
// Safety: CPU Lock inactive
451+
unsafe { Self::enter_cpu_lock() };
452+
true
453+
}
454+
}
455+
444456
/// Prepare the task for activation. More specifically, set the current
445457
/// program counter to [`TaskAttr::entry_point`] and the current stack
446458
/// pointer to either end of [`TaskAttr::stack`], ensuring the task will

src/constance/src/kernel/utils.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,13 @@ impl<'a, Element: Clone, System: Kernel> CellLike<CpuLockGuardBorrowMut<'a, Syst
111111
/// Attempt to enter a CPU Lock state and get an RAII guard.
112112
/// Return `BadContext` if the kernel is already in a CPU Lock state.
113113
pub(super) fn lock_cpu<System: Kernel>() -> Result<CpuLockGuard<System>, BadContextError> {
114-
expect_cpu_lock_inactive::<System>()?;
115-
116-
// Safety: CPU Lock is currently inactive, and it's us (the kernel) who
117-
// are currently controlling the CPU Lock state
118-
unsafe {
119-
System::enter_cpu_lock();
114+
// Safety: `try_enter_cpu_lock` is only meant to be called by the kernel
115+
if unsafe { System::try_enter_cpu_lock() } {
116+
// Safety: We just entered a CPU Lock state
117+
Ok(unsafe { assume_cpu_lock() })
118+
} else {
119+
Err(BadContextError::BadContext)
120120
}
121-
122-
// Safety: We just entered a CPU Lock state
123-
Ok(unsafe { assume_cpu_lock() })
124121
}
125122

126123
/// Assume a CPU Lock state and get `CpuLockGuard`.

src/constance_port_riscv/src/threading/cfg.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ macro_rules! use_port {
9595
PORT_STATE.enter_cpu_lock::<Self>()
9696
}
9797

98+
#[inline(always)]
99+
unsafe fn try_enter_cpu_lock() -> bool {
100+
PORT_STATE.try_enter_cpu_lock::<Self>()
101+
}
102+
98103
#[inline(always)]
99104
unsafe fn leave_cpu_lock() {
100105
PORT_STATE.leave_cpu_lock::<Self>()

src/constance_port_riscv/src/threading/imp.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ mod mstatus {
3232
unsafe { asm!("csrsi mstatus, {}", const VALUE) };
3333
}
3434

35+
#[inline(always)]
36+
pub fn fetch_clear_i<const VALUE: usize>() -> usize {
37+
let read: usize;
38+
unsafe { asm!("csrrci {}, mstatus, {}", lateout(reg) read, const VALUE) };
39+
read
40+
}
41+
3542
#[inline(always)]
3643
pub fn read() -> usize {
3744
let read: usize;
@@ -567,6 +574,11 @@ impl State {
567574
mstatus::clear_i::<{ mstatus::MIE }>();
568575
}
569576

577+
#[inline(always)]
578+
pub unsafe fn try_enter_cpu_lock<System: PortInstance>(&self) -> bool {
579+
(mstatus::fetch_clear_i::<{ mstatus::MIE }>() & mstatus::MIE) != 0
580+
}
581+
570582
#[inline(always)]
571583
pub unsafe fn leave_cpu_lock<System: PortInstance>(&'static self) {
572584
mstatus::set_i::<{ mstatus::MIE }>();

0 commit comments

Comments
 (0)