feat: replace NullLock with SpinLock

This commit is contained in:
2021-10-21 19:10:41 +03:00
parent 67d49f8f0e
commit 24acc37cc1
15 changed files with 83 additions and 67 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use tock_registers::interfaces::{Readable, Writeable};
use tock_registers::registers::{ReadOnly, ReadWrite};
use tock_registers::{register_bitfields, register_structs};
@@ -63,7 +63,7 @@ impl GicdSharedRegs {
}
pub(super) struct Gicd {
shared_regs: IrqSafeNullLock<DeviceMemoryIo<GicdSharedRegs>>,
shared_regs: IrqSafeSpinLock<DeviceMemoryIo<GicdSharedRegs>>,
banked_regs: DeviceMemoryIo<GicdBankedRegs>,
}
@@ -73,7 +73,7 @@ impl Gicd {
banked_mmio: DeviceMemoryIo<GicdBankedRegs>,
) -> Self {
Self {
shared_regs: IrqSafeNullLock::new(shared_mmio),
shared_regs: IrqSafeSpinLock::new(shared_mmio),
banked_regs: banked_mmio,
}
}
+7 -4
View File
@@ -5,7 +5,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::{DeviceMemory, DeviceMemoryIo};
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
@@ -29,7 +29,7 @@ pub struct Gic {
gicd_base: usize,
gicc_base: usize,
scheduler_irq: IrqNumber,
table: IrqSafeNullLock<[Option<&'static (dyn IntSource + Sync)>; MAX_IRQ]>,
table: IrqSafeSpinLock<[Option<&'static (dyn IntSource + Sync)>; MAX_IRQ]>,
}
impl IrqNumber {
@@ -94,7 +94,10 @@ impl IntController for Gic {
let table = self.table.lock();
match table[irq_number] {
None => panic!("No handler registered for irq{}", irq_number),
Some(handler) => handler.handle_irq().expect("irq handler failed"),
Some(handler) => {
drop(table);
handler.handle_irq().expect("irq handler failed")
},
}
}
@@ -132,7 +135,7 @@ impl Gic {
gicd_base,
gicc_base,
scheduler_irq,
table: IrqSafeNullLock::new([None; MAX_IRQ]),
table: IrqSafeSpinLock::new([None; MAX_IRQ]),
}
}
}
@@ -10,7 +10,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::interfaces::{Readable, Writeable};
@@ -33,7 +33,7 @@ struct CpuxGpio {
}
pub struct Gpio {
cpux: InitOnce<IrqSafeNullLock<CpuxGpio>>,
cpux: InitOnce<IrqSafeSpinLock<CpuxGpio>>,
cpux_base: usize,
}
@@ -144,7 +144,7 @@ impl Device for Gpio {
}
unsafe fn enable(&self) -> Result<(), Errno> {
self.cpux.init(IrqSafeNullLock::new(CpuxGpio {
self.cpux.init(IrqSafeSpinLock::new(CpuxGpio {
regs: DeviceMemoryIo::map(self.name(), self.cpux_base, 1)?,
}));
Ok(())
@@ -5,7 +5,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::{
@@ -47,7 +47,7 @@ register_structs! {
}
pub struct Rtc {
regs: InitOnce<IrqSafeNullLock<DeviceMemoryIo<Regs>>>,
regs: InitOnce<IrqSafeSpinLock<DeviceMemoryIo<Regs>>>,
base: usize,
irq: IrqNumber,
}
@@ -90,7 +90,7 @@ impl Device for Rtc {
}
unsafe fn enable(&self) -> Result<(), Errno> {
self.regs.init(IrqSafeNullLock::new(DeviceMemoryIo::map(
self.regs.init(IrqSafeSpinLock::new(DeviceMemoryIo::map(
self.name(),
self.base,
1,
@@ -5,7 +5,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
@@ -77,7 +77,7 @@ struct UartInner {
}
pub(super) struct Uart {
inner: InitOnce<IrqSafeNullLock<UartInner>>,
inner: InitOnce<IrqSafeSpinLock<UartInner>>,
base: usize,
irq: IrqNumber,
}
@@ -92,7 +92,7 @@ impl Device for Uart {
regs: DeviceMemoryIo::map(self.name(), self.base, 1)?,
};
// TODO
self.inner.init(IrqSafeNullLock::new(inner));
self.inner.init(IrqSafeSpinLock::new(inner));
Ok(())
}
}
@@ -1,6 +1,6 @@
use crate::dev::Device;
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::{
@@ -39,7 +39,7 @@ register_structs! {
}
pub(super) struct RWdog {
inner: InitOnce<IrqSafeNullLock<DeviceMemoryIo<RWdogRegs>>>,
inner: InitOnce<IrqSafeSpinLock<DeviceMemoryIo<RWdogRegs>>>,
base: usize,
}
@@ -49,7 +49,7 @@ impl Device for RWdog {
}
unsafe fn enable(&self) -> Result<(), Errno> {
self.inner.init(IrqSafeNullLock::new(DeviceMemoryIo::map(
self.inner.init(IrqSafeSpinLock::new(DeviceMemoryIo::map(
self.name(),
self.base,
1,
+3 -3
View File
@@ -1,6 +1,6 @@
use crate::dev::{serial::SerialDevice, Device};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::{
@@ -17,7 +17,7 @@ register_structs! {
}
pub(super) struct Bcm283xMiniUart {
regs: InitOnce<IrqSafeNullLock<DeviceMemoryIo<Regs>>>,
regs: InitOnce<IrqSafeSpinLock<DeviceMemoryIo<Regs>>>,
base: usize,
}
@@ -27,7 +27,7 @@ impl Device for Bcm283xMiniUart {
}
unsafe fn enable(&self) -> Result<(), Errno> {
self.regs.init(IrqSafeNullLock::new(DeviceMemoryIo::map(
self.regs.init(IrqSafeSpinLock::new(DeviceMemoryIo::map(
self.name(),
self.base,
1,
+3 -3
View File
@@ -6,7 +6,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use error::Errno;
use tock_registers::{
@@ -49,7 +49,7 @@ struct Pl031Inner {
/// Device struct for PL031
pub struct Pl031 {
inner: InitOnce<IrqSafeNullLock<Pl031Inner>>,
inner: InitOnce<IrqSafeSpinLock<Pl031Inner>>,
base: usize,
irq: IrqNumber,
}
@@ -88,7 +88,7 @@ impl Device for Pl031 {
inner.regs.MR.set(inner.regs.DR.get() + 1);
inner.regs.CR.modify(CR::RTCStart::SET);
self.inner.init(IrqSafeNullLock::new(inner));
self.inner.init(IrqSafeSpinLock::new(inner));
Ok(())
}
+4 -3
View File
@@ -7,7 +7,7 @@ use crate::dev::{
Device,
};
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use core::fmt;
use error::Errno;
@@ -77,7 +77,7 @@ struct Pl011Inner {
/// Device struct for PL011
pub struct Pl011 {
inner: InitOnce<IrqSafeNullLock<Pl011Inner>>,
inner: InitOnce<IrqSafeSpinLock<Pl011Inner>>,
base: usize,
irq: IrqNumber,
}
@@ -134,6 +134,7 @@ impl IntSource for Pl011 {
inner.regs.ICR.write(ICR::ALL::CLEAR);
let byte = inner.regs.DR.get();
drop(inner);
debugln!("irq byte = {:#04x}", byte);
Ok(())
@@ -176,7 +177,7 @@ impl Device for Pl011 {
};
inner.enable();
self.inner.init(IrqSafeNullLock::new(inner));
self.inner.init(IrqSafeSpinLock::new(inner));
Ok(())
}
+3 -3
View File
@@ -1,6 +1,6 @@
//! Kernel heap allocation facilities
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
use core::alloc::{GlobalAlloc, Layout};
use core::ptr::null_mut;
@@ -49,7 +49,7 @@ fn alloc_error_handler(layout: Layout) -> ! {
#[global_allocator]
static SYSTEM_ALLOC: SystemAlloc = SystemAlloc;
static HEAP: InitOnce<IrqSafeNullLock<Heap>> = InitOnce::new();
static HEAP: InitOnce<IrqSafeSpinLock<Heap>> = InitOnce::new();
/// Initializes kernel heap with virtual `base` address and `size`.
///
@@ -61,5 +61,5 @@ pub unsafe fn init(base: usize, size: usize) {
infoln!("Kernel heap: {:#x}..{:#x}", base, base + size);
HEAP.init(IrqSafeNullLock::new(heap));
HEAP.init(IrqSafeSpinLock::new(heap));
}
+2 -2
View File
@@ -1,6 +1,6 @@
use super::{PageInfo, PageUsage};
use crate::mem::{virtualize, PAGE_SIZE};
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use core::mem;
use error::Errno;
@@ -73,4 +73,4 @@ unsafe impl Manager for SimpleManager {
}
}
pub(super) static MANAGER: IrqSafeNullLock<Option<SimpleManager>> = IrqSafeNullLock::new(None);
pub(super) static MANAGER: IrqSafeSpinLock<Option<SimpleManager>> = IrqSafeSpinLock::new(None);
+3 -3
View File
@@ -1,7 +1,7 @@
//! Process and thread manipulation facilities
use crate::mem;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use alloc::{
boxed::Box,
collections::{BTreeMap},
@@ -42,8 +42,8 @@ pub fn switch() {
}
/// Global list of all processes in the system
pub(self) static PROCESSES: IrqSafeNullLock<BTreeMap<Pid, ProcessRef>> =
IrqSafeNullLock::new(BTreeMap::new());
pub(self) static PROCESSES: IrqSafeSpinLock<BTreeMap<Pid, ProcessRef>> =
IrqSafeSpinLock::new(BTreeMap::new());
/// Sets up initial process and enters it.
///
+3 -12
View File
@@ -5,7 +5,7 @@ use crate::mem::{
virt::{MapAttributes, Space},
};
use crate::proc::{PROCESSES, SCHED};
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use alloc::rc::Rc;
use core::cell::UnsafeCell;
use core::fmt;
@@ -51,7 +51,7 @@ struct ProcessInner {
#[allow(dead_code)]
pub struct Process {
ctx: UnsafeCell<Context>,
inner: IrqSafeNullLock<ProcessInner>,
inner: IrqSafeSpinLock<ProcessInner>,
}
impl From<i32> for ExitCode {
@@ -141,9 +141,6 @@ impl Process {
proc.inner.lock().state = State::Running;
let ctx = proc.ctx.get();
// I don't think this is bad: process can't be dropped fully unless
// it's been reaped (and this function won't run for such process)
drop(proc);
(&mut *ctx).enter()
}
@@ -171,10 +168,6 @@ impl Process {
let src_ctx = src.ctx.get();
let dst_ctx = dst.ctx.get();
// See "drop" note in Process::enter()
drop(src);
drop(dst);
(&mut *src_ctx).switch(&mut *dst_ctx);
}
@@ -188,7 +181,7 @@ impl Process {
let id = Pid::new_kernel();
let res = Rc::new(Self {
ctx: UnsafeCell::new(Context::kernel(entry as usize, arg)),
inner: IrqSafeNullLock::new(ProcessInner {
inner: IrqSafeSpinLock::new(ProcessInner {
id,
exit: None,
space: None,
@@ -238,7 +231,6 @@ impl Process {
debugln!("r = {}", Rc::strong_count(&proc));
return Ok(r);
} else {
drop(proc);
cortex_a::asm::wfi();
}
}
@@ -312,7 +304,6 @@ impl Process {
drop(lock);
drop(proc);
(*ctx).enter();
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
//!
use crate::proc::{Pid, Process, ProcessRef, PROCESSES};
use crate::util::InitOnce;
use crate::sync::IrqSafeNullLock;
use crate::sync::IrqSafeSpinLock;
use alloc::{rc::Rc, collections::VecDeque};
struct SchedulerInner {
@@ -12,7 +12,7 @@ struct SchedulerInner {
/// Process scheduler state and queues
pub struct Scheduler {
inner: InitOnce<IrqSafeNullLock<SchedulerInner>>,
inner: InitOnce<IrqSafeSpinLock<SchedulerInner>>,
}
impl SchedulerInner {
@@ -35,7 +35,7 @@ impl Scheduler {
/// * idle thread
/// * process list/queue data structs
pub fn init(&self) {
self.inner.init(IrqSafeNullLock::new(SchedulerInner::new()));
self.inner.init(IrqSafeSpinLock::new(SchedulerInner::new()));
}
/// Schedules a thread for execution
+37 -16
View File
@@ -1,63 +1,84 @@
//! Synchronization facilities module
use crate::arch::platform::{irq_mask_save, irq_restore};
use core::sync::atomic::{AtomicBool, Ordering};
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
/// Lock structure ensuring IRQs are disabled when inner value is accessed
pub struct IrqSafeNullLock<T: ?Sized> {
pub struct IrqSafeSpinLock<T> {
value: UnsafeCell<T>,
state: AtomicBool
}
/// Guard-structure wrapping a reference to value owned by [IrqSafeNullLock].
/// Guard-structure wrapping a reference to value owned by [IrqSafeSpinLock].
/// Restores saved IRQ state when dropped.
pub struct IrqSafeNullLockGuard<'a, T: ?Sized> {
value: &'a mut T,
pub struct IrqSafeSpinLockGuard<'a, T> {
lock: &'a IrqSafeSpinLock<T>,
irq_state: u64,
}
impl<T> IrqSafeNullLock<T> {
impl<T> IrqSafeSpinLock<T> {
/// Constructs a new instance of the lock, wrapping `value`
#[inline(always)]
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(value),
state: AtomicBool::new(false)
}
}
/// Returns [IrqSafeNullLockGuard] for this lock
#[inline(always)]
fn try_lock(&self) -> Result<bool, bool> {
self.state.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
}
#[inline(always)]
unsafe fn force_release(&self) {
self.state.store(false, Ordering::Release);
cortex_a::asm::sev();
}
/// Returns [IrqSafeSpinLockGuard] for this lock
#[inline]
pub fn lock(&self) -> IrqSafeNullLockGuard<T> {
pub fn lock(&self) -> IrqSafeSpinLockGuard<T> {
let irq_state = unsafe { irq_mask_save() };
while self.try_lock().is_err() {
cortex_a::asm::wfe();
}
unsafe {
IrqSafeNullLockGuard {
value: &mut *self.value.get(),
irq_state: irq_mask_save(),
IrqSafeSpinLockGuard {
lock: self,
irq_state
}
}
}
}
impl<T: ?Sized> Deref for IrqSafeNullLockGuard<'_, T> {
impl<T> Deref for IrqSafeSpinLockGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.value
unsafe { &*self.lock.value.get() }
}
}
impl<T: ?Sized> DerefMut for IrqSafeNullLockGuard<'_, T> {
impl<T> DerefMut for IrqSafeSpinLockGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
unsafe { &mut *self.lock.value.get() }
}
}
impl<T: ?Sized> Drop for IrqSafeNullLockGuard<'_, T> {
impl<T> Drop for IrqSafeSpinLockGuard<'_, T> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
self.lock.force_release();
irq_restore(self.irq_state);
}
}
}
unsafe impl<T: ?Sized> Sync for IrqSafeNullLock<T> {}
unsafe impl<T> Sync for IrqSafeSpinLock<T> {}