Skip to content
Snippets Groups Projects
Commit 3d3557f9 authored by Per Lindgren's avatar Per Lindgren
Browse files

pool using cs

parent 79eb089e
No related branches found
No related tags found
No related merge requests found
......@@ -7,3 +7,4 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cortex-m = "0.7.2"
#![no_std]
use core::cell::UnsafeCell;
use core::mem;
use core::ops::{Deref, DerefMut, Drop};
use cortex_m::interrupt;
/// Internal replacement for `static mut T`
// TODO: Decide name and location.
......@@ -22,8 +23,26 @@ impl<T> RacyCell<T> {
//unsafe impl<T> Sync for RacyCell<T> where T: Sync {}
unsafe impl<T> Sync for RacyCell<T> {}
struct Box<T: 'static + Sized, const S: usize> {
// data: &'static mut T,
#[inline]
pub fn interrupt_free<F, R>(f: F) -> R
where
F: FnOnce() -> R,
{
if cfg!(target_arch = "arm") {
interrupt::free(|_| f())
} else {
f()
}
}
#[derive(Debug)]
pub enum Error {
Uninitialized,
OutOfMemory,
AlreadyInitialized,
}
pub struct Box<T: 'static + Sized, const S: usize> {
index: usize,
allocator: &'static PoolMan<T, S>,
}
......@@ -37,18 +56,27 @@ impl<T: 'static, const S: usize> Drop for Box<T, S> {
impl<T: 'static, const S: usize> Deref for Box<T, S> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &self.allocator.data.get_mut_unchecked()[self.index] }
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked(self.index)
}
}
}
impl<T: 'static, const S: usize> DerefMut for Box<T, S> {
// type Target = T;
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut self.allocator.data.get_mut_unchecked()[self.index] }
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked_mut(self.index)
}
}
}
struct PoolMan<T: 'static, const S: usize> {
pub struct PoolMan<T: 'static, const S: usize> {
data: RacyCell<[T; S]>,
free: RacyCell<[usize; S]>,
head: RacyCell<usize>,
......@@ -59,7 +87,7 @@ impl<T, const S: usize> PoolMan<T, S>
where
T: Sized,
{
const fn new(v: [T; S]) -> Self
pub const fn new(v: [T; S]) -> Self
where
T: Sized,
{
......@@ -71,64 +99,57 @@ where
}
}
fn init(&self) {
let free = unsafe { self.free.get_mut_unchecked() };
for (index, value) in free.iter_mut().enumerate() {
*value = index + 1;
}
*unsafe { self.init.get_mut_unchecked() } = true;
println!("init : free {:?}", unsafe { self.free.get_mut_unchecked() });
#[inline]
pub fn init(&self) -> Result<(), Error> {
interrupt_free(|| {
if *unsafe { self.init.get_mut_unchecked() } {
Err(Error::AlreadyInitialized)
} else {
let free = unsafe { self.free.get_mut_unchecked() };
for (index, value) in free.iter_mut().enumerate() {
*value = index + 1;
}
*unsafe { self.init.get_mut_unchecked() } = true;
Ok(())
}
})
}
// Safety:
// dealloc can only be called by dropping Box
// which can happen only if already initialized
// thus it is safe to assume init == true
//
// not accissible from user code
#[inline]
fn dealloc(&self, index: usize) {
unsafe {
if !*self.init.get_mut_unchecked() {
panic!();
}
self.free.get_mut_unchecked()[index] = *self.head.get_mut_unchecked();
interrupt_free(|| unsafe {
*self.free.get_mut_unchecked().get_unchecked_mut(index) =
*self.head.get_mut_unchecked();
*self.head.get_mut_unchecked() = index;
}
println!("dealloc index {}", index)
});
}
fn alloc(&'static self) -> Result<Box<T, S>, ()> {
unsafe {
if !*self.init.get_mut_unchecked() {
panic!();
}
let index = *self.head.get_mut_unchecked();
println!("index {}", self.head.get_mut_unchecked());
println!("head {}", self.head.get_mut_unchecked());
*self.head.get_mut_unchecked() = self.free.get_mut_unchecked()[index];
println!("new head {}", self.head.get_mut_unchecked());
if *self.head.get_mut_unchecked() > S {
Err(())
} else {
Ok(Box {
index,
allocator: self,
})
}
#[inline]
pub fn alloc(&'static self) -> Result<Box<T, S>, Error> {
// this check does not need to be inside of critical section
// as initialization is monotonic, cannot be undone
if !unsafe { *self.init.get_mut_unchecked() } {
Err(Error::Uninitialized)
} else {
interrupt_free(|| unsafe {
let index = *self.head.get_mut_unchecked();
*self.head.get_mut_unchecked() =
*self.free.get_mut_unchecked().get_unchecked(index);
if *self.head.get_mut_unchecked() > S {
Err(Error::OutOfMemory)
} else {
Ok(Box {
index,
allocator: self,
})
}
})
}
}
}
static P: PoolMan<u32, 2> = PoolMan::new([0; 2]);
fn main() {
P.init();
{
let e = P.alloc().unwrap();
println!("e {}", *e);
mem::drop(e);
let mut e1 = P.alloc().unwrap();
println!("e1 {}", *e1);
*e1 = 2;
println!("e1 {}", *e1);
let e2 = P.alloc().unwrap();
println!("e2 {}", *e2);
}
let e = P.alloc().unwrap();
println!("e {}", *e);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment