#![no_implicit_prelude]
extern crate core;
extern crate rpsp;
mod block;
mod device;
mod volume;
use core::cell::UnsafeCell;
use core::marker::Sync;
use core::mem::forget;
use core::ops::{Deref, DerefMut, Drop};
use core::ptr::NonNull;
use rpsp::locks::{Spinlock28, Spinlock29, Spinlock30};
pub use self::block::*;
pub use self::device::*;
pub use self::volume::*;
static CACHE: Cache = Cache::new();
pub struct BlockPtr(NonNull<Block>);
struct CacheInner {
a: Block,
b: Block,
lfn: LongName,
}
struct Cache(UnsafeCell<CacheInner>);
struct LongNamePtr(NonNull<LongName>);
impl Cache {
#[inline]
const fn new() -> Cache {
Cache(UnsafeCell::new(CacheInner {
a: Block::new(),
b: Block::new(),
lfn: LongName::empty(),
}))
}
#[inline]
fn lfn() -> LongNamePtr {
let c = Spinlock30::claim();
forget(c);
LongNamePtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).lfn) })
}
#[inline]
fn block_a() -> BlockPtr {
let c = Spinlock29::claim();
forget(c);
BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).a) })
}
#[inline]
fn block_b() -> BlockPtr {
let c = Spinlock28::claim();
forget(c);
BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).b) })
}
#[inline]
unsafe fn block_a_nolock() -> BlockPtr {
BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).a) })
}
}
impl Drop for BlockPtr {
#[inline]
fn drop(&mut self) {
if unsafe { self.0.as_ref() }.as_ptr() == unsafe { (*CACHE.0.get()).a.as_ptr() } {
unsafe { Spinlock29::free() }
} else {
unsafe { Spinlock28::free() }
}
}
}
impl Deref for BlockPtr {
type Target = Block;
#[inline]
fn deref(&self) -> &Block {
unsafe { self.0.as_ref() }
}
}
impl DerefMut for BlockPtr {
#[inline]
fn deref_mut(&mut self) -> &mut Block {
unsafe { &mut *self.0.as_ptr() }
}
}
impl Drop for LongNamePtr {
#[inline]
fn drop(&mut self) {
unsafe { Spinlock30::free() }
}
}
impl Deref for LongNamePtr {
type Target = LongName;
#[inline]
fn deref(&self) -> &LongName {
unsafe { self.0.as_ref() }
}
}
impl DerefMut for LongNamePtr {
#[inline]
fn deref_mut(&mut self) -> &mut LongName {
unsafe { &mut *self.0.as_ptr() }
}
}
unsafe impl Sync for Cache {}