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:
parent
7af579a20d
commit
e659c6b187
10 changed files with 184 additions and 25 deletions
|
|
@ -181,9 +181,15 @@ main(int argc, char *argv[])
|
|||
|
||||
// Worth one line under -v, because it is the moment names start working
|
||||
// and somebody watching a verbose boot may be waiting to know it.
|
||||
// One write(), prefix and all: two would let another job's line land
|
||||
// between them, which a verbose boot on real hardware showed as
|
||||
// "os.schos.keymapnameserver 192.168.1.1".
|
||||
if (verbose_boot) {
|
||||
puts_("resolvconf: ");
|
||||
write(1, buf, n);
|
||||
static char line[sizeof("resolvconf: ") + sizeof(buf)];
|
||||
int k = 0;
|
||||
for (const char *p = "resolvconf: "; *p; p++) line[k++] = *p;
|
||||
for (int j = 0; j < n; j++) line[k++] = buf[j];
|
||||
write(1, line, k);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,10 +119,34 @@ read_bootmode(void)
|
|||
if (n > 0) { b[n] = 0; verbose_boot = (b[0] == 'v'); }
|
||||
}
|
||||
|
||||
// Whole lines, in one write() each: the same buffer as schinitd's, for the
|
||||
// same reason -- a line written in pieces is a line another process can land
|
||||
// in the middle of. See emit() there.
|
||||
static char lbuf[512];
|
||||
static int lbn;
|
||||
|
||||
static void
|
||||
lflush(void)
|
||||
{
|
||||
if (lbn)
|
||||
write(1, lbuf, lbn);
|
||||
lbn = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
emit(const char *s, int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
lbuf[lbn++] = s[i];
|
||||
if (s[i] == '\n' || lbn == (int)sizeof lbuf)
|
||||
lflush();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
out(const char *s)
|
||||
{
|
||||
write(1, (void *)s, slen(s));
|
||||
emit(s, slen(s));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -410,6 +434,7 @@ spawn(struct schinit_spawn *s)
|
|||
out("schinit: cannot exec ");
|
||||
out(s->program);
|
||||
out("\n");
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
return pid;
|
||||
|
|
|
|||
|
|
@ -83,10 +83,40 @@ ends_with(const char *s, const char *suffix)
|
|||
return seq(s + ls - lf, suffix);
|
||||
}
|
||||
|
||||
// Whole lines, in one write() each.
|
||||
//
|
||||
// Every message here is assembled from pieces -- a prefix, a job's label, a
|
||||
// number -- and each piece used to be its own write(). The console keeps one
|
||||
// write() together, but nothing keeps two of them together, so a job starting
|
||||
// on another CPU landed in the middle of the line: "schinitd: starting vgpud:
|
||||
// os.schos.resolvconfno virtio-gpu on this machine" was this process and
|
||||
// vgpud taking turns a word at a time. The pieces now collect here and go out
|
||||
// at the newline.
|
||||
static char lbuf[512];
|
||||
static int lbn;
|
||||
|
||||
static void
|
||||
lflush(void)
|
||||
{
|
||||
if (lbn)
|
||||
write(1, lbuf, lbn);
|
||||
lbn = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
emit(const char *s, int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
lbuf[lbn++] = s[i];
|
||||
if (s[i] == '\n' || lbn == (int)sizeof lbuf)
|
||||
lflush();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
out(const char *s)
|
||||
{
|
||||
write(1, (void *)s, slen(s));
|
||||
emit(s, slen(s));
|
||||
}
|
||||
|
||||
// How the machine was booted, read once.
|
||||
|
|
@ -139,7 +169,7 @@ static void
|
|||
vout(const char *s)
|
||||
{
|
||||
if (verbose_boot)
|
||||
write(1, (void *)s, slen(s));
|
||||
emit(s, slen(s));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -626,14 +656,17 @@ main(void)
|
|||
h.reserved = 0;
|
||||
if (write(sock, &h, sizeof(h)) != sizeof(h)) {
|
||||
out("schinitd: no channel to pid 1\n");
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
if (read(sock, &h, sizeof(h)) != sizeof(h) || h.op != SCHINIT_WELCOME) {
|
||||
out("schinitd: pid 1 did not answer\n");
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
if (h.proto != SCHINIT_PROTO) {
|
||||
out("schinitd: protocol mismatch with pid 1\n");
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
|
||||
|
|
@ -742,7 +775,8 @@ main(void)
|
|||
// pinging -- which it has, because it is no longer talking to us.
|
||||
if (pr > 0 && (pf.revents & (POLLHUP | POLLERR | POLLNVAL))) {
|
||||
out("schinitd: channel closed; this supervisor has been replaced\n");
|
||||
exit();
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
|
||||
if (pr > 0 && (pf.revents & POLLIN)) {
|
||||
|
|
@ -752,7 +786,8 @@ main(void)
|
|||
// PID 1 closed the channel. It is the one process that cannot
|
||||
// have gone away, so this means we are being replaced.
|
||||
out("schinitd: channel closed\n");
|
||||
exit();
|
||||
lflush();
|
||||
exit();
|
||||
}
|
||||
if (m.op == SCHINIT_PING) {
|
||||
struct schinit_hello p;
|
||||
|
|
|
|||
|
|
@ -59,12 +59,42 @@ read_bootmode(void)
|
|||
if (n > 0) { b[n] = 0; verbose_boot = (b[0] == 'v'); }
|
||||
}
|
||||
|
||||
// Whole lines, in one write() each.
|
||||
//
|
||||
// Every message here is assembled from pieces -- a prefix, a job's label, a
|
||||
// number -- and each piece used to be its own write(). The console keeps one
|
||||
// write() together, but nothing keeps two of them together, so a job starting
|
||||
// on another CPU landed in the middle of the line: "schinitd: starting vgpud:
|
||||
// os.schos.resolvconfno virtio-gpu on this machine" was this process and
|
||||
// vgpud taking turns a word at a time. The pieces now collect here and go out
|
||||
// at the newline.
|
||||
static char lbuf[512];
|
||||
static int lbn;
|
||||
|
||||
static void
|
||||
lflush(void)
|
||||
{
|
||||
if (lbn)
|
||||
write(1, lbuf, lbn);
|
||||
lbn = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
emit(const char *s, int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
lbuf[lbn++] = s[i];
|
||||
if (s[i] == '\n' || lbn == (int)sizeof lbuf)
|
||||
lflush();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
puts(const char *s)
|
||||
{
|
||||
int n = 0;
|
||||
while (s[n]) n++;
|
||||
write(1, (void *)s, n);
|
||||
emit(s, n);
|
||||
}
|
||||
|
||||
// Progress, as opposed to news.
|
||||
|
|
@ -89,10 +119,10 @@ putn(long long v)
|
|||
{
|
||||
char b[24];
|
||||
int i = 0;
|
||||
if (v < 0) { write(1, "-", 1); v = -v; }
|
||||
if (v == 0) { write(1, "0", 1); return; }
|
||||
if (v < 0) { emit("-", 1); v = -v; }
|
||||
if (v == 0) { emit("0", 1); return; }
|
||||
while (v > 0) { b[i++] = '0' + (int)(v % 10); v /= 10; }
|
||||
while (i-- > 0) write(1, &b[i], 1);
|
||||
while (i-- > 0) emit(&b[i], 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -101,7 +131,7 @@ puthex(unsigned long long v, int digits)
|
|||
static const char h[] = "0123456789abcdef";
|
||||
char b[17];
|
||||
for (int i = digits - 1; i >= 0; i--) { b[i] = h[v & 0xF]; v >>= 4; }
|
||||
write(1, b, digits);
|
||||
emit(b, digits);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -123,6 +153,7 @@ nothing_to_do(const char *why)
|
|||
// still an exit the supervisor is told about, which is what stops it being
|
||||
// restarted fifteen times in forty-five seconds.
|
||||
vputs("vgpud: "); vputs(why); vputs("\n");
|
||||
lflush();
|
||||
exit_group(SCHINIT_EXIT_NORESTART);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue