1#![no_implicit_prelude]
21
22extern crate core;
23extern crate rpsp;
24
25mod block;
26mod device;
27mod volume;
28
29use core::cell::UnsafeCell;
30use core::marker::Sync;
31use core::mem::forget;
32use core::ops::{Deref, DerefMut, Drop};
33use core::ptr::NonNull;
34
35use rpsp::locks::{Spinlock28, Spinlock29, Spinlock30};
36
37pub use self::block::*;
38pub use self::device::*;
39pub use self::volume::*;
40
41static CACHE: Cache = Cache::new();
52
53pub struct BlockPtr(NonNull<Block>);
54
55struct CacheInner {
56 lfn: LongName,
57 block_a: Block,
58 block_b: Block,
59}
60struct Cache(UnsafeCell<CacheInner>);
61struct LongNamePtr(NonNull<LongName>);
62
63impl Cache {
64 #[inline(always)]
65 const fn new() -> Cache {
66 Cache(UnsafeCell::new(CacheInner {
67 lfn: LongName::empty(),
68 block_a: Block::new(),
69 block_b: Block::new(),
70 }))
71 }
72
73 #[inline(always)]
74 fn lfn() -> LongNamePtr {
75 let c = Spinlock30::claim();
76 forget(c);
77 LongNamePtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).lfn) })
78 }
79 #[inline(always)]
80 fn block_a() -> BlockPtr {
81 let c = Spinlock29::claim();
82 forget(c);
83 BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).block_a) })
84 }
85 #[inline(always)]
86 fn block_b() -> BlockPtr {
87 let c = Spinlock28::claim();
88 forget(c);
89 BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).block_b) })
90 }
91
92 #[inline(always)]
93 unsafe fn block_a_nolock() -> BlockPtr {
94 BlockPtr(unsafe { NonNull::new_unchecked(&mut (&mut *CACHE.0.get()).block_a) })
95 }
96}
97
98impl Drop for BlockPtr {
99 #[inline(always)]
100 fn drop(&mut self) {
101 if unsafe { self.0.as_ref() }.as_ptr() == unsafe { (*CACHE.0.get()).block_a.as_ptr() } {
102 unsafe { Spinlock29::free() }
103 } else {
104 unsafe { Spinlock28::free() }
105 }
106 }
107}
108impl Deref for BlockPtr {
109 type Target = Block;
110
111 #[inline(always)]
112 fn deref(&self) -> &Block {
113 unsafe { self.0.as_ref() }
114 }
115}
116impl DerefMut for BlockPtr {
117 #[inline(always)]
118 fn deref_mut(&mut self) -> &mut Block {
119 unsafe { &mut *self.0.as_ptr() }
120 }
121}
122
123impl Drop for LongNamePtr {
124 #[inline(always)]
125 fn drop(&mut self) {
126 unsafe { Spinlock30::free() }
127 }
128}
129impl Deref for LongNamePtr {
130 type Target = LongName;
131
132 #[inline(always)]
133 fn deref(&self) -> &LongName {
134 unsafe { self.0.as_ref() }
135 }
136}
137impl DerefMut for LongNamePtr {
138 #[inline(always)]
139 fn deref_mut(&mut self) -> &mut LongName {
140 unsafe { &mut *self.0.as_ptr() }
141 }
142}
143
144unsafe impl Sync for Cache {}