Nothing to see here, move along
at main 187 lines 5.1 kB view raw
1use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; 2 3use lancer_core::ipc::{MAX_IPC_BYTES, pack_bytes}; 4 5static STDOUT_SLOT: AtomicU64 = AtomicU64::new(u64::MAX); 6static DEBUG_PRINT_ENABLED: AtomicBool = AtomicBool::new(true); 7 8pub fn set_debug_print_enabled(enabled: bool) { 9 DEBUG_PRINT_ENABLED.store(enabled, Ordering::Relaxed); 10} 11 12pub fn debug_print_enabled() -> bool { 13 DEBUG_PRINT_ENABLED.load(Ordering::Relaxed) 14} 15 16const PARENT_NOTIF_SLOT: u64 = 5; 17const NOTIFY_BIT_CHILD_IPC: u64 = 0x200; 18 19pub fn set_stdout_slot(slot: u64) { 20 STDOUT_SLOT.store(slot, Ordering::Relaxed); 21} 22 23pub fn signal_parent() { 24 let _ = crate::syscall::notify_signal(PARENT_NOTIF_SLOT, NOTIFY_BIT_CHILD_IPC); 25} 26 27pub struct Stdout; 28 29impl core::fmt::Write for Stdout { 30 fn write_str(&mut self, s: &str) -> core::fmt::Result { 31 if DEBUG_PRINT_ENABLED.load(Ordering::Relaxed) { 32 crate::syscall::debug_print(s); 33 } 34 let slot = STDOUT_SLOT.load(Ordering::Relaxed); 35 match slot { 36 u64::MAX => {} 37 _ => s.as_bytes().chunks(MAX_IPC_BYTES).for_each(|chunk| { 38 let msg = pack_bytes(chunk); 39 let _ = crate::syscall::send(slot, msg); 40 }), 41 } 42 Ok(()) 43 } 44} 45 46pub fn write_bytes(data: &[u8]) { 47 let debug = DEBUG_PRINT_ENABLED.load(Ordering::Relaxed); 48 let slot = STDOUT_SLOT.load(Ordering::Relaxed); 49 data.chunks(MAX_IPC_BYTES).for_each(|chunk| { 50 if debug 51 && let Ok(s) = core::str::from_utf8(chunk) 52 { 53 crate::syscall::debug_print(s); 54 } 55 match slot { 56 u64::MAX => {} 57 _ => { 58 let msg = pack_bytes(chunk); 59 let _ = crate::syscall::send(slot, msg); 60 } 61 } 62 }); 63} 64 65const LOG_BUF_LEN: usize = 256; 66 67pub struct LogBuf { 68 buf: [u8; LOG_BUF_LEN], 69 pos: usize, 70} 71 72impl LogBuf { 73 pub const fn new() -> Self { 74 Self { 75 buf: [0u8; LOG_BUF_LEN], 76 pos: 0, 77 } 78 } 79 80 pub fn as_str(&self) -> &str { 81 unsafe { core::str::from_utf8_unchecked(&self.buf[..self.pos]) } 82 } 83} 84 85impl Default for LogBuf { 86 fn default() -> Self { 87 Self::new() 88 } 89} 90 91impl core::fmt::Write for LogBuf { 92 fn write_str(&mut self, s: &str) -> core::fmt::Result { 93 let bytes = s.as_bytes(); 94 let copy_len = bytes.len().min(LOG_BUF_LEN - self.pos); 95 self.buf[self.pos..self.pos + copy_len].copy_from_slice(&bytes[..copy_len]); 96 self.pos += copy_len; 97 Ok(()) 98 } 99} 100 101#[macro_export] 102macro_rules! log { 103 ($domain:ident, error, $($arg:tt)*) => {{ 104 $crate::io::user_log(lancer_log::Severity::Error, format_args!($($arg)*)); 105 }}; 106 ($domain:ident, warn, $($arg:tt)*) => {{ 107 $crate::io::user_log(lancer_log::Severity::Warn, format_args!($($arg)*)); 108 }}; 109 ($domain:ident, $($arg:tt)*) => {{ 110 $crate::io::user_log(lancer_log::Severity::Info, format_args!($($arg)*)); 111 }}; 112} 113 114pub fn user_log(severity: lancer_log::Severity, message: core::fmt::Arguments<'_>) { 115 use core::fmt::Write; 116 let mut buf = LogBuf::new(); 117 let _ = write!(buf, "{}", message); 118 crate::syscall::log(severity.as_u8(), buf.as_str()); 119} 120 121#[macro_export] 122macro_rules! show { 123 ($domain:ident, error, $($arg:tt)*) => {{ 124 $crate::io::user_show( 125 stringify!($domain), 126 lancer_log::Severity::Error, 127 format_args!($($arg)*), 128 ); 129 }}; 130 ($domain:ident, warn, $($arg:tt)*) => {{ 131 $crate::io::user_show( 132 stringify!($domain), 133 lancer_log::Severity::Warn, 134 format_args!($($arg)*), 135 ); 136 }}; 137 ($domain:ident, $($arg:tt)*) => {{ 138 $crate::io::user_show( 139 stringify!($domain), 140 lancer_log::Severity::Info, 141 format_args!($($arg)*), 142 ); 143 }}; 144} 145 146pub fn stdout_ipc(s: &str) { 147 let slot = STDOUT_SLOT.load(Ordering::Relaxed); 148 match slot { 149 u64::MAX => {} 150 _ => s.as_bytes().chunks(MAX_IPC_BYTES).for_each(|chunk| { 151 let msg = pack_bytes(chunk); 152 let _ = crate::syscall::send(slot, msg); 153 }), 154 } 155} 156 157const GLASS_BIT: u8 = 0x80; 158 159pub fn user_show(domain: &str, severity: lancer_log::Severity, message: core::fmt::Arguments<'_>) { 160 use core::fmt::Write; 161 let mut plain = LogBuf::new(); 162 let _ = write!(plain, "{}", message); 163 crate::syscall::log(severity.as_u8() | GLASS_BIT, plain.as_str()); 164 let mut formatted = LogBuf::new(); 165 let _ = lancer_log::format::write_gutter(&mut formatted, domain, severity, message, USER_SHOW_GUTTER); 166 let _ = formatted.write_str("\n"); 167 stdout_ipc(formatted.as_str()); 168} 169 170const USER_SHOW_GUTTER: usize = 13; 171 172#[macro_export] 173macro_rules! print { 174 ($($arg:tt)*) => {{ 175 use core::fmt::Write; 176 let _ = write!($crate::io::Stdout, $($arg)*); 177 }}; 178} 179 180#[macro_export] 181macro_rules! println { 182 () => { $crate::print!("\n") }; 183 ($($arg:tt)*) => {{ 184 use core::fmt::Write; 185 let _ = writeln!($crate::io::Stdout, $($arg)*); 186 }}; 187}