Skip to content

Releases: gburd/libxtc

v1.20.1

Choose a tag to compare

@github-actions github-actions released this 13 Jul 11:27

libxtc (1.20.1-1) unstable; urgency=medium

  • Build hygiene: libxtc now compiles with ZERO warnings on every build
    target and platform, and CI enforces it (warnings are build
    failures) so it stays that way. Fixed 7 library + 8 test warnings
    under gcc/clang (-Wall -Wextra -Wpedantic) and 79 -> 0 under MSVC
    /W3. The MSVC set included one real portability-layer type mismatch
    (__os_call_once passing __os_once_t* where the Windows compat
    pthread_once wants INIT_ONCE*); the rest were comment/macro/cast
    hygiene (dropped <ntstatus.h> which re-defined ~65 SDK macros,
    Winsock length casts, _Atomic-drop-on-free casts, an LLP64 sentinel
    widen, a pipe-macro redefine).
  • Enforcement: the gcc + clang CI build now uses CFLAGS=-Werror, and
    dist/build_msvc.bat adds /WX, so any new warning fails CI.
  • No public xtc_* API change and no behavior change from 1.20.0.

-- Greg Burd greg@burd.me Mon, 13 Jul 2026 06:48:58 -0400

v1.20.0

Choose a tag to compare

@github-actions github-actions released this 13 Jul 00:12

libxtc (1.20.0-1) unstable; urgency=medium

  • Windows IOCP AFD socket poll: three real bugs fixed on an MSVC
    Windows host. (1) The AFD poll IOCTL code was wrong
    (CTL_CODE(0x12,9,...)=0x00120024 was rejected with
    STATUS_INVALID_DEVICE_REQUEST); use the wepoll/libuv literal
    0x00012024. (2) A stale-GetLastError check made an empty 0 ms poll
    wrongly return XTC_E_INTERNAL and kill the loop; treat n_done==0 as
    a timeout. (3) Synchronous AFD completions (accept-ready,
    connect-complete) were never reaped; post a self-completion for the
    sync case. Accept + connect readiness now flow. The async
    data-ready completion remains open (the loopback echo stalls after
    the client send) and is documented; the socket-echo smoke stays a
    clean SKIP, and every other IOCP path (file AIO, cross-thread
    wakeup, selective receive, xtc_xproc) passes on the host.
  • Windows slab FlsAlloc magazine validated on MSVC: a microbench shows
    every alloc hits the fiber-local fast path (fast=2,000,000 slow=256,
    26.3 M ops/s). The spawn-scale curve is unchanged by it -- the
    spawn bottleneck past 4 loops is cross-loop work-steal cache thrash,
    not allocation (an honest, measured finding).
  • No public xtc_* API change from 1.19.0.

-- Greg Burd greg@burd.me Sun, 12 Jul 2026 19:50:23 -0400

v1.19.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 20:14

libxtc (1.19.0-1) unstable; urgency=medium

  • Layering: fixed the L2->L3 upward dependencies and added a
    machine-enforced gate. The slab core is now a layer-neutral
    allocator (only _os*); its one proc-dependent convenience
    (xtc_slab_reaper_spawn) moved to src/ptc/slab_reaper.c, so the L2
    event loop's use of the slab for the per-loop timer objects is no
    longer an upward call. xtc_loop_fini's direct proc-table
    unregister became a hook (__xtc_loop_fini_hook) the L3 proc layer
    installs. New dist/s_layer lint (in make check + CI) forbids any
    .c from including a strictly-higher layer's header, with one
    documented XTC_LAYER_OK exception (io_net.c cooperative-wait).
  • Removed the L5 PostgreSQL adapter (milestone M16) from the plan:
    libxtc is a general-purpose async runtime (L0-L4) that ships the
    primitives, not a downstream adapter. PLAN.md and docs updated;
    PostgreSQL survives only as illustrative motivation.
  • Windows scalability fast path: the slab per-thread magazine is now
    backed by Fiber Local Storage (FlsAlloc) on Windows -- an FLS slot
    correctly follows a fiber across SwitchToFiber, unlike the
    __declspec(thread) static TLS that had to be disabled earlier.
    Win32 FLS API usage MinGW-verified; full MSVC re-measurement awaits
    a Windows host (EC2 benchmark parked; the Windows AFD socket-echo
    remains host-blocked, documented).
  • CI: added a FreeBSD job (vmactions/freebsd-vm, full gmake check) and
    a RISC-V 64 job (qemu-user cross-arch build + unit/property suites).
    Both also re-verified by hand this round (FreeBSD 15, RISC-V 64
    native). illumos-in-CI intentionally not added (no runner; nested
    QEMU too slow per commit) -- stays periodic manual re-verify.
  • No public xtc_* API change from 1.18.0.

-- Greg Burd greg@burd.me Sun, 12 Jul 2026 15:50:33 -0400

