bug pass: whole console lines, a quiet SCI, an honest reserve warning

- schinit, schinitd and vgpud build every message from pieces, one
  write() each, so a job starting on another CPU landed mid-line:
  "schinitd: starting vgpud: os.schos.resolvconfno virtio-gpu on this
  machine". They now collect a line and write it at the newline;
  resolvconf's verbose line is one write with its prefix.
- The ACPI SCI registers IRQ_QUIET. A desktop's SCI never fires, and the
  poller took two seconds of silence for a misrouted line ("irq 9:
  nothing has arrived on it") and called the handler every tick. A line
  is only exempt while every handler on it is quiet.
- The loader claims each segment from where the last one's claim ended,
  so two segments sharing a page no longer ask for it twice. When a
  claim is still refused, it names the memory-map entries in the way.
- Stale divesymlink() declaration gone; the kernel.md struct table
  re-measured (inode, buf and file pools grow from slabs now).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 16:03:33 +02:00
commit e659c6b187
10 changed files with 184 additions and 25 deletions

View file

@ -13,6 +13,7 @@ struct irq_action {
void *arg;
const char *name;
uint64 count;
int quiet; // registered IRQ_QUIET
};
static struct {
@ -22,6 +23,7 @@ static struct {
int level_low;
int msi; // an MSI vector, not an IOAPIC pin: nothing to route
int polled; // handlers run from irq_poll_thread as well
int nquiet; // handlers registered IRQ_QUIET
uint64 delivered; // real interrupts, not polls
uint64 since; // ticks when the first handler was attached
uint64 unhandled;
@ -65,7 +67,9 @@ irq_register(int irq, irq_handler_t fn, void *arg, const char *name,
int level_low)
{
struct irq_action *a;
int quiet = (level_low & IRQ_QUIET) != 0;
level_low &= ~IRQ_QUIET;
if(irq < 0 || irq >= NIRQ || fn == 0)
return -1;
if(reserved(irq)){
@ -95,8 +99,10 @@ irq_register(int irq, irq_handler_t fn, void *arg, const char *name,
a->arg = arg;
a->name = name;
a->count = 0;
a->quiet = quiet;
__sync_synchronize(); // publish the entry before it is reachable
line[irq].n++;
line[irq].nquiet += quiet;
if(line[irq].n == 1)
line[irq].since = ticks;
@ -133,6 +139,7 @@ irq_unregister(int irq, irq_handler_t fn, void *arg)
ioapicmask(irq);
line[irq].enabled = 0;
line[irq].nquiet -= line[irq].act[i].quiet;
for(j = i; j + 1 < line[irq].n; j++)
line[irq].act[j] = line[irq].act[j+1];
line[irq].n--;
@ -423,6 +430,9 @@ irq_poll_thread(void)
for(int irq = 0; irq < NIRQ_IOAPIC; irq++){
if(line[irq].n == 0 || line[irq].msi || reserved(irq))
continue;
// Silent by design, and only its own handlers on it.
if(line[irq].nquiet == line[irq].n && !line[irq].polled)
continue;
int poll = line[irq].polled ||
(IRQ_IS_LEVEL(line[irq].level_low) && line[irq].delivered == 0 &&
now - line[irq].since > POLL_AFTER);