Skip to content

Commit

Permalink
Merge pull request #18 from hermit-os/interrupts
Browse files Browse the repository at this point in the history
Rework interrupt mutex
  • Loading branch information
mkroening authored Sep 18, 2023
2 parents 5b336d0 + 9bb47ac commit f71f5e7
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 164 deletions.
13 changes: 2 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hermit-sync"
version = "0.1.4"
version = "0.1.5"
authors = ["Martin Kröning <[email protected]>"]
edition = "2021"
description = "Synchronization primitives for kernels."
Expand All @@ -12,17 +12,8 @@ categories = ["rust-patterns", "no-std"]
[dependencies]
exclusive_cell = "0.1"
generic_once_cell = "0.1"
interrupts = "0.1"
lock_api = "0.4"

[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = { version = "0.14", default-features = false, features = [ "instructions" ] }

[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = "9.0"
tock-registers = { version = "0.8", default-features = false }

[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = "0.10"

[dev-dependencies]
rand = "0.8"
134 changes: 0 additions & 134 deletions src/interrupts.rs

This file was deleted.

3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@
#![warn(unsafe_op_in_unsafe_fn)]

mod backoff;
pub(crate) mod interrupts;
pub(crate) mod mutex;
pub(crate) mod rwlock;

pub use exclusive_cell::{CallOnce, CallOnceError, ExclusiveCell};
pub use interrupts::without_interrupts;
pub use interrupts::without as without_interrupts;
pub use mutex::interrupt::{InterruptMutex, InterruptMutexGuard, RawInterruptMutex};
pub use mutex::spin::{RawSpinMutex, SpinMutex, SpinMutexGuard};
pub use mutex::ticket::{RawTicketMutex, TicketMutex, TicketMutexGuard};
Expand Down
45 changes: 28 additions & 17 deletions src/mutex/interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,64 @@
use core::sync::atomic::Ordering;
use core::cell::UnsafeCell;
use core::mem::MaybeUninit;

use lock_api::RawMutex;

use crate::interrupts::{self, AtomicFlags};
use lock_api::{GuardNoSend, RawMutex};

/// An interrupt-safe mutex.
///
/// This mutex wraps another [`RawMutex`] and disables interrupts while locked.
/// Only has an effect if `target_os = "none"`.
pub struct RawInterruptMutex<I> {
inner: I,
interrupt_flags: AtomicFlags,
interrupt_guard: UnsafeCell<MaybeUninit<interrupts::Guard>>,
}

// SAFETY: The `UnsafeCell` is locked by `inner`, initialized on `lock` and uninitialized on `unlock`.
unsafe impl<I: Sync> Sync for RawInterruptMutex<I> {}
// SAFETY: Mutexes cannot be send to other threads while locked.
// Sending them while unlocked is fine.
unsafe impl<I: Send> Send for RawInterruptMutex<I> {}

unsafe impl<I: RawMutex> RawMutex for RawInterruptMutex<I> {
const INIT: Self = Self {
inner: I::INIT,
interrupt_flags: AtomicFlags::new(interrupts::DISABLE),
interrupt_guard: UnsafeCell::new(MaybeUninit::uninit()),
};

type GuardMarker = I::GuardMarker;
type GuardMarker = GuardNoSend;

#[inline]
fn lock(&self) {
let interrupt_flags = crate::interrupts::read_disable();
let guard = interrupts::disable();
self.inner.lock();
self.interrupt_flags
.store(interrupt_flags, Ordering::Relaxed);
// SAFETY: We have exclusive access through locking `inner`.
unsafe {
self.interrupt_guard.get().write(MaybeUninit::new(guard));
}
}

#[inline]
fn try_lock(&self) -> bool {
let interrupt_flags = crate::interrupts::read_disable();
let guard = interrupts::disable();
let ok = self.inner.try_lock();
if !ok {
crate::interrupts::restore(interrupt_flags);
if ok {
// SAFETY: We have exclusive access through locking `inner`.
unsafe {
self.interrupt_guard.get().write(MaybeUninit::new(guard));
}
}
ok
}

#[inline]
unsafe fn unlock(&self) {
let interrupt_flags = self
.interrupt_flags
.swap(interrupts::DISABLE, Ordering::Relaxed);
// SAFETY: We have exclusive access through locking `inner`.
let guard = unsafe { self.interrupt_guard.get().replace(MaybeUninit::uninit()) };
// SAFETY: `guard` was initialized when locking.
let guard = unsafe { guard.assume_init() };
unsafe {
self.inner.unlock();
}
crate::interrupts::restore(interrupt_flags);
drop(guard);
}

#[inline]
Expand Down

0 comments on commit f71f5e7

Please sign in to comment.