Repository navigation
c: libkore.so, the runtime and host of an independent C program - #32
SnowCheetos wants to merge 16 commits into
Conversation
## Why
`libkore.so` (the next commit) hosts an independent C program on thread 0
and ends the process with the program's own status, from whichever of its
threads asks. kore-rt offered that end only as `startup::finish`, with a
native `ExitCode`. Its managed threads could not wake thread 0, and a
panic's report could not be told apart from its thread's end. Kore
`eab77f8d` adds the three pieces to kore-rt, so they arrive here through the
exporter rather than as edits to the snapshot.
## What
- `native/` is re-exported byte for byte at
`eab77f8d904352eabe65fedb84a455d6ccee5b7d` with `tools/sync-native.py`. That
commit is on MicroPerceptron/kore#1494's branch, which also brings TinyCC to
the Kore shell. Ten of its 23 commits since `7074bda2` reach the closure,
which keeps its 26 packages and 382 files:
- `kore-rt`:
- `startup::barrier(finalize)`: the process barrier without the exit.
- Managed threads inherit their founder's wake send.
- `crash::report`: a panic's report without the thread's end.
- A per-thread C `errno` word and guarded worker stacks sized in bytes.
- The verbs and bundle call a shell's private install takes.
- `kore-abi`:
- The install request and its replies.
- The claimant band sized by driver rows (`MAX_CLAIMANT_FACES`), and the
device service that uses it.
- The services' `boot.toml` digests, resealed three times.
- No exported manifest changed, so `native/Cargo.lock` did not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
…m's host
## Why
`kore.h` was reachable only from inside a Rust program: `kore-ffi`'s
callbacks link into a Rust-founded host, and no crate built a shared
object. A C program a compiler writes on Kore (`tcc` at the shell) had no
runtime to call into. Nothing gave it a heap for `malloc`, a founded
executor for its filesystem session, or a way to stop its threads when it
ends.
## What
- `crates/c` (`kore-c`) builds `libkore.so`, which a C program links with
`-lkore`:
- It exports `kore.h`'s functions and `c-stdlib`'s C names (`malloc`,
`pthread_create`, ...).
- It installs the process heap over the founder's `HEAP` supply.
- A panic ends the program with its record published.
- The program host (`program.rs`), entered from the C library's start
(`__kore_program_start`):
- `main` runs on a main thread, a `DoorbellWorker` with a 1 MiB guarded
stack (`KORE_MAIN_STACK_BYTES`, `tcc`'s measured size).
- Thread 0 keeps the executor and the service faces. It serves what the
program's threads ask through one cell and one word, the shape
`kore-lua`'s VM bridge has.
- Every park is a doorbell park.
- `kore_fs_run(step, user, &error)` (`kore/program.h`) runs a `KoreFsStep`
program as the program's filesystem session.
- It uses the launch's own face and the directory the program was launched
in, through `kore-ffi`'s `Session`, attached on first use.
- The main thread waits; the callbacks run on the host, as on any native
executor.
- Any thread ends the program:
- The C library's `exit` and `_Exit` call `__kore_program_exit` after
their `atexit` handlers, and the first request wins.
- The host waits for a main thread that asked, then raises kore-rt's
process barrier, which runs the finalizers only after a clean stop.
- It ends the process with the C status through the C library's own exit.
- An end requested mid-session does not wait for the session.
- A launch that cannot carry a host runs the program on thread 0, as the C
library alone would. Its filesystem session is refused.
- `kore-ffi`: `RunError::foreign` maps a run's failure to the foreign status
and error, so the classification keeps one owner. Also a target-only
`pthread_testcancel` lint.
- Tools:
- `generate-bindings.py` generates `kore/program.h` from `kore-c` with
cbindgen 0.29.4. It includes `kore.h` and declares none of its types
again.
- `check-bindings.py` compiles a C consumer of it for every ISA.
- `check-program.py` (in `make cross` and CI's target jobs) links
`libkore.so` for every ISA. It checks a shared object with no entry
point, its soname, nothing needed or undefined, static initial-exec TLS,
and exactly the declared ABI exported.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
`kore-c` built `libkore.so` itself, as a `cdylib`. A distribution builds its shared libraries inside its own workspace, where its native owners are patched in. Kore does so for each one it ships, and a second `cdylib` named `kore` there would write the same `libkore.so` as this one. `kore-c` is now the library that image is built from, and the distribution owns the one-line `cdylib`: Kore's `user/runtime/libkore`, the pattern its `crates/pci-names` and `user/runtime/pci-names` already have. - `kore-c` is a library named `kore_c`. Its crate documentation states the link contract the shared object carries: the soname, no undefined symbol, no entry point, static TLS and the exported ABI. - `check-program.py` builds that `cdylib` in a temporary workspace, as `check-entry.py` builds its consumers, linked with `--soname=libkore.so --no-undefined`, and checks the image as before. Each ISA still exports exactly the declared ABI (85 symbols). - The soname and `--no-undefined` move from a build script to that link. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
A distribution ships `kore.h` and the `kore/` headers beside the `libkore.so` it builds. They have to come from the source revision the image was built from, not from a copy kept in the distribution. Cargo's metadata channel carries them: `kore-c` declares `links = "kore"`, and its build script publishes the generated include directory as `DEP_KORE_INCLUDE` to the dependent's build script. No native library is linked. The build script also refuses a checkout missing any of the four headers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
- README: `kore-c` joins the package table. `kore-ffi`'s row no longer says there is no standalone C runtime: `kore-c` is one. - `docs/languages.md`: the shared object a distribution builds, what a program that links it gets, the host's two halves (its filesystem session and the program's end), the program without a host, and the two weak entry points a C library calls. It states what `check-program.py` verifies, which evidence is boot evidence (Kore's `keytest-tcc-x86`) and which is not, and what is still Rust-host only (`kore_task_*`). - `docs/provenance.md`: the export at Kore `eab77f8d`, what of MicroPerceptron/kore#1494 reaches the closure, and `kore-c`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
## Why kore-ffi's pthreads run on kore-rt's thread controller, which waited by ceding a millisecond at a time. Its creators and joiners did the same, and it probed every child for its exit on each pass. Kore `0018956a` makes every one of those waits a futex park and every transition a futex wake. The controller becomes the wake hub of the threads it founds. A thread's end reaches it through an exit hook, and its reap parks on a join arm. That change arrives here through the exporter rather than as edits to the snapshot. ## What - `futex`: sends a thread adopts after its founding (`adopt_peer`), a `Hub` that relays a wake it is counted for and sweeps only then, and `wait_or_end`, a doorbell park whose join arm watches one task. - `thread`: the exit hook `exit` runs first, a thread's own kick at DOORBELL@OWN_KICK (a DoorbellWorker is founded holding one), and `WorkerCap::channel_space`, a revocable mint grant to endow. - `thread_controller`: the parking controller. The closure keeps its 26 packages and 382 files, and no exported manifest changed, so `native/Cargo.lock` did not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
- kore-ffi's `kore_thread_join` waited for the controller to retire its target by ceding a millisecond at a time. It now parks on the target's retirement word, which `retire` stores and then wakes. A joiner whose cancellation is enabled parks one slice at a time, as a cancellable futex wait already does: a cancellation request is a flag no wake carries. Both slices are now one named constant, `CANCEL_SLICE_NS`. Every other joiner, the program's main thread among them, parks until the controller wakes it. - kore-c founds the program's main thread holding a channel-space grant of its own. The first `pthread_create` starts kore-rt's thread controller on the main thread, which mints the controller's doorbell, and through it each child's, from that grant. Without one the controller still runs, on the deadline park. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
…ounder's arena `tools/sync-native.py` at MicroPerceptron/kore@2a0730dd6ba3369c82f025c9957184f0bb9f8a66. kore-rt founds the threads that found others (doorbell workers such as a C program's `main`, the thread controller and its threads) with the 256-slot founding granule rather than a task's 64. It returns a committed founding's scrubbed result names at once, budgets an SPMD launch before it mints or founds, and clamps the gang to what the arena can hold. Before this, `kore_spmd_dispatch` refused from C `main` and a C program kept at most two pthreads alive. The services' `boot.toml` digests follow Kore's reseal at 76fddb9f. `fmt`, `native-check`, `owners` and `bindings-check` pass on this export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
…aits for the reap `tools/sync-native.py` at MicroPerceptron/kore@6c57f344311306868f68e13a37f87abf0ce04e02. The export at 2a0730dd returned a thread founding's staged space to the slot ledger at commit. The Found consumes that space but leaves the founder's record of it binding until the reap, so the name was not free. Kore's production boot gate caught it: a later receive could not land on the name, and the first shell never reported ready. kore-rt now keeps the staged space in the join ticket and instead returns the boot staging page at commit, which the founding's delegation consumes. A founded thread still keeps four names until join, so the launch budgets and the controller's admission are those of 2a0730dd. `fmt`, `native-check`, `owners` and `bindings-check` pass on this export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
`tools/sync-native.py` at MicroPerceptron/kore@2d4998baa8be794191fdacaf63dffca295c2a109. kore-c-shim joins the owner paths, so the export now carries Kore's C library: the `printf` family over every conversion C17 names, floats included and exact; the standard streams behind an installable sink whose lock one call holds across its writes; `<string.h>`, `<stdlib.h>`'s parsers and `qsort`; and `errno`. Its allocator, `abort` and `<wctype.h>` classes each sit behind their own feature, so an image that brings its own allocator and `abort` (as `libkore.so` does) builds without them. kore-rt and the services are those of 6c57f344; their `boot.toml` digests follow Kore's reseal at e3d59c09. `fmt`, `native-check`, `owners` and `bindings-check` pass on this export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
A C program's `printf`, `puts`, `fwrite` and `fprintf(stderr, ...)` now reach the terminal it was run from. libkore.so links Kore's C library (kore-c-shim without its allocator and `abort`, which libkore exports itself) and installs its standard sink. The launcher's stream is bound to thread 0, the host, so every thread's bytes reach it through one in-process ring: - A writer holds the streams' lock across its whole C call, as POSIX's `flockfile` does, so one call's output is never split by another thread's. It kicks the host only if the host armed itself before parking, so a loop of `printf` costs no trap per call. The host holds no send into a pthread's doorbell, so every wait for room is bounded by the runtime's slice. - The host drains a pass at a time (what was queued when the pass began) and waits for the launcher's capacity when its records are full, so a slow terminal holds the program back rather than losing its output. Between passes it serves the program's end and its filesystem sessions, so a program that never stops printing still ends when it asks to. - The host's own writes (a filesystem step's callbacks run on it) cannot wait for the host. They are kept in order beside the ring, each stamped with the ring position it follows. - The end drains what was queued and closes the stream before the process ends, so the launcher shows the output before the exit status. An end committed on the host itself relays at once what the launcher has room for, and a write after the end reports `EOF`. `abort` ends the whole program with the aborted status, from any thread. cbindgen leaves it out of `kore/program.h`, since C declares it in `<stdlib.h>`, and `tools/check-program.py` holds libkore.so's exports to the declared ABI plus the C library's names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
`tools/sync-native.py` at MicroPerceptron/kore@10c7b400aa96c7533be05054fb76e43850408b23. kore-rt names the free part of a task's link window once (`Rt::link_free_span`), which a C program's `mmap` places in, and kore-c-shim's `errno` gains `ENXIO`, `EFAULT` and `ENOTSUP`. kore-ld joins the owner paths: its `SharedPlacer` is the one cursor a window's mappings take their addresses from, and kore-c is about to place with it. The export's packages are unchanged, since kore-ld was already in kore-late's closure. `fmt`, `native-check`, `owners` and `bindings-check` pass on this export. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
`open`, `close`, `mmap` and `munmap` are C's spelling for using a
capability the program was founded holding. They add no authority and no
policy:
int fd = open("/kore/memory", O_RDWR);
char *region = mmap(NULL, 1 << 20, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- The path is not a file. `open` looks it up in one static table whose
rows are a name and the bootstrap coordinate (role, index) it stands
for, and succeeds only for a capability the calling thread holds, with
access its rights cover. The first row is `/kore/memory`, the memory
supply the allocator grows on.
- A descriptor stores the coordinate, never the capability. Capabilities
are per thread on Kore, so each use resolves the coordinate in the
calling thread's boot block: numbers are the process's, and no
authority crosses a thread through one. `close` forgets the number.
- `mmap` on the supply answers fresh, zeroed memory, as mapping
`/dev/zero` does elsewhere, by the sequence a Wasmtime engine's guest
memory takes: a lease from the supply's top (clear of the allocator),
an address from the free part of the link window, the whole lease
mapped there. The caller never picks the address, and nothing a
program wrote is executable.
- Thread 0 carves and maps for whichever thread asked, over one request
cell, as it serves a filesystem session. The share of the supply a
thread is founded with carries no `REVOKE`, and a region that can be
unmapped again is a carve its holder may revoke; the supply's root is
thread 0's. A mapping is therefore the process's, and any thread may
`munmap` it.
- `munmap` removes the mapping and parks the region. The supply's and
the window's cursors only advance, so the program keeps the lease and
its address, and the next `mmap` of that length takes it, zeroed
again. One size mapped and unmapped in a loop uses one region.
- `kore_fd_describe` (`kore/program.h`) reads a descriptor's kind, what
its capability's rights permit, and a supply's length.
The streams' futex lock moves to `lock.rs`, which the cell's callers
share. The table and the request rules are plain data, tested on the host. The
POSIX names are exported on Kore alone, and `tools/check-program.py`
holds libkore.so's exports to the declared ABI with them.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
RUSTSEC-2026-0486: rustix 1.0.0 to 1.1.5 marked unwritten bytes as initialized when an extended-attribute function was given a zero-length buffer. The advisory reached the database after this branch's last green run, and `cargo audit --deny warnings` now refuses 1.1.5, which the lock already held. 1.1.6 is the patched release. Only the host crates' graph (wasmtime's) holds rustix; the native lock already had 1.1.6. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
…e command name `tools/sync-native.py` at MicroPerceptron/kore@dfece6447cd331375a28b2bb290691cb8d5ab060, which is Kore's branch after its merge of main. The export gains: - `ProcessIo::command` (page ABI 14): the name a launcher resolved a program by, beside the argument tail it always carried. kore-c is about to hand both to a C program's `main`. - the device inventory records (`kore_abi::device::state`) and the observations behind them, and the command snapshot's second ABI. - main's own changes to the exported crates: the filesystem's watch plane, the seat clipboard's window verbs, and the wakes a service owes the peers it publishes events to. `fmt`, `test`, `check`, `docs`, `owners`, `bindings-check`, `miri`, the native type composition and each ISA's target checks pass on this export with the change that follows it. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
`main` ran with `argc` zero: nothing read the launcher's page, and the page held only the tail of the command line, never the program's name. Kore's page now carries both. The host reads them once, on thread 0 before the main thread exists (`args::capture`), and splits the tail as every Kore program that wants words does: a POSIX shell's quoting without expansion (`kore_rt::process::words`). The C library's start asks for the vector through a third lifecycle hook, `__kore_program_arguments(&argv)`, and calls `main(argc, argv, envp)`: - `argv[0]` is the command name, or the empty string when the launcher gave none; `argv[argc]` is null; the strings are the program's to change, and live as long as it does. - A line that does not split (an unclosed quote, a lone trailing backslash, a NUL inside a word) is not handed to `main`. The host says why on `stderr` and ends the program with status 5 before it runs, as `wasm` and `tcc` answer the same line. - A launch that carried no page, or no host, runs with `argc` zero. The hook is the C library's, not an application API: cbindgen leaves it out of `kore/program.h`, and `check-program.py` expects it among the lifecycle symbols (130 exported). Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.
|
The red Nothing in the diff can change it; it clears when the Copilot quota resets or the review is re-requested. Generated by Claude Code |
What this changes
kore.hcould only be used from inside a Rust program:kore-ffi'scallbacks run in a Rust-founded host, and no crate built a shared object. A
C program a compiler writes on Kore had no runtime to call into. This adds
one, so the C surface works in an independent C program:
kore-c, the runtime oflibkore.so. A distribution builds the imagefrom a one-line
cdylibnamedkore(Kore'suser/runtime/libkore),linked with
--soname=libkore.so --no-undefined. It exports everykore.hfunction and thec-stdlibC names (malloc,pthread_create,...), and installs the process heap.
The program host.
mainruns on a main thread (aDoorbellWorkerwith a 1 MiB guarded stack), and thread 0 keeps the executor and the
launch's faces. They share one request cell and one word, the shape
kore-lua's VM bridge has, and every park is a doorbell park.kore_fs_run(step, user, &error)(newkore/program.h) runs aKoreFsStepprogram as the program's filesystem session, throughkore-ffi'sSessionover the launch's own face.exitends the program. The host stops every other thread,runs the finalizers after a clean stop, and commits the C status through
the C library's exit.
Its headers ship with the image.
kore-cdeclareslinks = "kore"and publishes the generated include directory as
DEP_KORE_INCLUDE, so adistribution ships headers from the revision it built.
A C program's threads park, never poll. pthreads run on kore-rt's
thread controller. Its creators, its joiners and the controller itself
each used to cede a millisecond at a time, and the controller probed
every child for its exit on each pass. Now every wait is a futex park
and every transition a futex wake.
a doorbell and relays the wakes they cannot deliver to each other.
thread::exitruns.Its reap parks on a join arm beside its word.
kore_thread_joinparks on its target's retirement word, which thecontroller wakes.
kore-cfoundsmainholding a channel-space grant to mint thedoorbells from. Without one the controller still runs, on the deadline
park.
A native re-export at Kore
0018956a(MicroPerceptron/kore#1494'sbranch). kore-rt gains the pieces the host needs:
startup::barrier: the process barrier without the exit;crash::report: a panic's report without the thread's end;peer sends, a relay
Hub, andwait_or_end.Threads that found take a founder's arena (
c476f32re-exports Kore at2a0730dd,5be44ebat6c57f344). Cmainis a doorbell worker, so it founds with the 256-slot founding granule, and a committed founding returns the names nothing binds any more. Before this,kore_spmd_dispatchrefused frommain(status 7) and a C program kept at most two pthreads alive. The founder's record of a founding's staged space keeps binding until the reap, so that one name waits for the join (MicroPerceptron/kore#1537).stdio for C programs (
13b0a91,0460f5c). The re-export at Kore2d4998bacarries Kore's C library, kore-c-shim. It provides:printffamily over every C17 conversion, floats exact,long doublein x87's and binary128's formats;<string.h>,<stdlib.h>'s parsers,qsortanderrno.libkore.so links it without its allocator and
abort, which libkore exports itself, and writesstdoutandstderrfor every thread:flockfiledoes, so one call's output is never split by another thread's. It copies into a 16 KiB in-process ring and kicks the host only if the host armed itself before parking, so a loop ofprintfcosts no trap per call. The host can kickmainbut holds no send into a pthread's doorbell, so every wait for room is bounded by the runtime's slice.EOF.abortends the program with the aborted status (134 at the shell) from any thread, running noatexithandler. cbindgen leaves it out ofkore/program.h, since C declares it in<stdlib.h>.Descriptors over the capabilities a C program holds, and
mmap(23a0ca0,c876e43).open,close,mmapandmunmapare C's spelling for using a capability the program was founded holding, and add no authority:openlooks it up in one static table (crates/c/src/fd.rs) whose rows are a name and the bootstrap coordinate (role, index) it stands for. It answers a descriptor only for a capability the calling thread holds, with access its rights cover. The first name is/kore/memory,role::HEAP@0, the supply the allocator grows on.closeforgets the number.mmapon the supply answers fresh, zeroed memory, by the sequence a Wasmtime engine's guest memory takes: a lease from the supply's top (heap::reserve_from_top, clear of the allocator), an address from the free part of the link window (Rt::link_free_span, new in the re-export at Kore10c7b400), the whole lease mapped there. The caller never picks the address, and nothing a program wrote is executable.REVOKE, and a region that can be unmapped again is a carve its holder may revoke; the supply's root is thread 0's. A mapping is the process's, and any thread maymunmapit.munmapparks the region. The supply's and the window's cursors only advance, so the program keeps the lease and its address, and the nextmmapof that length takes it again, zeroed. Lengths that never repeat each spend supply, and a program holds sixteen regions.kore_fd_describe(kore/program.h) reads a descriptor's kind, what its capability's rights permit, and a supply's length.lock.rs, which the request cell's callers share. kore-ld joins the owner paths for itsSharedPlacer.mainreceives its arguments (4289361re-exports Kore atdfece644,2ce41f1). Kore's process page now carries the name a launcher resolved a program by beside the tail of its command line. The host reads both once, on thread 0 before the main thread exists, and splits the tail as every Kore program that wants words does: a POSIX shell's quoting without expansion. The C library's start asks for the vector through a third lifecycle hook,__kore_program_arguments(&argv):argv[0]is the name, or the empty string when the launcher gave none;argv[argc]is null; the strings are the program's to change.main. The host says why onstderrand ends the program with status 5 before it runs.argczero.envpis empty.Coverage and checks
tools/check-program.py(make cross, and a CI step per ISA) linkslibkore.soas a distribution does and checks it:kore/program.his generated by cbindgen 0.29.4 likekore.h, includesit, and declares none of its types again.
bindings-checkcompiles a Cconsumer of it for every ISA.
first-request rule. kore-rt's own host suite (460 tests, run here through
the native export) covers the controller's join handshake, the relay's
order (counted before the hub's word moves), and the sweep's choice of
threads.
write framed into records and read back in order, the wrap of its bytes
and positions, room counted with headers, a stale read that never finds
room that is not there, the discard, and the order of the host's held
writes.
row or nothing, only an access mode is a flag, access is held to the
capability's rights, the lowest free number is handed out from 3, threads
never share a descriptor, each
mmaprequest with no meaning is refusedby its errno, and an unmapped region serves the next request of its
length.
the tail follows as a shell splits it, every word is its own terminated
string, and a line that does not split, or holds a NUL, is no vector.
2ce41f1:make fmt test check docs owners bindings-check miri, the native type composition, and for each ISA the target check,check-entry,check-alloc-symbolsandcheck-program, all green.Evidence
Kore's
make keytest-tcc-x86compiles a C program at Kore's shellagainst these headers, links
libkore.soand runs it toexit 42. Theprogram uses the heap, the clock, random, a hash table and a
kore_fs_runsession. The shell reads back the file the session wrote andthe one the
atexithandler wrote as the program ended. Its threads:pthread_exit;mainwakes.mainholds no sendinto that thread, and with cancellation disabled the wait has no slice
to fall back on, so only the controller's relay can end it.
On MicroPerceptron/kore#1494's branch (source
4633d3cc, sealed in76fddb9f, pinning this branch'sb9eb3c2), the keytest passes on theproduction image:
libkore-tour: linked 3 segments; exit 42. The shell then reads backwritten and read back through kore_fs_runandthe atexit handler ran.stdio, on the same branch (source
1db2c9da, sealed in0de59be2,pinning this branch's
0460f5c): the keytest compiles the shippedhello.cwith no flag, installs it and runs it. Every line reaches theterminal: integers, strings, floats in each style, an
snprintfinto itsown buffer and a line on stderr. Its zero status prints nothing. A
one-line program then prints a
long doublewith x87's digits(
0.1000000000000000000013553) andaborts, which ends it withexit 134after what it wrote. The tour above now also keeps two dozenthreads alive at once and dispatches an SPMD gang from
main.Descriptors and
mmap, on the same branch (source7068bea1, sealed inf2644e5b, pinning this branch'sc876e43): the keytest compiles theshipped
memory.cwith no flag, installs it and runs it to status 0. Itprints
descriptor 3 is memory: readable, writable, a 16 MiB supply,maps a megabyte (zeroed), writes and reads it back, maps a second
elsewhere, takes a region it had again after
munmap, and is refused anunknown name, a file flag, an offset, part of a mapping and a closed
descriptor.
Arguments, on the same branch (source
1510049d, sealed infd5919ac,pinning this branch's
2ce41f1): the keytest types a program that printsits
argv. Run asargs one 'two words' "" fourit prints its name andfour words, the quoted one whole and the empty one kept, and returns 45;
run alone it prints its name; and
args 'opennever reachesmain:kore: the ' opened at byte 0 is never closed,exit 5.stdio,
mmapand arguments have run on x86_64 only: in QEMU, and stdioand
mmap(from threads other thanmaintoo) on an x86 laptop. Noaarch64 or riscv64 boot has run a C program that prints, maps or takes
arguments, and arguments have not run on hardware.
This repository's checks are compiler and link evidence, not boot or
hardware evidence.
Not in this change
stdin,FILEstreams over files (fopen), and an environment:envpis the empty vector.
interrupts and DMA, and sending a region to another task.
kore_task_*) still needs a Rust host to admit itsbatch.
adapter.
🤖 Generated with Claude Code
https://claude.ai/code/session_01ACHC7gwT8vVUKqPGAjXfMM