Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(maitake-sync): mutex-traits integration #482

Merged
merged 41 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
eb8ac57
feat(maitake-sync): optional `lock_api` support
hawkw Jul 9, 2024
4ca4d63
feat(maitake-sync): update WaitQueue to use RawMutex
hawkw Jul 9, 2024
13cd5aa
feat(maitake-sync): make `Semaphore` generic over RawMutex
hawkw Jul 10, 2024
d86b684
feat(maitake-sync): make `RwLock` generic over RawMutex
hawkw Jul 10, 2024
6e215d7
feat(maitake-sync): lock api in async mutex
hawkw Jul 11, 2024
5af051e
docs
hawkw Jul 15, 2024
99cfb40
wip closure based API (broken)
hawkw Jul 18, 2024
ccc47d8
make WaitQueue actually work
hawkw Jul 20, 2024
db1890b
simplify wake_all implementation
hawkw Jul 20, 2024
791c2d4
update async `Mutex` to use scoped mutex API
hawkw Jul 20, 2024
03c9f0a
add `try_with` to `blocking::Mutex`, `Debug`
hawkw Jul 20, 2024
6f42ce3
also do waitqueue
hawkw Jul 20, 2024
86a933c
rename closure lock methods to `with_lock`
hawkw Jul 20, 2024
b3346c4
start on `ScopedMutexTraits` integration
hawkw Jul 22, 2024
b8b32a1
update everything to `mutex-traits`
hawkw Jul 25, 2024
b33c33b
fix simulated loom mutex
hawkw Jul 27, 2024
75b0a7f
add nicer debug logs to loom mutex
hawkw Jul 27, 2024
3a1b185
remove `lock_api` dep
hawkw Jul 27, 2024
6f97043
huge docs pass + missing constructors
hawkw Jul 27, 2024
2cea7c1
fix loom tests not compiling with no-default-features
hawkw Jul 27, 2024
c7b9c0b
sketch out `DefaultMutex`
hawkw Jul 28, 2024
1da4095
add `DefaultMutex` tests and fix some broken stuff
hawkw Jul 28, 2024
28e3226
plumbing, docs, and redo constructors
hawkw Jul 28, 2024
45804c1
make mycelium compile with breaking changes
hawkw Jul 28, 2024
76006e8
Update semaphore.rs
hawkw Jul 28, 2024
54984d6
fix `loom` version of `with_raw_mutex`
hawkw Jul 29, 2024
aa7dc8f
add missing `ConstInit` impls for `Spinlock`/`RwSpinlock`
hawkw Jul 29, 2024
78610c3
rename `with_raw_mutex` to `new_with_raw_mutex`
hawkw Jul 29, 2024
02036f1
docs fixes as suggested by @jamesmunns
hawkw Jul 29, 2024
0472bf4
`maitake` should also include new docs and feature flags
hawkw Jul 29, 2024
45e6380
`critical-section` features should also set `portable-atomic`'s feature
hawkw Jul 29, 2024
dd6656e
remove `spin::Mutex` aliases
hawkw Jul 29, 2024
99ce4e1
remove remaining `spin::Mutex` references
hawkw Aug 10, 2024
f370793
sync: always enable `tracing` with `cfg(loom)`
hawkw Aug 10, 2024
0be56fd
oh THAT'S what the import was for
hawkw Aug 10, 2024
48c84af
fix docs import error
hawkw Aug 10, 2024
ddb2346
s/RawScopedMutex/ScopedRawMutex in docs
hawkw Aug 10, 2024
3643e5c
fixup and document `Send`/`Sync` impls
hawkw Aug 10, 2024
9e5a3bf
mutex-traits is stable now
hawkw Aug 10, 2024
3251c85
fix wrong sync impl for mutex
hawkw Aug 10, 2024
93974d6
docs fixup
hawkw Aug 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,4 @@ tracing-core = { git = "https://github.com/tokio-rs/tracing" }
[profile.loom]
inherits = "test"
lto = true
opt-level = 3
opt-level = 3
114 changes: 60 additions & 54 deletions alloc/src/buddy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use mycelium_util::intrusive::{list, Linked, List};
use mycelium_util::math::Logarithm;
use mycelium_util::sync::{
atomic::{AtomicUsize, Ordering::*},
spin,
blocking::Mutex,
};