v1.18.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 17:18

libxtc (1.18.0-1) unstable; urgency=medium

  • Code-quality cleanup (no functional change; net -225 lines). From a
    read-only audit against DRY/KISS/SRP/Clean-Code, three verified,
    behavior-preserving refactors:
    • Extracted the fiber-stack pool and the S1 stack-reclaim lever
      (previously duplicated near-identically between the fcontext and
      ucontext coroutine substrates) into a new internal
      src/inc/coro_common.h that both mmap-based substrates include.
      Verified byte-faithful across default(uctx), forced-fctx, ASan
      (detect_stack_use_after_return=1), and clang ThreadSanitizer.
    • Factored the repeated "cancel park timer + clear field" idiom
      (10 inline copies across sync.c, lock_mgr.c, proc.c) into
      __xtc_task_cancel_park_timer().
    • Consistency: fsm.c/reg.c/xproc.c freed library-allocated recv
      buffers with xtc_free; converted to __os_free to match the rest
      of the library (xtc_free is the consumer alias, literally
      { __os_free(p); }, so this is pure consistency, not behavior).
      Renamed sync.c's __rd_ready/__wr_ready to __can_grant_read/write.
  • No public xtc_* API change from 1.17.0.

-- Greg Burd greg@burd.me Sun, 12 Jul 2026 13:02:39 -0400

v1.17.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 14:26

libxtc (1.17.0-1) unstable; urgency=medium

  • ThreadSanitizer support for the cooperative-fiber runtime (requested
    by the PG-integration team). The coro substrates now emit the TSan
    fiber-IDENTITY API (__tsan_create_fiber / __tsan_switch_to_fiber /
    __tsan_destroy_fiber) under clang -fsanitize=thread, so TSan tracks
    per-fiber happens-before across cooperative switches instead of
    collapsing every coroutine into one confused thread. This is
    DISTINCT from and mutually exclusive with the ASan stack-switch
    annotations (v1.13.0): a TSan build emits only the identity calls,
    an ASan build only the stack-switch calls, so a TSan build no longer
    link-fails on __sanitizer_start_switch_fiber (which the TSan runtime
    does not provide). clang-only by design (gcc libtsan has no fiber
    support). A full clang TSan build runs the fiber suite
    (test_fctx/async/proc/svr/chan) with zero TSan warnings; a new CI
    job (tsan-fibers) keeps it green. Zero cost / zero symbols in a
    non-sanitized build.
  • Test coverage: closed the documented io_common.c and svr.c
    branch-coverage gaps with targeted guard tests (io_init/fini/wakeup
    NULL guards, the live wakeup+coalesce path, and the xtc_svr
    start/stop/join/reply/call/cast XTC_E_INVAL edges).
  • Docs: corrected the stale "CI not flipped to SUAR=1" caveat (flipped
    since v1.13.0); recorded that Windows multi-core scalability is not
    claimed and is gated behind the Win32-fiber-substrate fix.
  • No public xtc_* API change from 1.16.0.

-- Greg Burd greg@burd.me Sun, 12 Jul 2026 10:06:55 -0400

v1.16.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 13:07

libxtc (1.16.0-1) unstable; urgency=medium

  • Windows xtc_xproc: fixed a cross-thread deadlock in the exit-latch
    callback (it took the proc-table lock, an SRWLock, while the loop
    thread held it inside xtc_monitor). The callback now only nudges
    the loop via xtc_io_wakeup; the shadow proc observes the exit latch
    on the loop thread. The control channel reads on a dedicated OS
    thread. The end-to-end monitor is still gated behind a separate,
    ASan-confirmed Win32-fiber-substrate memory-safety bug (documented);
    POSIX xtc_xproc remains fully tested.
  • Portability layer (from the pg_threads.h review, ahead of the
    Windows os_thread port): split the rwlock unlock into
    __os_rwlock_rdunlock / _wrunlock (the Windows SRWLock has no
    mode-agnostic release); static lock initializers XTC_OS_MUTEX_INIT /
    XTC_OS_RWLOCK_INIT; __os_call_once / __os_once_t over pthread_once /
    InitOnceExecuteOnce; and __os_thread_atexit for cleanup on threads
    libxtc did not create (interop with host / carrier threads). New
    m1 tests, man pages, and docs; no DST applies (OS threading
    primitives are not sim-reachable).
  • Docs: correct the stale "CI not flipped to SUAR=1" caveat (flipped
    since v1.13.0); record plainly that Windows multi-core scalability
    is NOT claimed and is gated behind the Win32-fiber-substrate fix.
  • No change to the public xtc_* API from 1.15.0; the new _os*
    primitives are the internal L0 portability surface.

-- Greg Burd greg@burd.me Sun, 12 Jul 2026 08:55:09 -0400

v1.15.0

