The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).
253 files now begin
SPDX-License-Identifier: LicenseRef-Starship-1.0
Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.
Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).
Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
135 lines
3.9 KiB
C
135 lines
3.9 KiB
C
/* SPDX-License-Identifier: LicenseRef-Starship-1.0
|
|
* Copyright (c) 2023-2026 Robert A. James
|
|
*/
|
|
/* wire.c -- a queue of whole messages. See wire.h.
|
|
*
|
|
* Nothing here uses the C library: the bare-metal kernel links this file.
|
|
*/
|
|
#include "v4/wire.h"
|
|
#include "v4/message.h"
|
|
|
|
void v4_wire_reset(v4_wire_queue *q)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < V4_WIRE_CELLS; i++) q->cell[i] = 0;
|
|
q->head = 0;
|
|
q->used = 0;
|
|
q->mark = 0;
|
|
q->arrived = 0;
|
|
q->freed = 0;
|
|
q->looked = 0;
|
|
}
|
|
|
|
unsigned v4_wire_cells(v4_cell length)
|
|
{
|
|
if (length < 0 || length > (v4_cell)V4_MSG_MAX_CHARS) return 0;
|
|
return V4_WIRE_HEADER + ((unsigned)length + 3u) / 4u;
|
|
}
|
|
|
|
/* the cell `off` cells from the front */
|
|
static unsigned slot(const v4_wire_queue *q, unsigned off)
|
|
{
|
|
unsigned s = q->head + off;
|
|
return s >= V4_WIRE_CELLS ? s - V4_WIRE_CELLS : s;
|
|
}
|
|
|
|
/* the cells the message `off` cells from the front takes */
|
|
static unsigned size_at(const v4_wire_queue *q, unsigned off)
|
|
{
|
|
return v4_wire_cells(q->cell[slot(q, off + 6u)]);
|
|
}
|
|
|
|
int v4_wire_room(const v4_wire_queue *q, unsigned cells)
|
|
{
|
|
return cells <= V4_WIRE_CELLS - q->used ? V4_WIRE_DONE : V4_WIRE_NO_ROOM;
|
|
}
|
|
|
|
/* `n` cells, already checked to fit, onto the back */
|
|
static unsigned back(v4_wire_queue *q, unsigned n)
|
|
{
|
|
unsigned at = q->used;
|
|
q->used += n;
|
|
q->arrived = 1;
|
|
return at;
|
|
}
|
|
|
|
int v4_wire_put(v4_wire_queue *q, const v4_cell *header7, const v4_cell *text)
|
|
{
|
|
unsigned n = v4_wire_cells(header7[6]), at, i;
|
|
if (n == 0) return V4_WIRE_NOT_A_MESSAGE;
|
|
if (v4_wire_room(q, n) != V4_WIRE_DONE) return V4_WIRE_NO_ROOM;
|
|
at = back(q, n);
|
|
for (i = 0; i < V4_WIRE_HEADER; i++) q->cell[slot(q, at + i)] = header7[i];
|
|
for (; i < n; i++) q->cell[slot(q, at + i)] = text[i - V4_WIRE_HEADER];
|
|
return V4_WIRE_DONE;
|
|
}
|
|
|
|
void v4_wire_first(v4_wire_queue *q)
|
|
{
|
|
q->looked = 0;
|
|
q->mark = 0;
|
|
}
|
|
|
|
int v4_wire_next(v4_wire_queue *q)
|
|
{
|
|
q->looked = 0;
|
|
if (q->mark >= q->used) return V4_WIRE_NO_MESSAGE;
|
|
q->mark += size_at(q, q->mark);
|
|
return q->mark < q->used ? V4_WIRE_DONE : V4_WIRE_NO_MESSAGE;
|
|
}
|
|
|
|
int v4_wire_look(v4_wire_queue *q, v4_cell *header7)
|
|
{
|
|
unsigned i;
|
|
if (q->mark >= q->used) return V4_WIRE_NO_MESSAGE;
|
|
for (i = 0; i < V4_WIRE_HEADER; i++) header7[i] = q->cell[slot(q, q->mark + i)];
|
|
q->looked = 1;
|
|
return V4_WIRE_DONE;
|
|
}
|
|
|
|
/* the marked message is off the queue; the mark is at the one that followed */
|
|
static void remove_marked(v4_wire_queue *q)
|
|
{
|
|
unsigned n = size_at(q, q->mark), i;
|
|
if (q->mark == 0) {
|
|
q->head = slot(q, n);
|
|
} else {
|
|
for (i = q->mark; i + n < q->used; i++) q->cell[slot(q, i)] = q->cell[slot(q, i + n)];
|
|
}
|
|
q->used -= n;
|
|
q->freed = 1;
|
|
q->looked = 0;
|
|
}
|
|
|
|
int v4_wire_take(v4_wire_queue *q, v4_cell *header7, v4_cell *text, unsigned text_cap)
|
|
{
|
|
unsigned n, i;
|
|
if (q->mark >= q->used) return V4_WIRE_NO_MESSAGE;
|
|
n = size_at(q, q->mark);
|
|
if (n - V4_WIRE_HEADER > text_cap) return V4_WIRE_NOT_A_MESSAGE;
|
|
for (i = 0; i < V4_WIRE_HEADER; i++) header7[i] = q->cell[slot(q, q->mark + i)];
|
|
for (; i < n; i++) text[i - V4_WIRE_HEADER] = q->cell[slot(q, q->mark + i)];
|
|
remove_marked(q);
|
|
return V4_WIRE_DONE;
|
|
}
|
|
|
|
int v4_wire_drop(v4_wire_queue *q)
|
|
{
|
|
if (q->mark >= q->used) return V4_WIRE_NO_MESSAGE;
|
|
remove_marked(q);
|
|
return V4_WIRE_DONE;
|
|
}
|
|
|
|
int v4_wire_move(v4_wire_queue *from, v4_wire_queue *to)
|
|
{
|
|
unsigned n, at, i;
|
|
if (from->mark >= from->used) return V4_WIRE_NO_MESSAGE;
|
|
n = size_at(from, from->mark);
|
|
if (from == to || v4_wire_room(to, n) != V4_WIRE_DONE) return V4_WIRE_NO_ROOM;
|
|
at = back(to, n);
|
|
for (i = 0; i < n; i++) to->cell[slot(to, at + i)] = from->cell[slot(from, from->mark + i)];
|
|
to->cell[slot(to, at + 3u)] = (v4_cell)((v4_ucell)from->cell[slot(from, from->mark + 3u)] - 1u); /* in the unsigned type: no overflow at the least cell */
|
|
remove_marked(from);
|
|
return V4_WIRE_DONE;
|
|
}
|