twizzler_io/
packet.rs

1use std::cell::UnsafeCell;
2
3use bitset_core::BitSet;
4use twizzler::{
5    BaseType, Invariant,
6    error::TwzError,
7    object::{ObjID, Object, ObjectBuilder, RawObject, TypedObject},
8};
9use twizzler_abi::{object::NULLPAGE_SIZE, syscall::ObjectCreate};
10
11pub const MAX_PACKET_BITS: usize = 1024;
12pub const MIN_PACKET_SIZE: usize = 32;
13
14#[derive(Invariant, BaseType)]
15pub struct PacketBufferBase {
16    nr_packets: usize,
17    packet_size: usize,
18    bitmap: UnsafeCell<[u8; MAX_PACKET_BITS]>,
19}
20
21impl PacketBufferBase {
22    fn packet_mem_offset_from_base(&self) -> usize {
23        (size_of::<PacketBufferBase>()).next_multiple_of(MIN_PACKET_SIZE.max(self.packet_size))
24    }
25
26    fn get_bitmap_mut(&self) -> &mut [u8; MAX_PACKET_BITS] {
27        unsafe { self.bitmap.get().as_mut().unwrap() }
28    }
29
30    fn allocate_packet(&self) -> Option<usize> {
31        let bm = self.get_bitmap_mut();
32        for i in 0..bm.bit_len().min(self.nr_packets) {
33            if !bm.bit_test(i) {
34                bm.bit_set(i);
35                return Some(i);
36            }
37        }
38        None
39    }
40
41    fn release_packet(&self, packet: usize) {
42        let bm = self.get_bitmap_mut();
43        assert!(bm.bit_test(packet));
44        bm.bit_reset(packet);
45    }
46}
47
48#[derive(Clone)]
49pub struct PacketObject {
50    obj: Object<PacketBufferBase>,
51}
52
53impl From<Object<PacketBufferBase>> for PacketObject {
54    fn from(obj: Object<PacketBufferBase>) -> Self {
55        Self { obj }
56    }
57}
58
59impl PacketObject {
60    pub fn id(&self) -> ObjID {
61        self.obj.id()
62    }
63
64    pub fn object(&self) -> &Object<PacketBufferBase> {
65        &self.obj
66    }
67
68    pub fn new(
69        spec: ObjectCreate,
70        nr_packets: usize,
71        packet_size: usize,
72    ) -> Result<Self, TwzError> {
73        Ok(Self::from(ObjectBuilder::new(spec).build(
74            PacketBufferBase {
75                nr_packets,
76                packet_size,
77                bitmap: UnsafeCell::new([0; _]),
78            },
79        )?))
80    }
81
82    pub fn packet_size(&self) -> usize {
83        self.obj.base().packet_size.max(MIN_PACKET_SIZE)
84    }
85
86    pub fn packet_offset(&self, id: u32) -> usize {
87        let offset =
88            self.obj.base().packet_mem_offset_from_base() + (id as usize * self.packet_size());
89        offset + NULLPAGE_SIZE
90    }
91
92    pub fn packet_mem(&self, id: u32) -> &[u8] {
93        let offset =
94            self.obj.base().packet_mem_offset_from_base() + (id as usize * self.packet_size());
95        let ptr = self
96            .obj
97            .lea(offset + NULLPAGE_SIZE, self.packet_size())
98            .unwrap();
99        unsafe { core::slice::from_raw_parts(ptr, self.packet_size()) }
100    }
101
102    pub fn packet_mem_mut(&self, id: u32) -> &mut [u8] {
103        let offset =
104            self.obj.base().packet_mem_offset_from_base() + (id as usize * self.packet_size());
105        let ptr = self
106            .obj
107            .lea_mut(offset + NULLPAGE_SIZE, self.packet_size())
108            .unwrap();
109        unsafe { core::slice::from_raw_parts_mut(ptr, self.packet_size()) }
110    }
111
112    pub fn allocate_packet(&self) -> Option<u32> {
113        self.obj
114            .base()
115            .allocate_packet()
116            .map(|x| x.try_into().ok())
117            .flatten()
118    }
119
120    pub fn release_packet(&self, id: u32) {
121        if let Ok(id) = id.try_into() {
122            self.obj.base().release_packet(id);
123        }
124    }
125}