Choose a tag to compare

@github-actions github-actions released this 12 Jul 02:03

libxtc (1.15.0-1) unstable; urgency=medium

  • Windows xtc_xproc control channel now uses a dedicated reader thread.
    Root-caused the v1.14.0 Windows end-to-end monitor hang: the child's
    pump proc waited for control-socket frames via xtc_proc_wait_fd, but
    the Windows IOCP loop cannot yet wait on an arbitrary socket's
    readability (the AFD-poll path is unfinished), so the child never
    received the parent's message and never exited. Fix: the Windows
    child reads the control socket on a dedicated OS thread (blocking
    recv) and forwards frames to the root proc via a cross-thread
    xtc_send, sidestepping the socket-readiness gap -- the same approach
    the BEAM uses for Windows port I/O. POSIX xtc_xproc is unchanged and
    fully tested; the Windows reader-thread path compiles clean (MinGW +
    MSVC in CI) and awaits an EC2 Windows box for end-to-end
    re-validation, so the MSVC-smoke xproc check stays a documented SKIP
    (KNOWN_ISSUES records it as implemented-pending-validation).
  • Benchmark note (not a code change): the reuse-mode loops=1->4
    throughput dip observed on the EC2 192-core box is a placement
    artifact, not a runtime bug -- libxtc deliberately does not pin loop
    threads (the embedder pins), so at low core counts the OS floats the
    reschedule-heavy threads across both NUMA sockets and work-stealing
    thrashes cross-socket cache. Documented; numactl pinning is the
    benchmark-side fix.
  • No public API change from 1.14.0; a Windows-only internal
    reorganization of the xtc_xproc child runtime.

-- Greg Burd greg@burd.me Sat, 11 Jul 2026 21:43:35 -0400

v1.14.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 23:31

libxtc (1.14.0-1) unstable; urgency=medium

  • Fiber-stack pool (both coro substrates): a per-thread, bounded pool
    recycles freed fiber stacks so a spawn skips the mmap AND the
    guard-page mprotect. Found on an EC2 192-core box: the exec-scale
    spawn path was flat at ~7 M/s regardless of core count while the
    scheduler / work-stealing / message paths scaled to 249 M/s, and
    perf showed 56% of spawn time in mprotect -> the process-wide
    mmap_lock. The pool removes that syscall + lock from every
    steady-state spawn (perf-verified 56% -> 0.78%). Honest framing: it
    is a syscall/lock elimination, not a throughput number on the
    current benchmarks -- those are only mprotect-bound under a
    pathological all-live-at-once burst the pool cannot help, and
    realistic workloads already scale. Kept for the latency/scalability
    win at near-zero cost.
  • bench_xproc_fanout: a cross-fork spawn/monitor scale probe (forks N
    children, monitors each, collects every DOWN). 1000 real
    forked+monitored children verified correct on the EC2 box.
  • First x86_64-Windows validation (EC2 Windows Server 2022, MSVC 2022
    Build Tools; prior MSVC coverage was ARM64/santorini only): the
    entire tree -- including the Windows xtc_xproc port, the stack-pool
    coro substrates, and xtc_tail -- compiles + links with MSVC x86_64,
    and every MSVC smoke check passes. The xtc_xproc CHILD path
    (CreateProcess re-exec + sentinel + loopback control) works; the
    end-to-end parent monitor round-trip is a documented WIP SKIP (POSIX
    xtc_xproc is fully tested). Fixed a brittle argv sentinel scan in
    xtc_xproc_win_child_maybe.
  • DST coverage: test_sim_pg (process-group broadcast fan-out to N
    subscribers, deterministic + replay-identical), completing DST for
    the recent orchestration features. The sim suite is now 52
    deterministic tests.
  • Internal: EC2 scale-benchmark findings recorded (Intel Sapphire
    Rapids vs Graviton4 -- the mprotect spawn ceiling is markedly worse
    on Intel; the scheduler scales to 192 cores on both).

-- Greg Burd greg@burd.me Sat, 11 Jul 2026 19:18:50 -0400

v1.13.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 20:44