#[derive(Debug)]
Expand All @@ -41,7 +41,7 @@ pub struct Alloc<const FREE_LISTS: usize> {
/// Array of free lists by "order". The order of an block is the number
/// of times the minimum page size must be doubled to reach that block's
/// size.
free_lists: [spin::Mutex<List<Free>>; FREE_LISTS],
free_lists: [Mutex<List<Free>>; FREE_LISTS],
}

type Result<T> = core::result::Result<T, AllocErr>;
Expand All @@ -65,7 +65,7 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
//
// see https://github.com/rust-lang/rust-clippy/issues/7665
#[allow(clippy::declare_interior_mutable_const)]
const ONE_FREE_LIST: spin::Mutex<List<Free>> = spin::Mutex::new(List::new());
const ONE_FREE_LIST: Mutex<List<Free>> = Mutex::new(List::new());

// ensure we don't split memory into regions too small to fit the free
// block header in them.
Expand Down Expand Up @@ -190,16 +190,12 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
let _span =
tracing::debug_span!("free_list", order, size = self.size_for_order(order),)
.entered();
match list.try_lock() {
Some(list) => {
for entry in list.iter() {
tracing::debug!("entry={entry:?}");
}
}
None => {
tracing::debug!("<THIS IS THE ONE WHERE THE PANIC HAPPENED LOL>");
list.try_with_lock(|list| {
for entry in list.iter() {
tracing::debug!("entry={entry:?}");
}
}
})
.unwrap_or_else(|| tracing::debug!("<THIS IS THE ONE WHERE THE PANIC HAPPENED LOL>"))
}
}

Expand Down Expand Up @@ -283,29 +279,35 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
tracing::trace!(curr_order = idx + order);

