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}