Skip to main content

dma_api/
pool.rs

1use core::ops::{Deref, DerefMut};
2
3use alloc::{
4    collections::VecDeque,
5    sync::{Arc, Weak},
6};
7use spin::Mutex;
8
9use crate::{DArray, DeviceDma, DmaDirection, DmaError};
10
11#[derive(Clone, Debug)]
12pub(crate) struct DArrayConfig {
13    pub size: usize,
14    pub align: usize,
15    pub direction: DmaDirection,
16}
17
18#[derive(Clone)]
19pub struct DArrayPool {
20    inner: Arc<Mutex<Inner>>,
21}
22
23pub struct DBuff {
24    data: Option<DArray<u8>>,
25    pool: Weak<Mutex<Inner>>,
26}
27
28unsafe impl Send for DBuff {}
29
30impl Deref for DBuff {
31    type Target = DArray<u8>;
32
33    fn deref(&self) -> &Self::Target {
34        self.data.as_ref().unwrap()
35    }
36}
37
38impl DerefMut for DBuff {
39    fn deref_mut(&mut self) -> &mut Self::Target {
40        self.data.as_mut().unwrap()
41    }
42}
43
44impl Drop for DBuff {
45    fn drop(&mut self) {
46        if let Some(data) = self.data.take()
47            && let Some(pool) = self.pool.upgrade()
48        {
49            let mut inner = pool.lock();
50            inner.dealloc(data);
51        }
52    }
53}
54
55struct Inner {
56    dev: DeviceDma,
57    config: DArrayConfig,
58    pool: VecDeque<DArray<u8>>,
59}
60
61impl Inner {
62    fn alloc(&mut self) -> Option<DArray<u8>> {
63        self.pool.pop_front()
64    }
65
66    fn dealloc(&mut self, dvec: DArray<u8>) {
67        self.pool.push_back(dvec);
68    }
69}
70
71impl DArrayPool {
72    pub(crate) fn new_pool(dev: DeviceDma, config: DArrayConfig, cap: usize) -> DArrayPool {
73        let mut pool = VecDeque::with_capacity(cap);
74        for _ in 0..cap {
75            if let Ok(dvec) =
76                // DArray::zeros(config.dma_mask, config.size, config.align, config.direction)
77                DArray::new_zero_with_align(
78                    &dev,
79                    config.size,
80                    config.align,
81                    config.direction,
82                )
83            {
84                pool.push_back(dvec);
85            }
86        }
87
88        DArrayPool {
89            inner: Arc::new(Mutex::new(Inner { dev, pool, config })),
90        }
91    }
92
93    pub fn alloc(&self) -> Result<DBuff, DmaError> {
94        let config;
95        let dev;
96        {
97            let mut inner = self.inner.lock();
98            if let Some(dvec) = inner.alloc() {
99                return Ok(DBuff {
100                    data: Some(dvec),
101                    pool: Arc::downgrade(&self.inner),
102                });
103            } else {
104                config = inner.config.clone();
105                dev = inner.dev.clone();
106            }
107        };
108
109        let dvec = DArray::new_zero_with_align(&dev, config.size, config.align, config.direction)?;
110        Ok(DBuff {
111            data: Some(dvec),
112            pool: Arc::downgrade(&self.inner),
113        })
114    }
115}