libxtc (1.13.0-1) unstable; urgency=medium

  • Proc-teardown refcount: closes a use-after-free RACE CLASS at its
    shared root. __resolve() handed out a struct xtc_proc * after
    releasing the table lock, so a concurrent exit could free it
    mid-delivery (a DOWN send, a cross-thread wake, a mailbox-stats
    read). An atomic refcount taken while the table lock is held pins
    the proc across every resolve->deliver; the struct is freed only
    when the last reference drops. Validated by the CI ASan job, which
    now runs with detect_stack_use_after_return=1 (previously blocked by
    this race). New DST test test_sim_proc_teardown models the race
    deterministically.
  • Sanitizer fiber-switch annotations: both coro substrates (fcontext
    and ucontext) now call __sanitizer_start/finish_switch_fiber around
    every stack switch, so ASan/TSan/LSan track libxtc's user-space
    fiber switches instead of mis-attributing stack memory. The full
    fiber runtime passes ASan with detect_stack_use_after_return=1 on
    both substrates -- previously impossible. Zero cost / zero symbols
    in a non-sanitized build. Requested by the threaded-PostgreSQL
    integration.
  • Windows cross-process spawn/monitor (xtc_xproc): a real port, no
    longer an XTC_E_NOSYS decline. A portable child-entry registry
    (xtc_xproc_register_entry + xtc_xspawn_entry) addresses the child by
    a registered NAME the identical binary resolves in parent and child,
    bridging the absence of fork(); the Windows path re-execs via
    CreateProcess, uses a hardened loopback-TCP control channel (Winsock
    has no socketpair) with a per-spawn nonce, monitors exit via
    RegisterWaitForSingleObject, and maps the unhandled-exception
    NTSTATUS to a POSIX signal so a Windows crash surfaces as the same
    SIGNAL-kind DOWN as POSIX. xtc_xproc_win_child_maybe() is wired into
    the embedder's main().
  • xtc_xlink: bidirectional cross-fork fate (xtc_link across the fork
    boundary), rounding out the xtc_xproc relation set.
  • xtc_tail runtime microscope: (a) the binary dump format is now
    compact AND portable -- a little-endian header + LEB128 delta-encoded
    events (~9 bytes/event vs a 32-byte struct), byte-identical across
    endianness and padding, matching dial9's space discipline; (b) the
    MSG source records send / receive / mailbox-depth high-water
    alongside the existing SCHED source; (c) a new offline viewer,
    tools/xtc-tail.py, reads / filters / steps / summarizes a captured
    trace (including --wake-latency to find lost/late wakeups), and the
    gdb xtc-tail-dump command writes a live program's ring for it.
  • Docs: a consolidated, honest Windows-vs-POSIX model-gap section
    (no fork, no socketpair, the int-fd Unix-ism, the DLL-export gap,
    unlink-of-open-file) in the Windows matrix.
  • New public API: xtc_xproc_register_entry, xtc_xspawn_entry,
    xtc_xlink, xtc_xproc_win_child_maybe; xtc_tail SEND/RECV/MBOX_HWM
    event kinds; XTC_DOWN_KIND_NOCONNECTION (from 1.12.0). Sim suite
    grows to 51 deterministic tests.

-- Greg Burd greg@burd.me Sat, 11 Jul 2026 16:27:48 -0400

v1.12.0

Choose a tag to compare

@github-actions github-actions released this 10 Jul 23:18

libxtc (1.12.0-1) unstable; urgency=medium

  • Crash-aware registry (the R5 remainder). xtc_reg_reaper is a proc
    the embedder spawns once with the registry as its argument; it
    monitors every pid registered via xtc_reg_register_mon and
    auto-drops it (xtc_reg_drop_pid) when that pid goes DOWN -- the
    automatic form of the manual cleanup. xtc_svr_call_name adds
    via-dispatch: address a gen_server by registered name instead of by
    pid (the Erlang {via, ...} / global-name pattern). See xtc_reg(3).
  • Cross-fork spawn / send / monitor: xtc_xproc. Extends the
    Erlang-style process relations across a fork() boundary -- a parent
    xtc_xspawn()s a child running its own xtc runtime, then xtc_xsend()s
    to it and xtc_xmonitor()s it as if it were a local process. A child
    crash or exit surfaces as a normal, fully-classified xtc DOWN (exit
    code / signal decoded from the child's waitpid status), or
    XTC_DOWN_KIND_NOCONNECTION if the control channel dies first. The
    single-host subset of the distributed design, over an xtc_osproc
    control socketpair rather than TCP. POSIX only (Windows declines
    with XTC_E_NOSYS). See xtc_xproc(3).
  • xtc_tail runtime microscope (phase 1). A dial9-inspired recorder of
    individual runtime events tied to a precise instant -- the
    event-level complement to xtc_stats (aggregates) and xtc_trace
    (causal message trace). Phase 1 ships the SCHED source (proc spawn
    / exit), an in-process read visitor, and a versioned binary dump for
    a future offline viewer. OFF by default and one branch when a
    source is disabled, so it is safe to compile into production. The
    MSG / IO / OS sources, on-disk spill, and viewer are staged
    follow-ons. See xtc_tail(3).
  • New XTC_DOWN_KIND_NOCONNECTION down-kind (cross-process channel
    death). New installed headers xtc_xproc.h, xtc_tail.h. New DST
    coverage: test_sim_reg gains a dup-key membership + drop_pid
    scenario (deterministic, replay-identical).

-- Greg Burd greg@burd.me Fri, 10 Jul 2026 18:57:22 -0400