diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-01 17:38:57 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-01 17:38:57 +0200 |
| commit | 8f05ea44f69cb796e7b1f581ba1b8045c98d615b (patch) | |
| tree | 3049f0a5fc33dd08f94af0e6493c588b2a4818b9 /rsnix/src/klog.rs | |
| parent | CONTEXT.md: versioning policy (a.b.c — overhaul/feature/fix) (diff) | |
| download | rs-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/klog.rs')
| -rw-r--r-- | rsnix/src/klog.rs | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/rsnix/src/klog.rs b/rsnix/src/klog.rs index 0c7dc06..5da5094 100644 --- a/rsnix/src/klog.rs +++ b/rsnix/src/klog.rs | |||
| @@ -79,16 +79,19 @@ pub fn append(line: &str, mut ms: u64) { | |||
| 79 | r.seq += 1; | 79 | r.seq += 1; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | /// Append the formatted output of a `serial_println!` — the macro hook. | 82 | /// Format one serial line, write it to the serial port, and append it |
| 83 | /// `fmt::Write` may deliver the line in several chunks, so accumulate | 83 | /// to the ring — all under the scheduler lock, so a line from one task |
| 84 | /// into one line buffer first, then append the whole line. The | 84 | /// never interleaves with another task's line (line atomicity). |
| 85 | /// timestamp is taken when the line is emitted (monotonic ms since | 85 | /// `serial_println!` funnels through here. |
| 86 | /// boot, from the PIT tick + live-counter interpolation). | 86 | pub fn emit(args: core::fmt::Arguments<'_>) { |
| 87 | pub fn append_fmt(args: core::fmt::Arguments<'_>) { | ||
| 88 | let ms = crate::interrupts::uptime_ms(); | ||
| 89 | let mut line = LineBuf::new(); | 87 | let mut line = LineBuf::new(); |
| 90 | let _ = core::fmt::write(&mut line, args); | 88 | let _ = core::fmt::write(&mut line, args); |
| 89 | let ms = crate::interrupts::uptime_ms(); | ||
| 90 | crate::sched::lock(); | ||
| 91 | crate::serial::write_raw(line.as_str()); | ||
| 92 | crate::serial::write_raw("\r\n"); | ||
| 91 | append(line.as_str(), ms); | 93 | append(line.as_str(), ms); |
| 94 | crate::sched::unlock(); | ||
| 92 | } | 95 | } |
| 93 | 96 | ||
| 94 | struct LineBuf { | 97 | struct LineBuf { |
