kernel/kprint/
ringbuffer.rs1use crate::kprint::log_entry::{LogEntryHeader, LogFlags, LogLevel};
7use crate::lib::types::packed_u8::PackedU8;
8
9pub struct Ringbuffer {
11 seq: u64,
12 buffer: [u8; Self::SIZE],
13 head: usize,
14 tail: usize
15}
16
17impl Ringbuffer {
18 pub const SIZE: usize = 1 << 20;
20
21 pub const fn new() -> Self {
23 Self {
24 seq: 0,
25 buffer: [0u8; Self::SIZE],
26 head: 0,
27 tail: 0
28 }
29 }
30
31 pub fn write_entry(
33 &mut self,
34 log_level: LogLevel,
35 log_flags: LogFlags,
36 text: &[u8]
37 ) -> LogEntryHeader {
38 use super::log_entry::LogEntryHeader;
39
40 let seq = self.seq;
41 self.seq += 1;
42
43 let ts_nsec = 0;
45
46 let mut flags_and_level = PackedU8::default();
47 flags_and_level.set(
48 LogEntryHeader::FLAGS_START_BIT,
49 LogEntryHeader::FLAGS_NUM_BITS,
50 log_flags.as_u8()
51 );
52 flags_and_level.set(
53 LogEntryHeader::LEVEL_START_BIT,
54 LogEntryHeader::LEVEL_NUM_BITS,
55 log_level as u8
56 );
57
58 let header = LogEntryHeader {
59 seq,
60 ts_nsec,
61 text_len: text.len() as u16,
62 flags_and_level
63 };
64 let header_bytes = unsafe {
65 core::slice::from_raw_parts(
66 &raw const header as *const u8,
67 size_of::<LogEntryHeader>()
68 )
69 };
70
71 self.write_bytes(header_bytes);
72 self.write_bytes(text);
73
74 header
75 }
76
77 fn write_bytes(&mut self, bytes: &[u8]) {
79 for byte in bytes {
80 self.buffer[self.head % Self::SIZE] = *byte;
81 self.head = self.head.wrapping_add(1);
82
83 if self.head.wrapping_sub(self.tail) > Self::SIZE {
84 self.advance_tail();
85 }
86 }
87 }
88
89 fn advance_tail(&mut self) {
91 let header_size = size_of::<LogEntryHeader>();
92
93 let lo = self.buffer[(self.tail + 16) % Self::SIZE];
94 let hi = self.buffer[(self.tail + 17) % Self::SIZE];
95 let text_len = u16::from_ne_bytes([lo, hi]) as usize;
96
97 self.tail = self.tail.wrapping_add(header_size + text_len);
98 }
99}