// Is there an available block on this free list?
let mut free_list = free_list.lock();
if let Some(mut block) = free_list.pop_back() {
let block = unsafe { block.as_mut() };
tracing::trace!(?block, ?free_list, "found");

// Unless this is the free list on which we'd expect to find a
// block of the requested size (the first free list we checked),
// the block is larger than the requested allocation. In that
// case, we'll need to split it down and push the remainder onto
// the appropriate free lists.
if idx > 0 {
let curr_order = idx + order;
tracing::trace!(?curr_order, ?order, "split down");
self.split_down(block, curr_order, order);
}
let allocated = free_list.with_lock(|free_list| {
if let Some(mut block) = free_list.pop_back() {
let block = unsafe { block.as_mut() };
tracing::trace!(?block, ?free_list, "found");

// Unless this is the free list on which we'd expect to find a
// block of the requested size (the first free list we checked),
// the block is larger than the requested allocation. In that
// case, we'll need to split it down and push the remainder onto
// the appropriate free lists.
if idx > 0 {
let curr_order = idx + order;
tracing::trace!(?curr_order, ?order, "split down");
self.split_down(block, curr_order, order);
}

// Change the block's magic to indicate that it is allocated, so
// that we can avoid checking the free list if we try to merge
// it before the first word is written to.
block.make_busy();
tracing::trace!(?block, "made busy");
self.allocated_size.fetch_add(block.size(), Release);
return Some(block.into());
// Change the block's magic to indicate that it is allocated, so
// that we can avoid checking the free list if we try to merge
// it before the first word is written to.
block.make_busy();
tracing::trace!(?block, "made busy");
self.allocated_size.fetch_add(block.size(), Release);
Some(block.into())
} else {
None
}
});
if let Some(block) = allocated {
return Some(block);
}
}
None
Expand Down Expand Up @@ -334,25 +336,29 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
// Starting at the minimum order on which the freed range will fit
for (idx, free_list) in self.free_lists.as_ref()[min_order..].iter().enumerate() {
let curr_order = idx + min_order;
let mut free_list = free_list.lock();

// Is there a free buddy block at this order?
if let Some(mut buddy) = unsafe { self.take_buddy(block, curr_order, &mut free_list) } {
// Okay, merge the blocks, and try the next order!
if buddy < block {
mem::swap(&mut block, &mut buddy);
}
unsafe {
block.as_mut().merge(buddy.as_mut());
let done = free_list.with_lock(|free_list| {
// Is there a free buddy block at this order?
if let Some(mut buddy) = unsafe { self.take_buddy(block, curr_order, free_list) } {
// Okay, merge the blocks, and try the next order!
if buddy < block {
mem::swap(&mut block, &mut buddy);
}
unsafe {
block.as_mut().merge(buddy.as_mut());
}
tracing::trace!(?buddy, ?block, "merged with buddy");
// Keep merging!
false
} else {
// Okay, we can't keep merging, so push the block on the current
// free list.
free_list.push_front(block);
tracing::trace!("deallocated block");
self.allocated_size.fetch_sub(size, Release);
true
}
tracing::trace!(?buddy, ?block, "merged with buddy");
// Keep merging!
} else {
// Okay, we can't keep merging, so push the block on the current
// free list.
free_list.push_front(block);
tracing::trace!("deallocated block");
self.allocated_size.fetch_sub(size, Release);
});
if done {
return Ok(());
}
}
Expand All @@ -369,7 +375,7 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
if order > free_lists.len() {
todo!("(eliza): choppity chop chop down the block!");
}
free_lists[order].lock().push_front(block);
free_lists[order].with_lock(|list| list.push_front(block));
let mut sz = self.heap_size.load(Acquire);
while let Err(actual) =
// TODO(eliza): if this overflows that's bad news lol...
Expand Down Expand Up @@ -473,7 +479,7 @@ impl<const FREE_LISTS: usize> Alloc<FREE_LISTS> {
.split_back(size, self.offset())
.expect("block too small to split!");
tracing::trace!(?block, ?new_block);
free_lists[order].lock().push_front(new_block);
free_lists[order].with_lock(|list| list.push_front(new_block));
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion hal-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tracing = { git = "https://github.com/tokio-rs/tracing", default_features = false }
tracing = { git = "https://github.com/tokio-rs/tracing", default_features = false }
maitake-sync = { path = "../maitake-sync", default-features = false }
mycelium-util = { path = "../util" }
embedded-graphics-core = { version = "0.3", optional = true }
5 changes: 4 additions & 1 deletion hal-core/src/framebuffer.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use core::ops::{Deref, DerefMut};
use maitake_sync::blocking;

#[cfg(feature = "embedded-graphics-core")]
#[doc(cfg(feature = "embedded-graphics-core"))]
mod embedded_graphics;
#[cfg(feature = "embedded-graphics-core")]
#[doc(cfg(feature = "embedded-graphics-core"))]
pub use self::embedded_graphics::*;

pub trait Draw {
/// Return the width of the framebuffer in pixels.
fn width(&self) -> usize;
Expand Down Expand Up @@ -185,9 +187,10 @@ macro_rules! deref_draw_body {
};
}

impl<'lock, D> Draw for mycelium_util::sync::spin::MutexGuard<'lock, D>
impl<'lock, D, L> Draw for blocking::MutexGuard<'lock, D, L>
where
D: Draw,
L: blocking::RawMutex,
{
deref_draw_body! {}
}
Expand Down
18 changes: 11 additions & 7 deletions hal-x86_64/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use hal_core::interrupt::Control;
use hal_core::interrupt::{ctx, Handlers};
use mycelium_util::{
bits, fmt,
sync::{spin, InitOnce},
sync::{
blocking::{Mutex, MutexGuard},
spin::Spinlock,
InitOnce,
},
};

pub mod apic;
Expand Down Expand Up @@ -56,7 +60,7 @@ pub struct Interrupt<T = ()> {
enum InterruptModel {
/// Interrupts are handled by the [8259 Programmable Interrupt Controller
/// (PIC)](pic).
Pic(spin::Mutex<pic::CascadedPic>),
Pic(Mutex<pic::CascadedPic, Spinlock>),
/// Interrupts are handled by the [local] and [I/O] [Advanced Programmable
/// Interrupt Controller (APIC)s][apics].
///
Expand All @@ -68,7 +72,7 @@ enum InterruptModel {
// TODO(eliza): allow further configuration of the I/O APIC (e.g.
// masking/unmasking stuff...)
#[allow(dead_code)]
io: spin::Mutex<apic::IoApic>,
io: Mutex<apic::IoApic, Spinlock>,
},
}

Expand Down Expand Up @@ -127,13 +131,13 @@ pub struct Registers {
_pad2: [u16; 3],
}

static IDT: spin::Mutex<idt::Idt> = spin::Mutex::new(idt::Idt::new());
static IDT: Mutex<idt::Idt, Spinlock> = Mutex::new_with_raw_mutex(idt::Idt::new(), Spinlock::new());
static INTERRUPT_CONTROLLER: InitOnce<Controller> = InitOnce::uninitialized();

impl Controller {
// const DEFAULT_IOAPIC_BASE_PADDR: u64 = 0xFEC00000;

pub fn idt() -> spin::MutexGuard<'static, idt::Idt> {
pub fn idt() -> MutexGuard<'static, idt::Idt, Spinlock> {
IDT.lock()
}

Expand Down Expand Up @@ -207,7 +211,7 @@ impl Controller {

InterruptModel::Apic {
local,
io: spin::Mutex::new(io),
io: Mutex::new_with_raw_mutex(io, Spinlock::new()),
}
}
model => {
Expand All @@ -225,7 +229,7 @@ impl Controller {
// clear for you, the reader, that at this point they are definitely intentionally enabled.
pics.enable();
}
InterruptModel::Pic(spin::Mutex::new(pics))
InterruptModel::Pic(Mutex::new_with_raw_mutex(pics, Spinlock::new()))
}
};
tracing::trace!(interrupt_model = ?model);
Expand Down
12 changes: 8 additions & 4 deletions hal-x86_64/src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use crate::cpu;
use core::{fmt, marker::PhantomData};
use mycelium_util::{
io,
sync::{spin, Lazy},
sync::{
blocking::{Mutex, MutexGuard},
spin::Spinlock,
Lazy,
},
};

static COM1: Lazy<Option<Port>> = Lazy::new(|| Port::new(0x3F8).ok());
Expand All @@ -29,7 +33,7 @@ pub fn com4() -> Option<&'static Port> {

// #[derive(Debug)]
pub struct Port {
inner: spin::Mutex<Registers>,
inner: Mutex<Registers, Spinlock>,
}

// #[derive(Debug)]
Expand All @@ -40,7 +44,7 @@ pub struct Lock<'a, B = Blocking> {
}

struct LockInner<'a> {
inner: spin::MutexGuard<'a, Registers>,
inner: MutexGuard<'a, Registers, Spinlock>,
prev_divisor: Option<u16>,
}

Expand Down Expand Up @@ -110,7 +114,7 @@ impl Port {
})?;

Ok(Self {
inner: spin::Mutex::new(registers),
inner: Mutex::new_with_raw_mutex(registers, Spinlock::new()),
})
}

Expand Down
4 changes: 2 additions & 2 deletions hal-x86_64/src/time/pit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::{
use mycelium_util::{
bits::{bitfield, enum_from_bits},
fmt,
sync::spin::Mutex,
sync::{blocking::Mutex, spin::Spinlock},
};

/// Intel 8253/8254 Programmable Interval Timer (PIT).
Expand Down Expand Up @@ -210,7 +210,7 @@ enum_from_bits! {
/// publicly and is represented as a singleton. It's stored in a [`Mutex`] in
/// order to ensure that multiple CPU cores don't try to write conflicting
/// configurations to the PIT's configuration ports.
pub static PIT: Mutex<Pit> = Mutex::new(Pit::new());
pub static PIT: Mutex<Pit, Spinlock> = Mutex::new_with_raw_mutex(Pit::new(), Spinlock::new());

/// Are we currently sleeping on an interrupt?
static SLEEPING: AtomicBool = AtomicBool::new(false);
Expand Down
Loading
Loading