summaryrefslogtreecommitdiffstats
path: root/rsnix/src/serial.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-01 17:38:57 +0200
committersalmonik <salmonik@tuta.io>2026-08-01 17:38:57 +0200
commit8f05ea44f69cb796e7b1f581ba1b8045c98d615b (patch)
tree3049f0a5fc33dd08f94af0e6493c588b2a4818b9 /rsnix/src/serial.rs
parentCONTEXT.md: versioning policy (a.b.c — overhaul/feature/fix) (diff)
downloadrs-dos-8f05ea44f69cb796e7b1f581ba1b8045c98d615b.tar.gz
rs-dos-8f05ea44f69cb796e7b1f581ba1b8045c98d615b.zip
rsnix: preemptive kernel tasks (ADR 0003) — sched, IST fault stacks, 176-byte frames
- sched: 16-slot static table, shell=task 0, idle=task 1, spawn with guard page + 8 KiB stack, RR on the 100 Hz tick, int 0x60 yield, sleep_ms, lazy reap, jobs/bg/sleep/kill shell commands - gdt: own GDT mirroring UEFI selectors + TSS with IST1/IST2 (guard-page overflows die gracefully instead of triple-faulting) - interrupts: isr_dispatch returns next frame in rax; IntFrame grows rsp/ss fields — QEMU's 64-bit iretq always pops all five slots from a 176-byte frame, so synthetic task frames must carry rsp=top+ss (a 160-byte frame made the first iretq pop rsp/ss from the unmapped page beyond the frame) - panic handler: task panics abort the task, shell keeps running - main: sched::init moved after page allocator + adopted tables (the idle's stack+guard need both; it was silently not spawning)
Diffstat (limited to 'rsnix/src/serial.rs')
-rw-r--r--rsnix/src/serial.rs35
1 files changed, 27 insertions, 8 deletions
diff --git a/rsnix/src/serial.rs b/rsnix/src/serial.rs
index 484a114..2267225 100644
--- a/rsnix/src/serial.rs
+++ b/rsnix/src/serial.rs
@@ -60,8 +60,17 @@ pub fn try_get_byte() -> Option<u8> {
60 } 60 }
61} 61}
62 62
63/// Write a string to serial. 63/// Write a string to serial, holding the scheduler lock for the whole
64/// write so a line can't be interleaved with another task's output.
64pub fn write_str(s: &str) { 65pub fn write_str(s: &str) {
66 crate::sched::lock();
67 write_raw(s);
68 crate::sched::unlock();
69}
70
71/// Raw serial write — no scheduler lock. Callers must hold the lock
72/// (klog::emit does) or be in a context where preemption is impossible.
73pub fn write_raw(s: &str) {
65 for &b in s.as_bytes() { 74 for &b in s.as_bytes() {
66 if b == b'\n' { 75 if b == b'\n' {
67 put_byte(b'\r'); 76 put_byte(b'\r');
@@ -70,6 +79,16 @@ pub fn write_str(s: &str) {
70 } 79 }
71} 80}
72 81
82/// One scheduler-locked call: the line plus its CRLF, atomic with
83/// respect to context switches (used by the shell's term_println, where
84/// the line and its newline must not be split by a tick).
85pub fn write_line(s: &str) {
86 crate::sched::lock();
87 write_raw(s);
88 write_raw("\r\n");
89 crate::sched::unlock();
90}
91
73// --------------------------------------------------------------------------- 92// ---------------------------------------------------------------------------
74// fmt::Write implementation 93// fmt::Write implementation
75// --------------------------------------------------------------------------- 94// ---------------------------------------------------------------------------
@@ -96,17 +115,17 @@ macro_rules! serial_print {
96/// here, so the ring captures the whole boot sequence for free. 115/// here, so the ring captures the whole boot sequence for free.
97/// User-facing shell output must NOT use this macro (shell output would 116/// User-facing shell output must NOT use this macro (shell output would
98/// pollute the boot log); it writes to the serial port directly. 117/// pollute the boot log); it writes to the serial port directly.
118///
119/// The whole line is formatted, written, and logged under one scheduler
120/// lock (klog::emit), so lines from different tasks never interleave.
99#[macro_export] 121#[macro_export]
100macro_rules! serial_println { 122macro_rules! serial_println {
101 () => { 123 () => {
102 $crate::serial::write_str("\r\n"); 124 $crate::klog::emit(core::format_args!(""))
103 $crate::klog::append_fmt(core::format_args!("")); 125 };
126 ($($arg:tt)*) => {
127 $crate::klog::emit(core::format_args!($($arg)*))
104 }; 128 };
105 ($($arg:tt)*) => {{
106 $crate::serial_print!($($arg)*);
107 $crate::serial::write_str("\r\n");
108 $crate::klog::append_fmt(core::format_args!($($arg)*));
109 }};
110} 129}
111 130
112// --------------------------------------------------------------------------- 131// ---------------------------------------------------------------------------