diff --git a/assets/diagrams/00-course-map.excalidraw b/assets/diagrams/00-course-map.excalidraw index d1de3e5..141bdeb 100644 --- a/assets/diagrams/00-course-map.excalidraw +++ b/assets/diagrams/00-course-map.excalidraw @@ -2627,13 +2627,13 @@ "updated": 1, "link": null, "locked": false, - "text": "The six artifacts grow across their part arcs and converge in the Chapter 41 capstone fleet.", + "text": "The six artifacts grow across their part arcs and converge in the Chapter 41 final-project fleet.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "The six artifacts grow across their part arcs and converge in the Chapter 41 capstone fleet.", + "originalText": "The six artifacts grow across their part arcs and converge in the Chapter 41 final-project fleet.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/00-course-map.svg b/assets/diagrams/00-course-map.svg index dc07247..237a796 100644 --- a/assets/diagrams/00-course-map.svg +++ b/assets/diagrams/00-course-map.svg @@ -77,5 +77,5 @@ -The six artifacts grow across their part arcs and converge in the Chapter 41 capstone fleet. +The six artifacts grow across their part arcs and converge in the Chapter 41 final-project fleet. \ No newline at end of file diff --git a/assets/diagrams/02-lab-topology.excalidraw b/assets/diagrams/02-lab-topology.excalidraw index a33f1ee..8ef2a84 100644 --- a/assets/diagrams/02-lab-topology.excalidraw +++ b/assets/diagrams/02-lab-topology.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "host \u2014 Fedora 44, kernel 7.1.3 (workstation stays untouched)", + "text": "host: Fedora 44, kernel 7.1.3 (workstation stays untouched)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "host \u2014 Fedora 44, kernel 7.1.3 (workstation stays untouched)", + "originalText": "host: Fedora 44, kernel 7.1.3 (workstation stays untouched)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "libvirt NAT network 'default' \u2014 192.168.124.0/24 (gateway .1)", + "text": "libvirt NAT network 'default': 192.168.124.0/24 (gateway .1)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "libvirt NAT network 'default' \u2014 192.168.124.0/24 (gateway .1)", + "originalText": "libvirt NAT network 'default': 192.168.124.0/24 (gateway .1)", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/02-lab-topology.svg b/assets/diagrams/02-lab-topology.svg index 2ef7d00..50219ad 100644 --- a/assets/diagrams/02-lab-topology.svg +++ b/assets/diagrams/02-lab-topology.svg @@ -1,9 +1,9 @@ -host — Fedora 44, kernel 7.1.3 (workstation stays untouched) +host: Fedora 44, kernel 7.1.3 (workstation stays untouched) -libvirt NAT network 'default' — 192.168.124.0/24 (gateway .1) +libvirt NAT network 'default': 192.168.124.0/24 (gateway .1) libvirtd / KVM qemu:///system diff --git a/assets/diagrams/05-error-flow-three-ways.excalidraw b/assets/diagrams/05-error-flow-three-ways.excalidraw index 7a9290f..cacab06 100644 --- a/assets/diagrams/05-error-flow-three-ways.excalidraw +++ b/assets/diagrams/05-error-flow-three-ways.excalidraw @@ -315,13 +315,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ENOSPC \u2014 the ABI", + "text": "ENOSPC: the ABI", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ENOSPC \u2014 the ABI", + "originalText": "ENOSPC: the ABI", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/05-error-flow-three-ways.svg b/assets/diagrams/05-error-flow-three-ways.svg index e2b7d15..66484e5 100644 --- a/assets/diagrams/05-error-flow-three-ways.svg +++ b/assets/diagrams/05-error-flow-three-ways.svg @@ -9,7 +9,7 @@ returns -ENOSPC errno = 28 -ENOSPC — the ABI +ENOSPC: the ABI std::expected<T, std::error_code> diff --git a/assets/diagrams/06-three-concurrency-models.excalidraw b/assets/diagrams/06-three-concurrency-models.excalidraw index 2454fad..dcb59c9 100644 --- a/assets/diagrams/06-three-concurrency-models.excalidraw +++ b/assets/diagrams/06-three-concurrency-models.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++23 \u2014 what the standard gives", + "text": "C++23: what the standard gives", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++23 \u2014 what the standard gives", + "originalText": "C++23: what the standard gives", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Go \u2014 the GMP runtime", + "text": "Go: the GMP runtime", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Go \u2014 the GMP runtime", + "originalText": "Go: the GMP runtime", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Rust \u2014 ownership-checked", + "text": "Rust: ownership-checked", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Rust \u2014 ownership-checked", + "originalText": "Rust: ownership-checked", "lineHeight": 1.25, "baseline": 12 }, @@ -2200,13 +2200,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one program shape, three vocabularies \u2014 byte-identical stdout", + "text": "one program shape, three vocabularies: byte-identical stdout", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one program shape, three vocabularies \u2014 byte-identical stdout", + "originalText": "one program shape, three vocabularies: byte-identical stdout", "lineHeight": 1.25, "baseline": 11 }, @@ -2235,13 +2235,13 @@ "updated": 1, "link": null, "locked": false, - "text": "same kernel threads underneath \u2014 /proc//task while hashing: C++ 6, Go 10, Rust 5", + "text": "same kernel threads underneath: /proc//task while hashing: C++ 6, Go 10, Rust 5", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "same kernel threads underneath \u2014 /proc//task while hashing: C++ 6, Go 10, Rust 5", + "originalText": "same kernel threads underneath: /proc//task while hashing: C++ 6, Go 10, Rust 5", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/06-three-concurrency-models.svg b/assets/diagrams/06-three-concurrency-models.svg index fafe454..acae794 100644 --- a/assets/diagrams/06-three-concurrency-models.svg +++ b/assets/diagrams/06-three-concurrency-models.svg @@ -1,11 +1,11 @@ -C++23 — what the standard gives +C++23: what the standard gives -Go — the GMP runtime +Go: the GMP runtime -Rust — ownership-checked +Rust: ownership-checked main thread walks the tree, push() @@ -69,6 +69,6 @@ flag polled flag polled -one program shape, three vocabularies — byte-identical stdout -same kernel threads underneath — /proc/<pid>/task while hashing: C++ 6, Go 10, Rust 5 +one program shape, three vocabularies: byte-identical stdout +same kernel threads underneath: /proc/<pid>/task while hashing: C++ 6, Go 10, Rust 5 \ No newline at end of file diff --git a/assets/diagrams/07-fd-table-vfs.excalidraw b/assets/diagrams/07-fd-table-vfs.excalidraw index 3d0887c..1b6faaf 100644 --- a/assets/diagrams/07-fd-table-vfs.excalidraw +++ b/assets/diagrams/07-fd-table-vfs.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fwatch process \u2014 fd table (ls -l /proc/PID/fd)", + "text": "fwatch process: fd table (ls -l /proc/PID/fd)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fwatch process \u2014 fd table (ls -l /proc/PID/fd)", + "originalText": "fwatch process: fd table (ls -l /proc/PID/fd)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 open file descriptions (flags + offset live here)", + "text": "kernel: open file descriptions (flags + offset live here)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 open file descriptions (flags + offset live here)", + "originalText": "kernel: open file descriptions (flags + offset live here)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "VFS \u2014 inodes (what ls -li numbers)", + "text": "VFS: inodes (what ls -li numbers)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "VFS \u2014 inodes (what ls -li numbers)", + "originalText": "VFS: inodes (what ls -li numbers)", "lineHeight": 1.25, "baseline": 12 }, @@ -2384,13 +2384,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one paused fwatch walk: four dirfds, one recursion chain \u2014 cloexec is a per-fd bit; flags and offset are per-description", + "text": "one paused fwatch walk: four dirfds, one recursion chain: cloexec is a per-fd bit; flags and offset are per-description", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one paused fwatch walk: four dirfds, one recursion chain \u2014 cloexec is a per-fd bit; flags and offset are per-description", + "originalText": "one paused fwatch walk: four dirfds, one recursion chain: cloexec is a per-fd bit; flags and offset are per-description", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/07-fd-table-vfs.svg b/assets/diagrams/07-fd-table-vfs.svg index 1a52c3b..acc12e6 100644 --- a/assets/diagrams/07-fd-table-vfs.svg +++ b/assets/diagrams/07-fd-table-vfs.svg @@ -1,11 +1,11 @@ -fwatch process — fd table (ls -l /proc/PID/fd) +fwatch process: fd table (ls -l /proc/PID/fd) -kernel — open file descriptions (flags + offset live here) +kernel: open file descriptions (flags + offset live here) -VFS — inodes (what ls -li numbers) +VFS: inodes (what ls -li numbers) fd 0 · 1 · 2 stdin/out/err @@ -71,7 +71,7 @@ openat openat -one paused fwatch walk: four dirfds, one recursion chain — cloexec is a per-fd bit; flags and offset are per-description +one paused fwatch walk: four dirfds, one recursion chain: cloexec is a per-fd bit; flags and offset are per-description dup/fork copy fd entries; descriptions are shared fdinfo ino == ls -li diff --git a/assets/diagrams/08-write-path-page-cache.excalidraw b/assets/diagrams/08-write-path-page-cache.excalidraw index 4a95c1e..4092f08 100644 --- a/assets/diagrams/08-write-path-page-cache.excalidraw +++ b/assets/diagrams/08-write-path-page-cache.excalidraw @@ -378,13 +378,13 @@ "updated": 1, "link": null, "locked": false, - "text": "write(2) copies in and dirties pages \u2014 Dirty: in /proc/meminfo", + "text": "write(2) copies in and dirties pages: Dirty: in /proc/meminfo", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "write(2) copies in and dirties pages \u2014 Dirty: in /proc/meminfo", + "originalText": "write(2) copies in and dirties pages: Dirty: in /proc/meminfo", "lineHeight": 1.25, "baseline": 11 }, @@ -687,13 +687,13 @@ "updated": 1, "link": null, "locked": false, - "text": "write(2) \u2014 a memcpy", + "text": "write(2): a memcpy", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "write(2) \u2014 a memcpy", + "originalText": "write(2): a memcpy", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/08-write-path-page-cache.svg b/assets/diagrams/08-write-path-page-cache.svg index 1e66396..d863834 100644 --- a/assets/diagrams/08-write-path-page-cache.svg +++ b/assets/diagrams/08-write-path-page-cache.svg @@ -11,7 +11,7 @@ one 64 KiB block, 4096-aligned, written M x 16 times page cache -write(2) copies in and dirties pages — Dirty: in /proc/meminfo +write(2) copies in and dirties pages: Dirty: in /proc/meminfo no cache copy kernel DMAs straight @@ -20,8 +20,8 @@ NVMe device bytes are durable only after they land here -write(2) — a memcpy -write(2) — a memcpy +write(2): a memcpy +write(2): a memcpy writeback, later writeback, later diff --git a/assets/diagrams/09-event-loop-anatomy.excalidraw b/assets/diagrams/09-event-loop-anatomy.excalidraw index 492db42..4d15249 100644 --- a/assets/diagrams/09-event-loop-anatomy.excalidraw +++ b/assets/diagrams/09-event-loop-anatomy.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "user space \u2014 one thread; nothing blocks except epoll_wait(2)", + "text": "user space: one thread; nothing blocks except epoll_wait(2)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "user space \u2014 one thread; nothing blocks except epoll_wait(2)", + "originalText": "user space: one thread; nothing blocks except epoll_wait(2)", "lineHeight": 1.25, "baseline": 12 }, @@ -714,13 +714,13 @@ "updated": 1, "link": null, "locked": false, - "text": "eventpoll \u2014 interest list", + "text": "eventpoll: interest list", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "eventpoll \u2014 interest list", + "originalText": "eventpoll: interest list", "lineHeight": 1.25, "baseline": 14 }, @@ -812,13 +812,13 @@ "updated": 1, "link": null, "locked": false, - "text": "inotify fd \u2014 token 0", + "text": "inotify fd: token 0", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "inotify fd \u2014 token 0", + "originalText": "inotify fd: token 0", "lineHeight": 1.25, "baseline": 14 }, @@ -945,13 +945,13 @@ "updated": 1, "link": null, "locked": false, - "text": "timerfd \u2014 token 1", + "text": "timerfd: token 1", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "timerfd \u2014 token 1", + "originalText": "timerfd: token 1", "lineHeight": 1.25, "baseline": 14 }, @@ -1078,13 +1078,13 @@ "updated": 1, "link": null, "locked": false, - "text": "signalfd \u2014 token 2", + "text": "signalfd: token 2", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "signalfd \u2014 token 2", + "originalText": "signalfd: token 2", "lineHeight": 1.25, "baseline": 14 }, @@ -1901,13 +1901,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fwatch watch \u2014 one epoll loop, three event sources", + "text": "fwatch watch: one epoll loop, three event sources", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fwatch watch \u2014 one epoll loop, three event sources", + "originalText": "fwatch watch: one epoll loop, three event sources", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/09-event-loop-anatomy.svg b/assets/diagrams/09-event-loop-anatomy.svg index ac7b27d..6926acd 100644 --- a/assets/diagrams/09-event-loop-anatomy.svg +++ b/assets/diagrams/09-event-loop-anatomy.svg @@ -1,7 +1,7 @@ -user space — one thread; nothing blocks except epoll_wait(2) +user space: one thread; nothing blocks except epoll_wait(2) kernel @@ -21,18 +21,18 @@ read until EAGAIN, coalesce, flush due -eventpoll — interest list +eventpoll: interest list tfd 3·4·5, level-triggered EPOLLIN -inotify fd — token 0 +inotify fd: token 0 wd 1 on DIR, mask 0x3c6 per-watch event queue -timerfd — token 1 +timerfd: token 1 CLOCK_MONOTONIC, one-shot expirations -signalfd — token 2 +signalfd: token 2 blocked SIGINT/SIGTERM as readable data @@ -60,6 +60,6 @@ ready: {EPOLLIN, token} ready: {EPOLLIN, token} -fwatch watch — one epoll loop, three event sources +fwatch watch: one epoll loop, three event sources Go inverts this picture: the runtime netpoller owns the loop (epoll_pwait) and surfaces each source as a channel \ No newline at end of file diff --git a/assets/diagrams/10-readiness-vs-completion.excalidraw b/assets/diagrams/10-readiness-vs-completion.excalidraw index 83a7fac..3fe4f9b 100644 --- a/assets/diagrams/10-readiness-vs-completion.excalidraw +++ b/assets/diagrams/10-readiness-vs-completion.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "readiness \u2014 epoll (chapter 9)", + "text": "readiness: epoll (chapter 9)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "readiness \u2014 epoll (chapter 9)", + "originalText": "readiness: epoll (chapter 9)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "completion \u2014 io_uring (this chapter)", + "text": "completion: io_uring (this chapter)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "completion \u2014 io_uring (this chapter)", + "originalText": "completion: io_uring (this chapter)", "lineHeight": 1.25, "baseline": 12 }, @@ -413,13 +413,13 @@ "updated": 1, "link": null, "locked": false, - "text": "read(fd) / write(fd) \u2014 one syscall per op", + "text": "read(fd) / write(fd): one syscall per op", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "read(fd) / write(fd) \u2014 one syscall per op", + "originalText": "read(fd) / write(fd): one syscall per op", "lineHeight": 1.25, "baseline": 11 }, @@ -672,13 +672,13 @@ "updated": 1, "link": null, "locked": false, - "text": "io_uring_enter \u2014 submit N, wait M", + "text": "io_uring_enter: submit N, wait M", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "io_uring_enter \u2014 submit N, wait M", + "originalText": "io_uring_enter: submit N, wait M", "lineHeight": 1.25, "baseline": 14 }, @@ -903,13 +903,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cqe.res = bytes done \u2014 no second syscall", + "text": "cqe.res = bytes done: no second syscall", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cqe.res = bytes done \u2014 no second syscall", + "originalText": "cqe.res = bytes done: no second syscall", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/10-readiness-vs-completion.svg b/assets/diagrams/10-readiness-vs-completion.svg index b680489..338938d 100644 --- a/assets/diagrams/10-readiness-vs-completion.svg +++ b/assets/diagrams/10-readiness-vs-completion.svg @@ -1,9 +1,9 @@ -readiness — epoll (chapter 9) +readiness: epoll (chapter 9) -completion — io_uring (this chapter) +completion: io_uring (this chapter) epoll_wait(epfd, ...) “tell me when these fds are ready” @@ -12,7 +12,7 @@ fd 7 readable, fd 12 writable ... you still do the I/O yourself -read(fd) / write(fd) — one syscall per op +read(fd) / write(fd): one syscall per op and it can still fail with EAGAIN readiness is a hint, not a result @@ -20,14 +20,14 @@ queue SQEs describing the I/O “read 128 KiB at offset 0 into this buffer” -io_uring_enter — submit N, wait M +io_uring_enter: submit N, wait M one syscall carries the whole batch kernel does the I/O inline if it can, io-wq workers if it would block CQEs carry finished results -cqe.res = bytes done — no second syscall +cqe.res = bytes done: no second syscall wakeup diff --git a/assets/diagrams/10-uring-rings.excalidraw b/assets/diagrams/10-uring-rings.excalidraw index 6667858..c3b5149 100644 --- a/assets/diagrams/10-uring-rings.excalidraw +++ b/assets/diagrams/10-uring-rings.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "user space \u2014 fwatch", + "text": "user space: fwatch", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "user space \u2014 fwatch", + "originalText": "user space: fwatch", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "shared memory \u2014 mmap'd from the ring fd", + "text": "shared memory: mmap'd from the ring fd", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "shared memory \u2014 mmap'd from the ring fd", + "originalText": "shared memory: mmap'd from the ring fd", "lineHeight": 1.25, "baseline": 12 }, @@ -476,13 +476,13 @@ "updated": 1, "link": null, "locked": false, - "text": "drain() \u2014 pop CQEs", + "text": "drain(): pop CQEs", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "drain() \u2014 pop CQEs", + "originalText": "drain(): pop CQEs", "lineHeight": 1.25, "baseline": 14 }, @@ -1863,13 +1863,13 @@ "updated": 1, "link": null, "locked": false, - "text": "io_uring: two lock-free rings shared with the kernel \u2014 describe operations, don't call them", + "text": "io_uring: two lock-free rings shared with the kernel: describe operations, don't call them", "fontSize": 13, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "io_uring: two lock-free rings shared with the kernel \u2014 describe operations, don't call them", + "originalText": "io_uring: two lock-free rings shared with the kernel: describe operations, don't call them", "lineHeight": 1.25, "baseline": 13 }, @@ -1898,13 +1898,13 @@ "updated": 1, "link": null, "locked": false, - "text": "on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP \u2014 SQ+CQ rings in one 2368-byte mapping at offset 0,", + "text": "on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP: SQ+CQ rings in one 2368-byte mapping at offset 0,", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP \u2014 SQ+CQ rings in one 2368-byte mapping at offset 0,", + "originalText": "on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP: SQ+CQ rings in one 2368-byte mapping at offset 0,", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/10-uring-rings.svg b/assets/diagrams/10-uring-rings.svg index ba903c7..ed5d5ca 100644 --- a/assets/diagrams/10-uring-rings.svg +++ b/assets/diagrams/10-uring-rings.svg @@ -1,9 +1,9 @@ -user space — fwatch +user space: fwatch -shared memory — mmap'd from the ring fd +shared memory: mmap'd from the ring fd kernel @@ -14,7 +14,7 @@ submit_and_wait(2·pairs) store-release SQ tail, then enter -drain() — pop CQEs +drain(): pop CQEs load-acquire CQ tail, bump head SQ ring @@ -60,7 +60,7 @@ post results post results -io_uring: two lock-free rings shared with the kernel — describe operations, don't call them -on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP — SQ+CQ rings in one 2368-byte mapping at offset 0, +io_uring: two lock-free rings shared with the kernel: describe operations, don't call them +on this host (kernel 7.1.3): IORING_FEAT_SINGLE_MMAP: SQ+CQ rings in one 2368-byte mapping at offset 0, SQE array in a second mapping at IORING_OFF_SQES (0x10000000) \ No newline at end of file diff --git a/assets/diagrams/11-fork-exec-wait-seq.excalidraw b/assets/diagrams/11-fork-exec-wait-seq.excalidraw index 75894bb..25c3a43 100644 --- a/assets/diagrams/11-fork-exec-wait-seq.excalidraw +++ b/assets/diagrams/11-fork-exec-wait-seq.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "parent \u2014 pmon", + "text": "parent: pmon", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "parent \u2014 pmon", + "originalText": "parent: pmon", "lineHeight": 1.25, "baseline": 12 }, @@ -413,13 +413,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fd table copied \u2014 pipe write end inherited", + "text": "fd table copied: pipe write end inherited", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fd table copied \u2014 pipe write end inherited", + "originalText": "fd table copied: pipe write end inherited", "lineHeight": 1.25, "baseline": 11 }, @@ -1500,13 +1500,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Go\u2019s os/exec and Rust\u2019s Command run this same sequence internally \u2014 strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND})", + "text": "Go\u2019s os/exec and Rust\u2019s Command run this same sequence internally: strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND})", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Go\u2019s os/exec and Rust\u2019s Command run this same sequence internally \u2014 strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND})", + "originalText": "Go\u2019s os/exec and Rust\u2019s Command run this same sequence internally: strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND})", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/11-fork-exec-wait-seq.svg b/assets/diagrams/11-fork-exec-wait-seq.svg index 3e201d8..983b443 100644 --- a/assets/diagrams/11-fork-exec-wait-seq.svg +++ b/assets/diagrams/11-fork-exec-wait-seq.svg @@ -1,7 +1,7 @@ -parent — pmon +parent: pmon child → the command @@ -12,7 +12,7 @@ COW: pages shared until either side writes same program, pid of its own -fd table copied — pipe write end inherited +fd table copied: pipe write end inherited execvp(CMD) success: O_CLOEXEC closes the pipe end @@ -46,5 +46,5 @@ zombie until reaped · SIGCHLD pmon’s lifecycle: fork → exec → wait, with a CLOEXEC self-pipe carrying the exec verdict -Go’s os/exec and Rust’s Command run this same sequence internally — strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND}) +Go’s os/exec and Rust’s Command run this same sequence internally: strace shows clone(CLONE_VM|CLONE_PIDFD|CLONE_VFORK|SIGCHLD) and clone3({CLONE_VM|CLONE_VFORK|CLONE_CLEAR_SIGHAND}) \ No newline at end of file diff --git a/assets/diagrams/11-process-lifecycle-states.excalidraw b/assets/diagrams/11-process-lifecycle-states.excalidraw index 9387c19..4d14358 100644 --- a/assets/diagrams/11-process-lifecycle-states.excalidraw +++ b/assets/diagrams/11-process-lifecycle-states.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "alive \u2014 address space, threads, fds", + "text": "alive: address space, threads, fds", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "alive \u2014 address space, threads, fds", + "originalText": "alive: address space, threads, fds", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "after exit \u2014 only the task record", + "text": "after exit: only the task record", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "after exit \u2014 only the task record", + "originalText": "after exit: only the task record", "lineHeight": 1.25, "baseline": 12 }, @@ -742,13 +742,13 @@ "updated": 1, "link": null, "locked": false, - "text": "reaped \u2014 pid table slot free", + "text": "reaped: pid table slot free", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "reaped \u2014 pid table slot free", + "originalText": "reaped: pid table slot free", "lineHeight": 1.25, "baseline": 14 }, @@ -1358,13 +1358,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Process states as ps STAT letters \u2014 the kernel keeps a zombie until someone reaps it", + "text": "Process states as ps STAT letters: the kernel keeps a zombie until someone reaps it", "fontSize": 13, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Process states as ps STAT letters \u2014 the kernel keeps a zombie until someone reaps it", + "originalText": "Process states as ps STAT letters: the kernel keeps a zombie until someone reaps it", "lineHeight": 1.25, "baseline": 13 }, diff --git a/assets/diagrams/11-process-lifecycle-states.svg b/assets/diagrams/11-process-lifecycle-states.svg index ade20f4..b01fde9 100644 --- a/assets/diagrams/11-process-lifecycle-states.svg +++ b/assets/diagrams/11-process-lifecycle-states.svg @@ -1,9 +1,9 @@ -alive — address space, threads, fds +alive: address space, threads, fds -after exit — only the task record +after exit: only the task record fork / clone3 returns twice @@ -22,7 +22,7 @@ exit status + rusage only VmRSS gone, rss field 0 -reaped — pid table slot free +reaped: pid table slot free status copied to the parent child starts @@ -45,6 +45,6 @@ parent wait4 / waitid parent wait4 / waitid -Process states as ps STAT letters — the kernel keeps a zombie until someone reaps it +Process states as ps STAT letters: the kernel keeps a zombie until someone reaps it observed: pmon stopped mid-wait (STAT TN) left its exited child as ZN ‘[sleep] <defunct>’ for a 4 s window; SIGCONT reaped it \ No newline at end of file diff --git a/assets/diagrams/12-signal-delivery-paths.excalidraw b/assets/diagrams/12-signal-delivery-paths.excalidraw index cc0eff0..1c54df0 100644 --- a/assets/diagrams/12-signal-delivery-paths.excalidraw +++ b/assets/diagrams/12-signal-delivery-paths.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 every signal passes the same three words", + "text": "kernel: every signal passes the same three words", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 every signal passes the same three words", + "originalText": "kernel: every signal passes the same three words", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon supervise \u2014 three ways to hear the same signals, none in signal context", + "text": "pmon supervise: three ways to hear the same signals, none in signal context", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon supervise \u2014 three ways to hear the same signals, none in signal context", + "originalText": "pmon supervise: three ways to hear the same signals, none in signal context", "lineHeight": 1.25, "baseline": 12 }, @@ -609,13 +609,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one bit per signal \u2014 coalesces", + "text": "one bit per signal: coalesces", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one bit per signal \u2014 coalesces", + "originalText": "one bit per signal: coalesces", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/12-signal-delivery-paths.svg b/assets/diagrams/12-signal-delivery-paths.svg index aef01ac..9113c82 100644 --- a/assets/diagrams/12-signal-delivery-paths.svg +++ b/assets/diagrams/12-signal-delivery-paths.svg @@ -1,9 +1,9 @@ -kernel — every signal passes the same three words +kernel: every signal passes the same three words -pmon supervise — three ways to hear the same signals, none in signal context +pmon supervise: three ways to hear the same signals, none in signal context kill -TERM <pid> tgkill, terminal ^C @@ -18,7 +18,7 @@ blocked signals wait pending set -one bit per signal — coalesces +one bit per signal: coalesces delivery only when unblocked diff --git a/assets/diagrams/12-supervisor-state-machine.excalidraw b/assets/diagrams/12-supervisor-state-machine.excalidraw index 02eb1e6..4d82af5 100644 --- a/assets/diagrams/12-supervisor-state-machine.excalidraw +++ b/assets/diagrams/12-supervisor-state-machine.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon supervise \u2014 one loop, two live states", + "text": "pmon supervise: one loop, two live states", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon supervise \u2014 one loop, two live states", + "originalText": "pmon supervise: one loop, two live states", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/12-supervisor-state-machine.svg b/assets/diagrams/12-supervisor-state-machine.svg index 8da57e5..888cd52 100644 --- a/assets/diagrams/12-supervisor-state-machine.svg +++ b/assets/diagrams/12-supervisor-state-machine.svg @@ -1,7 +1,7 @@ -pmon supervise — one loop, two live states +pmon supervise: one loop, two live states child running poll timeout = infinite diff --git a/assets/diagrams/13-pid-reuse-race-pidfd.excalidraw b/assets/diagrams/13-pid-reuse-race-pidfd.excalidraw index b33befa..e2dd010 100644 --- a/assets/diagrams/13-pid-reuse-race-pidfd.excalidraw +++ b/assets/diagrams/13-pid-reuse-race-pidfd.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "supervising by pid number \u2014 five steps to signalling a stranger", + "text": "supervising by pid number: five steps to signalling a stranger", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "supervising by pid number \u2014 five steps to signalling a stranger", + "originalText": "supervising by pid number: five steps to signalling a stranger", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "supervising by pidfd \u2014 the fd pins the identity", + "text": "supervising by pidfd: the fd pins the identity", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "supervising by pidfd \u2014 the fd pins the identity", + "originalText": "supervising by pidfd: the fd pins the identity", "lineHeight": 1.25, "baseline": 12 }, @@ -483,13 +483,13 @@ "updated": 1, "link": null, "locked": false, - "text": "a wait() collects it \u2014", + "text": "a wait() collects it", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "a wait() collects it \u2014", + "originalText": "a wait() collects it", "lineHeight": 1.25, "baseline": 11 }, @@ -1015,13 +1015,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pidfd 4 turns readable \u2014", + "text": "pidfd 4 turns readable", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pidfd 4 turns readable \u2014", + "originalText": "pidfd 4 turns readable", "lineHeight": 1.25, "baseline": 11 }, @@ -1281,13 +1281,13 @@ "updated": 1, "link": null, "locked": false, - "text": "after exit: ESRCH \u2014", + "text": "after exit: ESRCH", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "after exit: ESRCH \u2014", + "originalText": "after exit: ESRCH", "lineHeight": 1.25, "baseline": 11 }, @@ -1835,13 +1835,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Real run on this host: /proc//fdinfo/4 reads Pid: 2624390 \u2014 the fd itself names the child;", + "text": "Real run on this host: /proc//fdinfo/4 reads Pid: 2624390 : the fd itself names the child;", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Real run on this host: /proc//fdinfo/4 reads Pid: 2624390 \u2014 the fd itself names the child;", + "originalText": "Real run on this host: /proc//fdinfo/4 reads Pid: 2624390 : the fd itself names the child;", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/13-pid-reuse-race-pidfd.svg b/assets/diagrams/13-pid-reuse-race-pidfd.svg index 645a6cc..fef0a6a 100644 --- a/assets/diagrams/13-pid-reuse-race-pidfd.svg +++ b/assets/diagrams/13-pid-reuse-race-pidfd.svg @@ -1,9 +1,9 @@ -supervising by pid number — five steps to signalling a stranger +supervising by pid number: five steps to signalling a stranger -supervising by pidfd — the fd pins the identity +supervising by pidfd: the fd pins the identity 1 spawn remember pid 4242 @@ -14,7 +14,7 @@ reserved, status pending 3 reaped elsewhere -a wait() collects it — +a wait() collects it pid 4242 is now free 4 kernel recycles @@ -30,7 +30,7 @@ fd refers to the process 2 child exits -pidfd 4 turns readable — +pidfd 4 turns readable poll/epoll sees POLLIN 3 waitid(P_PIDFD, 4) @@ -38,7 +38,7 @@ behind the fd 4 pidfd_send_signal(4) -after exit: ESRCH — +after exit: ESRCH never a recycled pid @@ -55,7 +55,7 @@ readable The window 3->5 can be microseconds or hours; nothing the supervisor holds distinguishes old 4242 from new 4242. -Real run on this host: /proc/<pmon>/fdinfo/4 reads Pid: 2624390 — the fd itself names the child; +Real run on this host: /proc/<pmon>/fdinfo/4 reads Pid: 2624390 : the fd itself names the child; strace: pidfd_open(2624926)=4, poll([pidfd,signalfd]) -> POLLIN, waitid(P_PIDFD,4)=CLD_KILLED, pidfd_send_signal(4,SIGTERM)=0. Steps 1-5 above are the classic pid-reuse race every kill(2)-based supervisor carries; the lower lane is pmon v2's default engine. \ No newline at end of file diff --git a/assets/diagrams/14-credential-sets-caps.excalidraw b/assets/diagrams/14-credential-sets-caps.excalidraw index 29fd6ce..6d8cba4 100644 --- a/assets/diagrams/14-credential-sets-caps.excalidraw +++ b/assets/diagrams/14-credential-sets-caps.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "three uids, one state machine \u2014 setresuid(65534, 65534, 65534) moves all three at once", + "text": "three uids, one state machine: setresuid(65534, 65534, 65534) moves all three at once", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "three uids, one state machine \u2014 setresuid(65534, 65534, 65534) moves all three at once", + "originalText": "three uids, one state machine: setresuid(65534, 65534, 65534) moves all three at once", "lineHeight": 1.25, "baseline": 12 }, @@ -518,13 +518,13 @@ "updated": 1, "link": null, "locked": false, - "text": "the way back \u2014 gone after the drop", + "text": "the way back: gone after the drop", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "the way back \u2014 gone after the drop", + "originalText": "the way back: gone after the drop", "lineHeight": 1.25, "baseline": 11 }, @@ -2409,13 +2409,13 @@ "updated": 1, "link": null, "locked": false, - "text": "seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back \u2014 pmon sets all three so there is no way back.", + "text": "seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back: pmon sets all three so there is no way back.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back \u2014 pmon sets all three so there is no way back.", + "originalText": "seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back: pmon sets all three so there is no way back.", "lineHeight": 1.25, "baseline": 11 }, @@ -2479,13 +2479,13 @@ "updated": 1, "link": null, "locked": false, - "text": "capsh --decode=0000000000000400 \u2192 cap_net_bind_service; the bounding set masks what execve may grant \u2014 it never grants anything itself.", + "text": "capsh --decode=0000000000000400 \u2192 cap_net_bind_service; the bounding set masks what execve may grant: it never grants anything itself.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "capsh --decode=0000000000000400 \u2192 cap_net_bind_service; the bounding set masks what execve may grant \u2014 it never grants anything itself.", + "originalText": "capsh --decode=0000000000000400 \u2192 cap_net_bind_service; the bounding set masks what execve may grant: it never grants anything itself.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/14-credential-sets-caps.svg b/assets/diagrams/14-credential-sets-caps.svg index f3950ed..a1d87a5 100644 --- a/assets/diagrams/14-credential-sets-caps.svg +++ b/assets/diagrams/14-credential-sets-caps.svg @@ -1,7 +1,7 @@ -three uids, one state machine — setresuid(65534, 65534, 65534) moves all three at once +three uids, one state machine: setresuid(65534, 65534, 65534) moves all three at once capability sets across pmon drop --user nobody --keep-cap net_bind_service (values from /proc/<pid>/status on systems-target) @@ -15,7 +15,7 @@ saved uid 0 → 65534 -the way back — gone after the drop +the way back: gone after the drop pmon (root) uid r/e/s = 0/0/0 @@ -71,8 +71,8 @@ nothing to raise nothing to raise -seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back — pmon sets all three so there is no way back. +seteuid() moves only the middle one; the saved uid is what lets a set-uid binary flip back: pmon sets all three so there is no way back. child status, kept-cap run: CapInh = CapPrm = CapEff = CapAmb = 0000000000000400 · CapBnd = 000001ffffffffff -capsh --decode=0000000000000400 → cap_net_bind_service; the bounding set masks what execve may grant — it never grants anything itself. +capsh --decode=0000000000000400 → cap_net_bind_service; the bounding set masks what execve may grant: it never grants anything itself. negative control: getpcaps prints an empty set and every Cap line but CapBnd reads 0000000000000000. \ No newline at end of file diff --git a/assets/diagrams/15-address-space-map.excalidraw b/assets/diagrams/15-address-space-map.excalidraw index 8a60d91..eaea4ba 100644 --- a/assets/diagrams/15-address-space-map.excalidraw +++ b/assets/diagrams/15-address-space-map.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "mmap region \u2014 kernel hands out addresses top-down", + "text": "mmap region: kernel hands out addresses top-down", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "mmap region \u2014 kernel hands out addresses top-down", + "originalText": "mmap region: kernel hands out addresses top-down", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "[vsyscall] --xp \u2014 legacy, kernel-owned", + "text": "[vsyscall] --xp: legacy, kernel-owned", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "[vsyscall] --xp \u2014 legacy, kernel-owned", + "originalText": "[vsyscall] --xp: legacy, kernel-owned", "lineHeight": 1.25, "baseline": 14 }, @@ -280,13 +280,13 @@ "updated": 1, "link": null, "locked": false, - "text": "unmapped \u2014 gigabytes of gap", + "text": "unmapped: gigabytes of gap", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "unmapped \u2014 gigabytes of gap", + "originalText": "unmapped: gigabytes of gap", "lineHeight": 1.25, "baseline": 14 }, @@ -343,13 +343,13 @@ "updated": 1, "link": null, "locked": false, - "text": "[vdso] [vvar] \u2014 kernel-provided pages", + "text": "[vdso] [vvar]: kernel-provided pages", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "[vdso] [vvar] \u2014 kernel-provided pages", + "originalText": "[vdso] [vvar]: kernel-provided pages", "lineHeight": 1.25, "baseline": 14 }, @@ -406,13 +406,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ld-linux, libc.so.6 \u2014 4 segments each", + "text": "ld-linux, libc.so.6: 4 segments each", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ld-linux, libc.so.6 \u2014 4 segments each", + "originalText": "ld-linux, libc.so.6: 4 segments each", "lineHeight": 1.25, "baseline": 14 }, @@ -539,13 +539,13 @@ "updated": 1, "link": null, "locked": false, - "text": "mmap(NULL, 67112960, ...) \u2014 the big allocation", + "text": "mmap(NULL, 67112960, ...): the big allocation", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "mmap(NULL, 67112960, ...) \u2014 the big allocation", + "originalText": "mmap(NULL, 67112960, ...): the big allocation", "lineHeight": 1.25, "baseline": 11 }, @@ -665,13 +665,13 @@ "updated": 1, "link": null, "locked": false, - "text": "[heap] rw-p \u2014 the brk arena", + "text": "[heap] rw-p: the brk arena", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "[heap] rw-p \u2014 the brk arena", + "originalText": "[heap] rw-p: the brk arena", "lineHeight": 1.25, "baseline": 14 }, diff --git a/assets/diagrams/15-address-space-map.svg b/assets/diagrams/15-address-space-map.svg index 094f0f4..e8a6781 100644 --- a/assets/diagrams/15-address-space-map.svg +++ b/assets/diagrams/15-address-space-map.svg @@ -1,26 +1,26 @@ -mmap region — kernel hands out addresses top-down +mmap region: kernel hands out addresses top-down -[vsyscall] --xp — legacy, kernel-owned +[vsyscall] --xp: legacy, kernel-owned [stack] rw-p grows down; 8 MiB rlimit -unmapped — gigabytes of gap +unmapped: gigabytes of gap -[vdso] [vvar] — kernel-provided pages +[vdso] [vvar]: kernel-provided pages -ld-linux, libc.so.6 — 4 segments each +ld-linux, libc.so.6: 4 segments each r-xp / r--p / r--p / rw-p 64 MiB anonymous rw-p -mmap(NULL, 67112960, ...) — the big allocation +mmap(NULL, 67112960, ...): the big allocation unmapped -[heap] rw-p — the brk arena +[heap] rw-p: the brk arena 204 KiB at startup; small allocations data + relro rw-p / r--p diff --git a/assets/diagrams/15-fault-flow.excalidraw b/assets/diagrams/15-fault-flow.excalidraw index 3f1294c..bb2c4fd 100644 --- a/assets/diagrams/15-fault-flow.excalidraw +++ b/assets/diagrams/15-fault-flow.excalidraw @@ -483,13 +483,13 @@ "updated": 1, "link": null, "locked": false, - "text": "new zero-filled frame \u2014 minor", + "text": "new zero-filled frame: minor", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "new zero-filled frame \u2014 minor", + "originalText": "new zero-filled frame: minor", "lineHeight": 1.25, "baseline": 11 }, @@ -581,13 +581,13 @@ "updated": 1, "link": null, "locked": false, - "text": "map it + fault-around \u2014 minor", + "text": "map it + fault-around: minor", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "map it + fault-around \u2014 minor", + "originalText": "map it + fault-around: minor", "lineHeight": 1.25, "baseline": 11 }, @@ -679,13 +679,13 @@ "updated": 1, "link": null, "locked": false, - "text": "read from disk, sleep \u2014 major", + "text": "read from disk, sleep: major", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "read from disk, sleep \u2014 major", + "originalText": "read from disk, sleep: major", "lineHeight": 1.25, "baseline": 11 }, @@ -1042,13 +1042,13 @@ "updated": 1, "link": null, "locked": false, - "text": "heap 64 MiB written: minor=16385 major=0 \u2014 one fault per touched page", + "text": "heap 64 MiB written: minor=16385 major=0: one fault per touched page", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "heap 64 MiB written: minor=16385 major=0 \u2014 one fault per touched page", + "originalText": "heap 64 MiB written: minor=16385 major=0: one fault per touched page", "lineHeight": 1.25, "baseline": 11 }, @@ -1077,13 +1077,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fault-walk 16 MiB read: minor=32 per 512-page step \u2014 fault-around maps 16 pages/fault", + "text": "fault-walk 16 MiB read: minor=32 per 512-page step: fault-around maps 16 pages/fault", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fault-walk 16 MiB read: minor=32 per 512-page step \u2014 fault-around maps 16 pages/fault", + "originalText": "fault-walk 16 MiB read: minor=32 per 512-page step: fault-around maps 16 pages/fault", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/15-fault-flow.svg b/assets/diagrams/15-fault-flow.svg index 8a1ef8f..5dc3545 100644 --- a/assets/diagrams/15-fault-flow.svg +++ b/assets/diagrams/15-fault-flow.svg @@ -14,13 +14,13 @@ SIGSEGV anonymous, first write -new zero-filled frame — minor +new zero-filled frame: minor file page in page cache -map it + fault-around — minor +map it + fault-around: minor file page not cached -read from disk, sleep — major +read from disk, sleep: major trap @@ -30,7 +30,7 @@ measured this chapter (getrusage deltas): -heap 64 MiB written: minor=16385 major=0 — one fault per touched page -fault-walk 16 MiB read: minor=32 per 512-page step — fault-around maps 16 pages/fault +heap 64 MiB written: minor=16385 major=0: one fault per touched page +fault-walk 16 MiB read: minor=32 per 512-page step: fault-around maps 16 pages/fault major=0 everywhere: the walk file was written moments earlier, so it is in the page cache \ No newline at end of file diff --git a/assets/diagrams/16-mapping-page-cache.excalidraw b/assets/diagrams/16-mapping-page-cache.excalidraw index 940df4b..03c9c67 100644 --- a/assets/diagrams/16-mapping-page-cache.excalidraw +++ b/assets/diagrams/16-mapping-page-cache.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "process A \u2014 shmkv set (writer)", + "text": "process A: shmkv set (writer)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "process A \u2014 shmkv set (writer)", + "originalText": "process A: shmkv set (writer)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "process B \u2014 shmkv get (reader)", + "text": "process B: shmkv get (reader)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "process B \u2014 shmkv get (reader)", + "originalText": "process B: shmkv get (reader)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 one page cache, shared by every mapper", + "text": "kernel: one page cache, shared by every mapper", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 one page cache, shared by every mapper", + "originalText": "kernel: one page cache, shared by every mapper", "lineHeight": 1.25, "baseline": 12 }, @@ -1265,13 +1265,13 @@ "updated": 1, "link": null, "locked": false, - "text": "A's store and B's load meet in the same physical pages \u2014 no copy, no syscall between them", + "text": "A's store and B's load meet in the same physical pages: no copy, no syscall between them", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "A's store and B's load meet in the same physical pages \u2014 no copy, no syscall between them", + "originalText": "A's store and B's load meet in the same physical pages: no copy, no syscall between them", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/16-mapping-page-cache.svg b/assets/diagrams/16-mapping-page-cache.svg index 7477330..7869a8d 100644 --- a/assets/diagrams/16-mapping-page-cache.svg +++ b/assets/diagrams/16-mapping-page-cache.svg @@ -1,11 +1,11 @@ -process A — shmkv set (writer) +process A: shmkv set (writer) -process B — shmkv get (reader) +process B: shmkv get (reader) -kernel — one page cache, shared by every mapper +kernel: one page cache, shared by every mapper disk @@ -41,5 +41,5 @@ writeback, eventually writeback, eventually -A's store and B's load meet in the same physical pages — no copy, no syscall between them +A's store and B's load meet in the same physical pages: no copy, no syscall between them \ No newline at end of file diff --git a/assets/diagrams/16-shmkv-layout.excalidraw b/assets/diagrams/16-shmkv-layout.excalidraw index f9c0812..f494deb 100644 --- a/assets/diagrams/16-shmkv-layout.excalidraw +++ b/assets/diagrams/16-shmkv-layout.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "store.kv \u2014 1034 bytes = 10-byte header + 4 x 256-byte slots", + "text": "store.kv: 1034 bytes = 10-byte header + 4 x 256-byte slots", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "store.kv \u2014 1034 bytes = 10-byte header + 4 x 256-byte slots", + "originalText": "store.kv: 1034 bytes = 10-byte header + 4 x 256-byte slots", "lineHeight": 1.25, "baseline": 12 }, @@ -1474,13 +1474,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Every field is bytes with a stated width and order (u32 little-endian) \u2014 no language repr, padding, or endianness can leak in", + "text": "Every field is bytes with a stated width and order (u32 little-endian): no language repr, padding, or endianness can leak in", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Every field is bytes with a stated width and order (u32 little-endian) \u2014 no language repr, padding, or endianness can leak in", + "originalText": "Every field is bytes with a stated width and order (u32 little-endian): no language repr, padding, or endianness can leak in", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/16-shmkv-layout.svg b/assets/diagrams/16-shmkv-layout.svg index 1a07167..4665437 100644 --- a/assets/diagrams/16-shmkv-layout.svg +++ b/assets/diagrams/16-shmkv-layout.svg @@ -1,7 +1,7 @@ -store.kv — 1034 bytes = 10-byte header + 4 x 256-byte slots +store.kv: 1034 bytes = 10-byte header + 4 x 256-byte slots one slot, 256 bytes @@ -44,6 +44,6 @@ -Every field is bytes with a stated width and order (u32 little-endian) — no language repr, padding, or endianness can leak in +Every field is bytes with a stated width and order (u32 little-endian): no language repr, padding, or endianness can leak in cmp(1) proves it: a store built by the Rust binary and one built by the C++ binary are byte-identical \ No newline at end of file diff --git a/assets/diagrams/17-arena-vs-gc.excalidraw b/assets/diagrams/17-arena-vs-gc.excalidraw index 2070391..e8cb3e4 100644 --- a/assets/diagrams/17-arena-vs-gc.excalidraw +++ b/assets/diagrams/17-arena-vs-gc.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "free one by one \u2014 glibc malloc / Rust GlobalAlloc", + "text": "free one by one: glibc malloc / Rust GlobalAlloc", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "free one by one \u2014 glibc malloc / Rust GlobalAlloc", + "originalText": "free one by one: glibc malloc / Rust GlobalAlloc", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "arena / pool \u2014 pmr, bumpalo, sync.Pool", + "text": "arena / pool: pmr, bumpalo, sync.Pool", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "arena / pool \u2014 pmr, bumpalo, sync.Pool", + "originalText": "arena / pool: pmr, bumpalo, sync.Pool", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "tracing GC \u2014 the Go heap", + "text": "tracing GC: the Go heap", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "tracing GC \u2014 the Go heap", + "originalText": "tracing GC: the Go heap", "lineHeight": 1.25, "baseline": 12 }, @@ -2095,13 +2095,13 @@ "updated": 1, "link": null, "locked": false, - "text": "all numbers: allocbench --allocs 200000 on the reference host \u2014 peak_rss is getrusage ru_maxrss (KB)", + "text": "all numbers: allocbench --allocs 200000 on the reference host: peak_rss is getrusage ru_maxrss (KB)", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "all numbers: allocbench --allocs 200000 on the reference host \u2014 peak_rss is getrusage ru_maxrss (KB)", + "originalText": "all numbers: allocbench --allocs 200000 on the reference host: peak_rss is getrusage ru_maxrss (KB)", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/17-arena-vs-gc.svg b/assets/diagrams/17-arena-vs-gc.svg index 476a55a..1310b54 100644 --- a/assets/diagrams/17-arena-vs-gc.svg +++ b/assets/diagrams/17-arena-vs-gc.svg @@ -1,11 +1,11 @@ -free one by one — glibc malloc / Rust GlobalAlloc +free one by one: glibc malloc / Rust GlobalAlloc -arena / pool — pmr, bumpalo, sync.Pool +arena / pool: pmr, bumpalo, sync.Pool -tracing GC — the Go heap +tracing GC: the Go heap 200,000 short-lived strings key / frag / value per iteration @@ -66,5 +66,5 @@ cycle fires cycle fires -all numbers: allocbench --allocs 200000 on the reference host — peak_rss is getrusage ru_maxrss (KB) +all numbers: allocbench --allocs 200000 on the reference host: peak_rss is getrusage ru_maxrss (KB) \ No newline at end of file diff --git a/assets/diagrams/18-log-topology.excalidraw b/assets/diagrams/18-log-topology.excalidraw index 6df7a70..715ad4e 100644 --- a/assets/diagrams/18-log-topology.excalidraw +++ b/assets/diagrams/18-log-topology.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon supervise (pid 2633754) \u2014 capture", + "text": "pmon supervise (pid 2633754): capture", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon supervise (pid 2633754) \u2014 capture", + "originalText": "pmon supervise (pid 2633754): capture", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon tail (pid 2634759) \u2014 relay", + "text": "pmon tail (pid 2634759): relay", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon tail (pid 2634759) \u2014 relay", + "originalText": "pmon tail (pid 2634759): relay", "lineHeight": 1.25, "baseline": 12 }, @@ -777,13 +777,13 @@ "updated": 1, "link": null, "locked": false, - "text": "live.log \u2014 fd 3", + "text": "live.log: fd 3", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "live.log \u2014 fd 3", + "originalText": "live.log: fd 3", "lineHeight": 1.25, "baseline": 14 }, @@ -910,13 +910,13 @@ "updated": 1, "link": null, "locked": false, - "text": "live.log \u2014 fd 3", + "text": "live.log: fd 3", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "live.log \u2014 fd 3", + "originalText": "live.log: fd 3", "lineHeight": 1.25, "baseline": 14 }, @@ -1078,13 +1078,13 @@ "updated": 1, "link": null, "locked": false, - "text": "FIFO writer \u2014 fd 4", + "text": "FIFO writer: fd 4", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "FIFO writer \u2014 fd 4", + "originalText": "FIFO writer: fd 4", "lineHeight": 1.25, "baseline": 14 }, @@ -1344,13 +1344,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cat \u2014 fd 3", + "text": "cat: fd 3", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cat \u2014 fd 3", + "originalText": "cat: fd 3", "lineHeight": 1.25, "baseline": 14 }, @@ -2151,13 +2151,13 @@ "updated": 1, "link": null, "locked": false, - "text": "reader killed \u2192 splice = -1 EPIPE \u2192 \"pmon: tail reader detached\" \u2014 the relay survives and re-splices undelivered bytes to the next reader", + "text": "reader killed \u2192 splice = -1 EPIPE \u2192 \"pmon: tail reader detached\": the relay survives and re-splices undelivered bytes to the next reader", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "reader killed \u2192 splice = -1 EPIPE \u2192 \"pmon: tail reader detached\" \u2014 the relay survives and re-splices undelivered bytes to the next reader", + "originalText": "reader killed \u2192 splice = -1 EPIPE \u2192 \"pmon: tail reader detached\": the relay survives and re-splices undelivered bytes to the next reader", "lineHeight": 1.25, "baseline": 11 }, @@ -2186,13 +2186,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon v4's log pipeline \u2014 every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs", + "text": "pmon v4's log pipeline: every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon v4's log pipeline \u2014 every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs", + "originalText": "pmon v4's log pipeline: every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/18-log-topology.svg b/assets/diagrams/18-log-topology.svg index edd7f06..70dbd61 100644 --- a/assets/diagrams/18-log-topology.svg +++ b/assets/diagrams/18-log-topology.svg @@ -1,9 +1,9 @@ -pmon supervise (pid 2633754) — capture +pmon supervise (pid 2633754): capture -pmon tail (pid 2634759) — relay +pmon tail (pid 2634759): relay kernel FIFO + reader @@ -23,16 +23,16 @@ pipe read ends 5 and 7 LineRelay tags each line -live.log — fd 3 +live.log: fd 3 O_WRONLY|O_APPEND "[out] …" / "[err] …" -live.log — fd 3 +live.log: fd 3 O_RDONLY, fdinfo pos 10 offset advances only for delivered bytes -FIFO writer — fd 4 +FIFO writer: fd 4 fdinfo flags 02100001 O_NONBLOCK cleared after ENXIO wait loop @@ -40,7 +40,7 @@ live.fifo S_IFIFO, mode 0644 -cat — fd 3 +cat: fd 3 detach → EPIPE upstream next reader loses nothing @@ -70,6 +70,6 @@ read(2) read(2) -reader killed → splice = -1 EPIPE → "pmon: tail reader detached" — the relay survives and re-splices undelivered bytes to the next reader -pmon v4's log pipeline — every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs +reader killed → splice = -1 EPIPE → "pmon: tail reader detached": the relay survives and re-splices undelivered bytes to the next reader +pmon v4's log pipeline: every pid, fd number, pipe inode, flag value, and splice return in this figure comes from the chapter's live runs \ No newline at end of file diff --git a/assets/diagrams/18-pipe-internals.excalidraw b/assets/diagrams/18-pipe-internals.excalidraw index 9fee9c3..3e69cf1 100644 --- a/assets/diagrams/18-pipe-internals.excalidraw +++ b/assets/diagrams/18-pipe-internals.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "writer \u2014 sh (child 2633756)", + "text": "writer: sh (child 2633756)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "writer \u2014 sh (child 2633756)", + "originalText": "writer: sh (child 2633756)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 struct pipe_inode_info, inode 16462630", + "text": "kernel: struct pipe_inode_info, inode 16462630", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 struct pipe_inode_info, inode 16462630", + "originalText": "kernel: struct pipe_inode_info, inode 16462630", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "reader \u2014 pmon supervise", + "text": "reader: pmon supervise", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "reader \u2014 pmon supervise", + "originalText": "reader: pmon supervise", "lineHeight": 1.25, "baseline": 12 }, @@ -245,13 +245,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fd 1 \u2014 write end", + "text": "fd 1: write end", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fd 1 \u2014 write end", + "originalText": "fd 1: write end", "lineHeight": 1.25, "baseline": 14 }, @@ -378,13 +378,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fd 5 \u2014 read end", + "text": "fd 5: read end", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fd 5 \u2014 read end", + "originalText": "fd 5: read end", "lineHeight": 1.25, "baseline": 14 }, @@ -1186,13 +1186,13 @@ "updated": 1, "link": null, "locked": false, - "text": "head \u2014 next write lands here", + "text": "head: next write lands here", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "head \u2014 next write lands here", + "originalText": "head: next write lands here", "lineHeight": 1.25, "baseline": 11 }, @@ -1264,13 +1264,13 @@ "updated": 1, "link": null, "locked": false, - "text": "tail \u2014 read drains here", + "text": "tail: read drains here", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "tail \u2014 read drains here", + "originalText": "tail: read drains here", "lineHeight": 1.25, "baseline": 11 }, @@ -1299,13 +1299,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ring of 16 slots, one page each \u2014 only 8 drawn", + "text": "ring of 16 slots, one page each: only 8 drawn", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ring of 16 slots, one page each \u2014 only 8 drawn", + "originalText": "ring of 16 slots, one page each: only 8 drawn", "lineHeight": 1.25, "baseline": 11 }, @@ -1334,13 +1334,13 @@ "updated": 1, "link": null, "locked": false, - "text": "capacity: 16 \u00d7 4096 B = 65536 B \u2014 read live with fcntl(F_GETPIPE_SZ)", + "text": "capacity: 16 \u00d7 4096 B = 65536 B: read live with fcntl(F_GETPIPE_SZ)", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "capacity: 16 \u00d7 4096 B = 65536 B \u2014 read live with fcntl(F_GETPIPE_SZ)", + "originalText": "capacity: 16 \u00d7 4096 B = 65536 B: read live with fcntl(F_GETPIPE_SZ)", "lineHeight": 1.25, "baseline": 11 }, @@ -1474,13 +1474,13 @@ "updated": 1, "link": null, "locked": false, - "text": "another writer's \u2014 but reads may still return partial chunks:", + "text": "another writer's: but reads may still return partial chunks:", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "another writer's \u2014 but reads may still return partial chunks:", + "originalText": "another writer's: but reads may still return partial chunks:", "lineHeight": 1.25, "baseline": 11 }, @@ -1684,13 +1684,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one pipe from the chapter's live supervise run \u2014 both fd numbers, the inode, and every byte count are from /proc", + "text": "one pipe from the chapter's live supervise run: both fd numbers, the inode, and every byte count are from /proc", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one pipe from the chapter's live supervise run \u2014 both fd numbers, the inode, and every byte count are from /proc", + "originalText": "one pipe from the chapter's live supervise run: both fd numbers, the inode, and every byte count are from /proc", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/18-pipe-internals.svg b/assets/diagrams/18-pipe-internals.svg index 043dbca..3da122d 100644 --- a/assets/diagrams/18-pipe-internals.svg +++ b/assets/diagrams/18-pipe-internals.svg @@ -1,17 +1,17 @@ -writer — sh (child 2633756) +writer: sh (child 2633756) -kernel — struct pipe_inode_info, inode 16462630 +kernel: struct pipe_inode_info, inode 16462630 -reader — pmon supervise +reader: pmon supervise -fd 1 — write end +fd 1: write end pipe:[16462630] pipe2(…, O_CLOEXEC) -fd 5 — read end +fd 5: read end pipe:[16462630] fdinfo flags 02000000 @@ -37,21 +37,21 @@ read(2) read(2) -head — next write lands here -head — next write lands here +head: next write lands here +head: next write lands here -tail — read drains here -tail — read drains here -ring of 16 slots, one page each — only 8 drawn -capacity: 16 × 4096 B = 65536 B — read live with fcntl(F_GETPIPE_SZ) +tail: read drains here +tail: read drains here +ring of 16 slots, one page each: only 8 drawn +capacity: 16 × 4096 B = 65536 B: read live with fcntl(F_GETPIPE_SZ) F_SETPIPE_SZ asked for 1 → rounded up to 4096 (one page); ceiling: /proc/sys/fs/pipe-max-size = 1048576 (unprivileged) PIPE_BUF = 4096: one write() of ≤ 4096 B never interleaves with -another writer's — but reads may still return partial chunks: +another writer's: but reads may still return partial chunks: atomicity is not message framing, and not delivery all write ends closed → read() returns 0 (EOF) no read end left → write() raises SIGPIPE / EPIPE -one pipe from the chapter's live supervise run — both fd numbers, the inode, and every byte count are from /proc +one pipe from the chapter's live supervise run: both fd numbers, the inode, and every byte count are from /proc \ No newline at end of file diff --git a/assets/diagrams/19-scm-rights-transfer.excalidraw b/assets/diagrams/19-scm-rights-transfer.excalidraw index 03035c2..c3a767f 100644 --- a/assets/diagrams/19-scm-rights-transfer.excalidraw +++ b/assets/diagrams/19-scm-rights-transfer.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon supervise \u2014 fd table (pid 2622904)", + "text": "pmon supervise: fd table (pid 2622904)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon supervise \u2014 fd table (pid 2622904)", + "originalText": "pmon supervise: fd table (pid 2622904)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmctl \u2014 fd table (pid 2623753)", + "text": "pmctl: fd table (pid 2623753)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmctl \u2014 fd table (pid 2623753)", + "originalText": "pmctl: fd table (pid 2623753)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 shared, system-wide", + "text": "kernel: shared, system-wide", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 shared, system-wide", + "originalText": "kernel: shared, system-wide", "lineHeight": 1.25, "baseline": 12 }, @@ -343,13 +343,13 @@ "updated": 1, "link": null, "locked": false, - "text": "slot 4 (receiver \u2014 new, lowest free)", + "text": "slot 4 (receiver: new, lowest free)", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "slot 4 (receiver \u2014 new, lowest free)", + "originalText": "slot 4 (receiver: new, lowest free)", "lineHeight": 1.25, "baseline": 14 }, @@ -574,13 +574,13 @@ "updated": 1, "link": null, "locked": false, - "text": "inode 95934 \u2014 pmon.log", + "text": "inode 95934: pmon.log", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "inode 95934 \u2014 pmon.log", + "originalText": "inode 95934: pmon.log", "lineHeight": 1.25, "baseline": 14 }, @@ -875,13 +875,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cmsg_data=[4] \u2014 kernel picked 4", + "text": "cmsg_data=[4]: kernel picked 4", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cmsg_data=[4] \u2014 kernel picked 4", + "originalText": "cmsg_data=[4]: kernel picked 4", "lineHeight": 1.25, "baseline": 11 }, @@ -1456,13 +1456,13 @@ "updated": 1, "link": null, "locked": false, - "text": "SCM_RIGHTS: the fd number does not travel \u2014 a reference to the open file description does", + "text": "SCM_RIGHTS: the fd number does not travel: a reference to the open file description does", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "SCM_RIGHTS: the fd number does not travel \u2014 a reference to the open file description does", + "originalText": "SCM_RIGHTS: the fd number does not travel: a reference to the open file description does", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/19-scm-rights-transfer.svg b/assets/diagrams/19-scm-rights-transfer.svg index 10dfc23..f263dd0 100644 --- a/assets/diagrams/19-scm-rights-transfer.svg +++ b/assets/diagrams/19-scm-rights-transfer.svg @@ -1,23 +1,23 @@ -pmon supervise — fd table (pid 2622904) +pmon supervise: fd table (pid 2622904) -pmctl — fd table (pid 2623753) +pmctl: fd table (pid 2623753) -kernel — shared, system-wide +kernel: shared, system-wide slot 3 (sender) close-on-exec: set at open (O_CLOEXEC) -slot 4 (receiver — new, lowest free) +slot 4 (receiver: new, lowest free) close-on-exec: set by MSG_CMSG_CLOEXEC one open file description pos: 47 flags: 02102002 O_RDWR|O_APPEND|O_CLOEXEC|O_LARGEFILE -inode 95934 — pmon.log +inode 95934: pmon.log 47 bytes: both /proc fdinfo agree, pos: 47 sendmsg(5, …) @@ -26,7 +26,7 @@ recvmsg(3, …, MSG_CMSG_CLOEXEC) cmsg SOL_SOCKET SCM_RIGHTS -cmsg_data=[4] — kernel picked 4 +cmsg_data=[4]: kernel picked 4 points at points at @@ -48,7 +48,7 @@ kernel installs new slot kernel installs new slot -SCM_RIGHTS: the fd number does not travel — a reference to the open file description does +SCM_RIGHTS: the fd number does not travel: a reference to the open file description does ch07's three layers: per-process slot (cloexec bit lives here) → shared description (pos, flags) → inode numbers from the chapter's held-open run \ No newline at end of file diff --git a/assets/diagrams/19-uds-control-plane.excalidraw b/assets/diagrams/19-uds-control-plane.excalidraw index bf2d0fe..9480376 100644 --- a/assets/diagrams/19-uds-control-plane.excalidraw +++ b/assets/diagrams/19-uds-control-plane.excalidraw @@ -1211,13 +1211,13 @@ "updated": 1, "link": null, "locked": false, - "text": "supervisor end \u2014 ss -xp: app,pid=2622904,fd=5", + "text": "supervisor end: ss -xp: app,pid=2622904,fd=5", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "supervisor end \u2014 ss -xp: app,pid=2622904,fd=5", + "originalText": "supervisor end: ss -xp: app,pid=2622904,fd=5", "lineHeight": 1.25, "baseline": 11 }, @@ -1309,13 +1309,13 @@ "updated": 1, "link": null, "locked": false, - "text": "client end \u2014 ss -xp: app,pid=2624432,fd=3", + "text": "client end: ss -xp: app,pid=2624432,fd=3", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "client end \u2014 ss -xp: app,pid=2624432,fd=3", + "originalText": "client end: ss -xp: app,pid=2624432,fd=3", "lineHeight": 1.25, "baseline": 11 }, @@ -1863,13 +1863,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon v5 control plane \u2014 every number from the chapter's live run", + "text": "pmon v5 control plane: every number from the chapter's live run", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon v5 control plane \u2014 every number from the chapter's live run", + "originalText": "pmon v5 control plane: every number from the chapter's live run", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/19-uds-control-plane.svg b/assets/diagrams/19-uds-control-plane.svg index 325c5e3..72b1d25 100644 --- a/assets/diagrams/19-uds-control-plane.svg +++ b/assets/diagrams/19-uds-control-plane.svg @@ -36,10 +36,10 @@ uptime=20s restarts=0 socket inode 16411996 -supervisor end — ss -xp: app,pid=2622904,fd=5 +supervisor end: ss -xp: app,pid=2622904,fd=5 socket inode 16422777 -client end — ss -xp: app,pid=2624432,fd=3 +client end: ss -xp: app,pid=2624432,fd=3 accept4 accept4 @@ -58,6 +58,6 @@ one stream, two ends one stream, two ends -pmon v5 control plane — every number from the chapter's live run +pmon v5 control plane: every number from the chapter's live run SO_PEERCRED: the kernel, not the client, names uid/pid \ No newline at end of file diff --git a/assets/diagrams/20-ipc-matrix.excalidraw b/assets/diagrams/20-ipc-matrix.excalidraw index a5498cd..11d4d33 100644 --- a/assets/diagrams/20-ipc-matrix.excalidraw +++ b/assets/diagrams/20-ipc-matrix.excalidraw @@ -1650,13 +1650,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Numbers are plainly bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway.", + "text": "Numbers are bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway.", "fontSize": 11.5, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Numbers are plainly bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway.", + "originalText": "Numbers are bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway.", "lineHeight": 1.25, "baseline": 11.5 } diff --git a/assets/diagrams/20-ipc-matrix.svg b/assets/diagrams/20-ipc-matrix.svg index 5acad5b..8a6090c 100644 --- a/assets/diagrams/20-ipc-matrix.svg +++ b/assets/diagrams/20-ipc-matrix.svg @@ -48,5 +48,5 @@ ~350x ~350x Latency climbs left to right; every measured channel except the poll loop lands within one order of magnitude. -Numbers are plainly bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway. +Numbers are bounded by this host (idle 8-core/16-thread Fedora 44 box); rankings, not absolutes, are the takeaway. \ No newline at end of file diff --git a/assets/diagrams/21-server-lifecycle.excalidraw b/assets/diagrams/21-server-lifecycle.excalidraw index bc0b363..4d60ef3 100644 --- a/assets/diagrams/21-server-lifecycle.excalidraw +++ b/assets/diagrams/21-server-lifecycle.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "serve \u2014 one listener thread", + "text": "serve: one listener thread", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "serve \u2014 one listener thread", + "originalText": "serve: one listener thread", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/21-server-lifecycle.svg b/assets/diagrams/21-server-lifecycle.svg index 1994e07..507c781 100644 --- a/assets/diagrams/21-server-lifecycle.svg +++ b/assets/diagrams/21-server-lifecycle.svg @@ -1,7 +1,7 @@ -serve — one listener thread +serve: one listener thread one std::jthread / goroutine / std::thread per accepted connection diff --git a/assets/diagrams/22-connection-state-machine.excalidraw b/assets/diagrams/22-connection-state-machine.excalidraw index 08794d5..c170647 100644 --- a/assets/diagrams/22-connection-state-machine.excalidraw +++ b/assets/diagrams/22-connection-state-machine.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "READ PATH \u2014 recv to EAGAIN, reassemble frames, fan out", + "text": "READ PATH: recv to EAGAIN, reassemble frames, fan out", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "READ PATH \u2014 recv to EAGAIN, reassemble frames, fan out", + "originalText": "READ PATH: recv to EAGAIN, reassemble frames, fan out", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "WRITE PATH + BACKPRESSURE \u2014 outbuf queue, EPOLLOUT re-arm", + "text": "WRITE PATH + BACKPRESSURE: outbuf queue, EPOLLOUT re-arm", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "WRITE PATH + BACKPRESSURE \u2014 outbuf queue, EPOLLOUT re-arm", + "originalText": "WRITE PATH + BACKPRESSURE: outbuf queue, EPOLLOUT re-arm", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/22-connection-state-machine.svg b/assets/diagrams/22-connection-state-machine.svg index 325f691..113bbce 100644 --- a/assets/diagrams/22-connection-state-machine.svg +++ b/assets/diagrams/22-connection-state-machine.svg @@ -1,9 +1,9 @@ -READ PATH — recv to EAGAIN, reassemble frames, fan out +READ PATH: recv to EAGAIN, reassemble frames, fan out -WRITE PATH + BACKPRESSURE — outbuf queue, EPOLLOUT re-arm +WRITE PATH + BACKPRESSURE: outbuf queue, EPOLLOUT re-arm recv() loop drain nonblocking diff --git a/assets/diagrams/22-netpoller-vs-epoll.excalidraw b/assets/diagrams/22-netpoller-vs-epoll.excalidraw index d198178..807c1cb 100644 --- a/assets/diagrams/22-netpoller-vs-epoll.excalidraw +++ b/assets/diagrams/22-netpoller-vs-epoll.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++ / Rust \u2014 you write the epoll loop", + "text": "C++ / Rust: you write the epoll loop", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++ / Rust \u2014 you write the epoll loop", + "originalText": "C++ / Rust: you write the epoll loop", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Go \u2014 you write goroutines; the runtime hides the epoll", + "text": "Go: you write goroutines; the runtime hides the epoll", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Go \u2014 you write goroutines; the runtime hides the epoll", + "originalText": "Go: you write goroutines; the runtime hides the epoll", "lineHeight": 1.25, "baseline": 12 }, @@ -217,13 +217,13 @@ "updated": 1, "link": null, "locked": false, - "text": "epoll_wait \u2014 4 calls for a 50-conn flood", + "text": "epoll_wait: 4 calls for a 50-conn flood", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "epoll_wait \u2014 4 calls for a 50-conn flood", + "originalText": "epoll_wait: 4 calls for a 50-conn flood", "lineHeight": 1.25, "baseline": 11 }, @@ -448,13 +448,13 @@ "updated": 1, "link": null, "locked": false, - "text": "channels fan out \u2014 ~7 OS threads total", + "text": "channels fan out : ~7 OS threads total", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "channels fan out \u2014 ~7 OS threads total", + "originalText": "channels fan out : ~7 OS threads total", "lineHeight": 1.25, "baseline": 11 }, @@ -546,13 +546,13 @@ "updated": 1, "link": null, "locked": false, - "text": "epoll_pwait \u2014 165 calls, edge-triggered EPOLLET", + "text": "epoll_pwait: 165 calls, edge-triggered EPOLLET", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "epoll_pwait \u2014 165 calls, edge-triggered EPOLLET", + "originalText": "epoll_pwait: 165 calls, edge-triggered EPOLLET", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/22-netpoller-vs-epoll.svg b/assets/diagrams/22-netpoller-vs-epoll.svg index ba99d23..7783561 100644 --- a/assets/diagrams/22-netpoller-vs-epoll.svg +++ b/assets/diagrams/22-netpoller-vs-epoll.svg @@ -1,22 +1,22 @@ -C++ / Rust — you write the epoll loop +C++ / Rust: you write the epoll loop -Go — you write goroutines; the runtime hides the epoll +Go: you write goroutines; the runtime hides the epoll 1 OS thread (Threads: 1) -epoll_wait — 4 calls for a 50-conn flood +epoll_wait: 4 calls for a 50-conn flood kernel eventpoll interest list tok 0 listener tok 1 signalfd tok 2..N every client socket, one process goroutine per conn (read + write) + hub -channels fan out — ~7 OS threads total +channels fan out : ~7 OS threads total runtime netpoller (hidden) -epoll_pwait — 165 calls, edge-triggered EPOLLET +epoll_pwait: 165 calls, edge-triggered EPOLLET same kernel sockets one process, N conns (ss -tp) diff --git a/assets/diagrams/23-discovery-sequence.excalidraw b/assets/diagrams/23-discovery-sequence.excalidraw index 527192f..b992d65 100644 --- a/assets/diagrams/23-discovery-sequence.excalidraw +++ b/assets/diagrams/23-discovery-sequence.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "UDP multicast discovery \u2014 connectionless, one datagram, boundary preserved", + "text": "UDP multicast discovery: connectionless, one datagram, boundary preserved", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "UDP multicast discovery \u2014 connectionless, one datagram, boundary preserved", + "originalText": "UDP multicast discovery: connectionless, one datagram, boundary preserved", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "TCP bridge \u2014 connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER)", + "text": "TCP bridge: connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "TCP bridge \u2014 connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER)", + "originalText": "TCP bridge: connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER)", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/23-discovery-sequence.svg b/assets/diagrams/23-discovery-sequence.svg index 662ed1e..be0fa5c 100644 --- a/assets/diagrams/23-discovery-sequence.svg +++ b/assets/diagrams/23-discovery-sequence.svg @@ -1,9 +1,9 @@ -UDP multicast discovery — connectionless, one datagram, boundary preserved +UDP multicast discovery: connectionless, one datagram, boundary preserved -TCP bridge — connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER) +TCP bridge: connection-oriented, reliable, the canonical chatterd chat frame (JOIN/DELIVER) announce loop sendto → group diff --git a/assets/diagrams/23-two-vm-topology.excalidraw b/assets/diagrams/23-two-vm-topology.excalidraw index 62768fe..d010d50 100644 --- a/assets/diagrams/23-two-vm-topology.excalidraw +++ b/assets/diagrams/23-two-vm-topology.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "libvirt default network \u2014 virbr0 bridge \u00b7 192.168.124.0/24 \u00b7 one L2 segment (NAT only toward the host)", + "text": "libvirt default network: virbr0 bridge \u00b7 192.168.124.0/24 \u00b7 one L2 segment (NAT only toward the host)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "libvirt default network \u2014 virbr0 bridge \u00b7 192.168.124.0/24 \u00b7 one L2 segment (NAT only toward the host)", + "originalText": "libvirt default network: virbr0 bridge \u00b7 192.168.124.0/24 \u00b7 one L2 segment (NAT only toward the host)", "lineHeight": 1.25, "baseline": 12 }, @@ -724,13 +724,13 @@ "updated": 1, "link": null, "locked": false, - "text": "TCP :9241 \u2014 one ch21 chat frame each way", + "text": "TCP :9241: one ch21 chat frame each way", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "TCP :9241 \u2014 one ch21 chat frame each way", + "originalText": "TCP :9241: one ch21 chat frame each way", "lineHeight": 1.25, "baseline": 11 }, @@ -759,13 +759,13 @@ "updated": 1, "link": null, "locked": false, - "text": "each guest sends one beacon to the group and hears the other's \u2014 dedup by name, then dial TCP", + "text": "each guest sends one beacon to the group and hears the other's: dedup by name, then dial TCP", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "each guest sends one beacon to the group and hears the other's \u2014 dedup by name, then dial TCP", + "originalText": "each guest sends one beacon to the group and hears the other's: dedup by name, then dial TCP", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/23-two-vm-topology.svg b/assets/diagrams/23-two-vm-topology.svg index 6b4dc97..69a280a 100644 --- a/assets/diagrams/23-two-vm-topology.svg +++ b/assets/diagrams/23-two-vm-topology.svg @@ -1,7 +1,7 @@ -libvirt default network — virbr0 bridge · 192.168.124.0/24 · one L2 segment (NAT only toward the host) +libvirt default network: virbr0 bridge · 192.168.124.0/24 · one L2 segment (NAT only toward the host) multicast group 239.23.7.1 : 51824 · TTL 1 @@ -22,7 +22,7 @@ beacon 34 B beacon 34 B -TCP :9241 — one ch21 chat frame each way -TCP :9241 — one ch21 chat frame each way -each guest sends one beacon to the group and hears the other's — dedup by name, then dial TCP +TCP :9241: one ch21 chat frame each way +TCP :9241: one ch21 chat frame each way +each guest sends one beacon to the group and hears the other's: dedup by name, then dial TCP \ No newline at end of file diff --git a/assets/diagrams/25-futex-fast-slow-path.excalidraw b/assets/diagrams/25-futex-fast-slow-path.excalidraw index 71911af..425f9d3 100644 --- a/assets/diagrams/25-futex-fast-slow-path.excalidraw +++ b/assets/diagrams/25-futex-fast-slow-path.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "user space \u2014 the lock word lives here (glibc pthread / libstdc++ / std)", + "text": "user space: the lock word lives here (glibc pthread / libstdc++ / std)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "user space \u2014 the lock word lives here (glibc pthread / libstdc++ / std)", + "originalText": "user space: the lock word lives here (glibc pthread / libstdc++ / std)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 entered only when the CAS loses", + "text": "kernel: entered only when the CAS loses", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 entered only when the CAS loses", + "originalText": "kernel: entered only when the CAS loses", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/25-futex-fast-slow-path.svg b/assets/diagrams/25-futex-fast-slow-path.svg index 86d968f..e046da7 100644 --- a/assets/diagrams/25-futex-fast-slow-path.svg +++ b/assets/diagrams/25-futex-fast-slow-path.svg @@ -1,9 +1,9 @@ -user space — the lock word lives here (glibc pthread / libstdc++ / std) +user space: the lock word lives here (glibc pthread / libstdc++ / std) -kernel — entered only when the CAS loses +kernel: entered only when the CAS loses Thread A: lock() word == 0 diff --git a/assets/diagrams/26-false-sharing.excalidraw b/assets/diagrams/26-false-sharing.excalidraw index 8675fb7..16aae8f 100644 --- a/assets/diagrams/26-false-sharing.excalidraw +++ b/assets/diagrams/26-false-sharing.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pad=off \u2014 head & tail share one 64 B line", + "text": "pad=off: head & tail share one 64 B line", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pad=off \u2014 head & tail share one 64 B line", + "originalText": "pad=off: head & tail share one 64 B line", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pad=on \u2014 head & tail on separate lines", + "text": "pad=on: head & tail on separate lines", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pad=on \u2014 head & tail on separate lines", + "originalText": "pad=on: head & tail on separate lines", "lineHeight": 1.25, "baseline": 12 }, @@ -1257,13 +1257,13 @@ "updated": 1, "link": null, "locked": false, - "text": "median 6.20 Mops \u2014 ~34% faster", + "text": "median 6.20 Mops: ~34% faster", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "median 6.20 Mops \u2014 ~34% faster", + "originalText": "median 6.20 Mops: ~34% faster", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/26-false-sharing.svg b/assets/diagrams/26-false-sharing.svg index bcd98f3..690d156 100644 --- a/assets/diagrams/26-false-sharing.svg +++ b/assets/diagrams/26-false-sharing.svg @@ -1,9 +1,9 @@ -pad=off — head & tail share one 64 B line +pad=off: head & tail share one 64 B line -pad=on — head & tail on separate lines +pad=on: head & tail on separate lines core 0 producer: writes tail @@ -40,5 +40,5 @@ L1 load-misses ~128 M median 4.64 Mops (capacity 1, 10 M items) L1 load-misses ~108 M -median 6.20 Mops — ~34% faster +median 6.20 Mops: ~34% faster \ No newline at end of file diff --git a/assets/diagrams/26-memory-ordering.excalidraw b/assets/diagrams/26-memory-ordering.excalidraw index c66d738..0fce254 100644 --- a/assets/diagrams/26-memory-ordering.excalidraw +++ b/assets/diagrams/26-memory-ordering.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "sequential consistency \u2014 strongest; Go's only setting", + "text": "sequential consistency: strongest; Go's only setting", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "sequential consistency \u2014 strongest; Go's only setting", + "originalText": "sequential consistency: strongest; Go's only setting", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "acquire / release \u2014 pairwise publish; C++ & Rust head/tail", + "text": "acquire / release: pairwise publish; C++ & Rust head/tail", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "acquire / release \u2014 pairwise publish; C++ & Rust head/tail", + "originalText": "acquire / release: pairwise publish; C++ & Rust head/tail", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "relaxed \u2014 atomicity only, no ordering; Rust ring slots", + "text": "relaxed: atomicity only, no ordering; Rust ring slots", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "relaxed \u2014 atomicity only, no ordering; Rust ring slots", + "originalText": "relaxed: atomicity only, no ordering; Rust ring slots", "lineHeight": 1.25, "baseline": 12 }, @@ -1039,13 +1039,13 @@ "updated": 1, "link": null, "locked": false, - "text": "On x86 the ordering is nearly free \u2014 the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers.", + "text": "On x86 the ordering is nearly free: the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "On x86 the ordering is nearly free \u2014 the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers.", + "originalText": "On x86 the ordering is nearly free: the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/26-memory-ordering.svg b/assets/diagrams/26-memory-ordering.svg index f46543d..2d57ce4 100644 --- a/assets/diagrams/26-memory-ordering.svg +++ b/assets/diagrams/26-memory-ordering.svg @@ -1,11 +1,11 @@ -sequential consistency — strongest; Go's only setting +sequential consistency: strongest; Go's only setting -acquire / release — pairwise publish; C++ & Rust head/tail +acquire / release: pairwise publish; C++ & Rust head/tail -relaxed — atomicity only, no ordering; Rust ring slots +relaxed: atomicity only, no ordering; Rust ring slots one total order over all seq_cst ops tail.Store(t) in Go @@ -33,5 +33,5 @@ compiles to compiles to -On x86 the ordering is nearly free — the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers. +On x86 the ordering is nearly free: the difference is the promise, not the instruction. On ARM/POWER the movs would need real barriers. \ No newline at end of file diff --git a/assets/diagrams/26-spsc-ring.excalidraw b/assets/diagrams/26-spsc-ring.excalidraw index 1b67ff4..c4ea3a2 100644 --- a/assets/diagrams/26-spsc-ring.excalidraw +++ b/assets/diagrams/26-spsc-ring.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Two threads, two owned counters \u2014 no lock", + "text": "Two threads, two owned counters: no lock", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Two threads, two owned counters \u2014 no lock", + "originalText": "Two threads, two owned counters: no lock", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Shared ring buf[K] \u2014 slot for logical position p is buf[p % K]", + "text": "Shared ring buf[K]: slot for logical position p is buf[p % K]", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Shared ring buf[K] \u2014 slot for logical position p is buf[p % K]", + "originalText": "Shared ring buf[K]: slot for logical position p is buf[p % K]", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/26-spsc-ring.svg b/assets/diagrams/26-spsc-ring.svg index 96d4f2a..8da08c2 100644 --- a/assets/diagrams/26-spsc-ring.svg +++ b/assets/diagrams/26-spsc-ring.svg @@ -1,9 +1,9 @@ -Two threads, two owned counters — no lock +Two threads, two owned counters: no lock -Shared ring buf[K] — slot for logical position p is buf[p % K] +Shared ring buf[K]: slot for logical position p is buf[p % K] Producer (core 0) owns tail, reads head diff --git a/assets/diagrams/27-coroutine-suspension.excalidraw b/assets/diagrams/27-coroutine-suspension.excalidraw index 6a1b65e..b0cefaa 100644 --- a/assets/diagrams/27-coroutine-suspension.excalidraw +++ b/assets/diagrams/27-coroutine-suspension.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "user \u2014 connection() coroutine (one heap-allocated frame per client)", + "text": "user: connection() coroutine (one heap-allocated frame per client)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "user \u2014 connection() coroutine (one heap-allocated frame per client)", + "originalText": "user: connection() coroutine (one heap-allocated frame per client)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "the single OS thread \u2014 Reactor::run()", + "text": "the single OS thread: Reactor::run()", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "the single OS thread \u2014 Reactor::run()", + "originalText": "the single OS thread: Reactor::run()", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 epoll interest list", + "text": "kernel: epoll interest list", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 epoll interest list", + "originalText": "kernel: epoll interest list", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/27-coroutine-suspension.svg b/assets/diagrams/27-coroutine-suspension.svg index 334f7fe..f5278ce 100644 --- a/assets/diagrams/27-coroutine-suspension.svg +++ b/assets/diagrams/27-coroutine-suspension.svg @@ -1,11 +1,11 @@ -user — connection() coroutine (one heap-allocated frame per client) +user: connection() coroutine (one heap-allocated frame per client) -the single OS thread — Reactor::run() +the single OS thread: Reactor::run() -kernel — epoll interest list +kernel: epoll interest list 1 co_await fill() recv() → EAGAIN diff --git a/assets/diagrams/27-gmp-scheduler.excalidraw b/assets/diagrams/27-gmp-scheduler.excalidraw index cd47b01..5655d3c 100644 --- a/assets/diagrams/27-gmp-scheduler.excalidraw +++ b/assets/diagrams/27-gmp-scheduler.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "goroutines (G) \u2014 one per connection, ~2 KB growable stacks", + "text": "goroutines (G): one per connection, ~2 KB growable stacks", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "goroutines (G) \u2014 one per connection, ~2 KB growable stacks", + "originalText": "goroutines (G): one per connection, ~2 KB growable stacks", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "scheduler \u2014 GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M)", + "text": "scheduler: GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "scheduler \u2014 GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M)", + "originalText": "scheduler: GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 netpoller (epoll) and OS threads", + "text": "kernel: netpoller (epoll) and OS threads", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 netpoller (epoll) and OS threads", + "originalText": "kernel: netpoller (epoll) and OS threads", "lineHeight": 1.25, "baseline": 12 }, @@ -1029,13 +1029,13 @@ "updated": 1, "link": null, "locked": false, - "text": "netpoller \u2014 one epoll instance", + "text": "netpoller: one epoll instance", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "netpoller \u2014 one epoll instance", + "originalText": "netpoller: one epoll instance", "lineHeight": 1.25, "baseline": 14 }, @@ -1693,13 +1693,13 @@ "updated": 1, "link": null, "locked": false, - "text": "no rewrite for async: a goroutine already suspends on I/O the way a coroutine does \u2014 the runtime hid it since 2012", + "text": "no rewrite for async: a goroutine already suspends on I/O the way a coroutine does: the runtime hid it since 2012", "fontSize": 10, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "no rewrite for async: a goroutine already suspends on I/O the way a coroutine does \u2014 the runtime hid it since 2012", + "originalText": "no rewrite for async: a goroutine already suspends on I/O the way a coroutine does: the runtime hid it since 2012", "lineHeight": 1.25, "baseline": 10 } diff --git a/assets/diagrams/27-gmp-scheduler.svg b/assets/diagrams/27-gmp-scheduler.svg index fe0cbdf..c2c6b92 100644 --- a/assets/diagrams/27-gmp-scheduler.svg +++ b/assets/diagrams/27-gmp-scheduler.svg @@ -1,11 +1,11 @@ -goroutines (G) — one per connection, ~2 KB growable stacks +goroutines (G): one per connection, ~2 KB growable stacks -scheduler — GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M) +scheduler: GOMAXPROCS=16 logical processors (P), each bound to an OS thread (M) -kernel — netpoller (epoll) and OS threads +kernel: netpoller (epoll) and OS threads G conn 1 @@ -31,7 +31,7 @@ … P15 (= 16 cores) -netpoller — one epoll instance +netpoller: one epoll instance epoll_wait for the whole runtime async preemption: runtime sends SIGURG to an M @@ -53,5 +53,5 @@ ready → runnable ready → runnable -no rewrite for async: a goroutine already suspends on I/O the way a coroutine does — the runtime hid it since 2012 +no rewrite for async: a goroutine already suspends on I/O the way a coroutine does: the runtime hid it since 2012 \ No newline at end of file diff --git a/assets/diagrams/27-tokio-task-lifecycle.excalidraw b/assets/diagrams/27-tokio-task-lifecycle.excalidraw index 8fe53ab..b6f08d7 100644 --- a/assets/diagrams/27-tokio-task-lifecycle.excalidraw +++ b/assets/diagrams/27-tokio-task-lifecycle.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "tokio tasks \u2014 async fn per connection (compiled to a state machine, not a thread)", + "text": "tokio tasks: async fn per connection (compiled to a state machine, not a thread)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "tokio tasks \u2014 async fn per connection (compiled to a state machine, not a thread)", + "originalText": "tokio tasks: async fn per connection (compiled to a state machine, not a thread)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "16 tokio-rt-worker threads (= cores) \u2014 work-stealing schedulers", + "text": "16 tokio-rt-worker threads (= cores): work-stealing schedulers", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "16 tokio-rt-worker threads (= cores) \u2014 work-stealing schedulers", + "originalText": "16 tokio-rt-worker threads (= cores): work-stealing schedulers", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "mio reactor \u2014 one epoll instance", + "text": "mio reactor: one epoll instance", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "mio reactor \u2014 one epoll instance", + "originalText": "mio reactor: one epoll instance", "lineHeight": 1.25, "baseline": 12 }, @@ -833,13 +833,13 @@ "updated": 1, "link": null, "locked": false, - "text": "epoll_wait \u2014 fd readable", + "text": "epoll_wait: fd readable", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "epoll_wait \u2014 fd readable", + "originalText": "epoll_wait: fd readable", "lineHeight": 1.25, "baseline": 14 }, @@ -1371,13 +1371,13 @@ "updated": 1, "link": null, "locked": false, - "text": "a task is a heap object the size of its locals \u2014 20k tasks share 16 threads; a Waker is the callback that says 'poll me again'", + "text": "a task is a heap object the size of its locals: 20k tasks share 16 threads; a Waker is the callback that says 'poll me again'", "fontSize": 10, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "a task is a heap object the size of its locals \u2014 20k tasks share 16 threads; a Waker is the callback that says 'poll me again'", + "originalText": "a task is a heap object the size of its locals: 20k tasks share 16 threads; a Waker is the callback that says 'poll me again'", "lineHeight": 1.25, "baseline": 10 } diff --git a/assets/diagrams/27-tokio-task-lifecycle.svg b/assets/diagrams/27-tokio-task-lifecycle.svg index 3ecc1af..b339424 100644 --- a/assets/diagrams/27-tokio-task-lifecycle.svg +++ b/assets/diagrams/27-tokio-task-lifecycle.svg @@ -1,11 +1,11 @@ -tokio tasks — async fn per connection (compiled to a state machine, not a thread) +tokio tasks: async fn per connection (compiled to a state machine, not a thread) -16 tokio-rt-worker threads (= cores) — work-stealing schedulers +16 tokio-rt-worker threads (= cores): work-stealing schedulers -mio reactor — one epoll instance +mio reactor: one epoll instance tokio::spawn handle_conn(...) @@ -25,7 +25,7 @@ run queue Waker::wake() re-enqueues task -epoll_wait — fd readable +epoll_wait: fd readable calls the registered Waker schedule @@ -45,5 +45,5 @@ re-poll re-poll -a task is a heap object the size of its locals — 20k tasks share 16 threads; a Waker is the callback that says 'poll me again' +a task is a heap object the size of its locals: 20k tasks share 16 threads; a Waker is the callback that says 'poll me again' \ No newline at end of file diff --git a/assets/diagrams/28-remote-debug-topology.excalidraw b/assets/diagrams/28-remote-debug-topology.excalidraw index d5bd4d2..d9cd8e1 100644 --- a/assets/diagrams/28-remote-debug-topology.excalidraw +++ b/assets/diagrams/28-remote-debug-topology.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "host (this session \u2014 verified)", + "text": "host (this session: verified)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "host (this session \u2014 verified)", + "originalText": "host (this session: verified)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "systems-target VM \u2014 documented, not run this session", + "text": "systems-target VM: documented, not run this session", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "systems-target VM \u2014 documented, not run this session", + "originalText": "systems-target VM: documented, not run this session", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/28-remote-debug-topology.svg b/assets/diagrams/28-remote-debug-topology.svg index 921fb2d..0037d8a 100644 --- a/assets/diagrams/28-remote-debug-topology.svg +++ b/assets/diagrams/28-remote-debug-topology.svg @@ -1,9 +1,9 @@ -host (this session — verified) +host (this session: verified) -systems-target VM — documented, not run this session +systems-target VM: documented, not run this session app crash SIGSEGV, exit 139 diff --git a/assets/diagrams/31-flamegraph-reading.excalidraw b/assets/diagrams/31-flamegraph-reading.excalidraw index 2f48ed6..3764239 100644 --- a/assets/diagrams/31-flamegraph-reading.excalidraw +++ b/assets/diagrams/31-flamegraph-reading.excalidraw @@ -511,13 +511,13 @@ "updated": 1, "link": null, "locked": false, - "text": "_start / runtime.main (100% \u2014 every sample passes through here)", + "text": "_start / runtime.main (100%: every sample passes through here)", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "_start / runtime.main (100% \u2014 every sample passes through here)", + "originalText": "_start / runtime.main (100%: every sample passes through here)", "lineHeight": 1.25, "baseline": 14 }, @@ -700,13 +700,13 @@ "updated": 1, "link": null, "locked": false, - "text": "spin_hot / hotSpin (99.2% \u2014 the wide box IS the hot path)", + "text": "spin_hot / hotSpin (99.2%: the wide box IS the hot path)", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "spin_hot / hotSpin (99.2% \u2014 the wide box IS the hot path)", + "originalText": "spin_hot / hotSpin (99.2%: the wide box IS the hot path)", "lineHeight": 1.25, "baseline": 14 }, @@ -763,13 +763,13 @@ "updated": 1, "link": null, "locked": false, - "text": "inner divisor loop (i % d == 0) \u2014 inlined, same width as its caller", + "text": "inner divisor loop (i % d == 0) : inlined, same width as its caller", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "inner divisor loop (i % d == 0) \u2014 inlined, same width as its caller", + "originalText": "inner divisor loop (i % d == 0) : inlined, same width as its caller", "lineHeight": 1.25, "baseline": 14 }, @@ -889,13 +889,13 @@ "updated": 1, "link": null, "locked": false, - "text": "(rest of spin_hot's samples, other instants \u2014 same function, same box below)", + "text": "(rest of spin_hot's samples, other instants: same function, same box below)", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "(rest of spin_hot's samples, other instants \u2014 same function, same box below)", + "originalText": "(rest of spin_hot's samples, other instants: same function, same box below)", "lineHeight": 1.25, "baseline": 14 }, @@ -1002,13 +1002,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Figure 31.1 \u2014 reading a flamegraph", + "text": "Figure 31.1: reading a flamegraph", "fontSize": 15, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Figure 31.1 \u2014 reading a flamegraph", + "originalText": "Figure 31.1: reading a flamegraph", "lineHeight": 1.25, "baseline": 15 }, @@ -1037,13 +1037,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Finding the hot path: scan for the widest unbroken column reaching toward the top \u2014 that name is where the cycles go.", + "text": "Finding the hot path: scan for the widest unbroken column reaching toward the top: that name is where the cycles go.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Finding the hot path: scan for the widest unbroken column reaching toward the top \u2014 that name is where the cycles go.", + "originalText": "Finding the hot path: scan for the widest unbroken column reaching toward the top: that name is where the cycles go.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/31-flamegraph-reading.svg b/assets/diagrams/31-flamegraph-reading.svg index 2006923..0cb36d1 100644 --- a/assets/diagrams/31-flamegraph-reading.svg +++ b/assets/diagrams/31-flamegraph-reading.svg @@ -15,22 +15,22 @@ color here = which language tab real tools often color per-module or random -_start / runtime.main (100% — every sample passes through here) +_start / runtime.main (100%: every sample passes through here) main / main.run (99.9%) -spin_hot / hotSpin (99.2% — the wide box IS the hot path) +spin_hot / hotSpin (99.2%: the wide box IS the hot path) -inner divisor loop (i % d == 0) — inlined, same width as its caller +inner divisor loop (i % d == 0) : inlined, same width as its caller leaf @ sample tick -(rest of spin_hot's samples, other instants — same function, same box below) +(rest of spin_hot's samples, other instants: same function, same box below) read UP one column: this is the call stack open at that instant read UP one column: this is the call stack open at that instant -Figure 31.1 — reading a flamegraph -Finding the hot path: scan for the widest unbroken column reaching toward the top — that name is where the cycles go. +Figure 31.1: reading a flamegraph +Finding the hot path: scan for the widest unbroken column reaching toward the top: that name is where the cycles go. \ No newline at end of file diff --git a/assets/diagrams/31-toolbelt-map.excalidraw b/assets/diagrams/31-toolbelt-map.excalidraw index 6d00ca3..49036ac 100644 --- a/assets/diagrams/31-toolbelt-map.excalidraw +++ b/assets/diagrams/31-toolbelt-map.excalidraw @@ -378,13 +378,13 @@ "updated": 1, "link": null, "locked": false, - "text": "external sampler, any ELF \u2014 spin_hot 99.9%", + "text": "external sampler, any ELF: spin_hot 99.9%", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "external sampler, any ELF \u2014 spin_hot 99.9%", + "originalText": "external sampler, any ELF: spin_hot 99.9%", "lineHeight": 1.25, "baseline": 11 }, @@ -1358,13 +1358,13 @@ "updated": 1, "link": null, "locked": false, - "text": "external sampler again \u2014 spin_hot inlined, ~100%", + "text": "external sampler again: spin_hot inlined, ~100%", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "external sampler again \u2014 spin_hot inlined, ~100%", + "originalText": "external sampler again: spin_hot inlined, ~100%", "lineHeight": 1.25, "baseline": 11 }, @@ -1914,13 +1914,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Figure 31.2 \u2014 one target, three native toolbelts", + "text": "Figure 31.2: one target, three native toolbelts", "fontSize": 15, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Figure 31.2 \u2014 one target, three native toolbelts", + "originalText": "Figure 31.2: one target, three native toolbelts", "lineHeight": 1.25, "baseline": 15 }, diff --git a/assets/diagrams/31-toolbelt-map.svg b/assets/diagrams/31-toolbelt-map.svg index f16a9df..70338c7 100644 --- a/assets/diagrams/31-toolbelt-map.svg +++ b/assets/diagrams/31-toolbelt-map.svg @@ -11,7 +11,7 @@ byte-identical result across all three perf record --call-graph fp -external sampler, any ELF — spin_hot 99.9% +external sampler, any ELF: spin_hot 99.9% perf report --stdio / perf stat cycles, instructions, flamegraph source @@ -41,7 +41,7 @@ static correctness checks perf record --call-graph fp -external sampler again — spin_hot inlined, ~100% +external sampler again: spin_hot inlined, ~100% cargo flamegraph inferno collapse+render, real SVG with spin_hot @@ -57,7 +57,7 @@ -Figure 31.2 — one target, three native toolbelts +Figure 31.2: one target, three native toolbelts Amber boxes are the CPU-profiling step this chapter cross-checks against each other: perf report / go tool pprof / perf report (or cargo flamegraph), all naming the same function. Dashed boxes are noted but out of scope here: gdb belongs to Chapter 28, tokio-console to the async runtimes of Chapter 27 (this program has no async runtime to show). \ No newline at end of file diff --git a/assets/diagrams/32-cgroup-hierarchy.excalidraw b/assets/diagrams/32-cgroup-hierarchy.excalidraw index cdf1c96..fe4fa53 100644 --- a/assets/diagrams/32-cgroup-hierarchy.excalidraw +++ b/assets/diagrams/32-cgroup-hierarchy.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "/sys/fs/cgroup (root \u2014 exempt from the \"no internal process\" rule)", + "text": "/sys/fs/cgroup (root: exempt from the \"no internal process\" rule)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "/sys/fs/cgroup (root \u2014 exempt from the \"no internal process\" rule)", + "originalText": "/sys/fs/cgroup (root: exempt from the \"no internal process\" rule)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 real dmesg from this session's OOM run", + "text": "kernel: real dmesg from this session's OOM run", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 real dmesg from this session's OOM run", + "originalText": "kernel: real dmesg from this session's OOM run", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/32-cgroup-hierarchy.svg b/assets/diagrams/32-cgroup-hierarchy.svg index da9e2e6..613c9f6 100644 --- a/assets/diagrams/32-cgroup-hierarchy.svg +++ b/assets/diagrams/32-cgroup-hierarchy.svg @@ -1,11 +1,11 @@ -/sys/fs/cgroup (root — exempt from the "no internal process" rule) +/sys/fs/cgroup (root: exempt from the "no internal process" rule) /sys/fs/cgroup/pmon-oomdemo (leaf, created by setup_cgroup()) -kernel — real dmesg from this session's OOM run +kernel: real dmesg from this session's OOM run cgroup.controllers cpuset cpu io memory hugetlb pids rdma misc dmem diff --git a/assets/diagrams/32-clone3-flow.excalidraw b/assets/diagrams/32-clone3-flow.excalidraw index 161e0b4..df11165 100644 --- a/assets/diagrams/32-clone3-flow.excalidraw +++ b/assets/diagrams/32-clone3-flow.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++ / Rust \u2014 unshare(2) then clone3/fork(flags=0)", + "text": "C++ / Rust: unshare(2) then clone3/fork(flags=0)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++ / Rust \u2014 unshare(2) then clone3/fork(flags=0)", + "originalText": "C++ / Rust: unshare(2) then clone3/fork(flags=0)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Go, first attempt \u2014 unshare(2) then re-exec via os/exec", + "text": "Go, first attempt: unshare(2) then re-exec via os/exec", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Go, first attempt \u2014 unshare(2) then re-exec via os/exec", + "originalText": "Go, first attempt: unshare(2) then re-exec via os/exec", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Go, shipped fix \u2014 Cloneflags on the re-exec's SysProcAttr", + "text": "Go, shipped fix: Cloneflags on the re-exec's SysProcAttr", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Go, shipped fix \u2014 Cloneflags on the re-exec's SysProcAttr", + "originalText": "Go, shipped fix: Cloneflags on the re-exec's SysProcAttr", "lineHeight": 1.25, "baseline": 12 }, @@ -476,13 +476,13 @@ "updated": 1, "link": null, "locked": false, - "text": "PASS \u2014 real run, this session", + "text": "PASS: real run, this session", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "PASS \u2014 real run, this session", + "originalText": "PASS: real run, this session", "lineHeight": 1.25, "baseline": 11 }, @@ -770,13 +770,13 @@ "updated": 1, "link": null, "locked": false, - "text": "\"fork/exec: cannot allocate memory\" \u2014 real, this session", + "text": "\"fork/exec: cannot allocate memory\": real, this session", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "\"fork/exec: cannot allocate memory\" \u2014 real, this session", + "originalText": "\"fork/exec: cannot allocate memory\": real, this session", "lineHeight": 1.25, "baseline": 11 }, @@ -868,13 +868,13 @@ "updated": 1, "link": null, "locked": false, - "text": "(unchanged \u2014 inherited across fork)", + "text": "(unchanged: inherited across fork)", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "(unchanged \u2014 inherited across fork)", + "originalText": "(unchanged: inherited across fork)", "lineHeight": 1.25, "baseline": 11 }, @@ -1029,13 +1029,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ONE clone(2) creates the child already inside all four namespaces \u2014 no prior unshare(), no LockOSThread needed", + "text": "ONE clone(2) creates the child already inside all four namespaces: no prior unshare(), no LockOSThread needed", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ONE clone(2) creates the child already inside all four namespaces \u2014 no prior unshare(), no LockOSThread needed", + "originalText": "ONE clone(2) creates the child already inside all four namespaces: no prior unshare(), no LockOSThread needed", "lineHeight": 1.25, "baseline": 14 }, @@ -1127,13 +1127,13 @@ "updated": 1, "link": null, "locked": false, - "text": "PASS 13/13 \u2014 cpp, go, rust \u2014 systems-target, this session", + "text": "PASS 13/13: cpp, go, rust: systems-target, this session", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "PASS 13/13 \u2014 cpp, go, rust \u2014 systems-target, this session", + "originalText": "PASS 13/13: cpp, go, rust: systems-target, this session", "lineHeight": 1.25, "baseline": 14 }, diff --git a/assets/diagrams/32-clone3-flow.svg b/assets/diagrams/32-clone3-flow.svg index f3b7417..f5b336e 100644 --- a/assets/diagrams/32-clone3-flow.svg +++ b/assets/diagrams/32-clone3-flow.svg @@ -1,11 +1,11 @@ -C++ / Rust — unshare(2) then clone3/fork(flags=0) +C++ / Rust: unshare(2) then clone3/fork(flags=0) -Go, first attempt — unshare(2) then re-exec via os/exec +Go, first attempt: unshare(2) then re-exec via os/exec -Go, shipped fix — Cloneflags on the re-exec's SysProcAttr +Go, shipped fix: Cloneflags on the re-exec's SysProcAttr unshare(NEWNS|NEWUTS|NEWNET|NEWPID) takes effect on the caller now @@ -14,7 +14,7 @@ = fork(2): child becomes PID 1 child: print pid/hostname, execvp(CMD) -PASS — real run, this session +PASS: real run, this session runtime.LockOSThread(); unshare(...) pins goroutine, then unshares @@ -23,18 +23,18 @@ internal vfork/pidfd probe fork first clone() = -1 ENOMEM -"fork/exec: cannot allocate memory" — real, this session +"fork/exec: cannot allocate memory": real, this session setup_cgroup(): write own pid first -(unchanged — inherited across fork) +(unchanged: inherited across fork) exec.Command(self, hostname, "--", CMD) SysProcAttr.Cloneflags = NEWNS|NEWUTS|NEWNET|NEWPID -ONE clone(2) creates the child already inside all four namespaces — no prior unshare(), no LockOSThread needed +ONE clone(2) creates the child already inside all four namespaces: no prior unshare(), no LockOSThread needed child re-execs itself as __ns_init__: mounts / MS_PRIVATE, sethostname, prints proof lines, execs CMD as PID 1 -PASS 13/13 — cpp, go, rust — systems-target, this session +PASS 13/13: cpp, go, rust: systems-target, this session diff --git a/assets/diagrams/32-namespace-overview.excalidraw b/assets/diagrams/32-namespace-overview.excalidraw index 97d16b4..25ebe22 100644 --- a/assets/diagrams/32-namespace-overview.excalidraw +++ b/assets/diagrams/32-namespace-overview.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "HOST \u2014 systems-target, pid 1 (systemd)", + "text": "HOST: systems-target, pid 1 (systemd)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "HOST \u2014 systems-target, pid 1 (systemd)", + "originalText": "HOST: systems-target, pid 1 (systemd)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon containerize child \u2014 new PID-1 task", + "text": "pmon containerize child: new PID-1 task", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon containerize child \u2014 new PID-1 task", + "originalText": "pmon containerize child: new PID-1 task", "lineHeight": 1.25, "baseline": 12 }, @@ -2072,13 +2072,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only \u2014 amber boxes are namespaces it actually unshares; grey/dashed", + "text": "pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only: amber boxes are namespaces it actually unshares; grey/dashed", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only \u2014 amber boxes are namespaces it actually unshares; grey/dashed", + "originalText": "pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only: amber boxes are namespaces it actually unshares; grey/dashed", "lineHeight": 1.25, "baseline": 12 }, @@ -2107,13 +2107,13 @@ "updated": 1, "link": null, "locked": false, - "text": "boxes are namespaces it deliberately leaves alone (time, IPC, user, cgroup) \u2014 every id above is a real readlink /proc//ns/* on systems-target.", + "text": "boxes are namespaces it leaves alone (time, IPC, user, cgroup): every id above is a real readlink /proc//ns/* on systems-target.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "boxes are namespaces it deliberately leaves alone (time, IPC, user, cgroup) \u2014 every id above is a real readlink /proc//ns/* on systems-target.", + "originalText": "boxes are namespaces it leaves alone (time, IPC, user, cgroup): every id above is a real readlink /proc//ns/* on systems-target.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/32-namespace-overview.svg b/assets/diagrams/32-namespace-overview.svg index 3579b08..ceb392b 100644 --- a/assets/diagrams/32-namespace-overview.svg +++ b/assets/diagrams/32-namespace-overview.svg @@ -1,9 +1,9 @@ -HOST — systems-target, pid 1 (systemd) +HOST: systems-target, pid 1 (systemd) -pmon containerize child — new PID-1 task +pmon containerize child: new PID-1 task PID pid:[4026531836] @@ -67,6 +67,6 @@ same inode same inode -pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only — amber boxes are namespaces it actually unshares; grey/dashed -boxes are namespaces it deliberately leaves alone (time, IPC, user, cgroup) — every id above is a real readlink /proc/<pid>/ns/* on systems-target. +pmon containerize requests CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWNET|CLONE_NEWPID only: amber boxes are namespaces it actually unshares; grey/dashed +boxes are namespaces it leaves alone (time, IPC, user, cgroup): every id above is a real readlink /proc/<pid>/ns/* on systems-target. \ No newline at end of file diff --git a/assets/diagrams/33-landlock-ruleset.excalidraw b/assets/diagrams/33-landlock-ruleset.excalidraw index 8a42217..2ee6025 100644 --- a/assets/diagrams/33-landlock-ruleset.excalidraw +++ b/assets/diagrams/33-landlock-ruleset.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "building the ruleset (unprivileged \u2014 no root, no VM needed)", + "text": "building the ruleset (unprivileged: no root, no VM needed)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "building the ruleset (unprivileged \u2014 no root, no VM needed)", + "originalText": "building the ruleset (unprivileged: no root, no VM needed)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "after landlock_restrict_self() \u2014 enforced against this process + every descendant", + "text": "after landlock_restrict_self(): enforced against this process + every descendant", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "after landlock_restrict_self() \u2014 enforced against this process + every descendant", + "originalText": "after landlock_restrict_self(): enforced against this process + every descendant", "lineHeight": 1.25, "baseline": 12 }, @@ -217,13 +217,13 @@ "updated": 1, "link": null, "locked": false, - "text": "probes the ABI \u2014 never hardcoded", + "text": "probes the ABI: never hardcoded", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "probes the ABI \u2014 never hardcoded", + "originalText": "probes the ABI: never hardcoded", "lineHeight": 1.25, "baseline": 11 }, @@ -805,13 +805,13 @@ "updated": 1, "link": null, "locked": false, - "text": "READ_FILE|READ_DIR allowed \u2014 watch loop works normally", + "text": "READ_FILE|READ_DIR allowed: watch loop works normally", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "READ_FILE|READ_DIR allowed \u2014 watch loop works normally", + "originalText": "READ_FILE|READ_DIR allowed: watch loop works normally", "lineHeight": 1.25, "baseline": 11 }, @@ -966,13 +966,13 @@ "updated": 1, "link": null, "locked": false, - "text": "handled_access_net left at 0 in this ruleset \u2014 no network mediation requested", + "text": "handled_access_net left at 0 in this ruleset: no network mediation requested", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "handled_access_net left at 0 in this ruleset \u2014 no network mediation requested", + "originalText": "handled_access_net left at 0 in this ruleset: no network mediation requested", "lineHeight": 1.25, "baseline": 14 }, @@ -1450,13 +1450,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Figure 33.2 \u2014 the Landlock ruleset/rule model, ABI-probed not assumed", + "text": "Figure 33.2: the Landlock ruleset/rule model, ABI-probed not assumed", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Figure 33.2 \u2014 the Landlock ruleset/rule model, ABI-probed not assumed", + "originalText": "Figure 33.2: the Landlock ruleset/rule model, ABI-probed not assumed", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/33-landlock-ruleset.svg b/assets/diagrams/33-landlock-ruleset.svg index 2bae41d..536c410 100644 --- a/assets/diagrams/33-landlock-ruleset.svg +++ b/assets/diagrams/33-landlock-ruleset.svg @@ -1,12 +1,12 @@ -building the ruleset (unprivileged — no root, no VM needed) +building the ruleset (unprivileged: no root, no VM needed) -after landlock_restrict_self() — enforced against this process + every descendant +after landlock_restrict_self(): enforced against this process + every descendant landlock_create_ruleset(NULL, 0, VERSION) -probes the ABI — never hardcoded +probes the ABI: never hardcoded host: ABI=9 · systems-target guest: ABI=7 same kernel line, different Landlock ABI @@ -24,12 +24,12 @@ irrevocable; TSYNC covers every Go OS thread /tmp/lsp33-watch-sandbox (= DIR) -READ_FILE|READ_DIR allowed — watch loop works normally +READ_FILE|READ_DIR allowed: watch loop works normally /tmp/lsp33-outside-target/secret.txt open(O_RDONLY) → -1 EACCES -handled_access_net left at 0 in this ruleset — no network mediation requested +handled_access_net left at 0 in this ruleset: no network mediation requested TCP bind/connect rights exist since ABI v4; UDP not until ABI v10 @@ -43,5 +43,5 @@ deny deny -Figure 33.2 — the Landlock ruleset/rule model, ABI-probed not assumed +Figure 33.2: the Landlock ruleset/rule model, ABI-probed not assumed \ No newline at end of file diff --git a/assets/diagrams/33-seccomp-filter-flow.excalidraw b/assets/diagrams/33-seccomp-filter-flow.excalidraw index 9727b29..cb2a059 100644 --- a/assets/diagrams/33-seccomp-filter-flow.excalidraw +++ b/assets/diagrams/33-seccomp-filter-flow.excalidraw @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel: seccomp-bpf filter \u2014 one cBPF program, RUN AGAIN on every syscall entry", + "text": "kernel: seccomp-bpf filter: one cBPF program, RUN AGAIN on every syscall entry", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel: seccomp-bpf filter \u2014 one cBPF program, RUN AGAIN on every syscall entry", + "originalText": "kernel: seccomp-bpf filter: one cBPF program, RUN AGAIN on every syscall entry", "lineHeight": 1.25, "baseline": 12 }, @@ -315,13 +315,13 @@ "updated": 1, "link": null, "locked": false, - "text": "you write the filter \u2014 Part 8's bpftrace observes; this decides", + "text": "you write the filter: Part 8's bpftrace observes; this decides", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "you write the filter \u2014 Part 8's bpftrace observes; this decides", + "originalText": "you write the filter: Part 8's bpftrace observes; this decides", "lineHeight": 1.25, "baseline": 11 }, @@ -770,13 +770,13 @@ "updated": 1, "link": null, "locked": false, - "text": "SCMP_ACT_ERRNO(EPERM) \u2014 fwatch's choice", + "text": "SCMP_ACT_ERRNO(EPERM): fwatch's choice", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "SCMP_ACT_ERRNO(EPERM) \u2014 fwatch's choice", + "originalText": "SCMP_ACT_ERRNO(EPERM): fwatch's choice", "lineHeight": 1.25, "baseline": 14 }, @@ -868,13 +868,13 @@ "updated": 1, "link": null, "locked": false, - "text": "SCMP_ACT_KILL_PROCESS \u2014 not used by fwatch", + "text": "SCMP_ACT_KILL_PROCESS: not used by fwatch", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "SCMP_ACT_KILL_PROCESS \u2014 not used by fwatch", + "originalText": "SCMP_ACT_KILL_PROCESS: not used by fwatch", "lineHeight": 1.25, "baseline": 14 }, @@ -1449,13 +1449,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Figure 33.1 \u2014 a syscall's path through fwatch's seccomp-bpf filter", + "text": "Figure 33.1: a syscall's path through fwatch's seccomp-bpf filter", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Figure 33.1 \u2014 a syscall's path through fwatch's seccomp-bpf filter", + "originalText": "Figure 33.1: a syscall's path through fwatch's seccomp-bpf filter", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/33-seccomp-filter-flow.svg b/assets/diagrams/33-seccomp-filter-flow.svg index 6cafb84..ac76a20 100644 --- a/assets/diagrams/33-seccomp-filter-flow.svg +++ b/assets/diagrams/33-seccomp-filter-flow.svg @@ -3,13 +3,13 @@ userspace: fwatch watch loop -kernel: seccomp-bpf filter — one cBPF program, RUN AGAIN on every syscall entry +kernel: seccomp-bpf filter: one cBPF program, RUN AGAIN on every syscall entry syscall(2) issued e.g. epoll_wait, read, socket this IS classic BPF (cBPF) -you write the filter — Part 8's bpftrace observes; this decides +you write the filter: Part 8's bpftrace observes; this decides BPF_LD|BPF_W|BPF_ABS load nr + arch offset @@ -23,10 +23,10 @@ no match → default action (seccomp_init's action arg) -SCMP_ACT_ERRNO(EPERM) — fwatch's choice +SCMP_ACT_ERRNO(EPERM): fwatch's choice socket(2) = -1 EPERM; process keeps running -SCMP_ACT_KILL_PROCESS — not used by fwatch +SCMP_ACT_KILL_PROCESS: not used by fwatch getpid() denied → +++ killed by SIGSYS +++ traps into kernel @@ -47,7 +47,7 @@ alternative action alternative action -Figure 33.1 — a syscall's path through fwatch's seccomp-bpf filter +Figure 33.1: a syscall's path through fwatch's seccomp-bpf filter Real: cpp/rust filters admit 26 syscalls, go's 39 (goroutine scheduler needs futex/clone/sigaltstack too). Guest (systems-target, kernel 6.19.10): socket(AF_INET,...) = -1 EPERM under fwatch's filter; a separate ACT_KILL_PROCESS probe on the same guest hit SIGSYS on getpid(). \ No newline at end of file diff --git a/assets/diagrams/35-kvm-virtio-stack.excalidraw b/assets/diagrams/35-kvm-virtio-stack.excalidraw index 539d2b0..3e5b8dc 100644 --- a/assets/diagrams/35-kvm-virtio-stack.excalidraw +++ b/assets/diagrams/35-kvm-virtio-stack.excalidraw @@ -1456,13 +1456,13 @@ "updated": 1, "link": null, "locked": false, - "text": "guest ~88ns/call \u2014 no vmexit on this path", + "text": "guest ~88ns/call: no vmexit on this path", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "guest ~88ns/call \u2014 no vmexit on this path", + "originalText": "guest ~88ns/call: no vmexit on this path", "lineHeight": 1.25, "baseline": 11 }, @@ -1554,13 +1554,13 @@ "updated": 1, "link": null, "locked": false, - "text": "guest ~15GB/s \u2014 EPT cost amortized", + "text": "guest ~15GB/s: EPT cost amortized", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "guest ~15GB/s \u2014 EPT cost amortized", + "originalText": "guest ~15GB/s: EPT cost amortized", "lineHeight": 1.25, "baseline": 11 }, @@ -1652,13 +1652,13 @@ "updated": 1, "link": null, "locked": false, - "text": "guest ~0.5k ops/s \u2014 the real vmexit tax", + "text": "guest ~0.5k ops/s: the real vmexit tax", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "guest ~0.5k ops/s \u2014 the real vmexit tax", + "originalText": "guest ~0.5k ops/s: the real vmexit tax", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/35-kvm-virtio-stack.svg b/assets/diagrams/35-kvm-virtio-stack.svg index f666920..a60a31b 100644 --- a/assets/diagrams/35-kvm-virtio-stack.svg +++ b/assets/diagrams/35-kvm-virtio-stack.svg @@ -44,13 +44,13 @@ cost lands here syscall (getpid): host ~88ns/call -guest ~88ns/call — no vmexit on this path +guest ~88ns/call: no vmexit on this path mem (128MiB scan): host ~14GB/s -guest ~15GB/s — EPT cost amortized +guest ~15GB/s: EPT cost amortized io (create+write+fsync): host ~1.3k ops/s -guest ~0.5k ops/s — the real vmexit tax +guest ~0.5k ops/s: the real vmexit tax ioctl(KVM_RUN) ioctl(KVM_RUN) diff --git a/assets/diagrams/36-proc-datasource-map.excalidraw b/assets/diagrams/36-proc-datasource-map.excalidraw index fb07451..ac7e590 100644 --- a/assets/diagrams/36-proc-datasource-map.excalidraw +++ b/assets/diagrams/36-proc-datasource-map.excalidraw @@ -2473,13 +2473,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Counters (stat, diskstats, net/dev) need TWO samples \u2014 a single read is cumulative since boot, not a rate.", + "text": "Counters (stat, diskstats, net/dev) need TWO samples: a single read is cumulative since boot, not a rate.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Counters (stat, diskstats, net/dev) need TWO samples \u2014 a single read is cumulative since boot, not a rate.", + "originalText": "Counters (stat, diskstats, net/dev) need TWO samples: a single read is cumulative since boot, not a rate.", "lineHeight": 1.25, "baseline": 12 }, @@ -2508,13 +2508,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Gauges (loadavg, meminfo, PSI avg10) are valid from one read \u2014 only the CPU line needs the delta.", + "text": "Gauges (loadavg, meminfo, PSI avg10) are valid from one read: only the CPU line needs the delta.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Gauges (loadavg, meminfo, PSI avg10) are valid from one read \u2014 only the CPU line needs the delta.", + "originalText": "Gauges (loadavg, meminfo, PSI avg10) are valid from one read: only the CPU line needs the delta.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/36-proc-datasource-map.svg b/assets/diagrams/36-proc-datasource-map.svg index 3a143a7..91d5019 100644 --- a/assets/diagrams/36-proc-datasource-map.svg +++ b/assets/diagrams/36-proc-datasource-map.svg @@ -77,6 +77,6 @@ join() join() -Counters (stat, diskstats, net/dev) need TWO samples — a single read is cumulative since boot, not a rate. -Gauges (loadavg, meminfo, PSI avg10) are valid from one read — only the CPU line needs the delta. +Counters (stat, diskstats, net/dev) need TWO samples: a single read is cumulative since boot, not a rate. +Gauges (loadavg, meminfo, PSI avg10) are valid from one read: only the CPU line needs the delta. \ No newline at end of file diff --git a/assets/diagrams/37-use-method-checklist.excalidraw b/assets/diagrams/37-use-method-checklist.excalidraw index 5a920c5..09ffd33 100644 --- a/assets/diagrams/37-use-method-checklist.excalidraw +++ b/assets/diagrams/37-use-method-checklist.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "loadmix analyze \u2014 run the real tools, read them by column name", + "text": "loadmix analyze: run the real tools, read them by column name", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "loadmix analyze \u2014 run the real tools, read them by column name", + "originalText": "loadmix analyze: run the real tools, read them by column name", "lineHeight": 1.25, "baseline": 12 }, @@ -854,13 +854,13 @@ "updated": 1, "link": null, "locked": false, - "text": "saturate \u2014 app --resource cpu|mem|io|net --seconds N", + "text": "saturate : app --resource cpu|mem|io|net --seconds N", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "saturate \u2014 app --resource cpu|mem|io|net --seconds N", + "originalText": "saturate : app --resource cpu|mem|io|net --seconds N", "lineHeight": 1.25, "baseline": 14 }, diff --git a/assets/diagrams/37-use-method-checklist.svg b/assets/diagrams/37-use-method-checklist.svg index 8a2c3eb..d701ccc 100644 --- a/assets/diagrams/37-use-method-checklist.svg +++ b/assets/diagrams/37-use-method-checklist.svg @@ -1,7 +1,7 @@ -loadmix analyze — run the real tools, read them by column name +loadmix analyze: run the real tools, read them by column name 4 pre-samples uptime · dmesg @@ -25,7 +25,7 @@ verdict max Saturation value / threshold -saturate — app --resource cpu|mem|io|net --seconds N +saturate : app --resource cpu|mem|io|net --seconds N a worker pool the concurrent analyze can attribute then diff --git a/assets/diagrams/38-otlp-pipeline.excalidraw b/assets/diagrams/38-otlp-pipeline.excalidraw index b465118..f54e336 100644 --- a/assets/diagrams/38-otlp-pipeline.excalidraw +++ b/assets/diagrams/38-otlp-pipeline.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "serve \u2014 one traced request per input line", + "text": "serve: one traced request per input line", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "serve \u2014 one traced request per input line", + "originalText": "serve: one traced request per input line", "lineHeight": 1.25, "baseline": 12 }, @@ -1485,13 +1485,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cpp \u00b7 go \u00b7 rust \u2014 each tags service.name = lsp-otel-, so the three never collide in the shared stack", + "text": "cpp \u00b7 go \u00b7 rust: each tags service.name = lsp-otel-, so the three never collide in the shared stack", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cpp \u00b7 go \u00b7 rust \u2014 each tags service.name = lsp-otel-, so the three never collide in the shared stack", + "originalText": "cpp \u00b7 go \u00b7 rust: each tags service.name = lsp-otel-, so the three never collide in the shared stack", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/38-otlp-pipeline.svg b/assets/diagrams/38-otlp-pipeline.svg index 6ff633c..8c1ff23 100644 --- a/assets/diagrams/38-otlp-pipeline.svg +++ b/assets/diagrams/38-otlp-pipeline.svg @@ -1,7 +1,7 @@ -serve — one traced request per input line +serve: one traced request per input line span: request (attr request.seq) @@ -46,5 +46,5 @@ metrics -cpp · go · rust — each tags service.name = lsp-otel-<lang>, so the three never collide in the shared stack +cpp · go · rust: each tags service.name = lsp-otel-<lang>, so the three never collide in the shared stack \ No newline at end of file diff --git a/assets/diagrams/39-benchmark-pipeline.excalidraw b/assets/diagrams/39-benchmark-pipeline.excalidraw index ee47710..136ded7 100644 --- a/assets/diagrams/39-benchmark-pipeline.excalidraw +++ b/assets/diagrams/39-benchmark-pipeline.excalidraw @@ -1274,13 +1274,13 @@ "updated": 1, "link": null, "locked": false, - "text": "no percentiles \u2014", + "text": "no percentiles", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "no percentiles \u2014", + "originalText": "no percentiles", "lineHeight": 1.25, "baseline": 11 }, @@ -1723,13 +1723,13 @@ "updated": 1, "link": null, "locked": false, - "text": "same codec, same fixed workload \u2014 the harness, not the code under test, is what changes the story", + "text": "same codec, same fixed workload: the harness, not the code under test, is what changes the story", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "same codec, same fixed workload \u2014 the harness, not the code under test, is what changes the story", + "originalText": "same codec, same fixed workload: the harness, not the code under test, is what changes the story", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/39-benchmark-pipeline.svg b/assets/diagrams/39-benchmark-pipeline.svg index 2ebdf6d..034d919 100644 --- a/assets/diagrams/39-benchmark-pipeline.svg +++ b/assets/diagrams/39-benchmark-pipeline.svg @@ -38,7 +38,7 @@ t1 - t0, single sample elapsed_ns printed -no percentiles — +no percentiles nothing to compute one from steady state @@ -50,5 +50,5 @@ -same codec, same fixed workload — the harness, not the code under test, is what changes the story +same codec, same fixed workload: the harness, not the code under test, is what changes the story \ No newline at end of file diff --git a/assets/diagrams/39-coordinated-omission.excalidraw b/assets/diagrams/39-coordinated-omission.excalidraw index 29cdf7b..fdab045 100644 --- a/assets/diagrams/39-coordinated-omission.excalidraw +++ b/assets/diagrams/39-coordinated-omission.excalidraw @@ -1829,13 +1829,13 @@ "updated": 1, "link": null, "locked": false, - "text": "raw p99 (1000-sample window): only 1 of the 1000 samples is the stall \u2014 buried, not the tail", + "text": "raw p99 (1000-sample window): only 1 of the 1000 samples is the stall: buried, not the tail", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "raw p99 (1000-sample window): only 1 of the 1000 samples is the stall \u2014 buried, not the tail", + "originalText": "raw p99 (1000-sample window): only 1 of the 1000 samples is the stall: buried, not the tail", "lineHeight": 1.25, "baseline": 11 }, @@ -1864,13 +1864,13 @@ "updated": 1, "link": null, "locked": false, - "text": "co_p99 backfills the requests that would have queued behind the stall \u2014 co_n grows, co_p99_ns \u2265 p99_ns always", + "text": "co_p99 backfills the requests that would have queued behind the stall: co_n grows, co_p99_ns \u2265 p99_ns always", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "co_p99 backfills the requests that would have queued behind the stall \u2014 co_n grows, co_p99_ns \u2265 p99_ns always", + "originalText": "co_p99 backfills the requests that would have queued behind the stall: co_n grows, co_p99_ns \u2265 p99_ns always", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/39-coordinated-omission.svg b/assets/diagrams/39-coordinated-omission.svg index 5f8f0f5..e7a30c9 100644 --- a/assets/diagrams/39-coordinated-omission.svg +++ b/assets/diagrams/39-coordinated-omission.svg @@ -54,6 +54,6 @@ same stall same stall -raw p99 (1000-sample window): only 1 of the 1000 samples is the stall — buried, not the tail -co_p99 backfills the requests that would have queued behind the stall — co_n grows, co_p99_ns ≥ p99_ns always +raw p99 (1000-sample window): only 1 of the 1000 samples is the stall: buried, not the tail +co_p99 backfills the requests that would have queued behind the stall: co_n grows, co_p99_ns ≥ p99_ns always \ No newline at end of file diff --git a/assets/diagrams/40-fastpath-datapath.excalidraw b/assets/diagrams/40-fastpath-datapath.excalidraw index 41b4ed0..1dbd78e 100644 --- a/assets/diagrams/40-fastpath-datapath.excalidraw +++ b/assets/diagrams/40-fastpath-datapath.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "naive \u2014 blocking read, migratable", + "text": "naive: blocking read, migratable", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "naive \u2014 blocking read, migratable", + "originalText": "naive: blocking read, migratable", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fastpath \u2014 busy-poll, pinned core", + "text": "fastpath: busy-poll, pinned core", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fastpath \u2014 busy-poll, pinned core", + "originalText": "fastpath: busy-poll, pinned core", "lineHeight": 1.25, "baseline": 12 }, @@ -280,13 +280,13 @@ "updated": 1, "link": null, "locked": false, - "text": "read(2) \u2014 blocks", + "text": "read(2): blocks", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "read(2) \u2014 blocks", + "originalText": "read(2): blocks", "lineHeight": 1.25, "baseline": 14 }, @@ -805,13 +805,13 @@ "updated": 1, "link": null, "locked": false, - "text": "scheduler \u2014 never entered", + "text": "scheduler: never entered", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "scheduler \u2014 never entered", + "originalText": "scheduler: never entered", "lineHeight": 1.25, "baseline": 14 }, @@ -1632,13 +1632,13 @@ "updated": 1, "link": null, "locked": false, - "text": "same 64-byte frame, same round trip \u2014 the difference is who the thread asks for its CPU back", + "text": "same 64-byte frame, same round trip: the difference is who the thread asks for its CPU back", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "same 64-byte frame, same round trip \u2014 the difference is who the thread asks for its CPU back", + "originalText": "same 64-byte frame, same round trip: the difference is who the thread asks for its CPU back", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/40-fastpath-datapath.svg b/assets/diagrams/40-fastpath-datapath.svg index 0bfe131..bd581aa 100644 --- a/assets/diagrams/40-fastpath-datapath.svg +++ b/assets/diagrams/40-fastpath-datapath.svg @@ -1,14 +1,14 @@ -naive — blocking read, migratable +naive: blocking read, migratable -fastpath — busy-poll, pinned core +fastpath: busy-poll, pinned core client sends 64B -read(2) — blocks +read(2): blocks fresh heap buf / msg kernel scheduler @@ -24,7 +24,7 @@ spin on EAGAIN, one reused buf pinned: CPU 1 -scheduler — never entered +scheduler: never entered write(2) echo 64B @@ -54,5 +54,5 @@ echo 64B voluntary_ctxt_switches ≈ 1 / msg voluntary_ctxt_switches ≈ 0 -same 64-byte frame, same round trip — the difference is who the thread asks for its CPU back +same 64-byte frame, same round trip: the difference is who the thread asks for its CPU back \ No newline at end of file diff --git a/assets/diagrams/41-fleet-topology.excalidraw b/assets/diagrams/41-fleet-topology.excalidraw index 48c97d9..375c29c 100644 --- a/assets/diagrams/41-fleet-topology.excalidraw +++ b/assets/diagrams/41-fleet-topology.excalidraw @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon \u2014 supervisor", + "text": "pmon: supervisor", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon \u2014 supervisor", + "originalText": "pmon: supervisor", "lineHeight": 1.25, "baseline": 14 }, @@ -574,13 +574,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon \u2014 supervisor", + "text": "pmon: supervisor", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon \u2014 supervisor", + "originalText": "pmon: supervisor", "lineHeight": 1.25, "baseline": 14 }, diff --git a/assets/diagrams/41-fleet-topology.svg b/assets/diagrams/41-fleet-topology.svg index 15fdcde..51b8c9b 100644 --- a/assets/diagrams/41-fleet-topology.svg +++ b/assets/diagrams/41-fleet-topology.svg @@ -5,7 +5,7 @@ systems-peer · node=peer -pmon — supervisor +pmon: supervisor drops caps · no_new_privs · restarts · health fwatch @@ -17,7 +17,7 @@ chatterd chat + bridge -pmon — supervisor +pmon: supervisor drops caps · no_new_privs · restarts · health chatterd diff --git a/assets/diagrams/41-supervise-lifecycle.excalidraw b/assets/diagrams/41-supervise-lifecycle.excalidraw index decc1b1..cd569be 100644 --- a/assets/diagrams/41-supervise-lifecycle.excalidraw +++ b/assets/diagrams/41-supervise-lifecycle.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmon \u2014 one child's supervise loop", + "text": "pmon: one child's supervise loop", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmon \u2014 one child's supervise loop", + "originalText": "pmon: one child's supervise loop", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/41-supervise-lifecycle.svg b/assets/diagrams/41-supervise-lifecycle.svg index 22c22cd..568d062 100644 --- a/assets/diagrams/41-supervise-lifecycle.svg +++ b/assets/diagrams/41-supervise-lifecycle.svg @@ -1,7 +1,7 @@ -pmon — one child's supervise loop +pmon: one child's supervise loop pmon per child diff --git a/assets/diagrams/44-gmp-scheduler.excalidraw b/assets/diagrams/44-gmp-scheduler.excalidraw index 344da83..6268ab3 100644 --- a/assets/diagrams/44-gmp-scheduler.excalidraw +++ b/assets/diagrams/44-gmp-scheduler.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "global run queue (sched.runq) \u2014 overflow / injection target, intrusive linked list", + "text": "global run queue (sched.runq): overflow / injection target, intrusive linked list", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "global run queue (sched.runq) \u2014 overflow / injection target, intrusive linked list", + "originalText": "global run queue (sched.runq): overflow / injection target, intrusive linked list", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "P \u2014 GOMAXPROCS scheduling contexts, each bound to one M (OS thread)", + "text": "P: GOMAXPROCS scheduling contexts, each bound to one M (OS thread)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "P \u2014 GOMAXPROCS scheduling contexts, each bound to one M (OS thread)", + "originalText": "P: GOMAXPROCS scheduling contexts, each bound to one M (OS thread)", "lineHeight": 1.25, "baseline": 12 }, @@ -469,13 +469,13 @@ "updated": 1, "link": null, "locked": false, - "text": "local runq \u2014 256 slots", + "text": "local runq: 256 slots", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "local runq \u2014 256 slots", + "originalText": "local runq: 256 slots", "lineHeight": 1.25, "baseline": 14 }, @@ -700,13 +700,13 @@ "updated": 1, "link": null, "locked": false, - "text": "local runq \u2014 256 slots", + "text": "local runq: 256 slots", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "local runq \u2014 256 slots", + "originalText": "local runq: 256 slots", "lineHeight": 1.25, "baseline": 14 }, @@ -735,13 +735,13 @@ "updated": 1, "link": null, "locked": false, - "text": "runnext: \u2014", + "text": "runnext:", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "runnext: \u2014", + "originalText": "runnext:", "lineHeight": 1.25, "baseline": 11 }, @@ -966,13 +966,13 @@ "updated": 1, "link": null, "locked": false, - "text": "sysmon \u2014 dedicated M, no P", + "text": "sysmon: dedicated M, no P", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "sysmon \u2014 dedicated M, no P", + "originalText": "sysmon: dedicated M, no P", "lineHeight": 1.25, "baseline": 14 }, @@ -1375,13 +1375,13 @@ "updated": 1, "link": null, "locked": false, - "text": "container-aware GOMAXPROCS default since Go 1.25 \u2014 min(logical CPUs, affinity, cgroup quota), floor 2", + "text": "container-aware GOMAXPROCS default since Go 1.25: min(logical CPUs, affinity, cgroup quota), floor 2", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "container-aware GOMAXPROCS default since Go 1.25 \u2014 min(logical CPUs, affinity, cgroup quota), floor 2", + "originalText": "container-aware GOMAXPROCS default since Go 1.25: min(logical CPUs, affinity, cgroup quota), floor 2", "lineHeight": 1.25, "baseline": 11 }, @@ -1410,13 +1410,13 @@ "updated": 1, "link": null, "locked": false, - "text": "M:N \u2014 many G onto few M via P", + "text": "M:N: many G onto few M via P", "fontSize": 20, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "M:N \u2014 many G onto few M via P", + "originalText": "M:N: many G onto few M via P", "lineHeight": 1.25, "baseline": 20 }, diff --git a/assets/diagrams/44-gmp-scheduler.svg b/assets/diagrams/44-gmp-scheduler.svg index 26e167b..2626ea1 100644 --- a/assets/diagrams/44-gmp-scheduler.svg +++ b/assets/diagrams/44-gmp-scheduler.svg @@ -1,9 +1,9 @@ -global run queue (sched.runq) — overflow / injection target, intrusive linked list +global run queue (sched.runq): overflow / injection target, intrusive linked list -P — GOMAXPROCS scheduling contexts, each bound to one M (OS thread) +P: GOMAXPROCS scheduling contexts, each bound to one M (OS thread) G @@ -14,22 +14,22 @@ P0 · M0 (thread) running: G (spinner) -local runq — 256 slots +local runq: 256 slots runnext: G7 (fast path) [G3][G9][G12] … P1 · M1 (thread) running: G (ticker) -local runq — 256 slots -runnext: — +local runq: 256 slots +runnext: [G5][G14] … … P2 – P15 GOMAXPROCS = 16 (this 16-CPU Fedora host) -sysmon — dedicated M, no P +sysmon: dedicated M, no P retake: preempt syscall/G > 10ms forcegc: every 2 min if idle netpoll backstop: unpolled > 10ms @@ -43,7 +43,7 @@ SIGURG → asyncPreempt (signal-based) SIGURG → asyncPreempt (signal-based) -container-aware GOMAXPROCS default since Go 1.25 — min(logical CPUs, affinity, cgroup quota), floor 2 -M:N — many G onto few M via P +container-aware GOMAXPROCS default since Go 1.25: min(logical CPUs, affinity, cgroup quota), floor 2 +M:N: many G onto few M via P GOMAXPROCS=1 still preempts: sysmon's SIGURG doesn't need a spare P \ No newline at end of file diff --git a/assets/diagrams/44-goroutines-not-threads.excalidraw b/assets/diagrams/44-goroutines-not-threads.excalidraw index fadd462..80c7a88 100644 --- a/assets/diagrams/44-goroutines-not-threads.excalidraw +++ b/assets/diagrams/44-goroutines-not-threads.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "netpoll theme (this chapter) \u2014 goroutines parked on the netpoller, no M held", + "text": "netpoll theme (this chapter): goroutines parked on the netpoller, no M held", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "netpoll theme (this chapter) \u2014 goroutines parked on the netpoller, no M held", + "originalText": "netpoll theme (this chapter): goroutines parked on the netpoller, no M held", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "contrast \u2014 a raw blocking syscall.Read pins its own M per goroutine", + "text": "contrast: a raw blocking syscall.Read pins its own M per goroutine", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "contrast \u2014 a raw blocking syscall.Read pins its own M per goroutine", + "originalText": "contrast: a raw blocking syscall.Read pins its own M per goroutine", "lineHeight": 1.25, "baseline": 12 }, @@ -315,13 +315,13 @@ "updated": 1, "link": null, "locked": false, - "text": "netpoller \u2014 1 shared epoll", + "text": "netpoller: 1 shared epoll", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "netpoller \u2014 1 shared epoll", + "originalText": "netpoller: 1 shared epoll", "lineHeight": 1.25, "baseline": 14 }, @@ -995,13 +995,13 @@ "updated": 1, "link": null, "locked": false, - "text": "parked \u2014 no M", + "text": "parked: no M", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "parked \u2014 no M", + "originalText": "parked: no M", "lineHeight": 1.25, "baseline": 11 }, @@ -1264,13 +1264,13 @@ "updated": 1, "link": null, "locked": false, - "text": "goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80 \u2014 a raw blocking read would need ~2000 threads", + "text": "goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80: a raw blocking read would need ~2000 threads", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80 \u2014 a raw blocking read would need ~2000 threads", + "originalText": "goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80: a raw blocking read would need ~2000 threads", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/44-goroutines-not-threads.svg b/assets/diagrams/44-goroutines-not-threads.svg index 73f66d6..5bad8a4 100644 --- a/assets/diagrams/44-goroutines-not-threads.svg +++ b/assets/diagrams/44-goroutines-not-threads.svg @@ -1,15 +1,15 @@ -netpoll theme (this chapter) — goroutines parked on the netpoller, no M held +netpoll theme (this chapter): goroutines parked on the netpoller, no M held -contrast — a raw blocking syscall.Read pins its own M per goroutine +contrast: a raw blocking syscall.Read pins its own M per goroutine 2000 goroutines blocked on os.Pipe read EAGAIN → gopark, no M -netpoller — 1 shared epoll +netpoller: 1 shared epoll EpollWait issues epoll_pwait(2) edge-triggered, per-fd pollDesc @@ -29,8 +29,8 @@ toward N (clone() storm) sysmon retake / startm / newm -parked — no M -parked — no M +parked: no M +parked: no M epoll event wakes G epoll event wakes G @@ -40,5 +40,5 @@ handoffp → startm/newm handoffp → startm/newm -goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80 — a raw blocking read would need ~2000 threads +goroutines != threads: 2000 parked goroutines, 12 OS threads, bound 80: a raw blocking read would need ~2000 threads \ No newline at end of file diff --git a/assets/diagrams/45-analysis-suite-landscape.excalidraw b/assets/diagrams/45-analysis-suite-landscape.excalidraw index 81667ca..85b091e 100644 --- a/assets/diagrams/45-analysis-suite-landscape.excalidraw +++ b/assets/diagrams/45-analysis-suite-landscape.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Cockpit \u2014 web console (VM)", + "text": "Cockpit: web console (VM)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Cockpit \u2014 web console (VM)", + "originalText": "Cockpit: web console (VM)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "SystemTap \u2014 kernel-module tracing (VM)", + "text": "SystemTap: kernel-module tracing (VM)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "SystemTap \u2014 kernel-module tracing (VM)", + "originalText": "SystemTap: kernel-module tracing (VM)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "PCP \u2014 pmcd + PMDAs (container, ch45)", + "text": "PCP: pmcd + PMDAs (container, ch45)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "PCP \u2014 pmcd + PMDAs (container, ch45)", + "originalText": "PCP: pmcd + PMDAs (container, ch45)", "lineHeight": 1.25, "baseline": 12 }, @@ -378,13 +378,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one process \u2014 WebSocket + D-Bus", + "text": "one process: WebSocket + D-Bus", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one process \u2014 WebSocket + D-Bus", + "originalText": "one process: WebSocket + D-Bus", "lineHeight": 1.25, "baseline": 11 }, @@ -1358,13 +1358,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pmda-bcc \u2014 NOT shipped", + "text": "pmda-bcc: NOT shipped", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pmda-bcc \u2014 NOT shipped", + "originalText": "pmda-bcc: NOT shipped", "lineHeight": 1.25, "baseline": 14 }, @@ -1807,13 +1807,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Web panels (Overview / Podman / Logs): described only \u2014", + "text": "Web panels (Overview / Podman / Logs): described only", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Web panels (Overview / Podman / Logs): described only \u2014", + "originalText": "Web panels (Overview / Podman / Logs): described only", "lineHeight": 1.25, "baseline": 11 }, @@ -1877,13 +1877,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Contrast: ch30's dyninst backend was inconclusive on this host \u2014", + "text": "Contrast: ch30's dyninst backend was inconclusive on this host", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Contrast: ch30's dyninst backend was inconclusive on this host \u2014", + "originalText": "Contrast: ch30's dyninst backend was inconclusive on this host", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/45-analysis-suite-landscape.svg b/assets/diagrams/45-analysis-suite-landscape.svg index 6a63976..ba9e6d6 100644 --- a/assets/diagrams/45-analysis-suite-landscape.svg +++ b/assets/diagrams/45-analysis-suite-landscape.svg @@ -1,17 +1,17 @@ -Cockpit — web console (VM) +Cockpit: web console (VM) -SystemTap — kernel-module tracing (VM) +SystemTap: kernel-module tracing (VM) -PCP — pmcd + PMDAs (container, ch45) +PCP: pmcd + PMDAs (container, ch45) browser https://<vm>:9090/ cockpit-ws -one process — WebSocket + D-Bus +one process: WebSocket + D-Bus systemd guest services @@ -41,7 +41,7 @@ pmda-podman podman.sock (ch34) -pmda-bcc — NOT shipped +pmda-bcc: NOT shipped super-privileged; ch30 on the VM HTTP 200 (verified) @@ -53,8 +53,8 @@ -Web panels (Overview / Podman / Logs): described only — +Web panels (Overview / Podman / Logs): described only no browser automation in this session. -Contrast: ch30's dyninst backend was inconclusive on this host — +Contrast: ch30's dyninst backend was inconclusive on this host the kernel-module path needed matching kernel-devel; now verified. \ No newline at end of file diff --git a/assets/diagrams/45-pcp-build-gate.excalidraw b/assets/diagrams/45-pcp-build-gate.excalidraw index e9634a5..9588b12 100644 --- a/assets/diagrams/45-pcp-build-gate.excalidraw +++ b/assets/diagrams/45-pcp-build-gate.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "builder \u2014 dnf install + PMDA activation", + "text": "builder: dnf install + PMDA activation", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "builder \u2014 dnf install + PMDA activation", + "originalText": "builder: dnf install + PMDA activation", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "smoke \u2014 build-time correctness gate (FROM builder)", + "text": "smoke: build-time correctness gate (FROM builder)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "smoke \u2014 build-time correctness gate (FROM builder)", + "originalText": "smoke: build-time correctness gate (FROM builder)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "runtime \u2014 shipped image (FROM smoke)", + "text": "runtime: shipped image (FROM smoke)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "runtime \u2014 shipped image (FROM smoke)", + "originalText": "runtime: shipped image (FROM smoke)", "lineHeight": 1.25, "baseline": 12 }, @@ -1225,13 +1225,13 @@ "updated": 1, "link": null, "locked": false, - "text": "not in this image \u2014 on systems-target via cloud-init", + "text": "not in this image: on systems-target via cloud-init", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "not in this image \u2014 on systems-target via cloud-init", + "originalText": "not in this image: on systems-target via cloud-init", "lineHeight": 1.25, "baseline": 11 }, @@ -1717,13 +1717,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Chaining runtime onto smoke forces podman to actually build the gate stage \u2014", + "text": "Chaining runtime onto smoke forces podman to actually build the gate stage", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Chaining runtime onto smoke forces podman to actually build the gate stage \u2014", + "originalText": "Chaining runtime onto smoke forces podman to actually build the gate stage", "lineHeight": 1.25, "baseline": 12 }, @@ -1822,13 +1822,13 @@ "updated": 1, "link": null, "locked": false, - "text": "PMNS/pmcd.conf \u2014 no third Install run.", + "text": "PMNS/pmcd.conf: no third Install run.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "PMNS/pmcd.conf \u2014 no third Install run.", + "originalText": "PMNS/pmcd.conf: no third Install run.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/45-pcp-build-gate.svg b/assets/diagrams/45-pcp-build-gate.svg index 80ca9e6..4c92f4a 100644 --- a/assets/diagrams/45-pcp-build-gate.svg +++ b/assets/diagrams/45-pcp-build-gate.svg @@ -1,11 +1,11 @@ -builder — dnf install + PMDA activation +builder: dnf install + PMDA activation -smoke — build-time correctness gate (FROM builder) +smoke: build-time correctness gate (FROM builder) -runtime — shipped image (FROM smoke) +runtime: shipped image (FROM smoke) dnf install pcp + pcp-pmda-openmetrics + pcp-pmda-podman @@ -37,7 +37,7 @@ /usr/libexec/pcp/bin/pmcd -f Cockpit + SystemTap -not in this image — on systems-target via cloud-init +not in this image: on systems-target via cloud-init @@ -51,8 +51,8 @@ FROM smoke FROM smoke -Chaining runtime onto smoke forces podman to actually build the gate stage — +Chaining runtime onto smoke forces podman to actually build the gate stage an unreferenced stage (e.g. “FROM builder AS runtime”) is silently skipped by podman build. Reuses smoke's already-activated -PMNS/pmcd.conf — no third Install run. +PMNS/pmcd.conf: no third Install run. \ No newline at end of file diff --git a/assets/diagrams/46-cmake-preset-graph.excalidraw b/assets/diagrams/46-cmake-preset-graph.excalidraw index 9d59a7c..2a4ab5a 100644 --- a/assets/diagrams/46-cmake-preset-graph.excalidraw +++ b/assets/diagrams/46-cmake-preset-graph.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "CMakePresets.json \u2014 configure presets (inherits _base)", + "text": "CMakePresets.json: configure presets (inherits _base)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "CMakePresets.json \u2014 configure presets (inherits _base)", + "originalText": "CMakePresets.json: configure presets (inherits _base)", "lineHeight": 1.25, "baseline": 12 }, @@ -1519,13 +1519,13 @@ "updated": 1, "link": null, "locked": false, - "text": "parity gate (Fig 46.2) \u2014 GCC presets vs clang twins are color-coded above.", + "text": "parity gate (Fig 46.2): GCC presets vs clang twins are color-coded above.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "parity gate (Fig 46.2) \u2014 GCC presets vs clang twins are color-coded above.", + "originalText": "parity gate (Fig 46.2): GCC presets vs clang twins are color-coded above.", "lineHeight": 1.25, "baseline": 12 }, @@ -1554,13 +1554,13 @@ "updated": 1, "link": null, "locked": false, - "text": "isolated \u2014 no inherits", + "text": "isolated: no inherits", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "isolated \u2014 no inherits", + "originalText": "isolated: no inherits", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/46-cmake-preset-graph.svg b/assets/diagrams/46-cmake-preset-graph.svg index 25227c1..526d155 100644 --- a/assets/diagrams/46-cmake-preset-graph.svg +++ b/assets/diagrams/46-cmake-preset-graph.svg @@ -1,7 +1,7 @@ -CMakePresets.json — configure presets (inherits _base) +CMakePresets.json: configure presets (inherits _base) Conan sub-target @@ -44,8 +44,8 @@ verify: parity gate ① clang diagnostics (shown) ① release + release-clang both feed the byte-identical -parity gate (Fig 46.2) — GCC presets vs clang twins are color-coded above. -isolated — no inherits +parity gate (Fig 46.2): GCC presets vs clang twins are color-coded above. +isolated: no inherits keeps CI's Conan-less build-smoke green \ No newline at end of file diff --git a/assets/diagrams/46-toolbox-pipeline.excalidraw b/assets/diagrams/46-toolbox-pipeline.excalidraw index 15b5719..e2460de 100644 --- a/assets/diagrams/46-toolbox-pipeline.excalidraw +++ b/assets/diagrams/46-toolbox-pipeline.excalidraw @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Build / parity arm \u2014 GCC vs clang", + "text": "Build / parity arm: GCC vs clang", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Build / parity arm \u2014 GCC vs clang", + "originalText": "Build / parity arm: GCC vs clang", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Static arm \u2014 compile-time checks", + "text": "Static arm: compile-time checks", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Static arm \u2014 compile-time checks", + "originalText": "Static arm: compile-time checks", "lineHeight": 1.25, "baseline": 12 }, @@ -245,13 +245,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Runtime arm \u2014 sanitizer + debugger", + "text": "Runtime arm: sanitizer + debugger", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Runtime arm \u2014 sanitizer + debugger", + "originalText": "Runtime arm: sanitizer + debugger", "lineHeight": 1.25, "baseline": 12 }, @@ -308,13 +308,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Accelerators \u2014 optional, not verified this session", + "text": "Accelerators: optional, not verified this session", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Accelerators \u2014 optional, not verified this session", + "originalText": "Accelerators: optional, not verified this session", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/46-toolbox-pipeline.svg b/assets/diagrams/46-toolbox-pipeline.svg index 2de5679..4bf2d5c 100644 --- a/assets/diagrams/46-toolbox-pipeline.svg +++ b/assets/diagrams/46-toolbox-pipeline.svg @@ -3,13 +3,13 @@ source -Build / parity arm — GCC vs clang +Build / parity arm: GCC vs clang -Static arm — compile-time checks +Static arm: compile-time checks -Runtime arm — sanitizer + debugger +Runtime arm: sanitizer + debugger -Accelerators — optional, not verified this session +Accelerators: optional, not verified this session toolbox.cpp single source, diff --git a/assets/diagrams/47-go-tool-gates.excalidraw b/assets/diagrams/47-go-tool-gates.excalidraw index 462d6e3..195dedf 100644 --- a/assets/diagrams/47-go-tool-gates.excalidraw +++ b/assets/diagrams/47-go-tool-gates.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Hard lane \u2014 go-native, VERIFIED on this host (ships inside the go binary)", + "text": "Hard lane: go-native, VERIFIED on this host (ships inside the go binary)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Hard lane \u2014 go-native, VERIFIED on this host (ships inside the go binary)", + "originalText": "Hard lane: go-native, VERIFIED on this host (ships inside the go binary)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Gated-if-present lane \u2014 reader installs; NOT verified on this host (shown as reference)", + "text": "Gated-if-present lane: reader installs; NOT verified on this host (shown as reference)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Gated-if-present lane \u2014 reader installs; NOT verified on this host (shown as reference)", + "originalText": "Gated-if-present lane: reader installs; NOT verified on this host (shown as reference)", "lineHeight": 1.25, "baseline": 12 }, @@ -2223,13 +2223,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Hard lane needs no install \u2014 it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary).", + "text": "Hard lane needs no install: it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary).", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Hard lane needs no install \u2014 it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary).", + "originalText": "Hard lane needs no install: it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary).", "lineHeight": 1.25, "baseline": 12 }, @@ -2258,13 +2258,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Gated lane needs `go install @latest` (govulncheck also needs network) \u2014 not run on this host; shown as reference only.", + "text": "Gated lane needs `go install @latest` (govulncheck also needs network): not run on this host; shown as reference only.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Gated lane needs `go install @latest` (govulncheck also needs network) \u2014 not run on this host; shown as reference only.", + "originalText": "Gated lane needs `go install @latest` (govulncheck also needs network): not run on this host; shown as reference only.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/47-go-tool-gates.svg b/assets/diagrams/47-go-tool-gates.svg index 8153ad3..860d2de 100644 --- a/assets/diagrams/47-go-tool-gates.svg +++ b/assets/diagrams/47-go-tool-gates.svg @@ -1,9 +1,9 @@ -Hard lane — go-native, VERIFIED on this host (ships inside the go binary) +Hard lane: go-native, VERIFIED on this host (ships inside the go binary) -Gated-if-present lane — reader installs; NOT verified on this host (shown as reference) +Gated-if-present lane: reader installs; NOT verified on this host (shown as reference) go module one source tree @@ -63,6 +63,6 @@ -Hard lane needs no install — it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary). -Gated lane needs `go install <tool>@latest` (govulncheck also needs network) — not run on this host; shown as reference only. +Hard lane needs no install: it is verified this session (gofmt/go generate/go vet/pprof/digest all ship inside the go binary). +Gated lane needs `go install <tool>@latest` (govulncheck also needs network): not run on this host; shown as reference only. \ No newline at end of file diff --git a/assets/diagrams/47-go-toolchain-pipeline.excalidraw b/assets/diagrams/47-go-toolchain-pipeline.excalidraw index 38a9447..c2a4581 100644 --- a/assets/diagrams/47-go-toolchain-pipeline.excalidraw +++ b/assets/diagrams/47-go-toolchain-pipeline.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "go.mod \u2192 GOTOOLCHAIN \u2192 go binary \u2014 version resolution", + "text": "go.mod \u2192 GOTOOLCHAIN \u2192 go binary: version resolution", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "go.mod \u2192 GOTOOLCHAIN \u2192 go binary \u2014 version resolution", + "originalText": "go.mod \u2192 GOTOOLCHAIN \u2192 go binary: version resolution", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "go generate arm \u2014 diff-clean gate (verified, go-native)", + "text": "go generate arm: diff-clean gate (verified, go-native)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "go generate arm \u2014 diff-clean gate (verified, go-native)", + "originalText": "go generate arm: diff-clean gate (verified, go-native)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "go build / go run arm \u2014 deterministic report \u2192 digest (verified, go-native)", + "text": "go build / go run arm: deterministic report \u2192 digest (verified, go-native)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "go build / go run arm \u2014 deterministic report \u2192 digest (verified, go-native)", + "originalText": "go build / go run arm: deterministic report \u2192 digest (verified, go-native)", "lineHeight": 1.25, "baseline": 12 }, @@ -2005,13 +2005,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host \u2014 no go install, no network.", + "text": "Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host: no go install, no network.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host \u2014 no go install, no network.", + "originalText": "Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host: no go install, no network.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/47-go-toolchain-pipeline.svg b/assets/diagrams/47-go-toolchain-pipeline.svg index 3eaddfc..5893f83 100644 --- a/assets/diagrams/47-go-toolchain-pipeline.svg +++ b/assets/diagrams/47-go-toolchain-pipeline.svg @@ -1,11 +1,11 @@ -go.mod → GOTOOLCHAIN → go binary — version resolution +go.mod → GOTOOLCHAIN → go binary: version resolution -go generate arm — diff-clean gate (verified, go-native) +go generate arm: diff-clean gate (verified, go-native) -go build / go run arm — deterministic report → digest (verified, go-native) +go build / go run arm: deterministic report → digest (verified, go-native) go.mod go 1.26 @@ -57,5 +57,5 @@ -Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host — no go install, no network. +Both gates are go-native (gofmt/vet/generate ship inside the go binary) and verified offline on this host: no go install, no network. \ No newline at end of file diff --git a/assets/diagrams/48-rust-tool-gates.excalidraw b/assets/diagrams/48-rust-tool-gates.excalidraw index db044b6..b4e61a7 100644 --- a/assets/diagrams/48-rust-tool-gates.excalidraw +++ b/assets/diagrams/48-rust-tool-gates.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Hard lane \u2014 pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components)", + "text": "Hard lane: pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Hard lane \u2014 pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components)", + "originalText": "Hard lane: pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components)", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Gated-if-present lane \u2014 reader installs; NOT verified on this host (shown as reference)", + "text": "Gated-if-present lane: reader installs; NOT verified on this host (shown as reference)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Gated-if-present lane \u2014 reader installs; NOT verified on this host (shown as reference)", + "originalText": "Gated-if-present lane: reader installs; NOT verified on this host (shown as reference)", "lineHeight": 1.25, "baseline": 12 }, @@ -2399,13 +2399,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Hard lane needs only the pinned toolchain \u2014 rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install.", + "text": "Hard lane needs only the pinned toolchain: rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Hard lane needs only the pinned toolchain \u2014 rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install.", + "originalText": "Hard lane needs only the pinned toolchain: rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install.", "lineHeight": 1.25, "baseline": 12 }, @@ -2434,13 +2434,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Gated lane needs `cargo install ` (cargo-audit also needs the advisory-db over network) \u2014 not run on this host; watch/flamegraph/sccache are accelerators shown, not gated.", + "text": "Gated lane needs `cargo install ` (cargo-audit also needs the advisory-db over network): not run on this host; watch/flamegraph/sccache are accelerators shown, not gated.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Gated lane needs `cargo install ` (cargo-audit also needs the advisory-db over network) \u2014 not run on this host; watch/flamegraph/sccache are accelerators shown, not gated.", + "originalText": "Gated lane needs `cargo install ` (cargo-audit also needs the advisory-db over network): not run on this host; watch/flamegraph/sccache are accelerators shown, not gated.", "lineHeight": 1.25, "baseline": 12 } diff --git a/assets/diagrams/48-rust-tool-gates.svg b/assets/diagrams/48-rust-tool-gates.svg index d3d14d3..4db5848 100644 --- a/assets/diagrams/48-rust-tool-gates.svg +++ b/assets/diagrams/48-rust-tool-gates.svg @@ -1,9 +1,9 @@ -Hard lane — pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components) +Hard lane: pinned-toolchain, VERIFIED on this host (rustfmt/clippy ship as toolchain components) -Gated-if-present lane — reader installs; NOT verified on this host (shown as reference) +Gated-if-present lane: reader installs; NOT verified on this host (shown as reference) rust crate one source tree @@ -68,6 +68,6 @@ -Hard lane needs only the pinned toolchain — rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install. -Gated lane needs `cargo install <tool>` (cargo-audit also needs the advisory-db over network) — not run on this host; watch/flamegraph/sccache are accelerators shown, not gated. +Hard lane needs only the pinned toolchain: rustfmt and clippy ship as rust-toolchain.toml components, so all five gates run offline with no cargo install. +Gated lane needs `cargo install <tool>` (cargo-audit also needs the advisory-db over network): not run on this host; watch/flamegraph/sccache are accelerators shown, not gated. \ No newline at end of file diff --git a/assets/diagrams/48-rust-toolchain-pipeline.excalidraw b/assets/diagrams/48-rust-toolchain-pipeline.excalidraw index ef3827a..532b6a2 100644 --- a/assets/diagrams/48-rust-toolchain-pipeline.excalidraw +++ b/assets/diagrams/48-rust-toolchain-pipeline.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "rust-toolchain.toml \u2192 rustup \u2192 cargo/rustc \u2014 version resolution", + "text": "rust-toolchain.toml \u2192 rustup \u2192 cargo/rustc: version resolution", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "rust-toolchain.toml \u2192 rustup \u2192 cargo/rustc \u2014 version resolution", + "originalText": "rust-toolchain.toml \u2192 rustup \u2192 cargo/rustc: version resolution", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cargo run -- report arm \u2014 deterministic digest gate (verified, rust-native)", + "text": "cargo run -- report arm: deterministic digest gate (verified, rust-native)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cargo run -- report arm \u2014 deterministic digest gate (verified, rust-native)", + "originalText": "cargo run -- report arm: deterministic digest gate (verified, rust-native)", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "cargo test arm \u2014 digest.rs unit test (verified, rust-native)", + "text": "cargo test arm: digest.rs unit test (verified, rust-native)", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "cargo test arm \u2014 digest.rs unit test (verified, rust-native)", + "originalText": "cargo test arm: digest.rs unit test (verified, rust-native)", "lineHeight": 1.25, "baseline": 12 }, @@ -2005,13 +2005,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Both gates are rust-native \u2014 cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host.", + "text": "Both gates are rust-native: cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Both gates are rust-native \u2014 cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host.", + "originalText": "Both gates are rust-native: cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host.", "lineHeight": 1.25, "baseline": 12 }, diff --git a/assets/diagrams/48-rust-toolchain-pipeline.svg b/assets/diagrams/48-rust-toolchain-pipeline.svg index 0572b46..45d1c34 100644 --- a/assets/diagrams/48-rust-toolchain-pipeline.svg +++ b/assets/diagrams/48-rust-toolchain-pipeline.svg @@ -1,11 +1,11 @@ -rust-toolchain.toml → rustup → cargo/rustc — version resolution +rust-toolchain.toml → rustup → cargo/rustc: version resolution -cargo run -- report arm — deterministic digest gate (verified, rust-native) +cargo run -- report arm: deterministic digest gate (verified, rust-native) -cargo test arm — digest.rs unit test (verified, rust-native) +cargo test arm: digest.rs unit test (verified, rust-native) rust-toolchain.toml channel 1.97.1 · edition 2024 @@ -57,6 +57,6 @@ -Both gates are rust-native — cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host. +Both gates are rust-native: cargo test and the deterministic report digest run inside the pinned toolchain, verified offline on this host. FNV-1a is language-independent: the same 0x481984990deee5ff digest appears in the ch46 C++ and ch47 Go toolbox reports. \ No newline at end of file diff --git a/assets/diagrams/49-concurrency-vs-parallelism.excalidraw b/assets/diagrams/49-concurrency-vs-parallelism.excalidraw index 6ad4632..4a08242 100644 --- a/assets/diagrams/49-concurrency-vs-parallelism.excalidraw +++ b/assets/diagrams/49-concurrency-vs-parallelism.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Not parallel \u2014 one CPU occupied", + "text": "Not parallel: one CPU occupied", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Not parallel \u2014 one CPU occupied", + "originalText": "Not parallel: one CPU occupied", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Parallel \u2014 many CPUs occupied", + "text": "Parallel: many CPUs occupied", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Parallel \u2014 many CPUs occupied", + "originalText": "Parallel: many CPUs occupied", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "conc \u2014 one workload, four models", + "text": "conc: one workload, four models", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "conc \u2014 one workload, four models", + "originalText": "conc: one workload, four models", "lineHeight": 1.25, "baseline": 14 }, @@ -1600,13 +1600,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration \u2014 every observable is a count or a set cardinality (see ch39).", + "text": "Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration: every observable is a count or a set cardinality (see ch39).", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration \u2014 every observable is a count or a set cardinality (see ch39).", + "originalText": "Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration: every observable is a count or a set cardinality (see ch39).", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/49-concurrency-vs-parallelism.svg b/assets/diagrams/49-concurrency-vs-parallelism.svg index e15cc80..06e1ae1 100644 --- a/assets/diagrams/49-concurrency-vs-parallelism.svg +++ b/assets/diagrams/49-concurrency-vs-parallelism.svg @@ -1,11 +1,11 @@ -Not parallel — one CPU occupied +Not parallel: one CPU occupied -Parallel — many CPUs occupied +Parallel: many CPUs occupied -conc — one workload, four models +conc: one workload, four models sequential 1 task in flight, 1 CPU @@ -46,5 +46,5 @@ Concurrency is STRUCTURE (how many tasks are in flight); parallelism is EXECUTION (how many CPUs are occupied). They are independent axes, which is why all four cells exist. -Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration — every observable is a count or a set cardinality (see ch39). +Numbers are from real runs on the 16-CPU reference host. Nothing here is a duration: every observable is a count or a set cardinality (see ch39). \ No newline at end of file diff --git a/assets/diagrams/49-execution-model-lanes.excalidraw b/assets/diagrams/49-execution-model-lanes.excalidraw index 4dedd8e..bf1f27a 100644 --- a/assets/diagrams/49-execution-model-lanes.excalidraw +++ b/assets/diagrams/49-execution-model-lanes.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Live on this toolchain \u2014 GCC 16.1.1, hard-gated, verified offline", + "text": "Live on this toolchain: GCC 16.1.1, hard-gated, verified offline", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Live on this toolchain \u2014 GCC 16.1.1, hard-gated, verified offline", + "originalText": "Live on this toolchain: GCC 16.1.1, hard-gated, verified offline", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Not implemented here \u2014 forward-looking prose, no gate, no committed dead code", + "text": "Not implemented here: forward-looking prose, no gate, no committed dead code", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Not implemented here \u2014 forward-looking prose, no gate, no committed dead code", + "originalText": "Not implemented here: forward-looking prose, no gate, no committed dead code", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++26 in ch49 \u2014 measured, not assumed", + "text": "C++26 in ch49: measured, not assumed", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++26 in ch49 \u2014 measured, not assumed", + "originalText": "C++26 in ch49: measured, not assumed", "lineHeight": 1.25, "baseline": 14 }, @@ -245,13 +245,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Contracts \u2014 P2900", + "text": "Contracts: P2900", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Contracts \u2014 P2900", + "originalText": "Contracts: P2900", "lineHeight": 1.25, "baseline": 14 }, @@ -1029,13 +1029,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::execution senders \u2014 P2300", + "text": "std::execution senders: P2300", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::execution senders \u2014 P2300", + "originalText": "std::execution senders: P2300", "lineHeight": 1.25, "baseline": 14 }, @@ -1267,13 +1267,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Static reflection \u2014 P2996", + "text": "Static reflection: P2996", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Static reflection \u2014 P2996", + "originalText": "Static reflection: P2996", "lineHeight": 1.25, "baseline": 14 }, @@ -1610,13 +1610,13 @@ "updated": 1, "link": null, "locked": false, - "text": "footer \u2014 never inferred from", + "text": "footer: never inferred from", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "footer \u2014 never inferred from", + "originalText": "footer: never inferred from", "lineHeight": 1.25, "baseline": 11 }, @@ -1766,13 +1766,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Two of the C++26 'Fab Four' run for real here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly.", + "text": "Two of the C++26 'Fab Four' run live here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Two of the C++26 'Fab Four' run for real here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly.", + "originalText": "Two of the C++26 'Fab Four' run live here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/49-execution-model-lanes.svg b/assets/diagrams/49-execution-model-lanes.svg index c10df70..483f2ed 100644 --- a/assets/diagrams/49-execution-model-lanes.svg +++ b/assets/diagrams/49-execution-model-lanes.svg @@ -1,13 +1,13 @@ -Live on this toolchain — GCC 16.1.1, hard-gated, verified offline +Live on this toolchain: GCC 16.1.1, hard-gated, verified offline -Not implemented here — forward-looking prose, no gate, no committed dead code +Not implemented here: forward-looking prose, no gate, no committed dead code -C++26 in ch49 — measured, not assumed +C++26 in ch49: measured, not assumed -Contracts — P2900 +Contracts: P2900 -fcontracts, __cpp_contracts=202502 one source → four binaries: ignore (silent) / observe (reports, runs on) @@ -30,14 +30,14 @@ that the check is absent from the binary instead -std::execution senders — P2300 +std::execution senders: P2300 __cpp_lib_senders = undefined GCC 16's <execution> is the C++17 parallel-algorithms header (__cpp_lib_execution = 201902) live comparison deferred to ch56 -Static reflection — P2996 +Static reflection: P2996 __cpp_impl_reflection = undefined GCC 16: no ^^T operator clang 22: -freflection rejected @@ -47,9 +47,9 @@ the rule for both lanes support status is MEASURED on this host and stated in the -footer — never inferred from +footer: never inferred from a standard's publication date -Two of the C++26 'Fab Four' run for real here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly. +Two of the C++26 'Fab Four' run live here and two do not. Both facts are measured on the reference host, and the chapter marks each section accordingly. \ No newline at end of file diff --git a/assets/diagrams/50-cancellation-two-roads.excalidraw b/assets/diagrams/50-cancellation-two-roads.excalidraw index f8e390a..910a23b 100644 --- a/assets/diagrams/50-cancellation-two-roads.excalidraw +++ b/assets/diagrams/50-cancellation-two-roads.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "pthread_cancel \u2014 asynchronous, and it unwinds", + "text": "pthread_cancel: asynchronous, and it unwinds", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "pthread_cancel \u2014 asynchronous, and it unwinds", + "originalText": "pthread_cancel: asynchronous, and it unwinds", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::jthread + stop_token \u2014 cooperative, C++20's answer", + "text": "std::jthread + stop_token: cooperative, C++20's answer", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::jthread + stop_token \u2014 cooperative, C++20's answer", + "originalText": "std::jthread + stop_token: cooperative, C++20's answer", "lineHeight": 1.25, "baseline": 12 }, @@ -1601,13 +1601,13 @@ "updated": 1, "link": null, "locked": false, - "text": "The trap is not that cancellation skips cleanup \u2014 it does not. The trap is that the mechanism is an exception the caller must be careful never to catch.", + "text": "The trap is not that cancellation skips cleanup: it does not. The trap is that the mechanism is an exception the caller must be careful never to catch.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "The trap is not that cancellation skips cleanup \u2014 it does not. The trap is that the mechanism is an exception the caller must be careful never to catch.", + "originalText": "The trap is not that cancellation skips cleanup: it does not. The trap is that the mechanism is an exception the caller must be careful never to catch.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/50-cancellation-two-roads.svg b/assets/diagrams/50-cancellation-two-roads.svg index dc7181a..d0e287a 100644 --- a/assets/diagrams/50-cancellation-two-roads.svg +++ b/assets/diagrams/50-cancellation-two-roads.svg @@ -1,9 +1,9 @@ -pthread_cancel — asynchronous, and it unwinds +pthread_cancel: asynchronous, and it unwinds -std::jthread + stop_token — cooperative, C++20's answer +std::jthread + stop_token: cooperative, C++20's answer two roads out of a running thread @@ -46,6 +46,6 @@ Both rows are real runs on this host (glibc 2.43). The upper row is why pthread_cancel is powerful; the dashed box is why C++ did not standardize it. -The trap is not that cancellation skips cleanup — it does not. The trap is that the mechanism is an exception the caller must be careful never to catch. +The trap is not that cancellation skips cleanup: it does not. The trap is that the mechanism is an exception the caller must be careful never to catch. Both cancel cases are hard-gated in verify.lua, including the abort: exit 134 with 'exception not rethrown' on stderr. \ No newline at end of file diff --git a/assets/diagrams/50-thread-two-identities.excalidraw b/assets/diagrams/50-thread-two-identities.excalidraw index a46e1b5..4821185 100644 --- a/assets/diagrams/50-thread-two-identities.excalidraw +++ b/assets/diagrams/50-thread-two-identities.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++ view \u2014 portable, and deliberately narrow", + "text": "C++ view: portable, and narrow by design", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++ view \u2014 portable, and deliberately narrow", + "originalText": "C++ view: portable, and narrow by design", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Linux view \u2014 the same thread, as the kernel and glibc see it", + "text": "Linux view: the same thread, as the kernel and glibc see it", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Linux view \u2014 the same thread, as the kernel and glibc see it", + "originalText": "Linux view: the same thread, as the kernel and glibc see it", "lineHeight": 1.25, "baseline": 12 }, @@ -1022,13 +1022,13 @@ "updated": 1, "link": null, "locked": false, - "text": "gettid() \u2014 the kernel tid", + "text": "gettid(): the kernel tid", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "gettid() \u2014 the kernel tid", + "originalText": "gettid(): the kernel tid", "lineHeight": 1.25, "baseline": 14 }, @@ -1190,13 +1190,13 @@ "updated": 1, "link": null, "locked": false, - "text": "naming \u2014 pthread_setname_np", + "text": "naming: pthread_setname_np", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "naming \u2014 pthread_setname_np", + "originalText": "naming: pthread_setname_np", "lineHeight": 1.25, "baseline": 14 }, @@ -1288,13 +1288,13 @@ "updated": 1, "link": null, "locked": false, - "text": "stack \u2014 pthread_attr_setstacksize", + "text": "stack: pthread_attr_setstacksize", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "stack \u2014 pthread_attr_setstacksize", + "originalText": "stack: pthread_attr_setstacksize", "lineHeight": 1.25, "baseline": 14 }, @@ -1386,13 +1386,13 @@ "updated": 1, "link": null, "locked": false, - "text": "affinity \u2014 one THREAD \u00b7 sched \u2014 SCHED_OTHER/0, FIFO \u2192 EPERM", + "text": "affinity: one THREAD \u00b7 sched: SCHED_OTHER/0, FIFO \u2192 EPERM", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "affinity \u2014 one THREAD \u00b7 sched \u2014 SCHED_OTHER/0, FIFO \u2192 EPERM", + "originalText": "affinity: one THREAD \u00b7 sched: SCHED_OTHER/0, FIFO \u2192 EPERM", "lineHeight": 1.25, "baseline": 14 }, @@ -1613,13 +1613,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle() \u2014 which is why the standard put it there.", + "text": "std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle(): which is why the standard put it there.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle() \u2014 which is why the standard put it there.", + "originalText": "std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle(): which is why the standard put it there.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/50-thread-two-identities.svg b/assets/diagrams/50-thread-two-identities.svg index 11dfe92..7ffeda1 100644 --- a/assets/diagrams/50-thread-two-identities.svg +++ b/assets/diagrams/50-thread-two-identities.svg @@ -1,9 +1,9 @@ -C++ view — portable, and deliberately narrow +C++ view: portable, and narrow by design -Linux view — the same thread, as the kernel and glibc see it +Linux view: the same thread, as the kernel and glibc see it one thread, two identities @@ -30,24 +30,24 @@ compare with pthread_equal NOT a number, not a tid -gettid() — the kernel tid +gettid(): the kernel tid a real integer; names a dir /proc/self/task/<tid>/ main thread: tid == pid -naming — pthread_setname_np +naming: pthread_setname_np → /proc/self/task/<tid>/comm · 15 max, 16 → ERANGE -stack — pthread_attr_setstacksize +stack: pthread_attr_setstacksize → 262144 · below PTHREAD_STACK_MIN=16384 → EINVAL -affinity — one THREAD · sched — SCHED_OTHER/0, FIFO → EPERM +affinity: one THREAD · sched: SCHED_OTHER/0, FIFO → EPERM every facet still reports digest=0x481984990deee5ff -std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle() — which is why the standard put it there. +std::thread wraps a pthread and exposes almost none of it. Everything in the lower band is reachable, but only through native_handle(): which is why the standard put it there. pthread_t and gettid() are not two spellings of one id: one is a glibc handle you may only compare, the other is the kernel's task id that /proc, perf, and gdb all speak. Every value shown is from a real run on the 16-CPU reference host (glibc 2.43). Nothing here is a duration; see ch39. \ No newline at end of file diff --git a/assets/diagrams/51-deadlock-and-scoped-lock.excalidraw b/assets/diagrams/51-deadlock-and-scoped-lock.excalidraw index 23c7074..fd65325 100644 --- a/assets/diagrams/51-deadlock-and-scoped-lock.excalidraw +++ b/assets/diagrams/51-deadlock-and-scoped-lock.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::lock_guard in opposing orders \u2014 the textbook deadlock", + "text": "std::lock_guard in opposing orders: the textbook deadlock", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::lock_guard in opposing orders \u2014 the textbook deadlock", + "originalText": "std::lock_guard in opposing orders: the textbook deadlock", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::scoped_lock \u2014 takes them all at once, so order stops mattering", + "text": "std::scoped_lock: takes them all at once, so order stops mattering", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::scoped_lock \u2014 takes them all at once, so order stops mattering", + "originalText": "std::scoped_lock: takes them all at once, so order stops mattering", "lineHeight": 1.25, "baseline": 12 }, @@ -581,13 +581,13 @@ "updated": 1, "link": null, "locked": false, - "text": "timeout(1) exit 124 \u2014 it never returns", + "text": "timeout(1) exit 124: it never returns", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "timeout(1) exit 124 \u2014 it never returns", + "originalText": "timeout(1) exit 124: it never returns", "lineHeight": 1.25, "baseline": 11 }, @@ -1008,13 +1008,13 @@ "updated": 1, "link": null, "locked": false, - "text": "try-all, back off, retry \u2014 not argument order", + "text": "try-all, back off, retry: not argument order", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "try-all, back off, retry \u2014 not argument order", + "originalText": "try-all, back off, retry: not argument order", "lineHeight": 1.25, "baseline": 14 }, @@ -1328,13 +1328,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading \u2014 the abstraction's failure mode, named by the kernel.", + "text": "Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading: the abstraction's failure mode, named by the kernel.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading \u2014 the abstraction's failure mode, named by the kernel.", + "originalText": "Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading: the abstraction's failure mode, named by the kernel.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/51-deadlock-and-scoped-lock.svg b/assets/diagrams/51-deadlock-and-scoped-lock.svg index 9c3cfaa..9ef9850 100644 --- a/assets/diagrams/51-deadlock-and-scoped-lock.svg +++ b/assets/diagrams/51-deadlock-and-scoped-lock.svg @@ -1,9 +1,9 @@ -std::lock_guard in opposing orders — the textbook deadlock +std::lock_guard in opposing orders: the textbook deadlock -std::scoped_lock — takes them all at once, so order stops mattering +std::scoped_lock: takes them all at once, so order stops mattering two mutexes, two threads, two outcomes @@ -17,7 +17,7 @@ the opposite order each holds what the other needs -timeout(1) exit 124 — it never returns +timeout(1) exit 124: it never returns no error, no exception, no diagnostic and the kernel names it: /proc/<pid>/task/*/wchan @@ -30,7 +30,7 @@ scoped_lock lock(b, a); still the opposite order -try-all, back off, retry — not argument order +try-all, back off, retry: not argument order 100,000 acquisitions completed, exit 0 the property lock_guard cannot give you @@ -38,7 +38,7 @@ -Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading — the abstraction's failure mode, named by the kernel. +Both rows are real runs on this host. The deadlock is reproduced under timeout(1) and hard-gated, including the wchan reading: the abstraction's failure mode, named by the kernel. Three threads park, not two: the two workers plus main, blocked in join(). All of them end up in the same kernel function. scoped_lock is not lock_guard with more arguments. It runs a deadlock-avoidance algorithm, which is why opposing orders are safe. \ No newline at end of file diff --git a/assets/diagrams/51-futex-cost-model.excalidraw b/assets/diagrams/51-futex-cost-model.excalidraw index ff7417d..7a89d7a 100644 --- a/assets/diagrams/51-futex-cost-model.excalidraw +++ b/assets/diagrams/51-futex-cost-model.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "User space \u2014 atomic compare-exchange on the futex word, no kernel involved", + "text": "User space: atomic compare-exchange on the futex word, no kernel involved", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "User space \u2014 atomic compare-exchange on the futex word, no kernel involved", + "originalText": "User space: atomic compare-exchange on the futex word, no kernel involved", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Kernel \u2014 futex(2), the syscall ch25 built by hand", + "text": "Kernel: futex(2), the syscall ch25 built by hand", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Kernel \u2014 futex(2), the syscall ch25 built by hand", + "originalText": "Kernel: futex(2), the syscall ch25 built by hand", "lineHeight": 1.25, "baseline": 12 }, @@ -245,13 +245,13 @@ "updated": 1, "link": null, "locked": false, - "text": "baseline \u2014 no mutex", + "text": "baseline: no mutex", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "baseline \u2014 no mutex", + "originalText": "baseline: no mutex", "lineHeight": 1.25, "baseline": 14 }, @@ -448,13 +448,13 @@ "updated": 1, "link": null, "locked": false, - "text": "uncontended \u2014 1 thread", + "text": "uncontended: 1 thread", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "uncontended \u2014 1 thread", + "originalText": "uncontended: 1 thread", "lineHeight": 1.25, "baseline": 14 }, @@ -721,13 +721,13 @@ "updated": 1, "link": null, "locked": false, - "text": "close \u2014 the dynamic loader.", + "text": "close: the dynamic loader.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "close \u2014 the dynamic loader.", + "originalText": "close: the dynamic loader.", "lineHeight": 1.25, "baseline": 11 }, @@ -854,13 +854,13 @@ "updated": 1, "link": null, "locked": false, - "text": "contended \u2014 8 threads", + "text": "contended: 8 threads", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "contended \u2014 8 threads", + "originalText": "contended: 8 threads", "lineHeight": 1.25, "baseline": 14 }, @@ -1400,13 +1400,13 @@ "updated": 1, "link": null, "locked": false, - "text": "kernel \u2014 there is no other way.", + "text": "kernel: there is no other way.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "kernel \u2014 there is no other way.", + "originalText": "kernel: there is no other way.", "lineHeight": 1.25, "baseline": 11 }, @@ -1599,13 +1599,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Same total work in all three cost cases \u2014 200,000 increments \u2014 so only the contention differs, which is what makes the syscall counts comparable.", + "text": "Same total work in all three cost cases: 200,000 increments: so only the contention differs, which is what makes the syscall counts comparable.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Same total work in all three cost cases \u2014 200,000 increments \u2014 so only the contention differs, which is what makes the syscall counts comparable.", + "originalText": "Same total work in all three cost cases: 200,000 increments: so only the contention differs, which is what makes the syscall counts comparable.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/51-futex-cost-model.svg b/assets/diagrams/51-futex-cost-model.svg index b2fe1f9..6c37c53 100644 --- a/assets/diagrams/51-futex-cost-model.svg +++ b/assets/diagrams/51-futex-cost-model.svg @@ -1,19 +1,19 @@ -User space — atomic compare-exchange on the futex word, no kernel involved +User space: atomic compare-exchange on the futex word, no kernel involved -Kernel — futex(2), the syscall ch25 built by hand +Kernel: futex(2), the syscall ch25 built by hand 200,000 lock/unlock pairs, two ways -baseline — no mutex +baseline: no mutex 200,000 plain increments the control futex calls: 1 (that 1 is the loader, not a lock) -uncontended — 1 thread +uncontended: 1 thread 200,000 lock/unlock pairs CAS succeeds every time futex calls: 1 @@ -21,11 +21,11 @@ whole syscall profile: 61 execve, mmap, openat, read, -close — the dynamic loader. +close: the dynamic loader. The 200,000 pairs contributed nothing to it. -contended — 8 threads +contended: 8 threads the SAME 200,000 pairs CAS fails often → sleep + wake futex calls: 1844–3111 @@ -41,13 +41,13 @@ one mechanism. A thread that must sleep until further notice has to tell the -kernel — there is no other way. +kernel: there is no other way. add contention add contention -Same total work in all three cost cases — 200,000 increments — so only the contention differs, which is what makes the syscall counts comparable. +Same total work in all three cost cases: 200,000 increments: so only the contention differs, which is what makes the syscall counts comparable. An uncontended std::mutex costs no syscalls at all. What costs is contention: identical work, two orders of magnitude more kernel involvement. Counted from outside with strace -f -c -e trace=futex. Nothing here is a duration; only the SIGN of the comparison is gated (see ch39). Measured on the Fedora 44 reference host, glibc 2.43, GCC 16.1.1. diff --git a/assets/diagrams/52-cancellation-three-ways.excalidraw b/assets/diagrams/52-cancellation-three-ways.excalidraw index b42960c..d91ff20 100644 --- a/assets/diagrams/52-cancellation-three-ways.excalidraw +++ b/assets/diagrams/52-cancellation-three-ways.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "One mistake \u2014 catch (...) without a rethrow \u2014 against three cancellation models", + "text": "One mistake: catch (...) without a rethrow: against three cancellation models", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "One mistake \u2014 catch (...) without a rethrow \u2014 against three cancellation models", + "originalText": "One mistake: catch (...) without a rethrow: against three cancellation models", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ch50 \u2014 pthread_cancel", + "text": "ch50: pthread_cancel", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ch50 \u2014 pthread_cancel", + "originalText": "ch50: pthread_cancel", "lineHeight": 1.25, "baseline": 14 }, @@ -385,13 +385,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ch52 \u2014 thread::interrupt()", + "text": "ch52: thread::interrupt()", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ch52 \u2014 thread::interrupt()", + "originalText": "ch52: thread::interrupt()", "lineHeight": 1.25, "baseline": 14 }, @@ -588,13 +588,13 @@ "updated": 1, "link": null, "locked": false, - "text": "ch51 \u2014 stop_token", + "text": "ch51: stop_token", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "ch51 \u2014 stop_token", + "originalText": "ch51: stop_token", "lineHeight": 1.25, "baseline": 14 }, @@ -826,13 +826,13 @@ "updated": 1, "link": null, "locked": false, - "text": "SIGABRT \u2014 exit 134", + "text": "SIGABRT: exit 134", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "SIGABRT \u2014 exit 134", + "originalText": "SIGABRT: exit 134", "lineHeight": 1.25, "baseline": 11 }, @@ -924,13 +924,13 @@ "updated": 1, "link": null, "locked": false, - "text": "process survives \u2014 exit 0", + "text": "process survives: exit 0", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "process survives \u2014 exit 0", + "originalText": "process survives: exit 0", "lineHeight": 1.25, "baseline": 14 }, @@ -1190,13 +1190,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Boost sits between the two \u2014 catchable like an exception,", + "text": "Boost sits between the two: catchable like an exception,", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Boost sits between the two \u2014 catchable like an exception,", + "originalText": "Boost sits between the two: catchable like an exception,", "lineHeight": 1.25, "baseline": 14 }, @@ -1424,13 +1424,13 @@ "updated": 1, "link": null, "locked": false, - "text": "The difference is not how careful the caller is \u2014 it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught.", + "text": "The difference is not how careful the caller is: it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "The difference is not how careful the caller is \u2014 it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught.", + "originalText": "The difference is not how careful the caller is: it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/52-cancellation-three-ways.svg b/assets/diagrams/52-cancellation-three-ways.svg index badde94..e683b45 100644 --- a/assets/diagrams/52-cancellation-three-ways.svg +++ b/assets/diagrams/52-cancellation-three-ways.svg @@ -1,33 +1,33 @@ -One mistake — catch (...) without a rethrow — against three cancellation models +One mistake: catch (...) without a rethrow: against three cancellation models cancellation across ch50, ch52, ch51 -ch50 — pthread_cancel +ch50: pthread_cancel glibc FORCED UNWIND destructors DO run but the unwind must propagate asynchronous: any cancellation point -ch52 — thread::interrupt() +ch52: thread::interrupt() an ORDINARY C++ exception boost::thread_interrupted thrown at defined points only sleep_for, cv wait, join, … -ch51 — stop_token +ch51: stop_token a FLAG, nothing thrown request_stop() sets it the target polls when it likes cooperative, poll-only FATAL: exception not rethrown -SIGABRT — exit 134 +SIGABRT: exit 134 the PROCESS dies, not the thread -process survives — exit 0 +process survives: exit 0 a swallowed exception is a bug, not a process kill @@ -35,12 +35,12 @@ there is no exception at all; the risk is never stopping -Boost sits between the two — catchable like an exception, +Boost sits between the two: catchable like an exception, because that is exactly what it is All three rows are real runs on this host. The ch50 abort and the ch52 survival are both hard-gated, in their own chapters' harnesses. -The difference is not how careful the caller is — it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught. +The difference is not how careful the caller is: it is what the mechanism IS. A forced unwind must propagate; an ordinary exception need not; a flag cannot be caught. Power runs left to right; safety runs right to left. Boost.Thread is the only one of the three that is both catchable and non-fatal when mishandled. \ No newline at end of file diff --git a/assets/diagrams/52-what-the-standard-took.excalidraw b/assets/diagrams/52-what-the-standard-took.excalidraw index 322eae8..726789e 100644 --- a/assets/diagrams/52-what-the-standard-took.excalidraw +++ b/assets/diagrams/52-what-the-standard-took.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Standardized \u2014 C++11 took Boost.Thread almost wholesale", + "text": "Standardized: C++11 took Boost.Thread almost wholesale", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Standardized \u2014 C++11 took Boost.Thread almost wholesale", + "originalText": "Standardized: C++11 took Boost.Thread almost wholesale", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Left behind \u2014 still Boost-only in C++23 on this toolchain", + "text": "Left behind: still Boost-only in C++23 on this toolchain", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Left behind \u2014 still Boost-only in C++23 on this toolchain", + "originalText": "Left behind: still Boost-only in C++23 on this toolchain", "lineHeight": 1.25, "baseline": 12 }, @@ -1624,13 +1624,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::upgrade_lock does not exist \u2014 not absent, undeclared", + "text": "std::upgrade_lock does not exist: not absent, undeclared", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::upgrade_lock does not exist \u2014 not absent, undeclared", + "originalText": "std::upgrade_lock does not exist: not absent, undeclared", "lineHeight": 1.25, "baseline": 14 }, @@ -1780,13 +1780,13 @@ "updated": 1, "link": null, "locked": false, - "text": "The .then() contrast is checked by the compiler on every run \u2014 a concept evaluated against std::future and boost::future \u2014 rather than asserted by the author once.", + "text": "The .then() contrast is checked by the compiler on every run: a concept evaluated against std::future and boost::future: rather than asserted by the author once.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "The .then() contrast is checked by the compiler on every run \u2014 a concept evaluated against std::future and boost::future \u2014 rather than asserted by the author once.", + "originalText": "The .then() contrast is checked by the compiler on every run: a concept evaluated against std::future and boost::future: rather than asserted by the author once.", "lineHeight": 1.25, "baseline": 11 }, @@ -1850,13 +1850,13 @@ "updated": 1, "link": null, "locked": false, - "text": "C++26's std::execution is the standard's answer to the composition gap \u2014 forward-looking in ch49, compared for real in ch56.", + "text": "C++26's std::execution is the standard's answer to the composition gap: forward-looking in ch49, compared directly in ch56.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "C++26's std::execution is the standard's answer to the composition gap \u2014 forward-looking in ch49, compared for real in ch56.", + "originalText": "C++26's std::execution is the standard's answer to the composition gap: forward-looking in ch49, compared directly in ch56.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/52-what-the-standard-took.svg b/assets/diagrams/52-what-the-standard-took.svg index 6cea291..a8a30e2 100644 --- a/assets/diagrams/52-what-the-standard-took.svg +++ b/assets/diagrams/52-what-the-standard-took.svg @@ -1,9 +1,9 @@ -Standardized — C++11 took Boost.Thread almost wholesale +Standardized: C++11 took Boost.Thread almost wholesale -Left behind — still Boost-only in C++23 on this toolchain +Left behind: still Boost-only in C++23 on this toolchain Boost.Thread → std::thread, 2011 @@ -48,11 +48,11 @@ the same byte-for-byte as ch50's POSIX call -std::upgrade_lock does not exist — not absent, undeclared +std::upgrade_lock does not exist: not absent, undeclared C++11 standardized Boost.Thread's types nearly unchanged. What it did not take is specific and still missing 15 years later: composition, the upgrade lock, and per-thread attributes. -The .then() contrast is checked by the compiler on every run — a concept evaluated against std::future<int> and boost::future<int> — rather than asserted by the author once. +The .then() contrast is checked by the compiler on every run: a concept evaluated against std::future<int> and boost::future<int>: rather than asserted by the author once. Measured on the Fedora 44 reference host: Boost 1.90.0 from boost-devel, BOOST_THREAD_VERSION=5, GCC 16.1.1. No Conan, no network. -C++26's std::execution is the standard's answer to the composition gap — forward-looking in ch49, compared for real in ch56. +C++26's std::execution is the standard's answer to the composition gap: forward-looking in ch49, compared directly in ch56. \ No newline at end of file diff --git a/assets/diagrams/53-frame-versus-stack.excalidraw b/assets/diagrams/53-frame-versus-stack.excalidraw index 4f6c502..5e5f838 100644 --- a/assets/diagrams/53-frame-versus-stack.excalidraw +++ b/assets/diagrams/53-frame-versus-stack.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "A thread \u2014 ch50 measured this", + "text": "A thread: ch50 measured this", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "A thread \u2014 ch50 measured this", + "originalText": "A thread: ch50 measured this", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "A coroutine frame \u2014 measured here, via operator new in the promise", + "text": "A coroutine frame: measured here, via operator new in the promise", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "A coroutine frame \u2014 measured here, via operator new in the promise", + "originalText": "A coroutine frame: measured here, via operator new in the promise", "lineHeight": 1.25, "baseline": 12 }, @@ -448,13 +448,13 @@ "updated": 1, "link": null, "locked": false, - "text": "the stack is VIRTUAL \u2014", + "text": "the stack is VIRTUAL", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "the stack is VIRTUAL \u2014", + "originalText": "the stack is VIRTUAL", "lineHeight": 1.25, "baseline": 14 }, @@ -1295,13 +1295,13 @@ "updated": 1, "link": null, "locked": false, - "text": "to the caller \u2014 nothing", + "text": "to the caller: nothing", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "to the caller \u2014 nothing", + "originalText": "to the caller: nothing", "lineHeight": 1.25, "baseline": 11 }, @@ -1514,13 +1514,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it \u2014 which is the whole reason coroutines exist.", + "text": "Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it: which is the whole reason coroutines exist.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it \u2014 which is the whole reason coroutines exist.", + "originalText": "Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it: which is the whole reason coroutines exist.", "lineHeight": 1.25, "baseline": 11 }, @@ -1549,13 +1549,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language deliberately hides.", + "text": "Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language hides.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language deliberately hides.", + "originalText": "Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language hides.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/53-frame-versus-stack.svg b/assets/diagrams/53-frame-versus-stack.svg index f5aa564..9acb10f 100644 --- a/assets/diagrams/53-frame-versus-stack.svg +++ b/assets/diagrams/53-frame-versus-stack.svg @@ -1,9 +1,9 @@ -A thread — ch50 measured this +A thread: ch50 measured this -A coroutine frame — measured here, via operator new in the promise +A coroutine frame: measured here, via operator new in the promise one paused computation, two prices @@ -13,7 +13,7 @@ plus a kernel task_struct and a tid in /proc -the stack is VIRTUAL — +the stack is VIRTUAL untouched pages are never backed, so it usually works. It still collides with overcommit limits, @@ -38,13 +38,13 @@ suspends only at co_await cooperative: control returns -to the caller — nothing +to the caller: nothing is preempted, nothing blocked 262,144 coroutine frames fit in one thread's stack -Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it — which is the whole reason coroutines exist. -Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language deliberately hides. +Both hold one paused computation. Only one of them reserves 8 MiB of address space and a kernel task to do it: which is the whole reason coroutines exist. +Frame sizes are measured by overloading operator new inside promise_type: the only portable way to see a size the language hides. Thread stack from ch50 (pthread_getattr_np); frame sizes from this chapter. GCC 16.1.1, C++23, Fedora 44. Nothing here is a duration. \ No newline at end of file diff --git a/assets/diagrams/53-halo-is-permitted.excalidraw b/assets/diagrams/53-halo-is-permitted.excalidraw index 5f4a436..f15f66f 100644 --- a/assets/diagrams/53-halo-is-permitted.excalidraw +++ b/assets/diagrams/53-halo-is-permitted.excalidraw @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "What the two compilers on this host actually do \u2014 1000 calls each", + "text": "What the two compilers on this host actually do: 1000 calls each", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "What the two compilers on this host actually do \u2014 1000 calls each", + "originalText": "What the two compilers on this host actually do: 1000 calls each", "lineHeight": 1.25, "baseline": 12 }, @@ -350,13 +350,13 @@ "updated": 1, "link": null, "locked": false, - "text": "\"may\" \u2014 there is no conforming way to depend on it", + "text": "\"may\": there is no conforming way to depend on it", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "\"may\" \u2014 there is no conforming way to depend on it", + "originalText": "\"may\": there is no conforming way to depend on it", "lineHeight": 1.25, "baseline": 11 }, @@ -1038,13 +1038,13 @@ "updated": 1, "link": null, "locked": false, - "text": "verify.lua does NOT gate on whether elision happens \u2014 that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two.", + "text": "verify.lua does NOT gate on whether elision happens: that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "verify.lua does NOT gate on whether elision happens \u2014 that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two.", + "originalText": "verify.lua does NOT gate on whether elision happens: that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/53-halo-is-permitted.svg b/assets/diagrams/53-halo-is-permitted.svg index 655102f..4581dba 100644 --- a/assets/diagrams/53-halo-is-permitted.svg +++ b/assets/diagrams/53-halo-is-permitted.svg @@ -3,14 +3,14 @@ What the standard says -What the two compilers on this host actually do — 1000 calls each +What the two compilers on this host actually do: 1000 calls each HALO: permitted, required of nobody [dcl.fct.def.coroutine] the implementation MAY elide the frame allocation when the frame provably does not outlive the caller -"may" — there is no conforming way to depend on it +"may": there is no conforming way to depend on it the test case is the easiest one there is: suspend_never at both ends, runs to completion inside @@ -30,6 +30,6 @@ Counted by overloading operator new on the promise type, so every frame allocation is observed rather than inferred from a profiler. -verify.lua does NOT gate on whether elision happens — that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two. +verify.lua does NOT gate on whether elision happens: that would encode one compiler's choice as a rule. It gates that the count is measured, and compares the two. If a future GCC starts eliding, the gate keeps passing and the chapter's numbers change. That is the intended behaviour. \ No newline at end of file diff --git a/assets/diagrams/54-scheduler-is-a-choice.excalidraw b/assets/diagrams/54-scheduler-is-a-choice.excalidraw index c9c712a..20432a7 100644 --- a/assets/diagrams/54-scheduler-is-a-choice.excalidraw +++ b/assets/diagrams/54-scheduler-is-a-choice.excalidraw @@ -413,13 +413,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one CPU occupied \u2014 concurrent, NOT parallel", + "text": "one CPU occupied: concurrent, NOT parallel", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one CPU occupied \u2014 concurrent, NOT parallel", + "originalText": "one CPU occupied: concurrent, NOT parallel", "lineHeight": 1.25, "baseline": 11 }, @@ -707,13 +707,13 @@ "updated": 1, "link": null, "locked": false, - "text": "concurrent AND parallel \u2014 the bottom-right", + "text": "concurrent AND parallel: the bottom-right", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "concurrent AND parallel \u2014 the bottom-right", + "originalText": "concurrent AND parallel: the bottom-right", "lineHeight": 1.25, "baseline": 14 }, @@ -938,13 +938,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one line \u2014 and it is yours to write, not a runtime's to decide (contrast ch44's Go)", + "text": "one line: and it is yours to write, not a runtime's to decide (contrast ch44's Go)", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one line \u2014 and it is yours to write, not a runtime's to decide (contrast ch44's Go)", + "originalText": "one line: and it is yours to write, not a runtime's to decide (contrast ch44's Go)", "lineHeight": 1.25, "baseline": 11 }, @@ -1016,13 +1016,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Both columns are real runs, tids collected with gettid() \u2014 the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs.", + "text": "Both columns are real runs, tids collected with gettid(): the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Both columns are real runs, tids collected with gettid() \u2014 the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs.", + "originalText": "Both columns are real runs, tids collected with gettid(): the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs.", "lineHeight": 1.25, "baseline": 11 }, @@ -1086,13 +1086,13 @@ "updated": 1, "link": null, "locked": false, - "text": "verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1 \u2014 the sign, never the magnitude, since the count is scheduler-dependent.", + "text": "verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1: the sign, never the magnitude, since the count is scheduler-dependent.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1 \u2014 the sign, never the magnitude, since the count is scheduler-dependent.", + "originalText": "verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1: the sign, never the magnitude, since the count is scheduler-dependent.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/54-scheduler-is-a-choice.svg b/assets/diagrams/54-scheduler-is-a-choice.svg index 4f3f1ee..168df3e 100644 --- a/assets/diagrams/54-scheduler-is-a-choice.svg +++ b/assets/diagrams/54-scheduler-is-a-choice.svg @@ -12,7 +12,7 @@ distinct_tids = 1 ch49's vocabulary: 16 tasks in flight, -one CPU occupied — concurrent, NOT parallel +one CPU occupied: concurrent, NOT parallel and that is a legitimate choice: no migration means no cross-thread synchronisation to reason about @@ -21,16 +21,16 @@ 4 threads pull from it; a fiber can resume elsewhere distinct_tids = 4 -concurrent AND parallel — the bottom-right +concurrent AND parallel: the bottom-right cell of ch49's grid, reached by choosing it the price: your fiber's data is now touched by several threads, and you own that problem boost::fibers::use_scheduling_algorithm<algo::shared_work>(); -one line — and it is yours to write, not a runtime's to decide (contrast ch44's Go) +one line: and it is yours to write, not a runtime's to decide (contrast ch44's Go) -Both columns are real runs, tids collected with gettid() — the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs. +Both columns are real runs, tids collected with gettid(): the same kernel task id ch50 established. shared_work reported 4 of 4 on five consecutive runs. Go's runtime makes this decision for you and mostly will not be argued with (ch44). Boost.Fiber makes you choose, which is more work and more control. -verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1 — the sign, never the magnitude, since the count is scheduler-dependent. +verify.lua gates round_robin at exactly 1 tid and shared_work at more than 1: the sign, never the magnitude, since the count is scheduler-dependent. \ No newline at end of file diff --git a/assets/diagrams/54-three-ways-to-pause.excalidraw b/assets/diagrams/54-three-ways-to-pause.excalidraw index 9f6ee51..2c480e0 100644 --- a/assets/diagrams/54-three-ways-to-pause.excalidraw +++ b/assets/diagrams/54-three-ways-to-pause.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Kernel-scheduled \u2014 the kernel knows about it", + "text": "Kernel-scheduled: the kernel knows about it", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Kernel-scheduled \u2014 the kernel knows about it", + "originalText": "Kernel-scheduled: the kernel knows about it", "lineHeight": 1.25, "baseline": 12 }, @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "User-scheduled, stackful \u2014 a real machine stack, switched by boost::context", + "text": "User-scheduled, stackful: a real machine stack, switched by boost::context", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "User-scheduled, stackful \u2014 a real machine stack, switched by boost::context", + "originalText": "User-scheduled, stackful: a real machine stack, switched by boost::context", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "User-scheduled, stackless \u2014 no stack at all", + "text": "User-scheduled, stackless: no stack at all", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "User-scheduled, stackless \u2014 no stack at all", + "originalText": "User-scheduled, stackless: no stack at all", "lineHeight": 1.25, "baseline": 12 }, @@ -308,13 +308,13 @@ "updated": 1, "link": null, "locked": false, - "text": "thread \u2014 ch50", + "text": "thread: ch50", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "thread \u2014 ch50", + "originalText": "thread: ch50", "lineHeight": 1.25, "baseline": 14 }, @@ -504,13 +504,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fiber \u2014 ch54", + "text": "fiber: ch54", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fiber \u2014 ch54", + "originalText": "fiber: ch54", "lineHeight": 1.25, "baseline": 14 }, @@ -637,13 +637,13 @@ "updated": 1, "link": null, "locked": false, - "text": "suspends from ANYWHERE in an ordinary call tree \u2014 measured at 6 frames deep", + "text": "suspends from ANYWHERE in an ordinary call tree: measured at 6 frames deep", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "suspends from ANYWHERE in an ordinary call tree \u2014 measured at 6 frames deep", + "originalText": "suspends from ANYWHERE in an ordinary call tree: measured at 6 frames deep", "lineHeight": 1.25, "baseline": 14 }, @@ -770,13 +770,13 @@ "updated": 1, "link": null, "locked": false, - "text": "coroutine frame \u2014 ch53", + "text": "coroutine frame: ch53", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "coroutine frame \u2014 ch53", + "originalText": "coroutine frame: ch53", "lineHeight": 1.25, "baseline": 14 }, @@ -903,13 +903,13 @@ "updated": 1, "link": null, "locked": false, - "text": "suspends ONLY at co_await, only in a coroutine body \u2014", + "text": "suspends ONLY at co_await, only in a coroutine body", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "suspends ONLY at co_await, only in a coroutine body \u2014", + "originalText": "suspends ONLY at co_await, only in a coroutine body", "lineHeight": 1.25, "baseline": 14 }, diff --git a/assets/diagrams/54-three-ways-to-pause.svg b/assets/diagrams/54-three-ways-to-pause.svg index 215b378..4954509 100644 --- a/assets/diagrams/54-three-ways-to-pause.svg +++ b/assets/diagrams/54-three-ways-to-pause.svg @@ -1,33 +1,33 @@ -Kernel-scheduled — the kernel knows about it +Kernel-scheduled: the kernel knows about it -User-scheduled, stackful — a real machine stack, switched by boost::context +User-scheduled, stackful: a real machine stack, switched by boost::context -User-scheduled, stackless — no stack at all +User-scheduled, stackless: no stack at all one paused computation, three prices -thread — ch50 +thread: ch50 8388608 bytes of stack preempted anywhere · a tid in /proc · a kernel task_struct suspends wherever the scheduler decides, with no cooperation needed -fiber — ch54 +fiber: ch54 131072 bytes (128 KiB) 64 fit in one thread stack -suspends from ANYWHERE in an ordinary call tree — measured at 6 frames deep +suspends from ANYWHERE in an ordinary call tree: measured at 6 frames deep no co_await, no coroutine, no function colouring. The stack is exactly what buys that. -coroutine frame — ch53 +coroutine frame: ch53 32 bytes 4096 fit in one fiber stack -suspends ONLY at co_await, only in a coroutine body — +suspends ONLY at co_await, only in a coroutine body every frame in the suspend path must itself be a coroutine 8 MiB → 128 KiB → 32 bytes, each number measured on this host diff --git a/assets/diagrams/55-strand-not-a-mutex.excalidraw b/assets/diagrams/55-strand-not-a-mutex.excalidraw index 5f1ea66..12f8688 100644 --- a/assets/diagrams/55-strand-not-a-mutex.excalidraw +++ b/assets/diagrams/55-strand-not-a-mutex.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Same handler, same 8 threads, same io_context \u2014 only the executor differs", + "text": "Same handler, same 8 threads, same io_context: only the executor differs", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Same handler, same 8 threads, same io_context \u2014 only the executor differs", + "originalText": "Same handler, same 8 threads, same io_context: only the executor differs", "lineHeight": 1.25, "baseline": 12 }, @@ -679,13 +679,13 @@ "updated": 1, "link": null, "locked": false, - "text": "std::mutex \u2014 BLOCKS the thread", + "text": "std::mutex: BLOCKS the thread", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "std::mutex \u2014 BLOCKS the thread", + "originalText": "std::mutex: BLOCKS the thread", "lineHeight": 1.25, "baseline": 14 }, @@ -812,13 +812,13 @@ "updated": 1, "link": null, "locked": false, - "text": "strand \u2014 DEFERS the handler", + "text": "strand: DEFERS the handler", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "strand \u2014 DEFERS the handler", + "originalText": "strand: DEFERS the handler", "lineHeight": 1.25, "baseline": 14 }, @@ -1038,13 +1038,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes \u2014 they move with scheduling.", + "text": "Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes: they move with scheduling.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes \u2014 they move with scheduling.", + "originalText": "Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes: they move with scheduling.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/55-strand-not-a-mutex.svg b/assets/diagrams/55-strand-not-a-mutex.svg index 6405156..07d3d83 100644 --- a/assets/diagrams/55-strand-not-a-mutex.svg +++ b/assets/diagrams/55-strand-not-a-mutex.svg @@ -1,7 +1,7 @@ -Same handler, same 8 threads, same io_context — only the executor differs +Same handler, same 8 threads, same io_context: only the executor differs And a strand is not a mutex wearing a different name @@ -20,17 +20,17 @@ the lost count is UB: reported, never gated the OVERLAP is what verify.lua asserts -std::mutex — BLOCKS the thread +std::mutex: BLOCKS the thread contention → futex(FUTEX_WAIT) into the kernel 1022 futex calls for 20,000 increments -strand — DEFERS the handler +strand: DEFERS the handler the thread returns to the pool and takes other work 52 futex calls for the identical 20,000 Both mechanisms produce the correct answer. The difference is what happens to a thread that loses the race: a mutex puts it to sleep, a strand gives it something else to do. -Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes — they move with scheduling. +Futex counts measured with ch51's method (strace -f -c -e trace=futex). Gated as a ratio, never as magnitudes: they move with scheduling. A strand costs no lock and no thread. What it costs instead is ordering: handlers on one strand can never run in parallel with each other, however many threads you have. Measured on the Fedora 44 reference host, Boost 1.90.0, GCC 16.1.1. \ No newline at end of file diff --git a/assets/diagrams/55-topologies-and-gather.excalidraw b/assets/diagrams/55-topologies-and-gather.excalidraw index 311ac98..584887e 100644 --- a/assets/diagrams/55-topologies-and-gather.excalidraw +++ b/assets/diagrams/55-topologies-and-gather.excalidraw @@ -56,13 +56,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Who runs the handlers \u2014 same 400 posts, four shapes of run()", + "text": "Who runs the handlers: same 400 posts, four shapes of run()", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Who runs the handlers \u2014 same 400 posts, four shapes of run()", + "originalText": "Who runs the handlers: same 400 posts, four shapes of run()", "lineHeight": 1.25, "baseline": 12 }, @@ -917,13 +917,13 @@ "updated": 1, "link": null, "locked": false, - "text": "tids from gettid() \u2014 ch50's instrument and ch49's", + "text": "tids from gettid(): ch50's instrument and ch49's", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "tids from gettid() \u2014 ch50's instrument and ch49's", + "originalText": "tids from gettid(): ch50's instrument and ch49's", "lineHeight": 1.25, "baseline": 14 }, @@ -1296,13 +1296,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Identical bytes reach the peer either way \u2014 the gate checks that too. What differs is the number of times the process crosses into the kernel.", + "text": "Identical bytes reach the peer either way: the gate checks that too. What differs is the number of times the process crosses into the kernel.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Identical bytes reach the peer either way \u2014 the gate checks that too. What differs is the number of times the process crosses into the kernel.", + "originalText": "Identical bytes reach the peer either way: the gate checks that too. What differs is the number of times the process crosses into the kernel.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/55-topologies-and-gather.svg b/assets/diagrams/55-topologies-and-gather.svg index e426e9a..71c7ef4 100644 --- a/assets/diagrams/55-topologies-and-gather.svg +++ b/assets/diagrams/55-topologies-and-gather.svg @@ -1,7 +1,7 @@ -Who runs the handlers — same 400 posts, four shapes of run() +Who runs the handlers: same 400 posts, four shapes of run() One buffer SEQUENCE is one syscall @@ -27,7 +27,7 @@ distinct_tids = 4 no run() call at all -tids from gettid() — ch50's instrument and ch49's +tids from gettid(): ch50's instrument and ch49's vocabulary, applied to an I/O runtime asio::write(sock, array<const_buffer,4>) @@ -38,7 +38,7 @@ → 4 socket write-family syscalls (sendto) the same 56 bytes, four trips -Identical bytes reach the peer either way — the gate checks that too. What differs is the number of times the process crosses into the kernel. +Identical bytes reach the peer either way: the gate checks that too. What differs is the number of times the process crosses into the kernel. This is the readv/writev machinery Part 5 covered, reached by handing Asio a buffer sequence instead of assembling an iovec array by hand. Syscall counts are deterministic and are gated exactly; plain write(2) is excluded because it is this program's own stdout. Nothing binds a port: the I/O cases use an AF_UNIX socketpair via local::connect_pair, so the example stays offline and unprivileged. diff --git a/assets/diagrams/56-one-workload-seven-models.excalidraw b/assets/diagrams/56-one-workload-seven-models.excalidraw index 85ed063..ca27021 100644 --- a/assets/diagrams/56-one-workload-seven-models.excalidraw +++ b/assets/diagrams/56-one-workload-seven-models.excalidraw @@ -119,13 +119,13 @@ "updated": 1, "link": null, "locked": false, - "text": "one OS thread \u2014 concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", + "text": "one OS thread: concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "one OS thread \u2014 concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", + "originalText": "one OS thread: concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", "lineHeight": 1.25, "baseline": 12 }, @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "many OS threads + a LOCK \u2014 a thread that loses the race is parked, and has to be woken", + "text": "many OS threads + a LOCK: a thread that loses the race is parked, and has to be woken", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "many OS threads + a LOCK \u2014 a thread that loses the race is parked, and has to be woken", + "originalText": "many OS threads + a LOCK: a thread that loses the race is parked, and has to be woken", "lineHeight": 1.25, "baseline": 12 }, @@ -245,13 +245,13 @@ "updated": 1, "link": null, "locked": false, - "text": "many OS threads + a STRAND \u2014 the handler is deferred, so no thread ever blocks", + "text": "many OS threads + a STRAND: the handler is deferred, so no thread ever blocks", "fontSize": 12, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "many OS threads + a STRAND \u2014 the handler is deferred, so no thread ever blocks", + "originalText": "many OS threads + a STRAND: the handler is deferred, so no thread ever blocks", "lineHeight": 1.25, "baseline": 12 }, @@ -1765,13 +1765,13 @@ "updated": 1, "link": null, "locked": false, - "text": "Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models \u2014 which is the only thing that makes this a comparison rather than a table of quotations.", + "text": "Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models: which is the only thing that makes this a comparison rather than a table of quotations.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models \u2014 which is the only thing that makes this a comparison rather than a table of quotations.", + "originalText": "Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models: which is the only thing that makes this a comparison rather than a table of quotations.", "lineHeight": 1.25, "baseline": 11 }, diff --git a/assets/diagrams/56-one-workload-seven-models.svg b/assets/diagrams/56-one-workload-seven-models.svg index 6f5a2fa..fc16ac4 100644 --- a/assets/diagrams/56-one-workload-seven-models.svg +++ b/assets/diagrams/56-one-workload-seven-models.svg @@ -3,11 +3,11 @@ ONE workload, shared verbatim by every model (workload.hpp) -one OS thread — concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with. +one OS thread: concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with. -many OS threads + a LOCK — a thread that loses the race is parked, and has to be woken +many OS threads + a LOCK: a thread that loses the race is parked, and has to be woken -many OS threads + a STRAND — the handler is deferred, so no thread ever blocks +many OS threads + a STRAND: the handler is deferred, so no thread ever blocks 8 tasks x 5000 rounds = 40000 folds into one accumulator every model below produced total = 0xb75768f6610642a0 (gate B, checked before any comparison is drawn) @@ -53,6 +53,6 @@ 1/8 the futex traffic of the row above 1/8 the futex traffic of the row above -Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models — which is the only thing that makes this a comparison rather than a table of quotations. +Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models: which is the only thing that makes this a comparison rather than a table of quotations. Futex magnitudes move on every run and are never gated; the three TIERS are. Measured on the Fedora 44 reference host, Boost 1.90.0, GCC 16.1.1. \ No newline at end of file diff --git a/assets/diagrams/56-two-assembled-axes.excalidraw b/assets/diagrams/56-two-assembled-axes.excalidraw index a201e0e..4c9c828 100644 --- a/assets/diagrams/56-two-assembled-axes.excalidraw +++ b/assets/diagrams/56-two-assembled-axes.excalidraw @@ -182,13 +182,13 @@ "updated": 1, "link": null, "locked": false, - "text": "thread \u2014 8388608 bytes", + "text": "thread: 8388608 bytes", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "thread \u2014 8388608 bytes", + "originalText": "thread: 8388608 bytes", "lineHeight": 1.25, "baseline": 14 }, @@ -315,13 +315,13 @@ "updated": 1, "link": null, "locked": false, - "text": "fiber \u2014 131072 bytes", + "text": "fiber: 131072 bytes", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "fiber \u2014 131072 bytes", + "originalText": "fiber: 131072 bytes", "lineHeight": 1.25, "baseline": 14 }, @@ -448,13 +448,13 @@ "updated": 1, "link": null, "locked": false, - "text": "coroutine frame \u2014 32 bytes", + "text": "coroutine frame: 32 bytes", "fontSize": 14, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "coroutine frame \u2014 32 bytes", + "originalText": "coroutine frame: 32 bytes", "lineHeight": 1.25, "baseline": 14 }, @@ -1241,13 +1241,13 @@ "updated": 1, "link": null, "locked": false, - "text": "NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them \u2014 the pattern ch54 established.", + "text": "NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them: the pattern ch54 established.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them \u2014 the pattern ch54 established.", + "originalText": "NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them: the pattern ch54 established.", "lineHeight": 1.25, "baseline": 11 }, @@ -1311,13 +1311,13 @@ "updated": 1, "link": null, "locked": false, - "text": "P2300 senders are absent from both bands on purpose: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", + "text": "P2300 senders are absent from both bands by design: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", "fontSize": 11, "fontFamily": 1, "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "P2300 senders are absent from both bands on purpose: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", + "originalText": "P2300 senders are absent from both bands by design: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", "lineHeight": 1.25, "baseline": 11 } diff --git a/assets/diagrams/56-two-assembled-axes.svg b/assets/diagrams/56-two-assembled-axes.svg index 64a9634..948174f 100644 --- a/assets/diagrams/56-two-assembled-axes.svg +++ b/assets/diagrams/56-two-assembled-axes.svg @@ -5,15 +5,15 @@ how cancellation arrives -thread — 8388608 bytes +thread: 8388608 bytes ch50, pthread_getattr_np the kernel schedules it, so it costs kernel state -fiber — 131072 bytes +fiber: 131072 bytes ch54, stack_traits::default_size() user-scheduled, but it keeps a real stack -coroutine frame — 32 bytes +coroutine frame: 32 bytes ch53, operator new in promise_type no stack: only what crosses a suspension @@ -38,7 +38,7 @@ divide by 4096 divide by 4096 -NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them — the pattern ch54 established. +NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them: the pattern ch54 established. Cost and capability move together and in opposite directions: the more a paused computation costs, the fewer restrictions there are on where it may pause. -P2300 senders are absent from both bands on purpose: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library. +P2300 senders are absent from both bands by design: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library. \ No newline at end of file diff --git a/assets/diagrams/README.md b/assets/diagrams/README.md index b6e34cb..353593d 100644 --- a/assets/diagrams/README.md +++ b/assets/diagrams/README.md @@ -18,67 +18,67 @@ here as you add them: | `04-runtime-syscall-layers` | 4 | The C++/Go/Rust layer stacks converging on the one register-level kernel ABI, with real strace -c totals | | `10-uring-rings` | 10 | The SQ ring, SQE array, and CQ ring shared via mmap, the acquire/release handoffs around them, and io_uring_enter as the only syscall | | `10-readiness-vs-completion` | 10 | Readiness (epoll answers "may I?") beside completion (io_uring answers "it is done"), with the real per-engine syscall counts from fwatch | -| `09-event-loop-anatomy` | 9 | One epoll loop over three event sources — inotify, timerfd, signalfd — with the kernel eventpoll interest list and the readiness path back into epoll_wait | +| `09-event-loop-anatomy` | 9 | One epoll loop over three event sources: inotify, timerfd, signalfd: with the kernel eventpoll interest list and the readiness path back into epoll_wait | | `06-three-concurrency-models` | 6 | parhash's producer/queue/workers/cancellation shape in all three vocabularies, with observed /proc thread counts | -| `06-cancellation-drain` | 6 | The SIGINT drain sequence — one flag flips, walker and workers wind down, in-flight hashes finish, exit 130 | +| `06-cancellation-drain` | 6 | The SIGINT drain sequence: one flag flips, walker and workers wind down, in-flight hashes finish, exit 130 | | `16-mapping-page-cache` | 16 | Two processes' MAP_SHARED mappings converging on one set of page-cache pages, msync vs writeback to disk, and a MAP_PRIVATE view forking its copy on first write | -| `16-shmkv-layout` | 16 | The shmkv v0 on-disk format byte for byte — magic, u32 LE slot_count, 256-byte slots split 64/192 — with the three languages reading the same bytes | -| `17-arena-vs-gc` | 17 | Three reclamation strategies side by side — free-one-by-one through glibc malloc, arena/pool batch release, and the Go GC's pacer — annotated with real allocbench peak_rss and gc_cycles numbers | -| `11-process-lifecycle-states` | 11 | Process states as ps STAT letters — running, sleeping, stopped, zombie — and the wait4/waitid reap that frees the pid, annotated with the chapter's live zombie window | +| `16-shmkv-layout` | 16 | The shmkv v0 on-disk format byte for byte: magic, u32 LE slot_count, 256-byte slots split 64/192: with the three languages reading the same bytes | +| `17-arena-vs-gc` | 17 | Three reclamation strategies side by side: free-one-by-one through glibc malloc, arena/pool batch release, and the Go GC's pacer: annotated with real allocbench peak_rss and gc_cycles numbers | +| `11-process-lifecycle-states` | 11 | Process states as ps STAT letters: running, sleeping, stopped, zombie: and the wait4/waitid reap that frees the pid, annotated with the chapter's live zombie window | | `11-fork-exec-wait-seq` | 11 | pmon's fork → exec → wait sequence with the CLOEXEC self-pipe carrying the exec verdict, and the clone flavors Go and Rust use for the same dance | -| `19-uds-control-plane` | 19 | pmon v5's supervise/pmctl control plane over a filesystem UNIX stream socket — listener, accepted fd with SO_PEERCRED, and the connected socket-inode pair ss -xp reported | +| `19-uds-control-plane` | 19 | pmon v5's supervise/pmctl control plane over a filesystem UNIX stream socket: listener, accepted fd with SO_PEERCRED, and the connected socket-inode pair ss -xp reported | | `19-scm-rights-transfer` | 19 | SCM_RIGHTS crossing the socket: sender slot 3 and receiver slot 4 pointing at one shared open file description (pos 47, inode 95934), with the real sendmsg/recvmsg cmsg values from the chapter run | -| `12-signal-delivery-paths` | 12 | Disposition, per-thread mask, and pending set in the kernel, feeding the three consumption paths pmon uses — signalfd reads, Go runtime channels, and the self-pipe doorbell | +| `12-signal-delivery-paths` | 12 | Disposition, per-thread mask, and pending set in the kernel, feeding the three consumption paths pmon uses: signalfd reads, Go runtime channels, and the self-pipe doorbell | | `12-supervisor-state-machine` | 12 | pmon supervise's two live states (child running, backoff wait) and the exits, with SIGTERM/SIGINT, SIGHUP reload, and the doubling backoff as transitions | -| `14-credential-sets-caps` | 14 | The three-uid state machine and the five capability sets across pmon's drop — KEEPCAPS → setresuid → capset → AMBIENT_RAISE → execve beside the negative control, annotated with the real /proc status values from systems-target | -| `15-address-space-map` | 15 | One x86-64 process address space top to bottom — [vsyscall], [stack], the mmap region with the 64 MiB anonymous allocation, [heap], data, text — with real addresses and growth arrows | -| `15-fault-flow` | 15 | One touched page's journey — MMU miss, trap, VMA lookup — fanning out to SIGSEGV, anonymous minor fault, page-cache minor fault with fault-around, and major fault, with measured counts | -| `20-futex-wait-wake` | 20 | One shmkv wake end to end — watcher parks in FUTEX_WAIT on the mapped word, writer publishes under the seqlock and calls FUTEX_WAKE, kernel wait queue keyed by (inode, offset) hands the watcher back — with the EAGAIN lost-wakeup guard | -| `20-ipc-matrix` | 20 | The coordination ladder as measured on this host — futex, eventfd, pipe, POSIX mq, UNIX socket, and the 1 ms poll loop, with bench p50/p99 and the voluntary context-switch evidence | -| `13-pid-reuse-race-pidfd` | 13 | The five-step pid-reuse race timeline — spawn, crash, reap, recycle, kill(2) hitting a stranger — above the four-step pidfd lane that pins identity to an fd, annotated with the real fdinfo Pid: and strace evidence from pmon v2 | -| `18-pipe-internals` | 18 | One live pipe as the kernel sees it — write end fd 1 and read end fd 5 around the 16-slot ring of pages, with the measured 65536 B capacity, the F_SETPIPE_SZ page rounding, and what PIPE_BUF atomicity does and does not promise | +| `14-credential-sets-caps` | 14 | The three-uid state machine and the five capability sets across pmon's drop: KEEPCAPS → setresuid → capset → AMBIENT_RAISE → execve beside the negative control, annotated with the real /proc status values from systems-target | +| `15-address-space-map` | 15 | One x86-64 process address space top to bottom: [vsyscall], [stack], the mmap region with the 64 MiB anonymous allocation, [heap], data, text: with real addresses and growth arrows | +| `15-fault-flow` | 15 | One touched page's journey: MMU miss, trap, VMA lookup: fanning out to SIGSEGV, anonymous minor fault, page-cache minor fault with fault-around, and major fault, with measured counts | +| `20-futex-wait-wake` | 20 | One shmkv wake end to end: watcher parks in FUTEX_WAIT on the mapped word, writer publishes under the seqlock and calls FUTEX_WAKE, kernel wait queue keyed by (inode, offset) hands the watcher back: with the EAGAIN lost-wakeup guard | +| `20-ipc-matrix` | 20 | The coordination ladder as measured on this host: futex, eventfd, pipe, POSIX mq, UNIX socket, and the 1 ms poll loop, with bench p50/p99 and the voluntary context-switch evidence | +| `13-pid-reuse-race-pidfd` | 13 | The five-step pid-reuse race timeline: spawn, crash, reap, recycle, kill(2) hitting a stranger: above the four-step pidfd lane that pins identity to an fd, annotated with the real fdinfo Pid: and strace evidence from pmon v2 | +| `18-pipe-internals` | 18 | One live pipe as the kernel sees it: write end fd 1 and read end fd 5 around the 16-slot ring of pages, with the measured 65536 B capacity, the F_SETPIPE_SZ page rounding, and what PIPE_BUF atomicity does and does not promise | | `28-remote-debug-topology` | 28 | The local core-dump path (app crash → systemd-coredump → coredumpctl → gdb on core.app, verified this session) beside the gdbserver/`target remote`/CLion remote path on systems-target, documented but not run in this lane | -| `28-stack-frame-anatomy` | 28 | The five real frames gdb's `bt full` names on `app`'s core — main → run_supervisor → handle_child → deref → std::println — beside the exact `.debug_line` addresses readelf/objdump report for lines 52 and 56 | -| `18-log-topology` | 18 | pmon v4's full log pipeline — child stdio through two O_CLOEXEC pipes into the supervisor's poll loop and the framed log, then tail splicing file→FIFO to a detachable cat reader, annotated with the run's real fds, inodes, flags, and splice return values | -| `25-futex-fast-slow-path` | 25 | pthread mutex as a futex — the uncontended fast path (userspace CAS 0→1, no syscall) beside the contended slow path (FUTEX_WAIT parks the loser on a kernel wait queue keyed by (mm, &word), FUTEX_WAKE releases it), annotated with the measured 5,186→488,818 futex-call and 455→123,986 voluntary-context-switch scaling | -| `25-mpmc-queue` | 25 | workq's bounded MPMC job queue shared three ways — P producers push, one mutex + not_full/not_empty condvars (a buffered channel in Go) bound capacity K, C consumers pop into per-consumer accumulators XOR-folded after join into the P/C/cap-independent checksum 42b3746c6cee7465 | -| `26-spsc-ring` | 26 | spscring's Lamport SPSC ring — producer-owned tail and consumer-owned head, each Release store publishing the slot the other thread Acquire-loads, over a buf[K] slot row with occupancy = tail - head | -| `26-memory-ordering` | 26 | The same hand-off under three orderings — seq-cst (Go, XCHGQ), acquire/release (C++/Rust head/tail, plain MOV), relaxed (Rust slots, plain MOV) — and what each compiles to on x86-64 TSO | +| `28-stack-frame-anatomy` | 28 | The five real frames gdb's `bt full` names on `app`'s core: main → run_supervisor → handle_child → deref → std::println: beside the exact `.debug_line` addresses readelf/objdump report for lines 52 and 56 | +| `18-log-topology` | 18 | pmon v4's full log pipeline: child stdio through two O_CLOEXEC pipes into the supervisor's poll loop and the framed log, then tail splicing file→FIFO to a detachable cat reader, annotated with the run's real fds, inodes, flags, and splice return values | +| `25-futex-fast-slow-path` | 25 | pthread mutex as a futex: the uncontended fast path (userspace CAS 0→1, no syscall) beside the contended slow path (FUTEX_WAIT parks the loser on a kernel wait queue keyed by (mm, &word), FUTEX_WAKE releases it), annotated with the measured 5,186→488,818 futex-call and 455→123,986 voluntary-context-switch scaling | +| `25-mpmc-queue` | 25 | workq's bounded MPMC job queue shared three ways: P producers push, one mutex + not_full/not_empty condvars (a buffered channel in Go) bound capacity K, C consumers pop into per-consumer accumulators XOR-folded after join into the P/C/cap-independent checksum 42b3746c6cee7465 | +| `26-spsc-ring` | 26 | spscring's Lamport SPSC ring: producer-owned tail and consumer-owned head, each Release store publishing the slot the other thread Acquire-loads, over a buf[K] slot row with occupancy = tail - head | +| `26-memory-ordering` | 26 | The same hand-off under three orderings: seq-cst (Go, XCHGQ), acquire/release (C++/Rust head/tail, plain MOV), relaxed (Rust slots, plain MOV): and what each compiles to on x86-64 TSO | | `26-false-sharing` | 26 | head and tail sharing one 64 B cache line ping-ponging between two cores versus padded onto separate lines, annotated with the real ~128 M vs ~108 M L1-dcache-load-misses and 4.64 vs 6.20 Mops | -| `21-server-lifecycle` | 21 | chatterd serve's listener path — socket → SO_REUSEADDR → bind → listen(128) → the accept4 loop spawning one thread per accepted fd (4, 5), with the SIGINT shutdown path that flips g_stop and closes the listener | -| `21-frame-format` | 21 | the length-prefixed wire frame byte for byte — a little-endian u32 length (0f 00 00 00 = 15) then name·NUL·text for alice sending "hello bob", plus the JOIN vs CHAT distinction and the len bounds | -| `23-two-vm-topology` | 23 | The two-guest lab topology on one virbr0 L2 segment — systems-target (192.168.124.7) and systems-peer (192.168.124.95) both joined to group 239.23.7.1:51824 with TTL 1, the two beacons (35 B and 34 B) crossing the bridge, and the TCP :9241 chat-frame bridge between them | -| `23-discovery-sequence` | 23 | One peer's discovery path — the connectionless UDP band (sendto beacon, recv one datagram, parse + dedup by name) bridging down into the connection-oriented TCP band (connect with retry, the reused ch21 length-prefixed frame each way, the printed discovered/says lines) | -| `24-clock-taxonomy` | 24 | The four POSIX clocks clock_gettime can read — REALTIME (steppable wall time), MONOTONIC (steady), BOOTTIME (monotonic + suspend), PROCESS_CPUTIME_ID — over the monotonic-vs-wall bug: an NTP step rewinds a wall-clock deadline while a CLOCK_MONOTONIC deadline fires on real silence | -| `24-heartbeat-timeout-seq` | 24 | chatterd v3's heartbeat/deadline/reconnect sequence — HELLO link, PING every 300 ms resetting the monotonic deadline, the listener killed, the deadline firing "peer A timed out", then the jittered exponential backoff (107, 245, 712 ms from the live run) | -| `27-coroutine-suspension` | 27 | chatterd v4's C++20 coroutine engine — one heap-allocated `connection()` frame per client suspending on `co_await ReadAwaitable` when `recv` hits EAGAIN, `wait_readable` parking the `std::coroutine_handle` in `waiters_[fd]` with `EPOLLIN|EPOLLONESHOT`, and the reactor's single `epoll_wait(-1)` resuming the exact handle on readiness — proving suspension is a return, not a blocked thread | -| `27-gmp-scheduler` | 27 | Go's G-M-P runtime for the same daemon — goroutines (one per connection) multiplexed by GOMAXPROCS=16 logical processors (P) bound to OS threads (M), the netpoller (one runtime epoll instance) parking a G blocked in `recv` and handing it back runnable on readiness, and SIGURG async preemption retiring a G that runs past 10 ms — why Go needed no async rewrite | -| `27-tokio-task-lifecycle` | 27 | tokio's task/Waker cycle for the Rust async engine — `tokio::spawn`ed `async fn` tasks polled by 16 `tokio-rt-worker` threads (= cores), `.await` returning `Poll::Pending` and registering a Waker with the mio reactor, `epoll_wait` calling that Waker on fd readiness to re-enqueue the task, and the re-poll to `Poll::Ready` — 20k tasks over 16 threads | -| `22-connection-state-machine` | 22 | chatterd v1's epoll engine per-connection state machine — recv() drained to EAGAIN into inbuf, take_frame reassembling whole frames, broadcast appending to every conn's outbuf, and the send()/EAGAIN backpressure loop that arms EPOLLOUT and resumes flush() on the next epoll_wait wakeup | -| `22-netpoller-vs-epoll` | 22 | the chapter's key comparison — C++/Rust one thread over a hand-written epoll interest list (4 epoll_wait calls, explicit outbuf+EPOLLOUT backpressure) beside Go's goroutine-per-conn with the runtime netpoller hidden underneath (165 edge-triggered epoll_pwait calls, ~7 OS threads, blocking-channel backpressure) | -| `31-flamegraph-reading` | 31 | a schematic flamegraph annotated with its two axes — x = share of samples (not time order), y = stack depth, bottom the root frame, top the leaf running at each sample tick — with the widest column labeled as spin_hot/hotSpin, the real hot path this chapter's three profilers agree on | -| `31-toolbelt-map` | 31 | one shared `app ` target feeding three native toolbelts — C++'s perf/clang-tidy/-fanalyzer, Go's runtime/pprof+go tool trace+delve, Rust's perf/cargo-flamegraph+clippy — with gdb (Ch. 28) and tokio-console (Ch. 27, not applicable here) noted as dashed, out-of-scope boxes | -| `29-tool-coverage-matrix` | 29 | the five bugfarm defects (leak, uninit, uaf, overflow, race) down the rows against C++/Go/Rust across the columns, each cell backed by a command run this session — valgrind memcheck and ASan both catching uaf/overflow, valgrind's 630-error confusion on the Go binary, Rust's borrow checker preventing four of five outright, and helgrind+TSan+`go -race` all catching the same race | -| `29-shadow-memory` | 29 | ASan's shadow-memory model — one shadow byte per 8 application bytes via `(app_addr >> 3) + offset` — with the real freed-block/redzone shadow bytes (`fa`/`fd`) this chapter's `uaf` run produced, and the measured 0.002s native vs 0.046s TSan vs 1.0s valgrind memcheck gap that the inline-check design explains | -| `30-ebpf-tooling-stack` | 30 | the layered eBPF observation stack on systems-target — kprobe/uprobe/tracepoint/perf_event/BTF at the bottom, bcc-tools/bpftrace/bpftool/c++filt above it (every box exercised live this session), SystemTap's kernel-module vs dyninst backends beside it, and the three target binaries' uprobe arg0 outcome (correct for C++/Rust's SysV ABI, wrong for Go's ABIInternal) | -| `30-uprobe-attachment` | 30 | one uprobe attach walked across all three binaries — C++'s and Rust's mangled `cmd_work` symbols demangled by `c++filt` (Itanium and Rust v0 both auto-detected) then attached by the mangled string, beside Go's plain unmangled `main.cmdWork` — with the real, measured RDI-vs-RAX argument-register mismatch that only the Go column hits | +| `21-server-lifecycle` | 21 | chatterd serve's listener path: socket → SO_REUSEADDR → bind → listen(128) → the accept4 loop spawning one thread per accepted fd (4, 5), with the SIGINT shutdown path that flips g_stop and closes the listener | +| `21-frame-format` | 21 | the length-prefixed wire frame byte for byte: a little-endian u32 length (0f 00 00 00 = 15) then name·NUL·text for alice sending "hello bob", plus the JOIN vs CHAT distinction and the len bounds | +| `23-two-vm-topology` | 23 | The two-guest lab topology on one virbr0 L2 segment: systems-target (192.168.124.7) and systems-peer (192.168.124.95) both joined to group 239.23.7.1:51824 with TTL 1, the two beacons (35 B and 34 B) crossing the bridge, and the TCP :9241 chat-frame bridge between them | +| `23-discovery-sequence` | 23 | One peer's discovery path: the connectionless UDP band (sendto beacon, recv one datagram, parse + dedup by name) bridging down into the connection-oriented TCP band (connect with retry, the reused ch21 length-prefixed frame each way, the printed discovered/says lines) | +| `24-clock-taxonomy` | 24 | The four POSIX clocks clock_gettime can read: REALTIME (steppable wall time), MONOTONIC (steady), BOOTTIME (monotonic + suspend), PROCESS_CPUTIME_ID: over the monotonic-vs-wall bug: an NTP step rewinds a wall-clock deadline while a CLOCK_MONOTONIC deadline fires on real silence | +| `24-heartbeat-timeout-seq` | 24 | chatterd v3's heartbeat/deadline/reconnect sequence: HELLO link, PING every 300 ms resetting the monotonic deadline, the listener killed, the deadline firing "peer A timed out", then the jittered exponential backoff (107, 245, 712 ms from the live run) | +| `27-coroutine-suspension` | 27 | chatterd v4's C++20 coroutine engine: one heap-allocated `connection()` frame per client suspending on `co_await ReadAwaitable` when `recv` hits EAGAIN, `wait_readable` parking the `std::coroutine_handle` in `waiters_[fd]` with `EPOLLIN|EPOLLONESHOT`, and the reactor's single `epoll_wait(-1)` resuming the exact handle on readiness: proving suspension is a return, not a blocked thread | +| `27-gmp-scheduler` | 27 | Go's G-M-P runtime for the same daemon: goroutines (one per connection) multiplexed by GOMAXPROCS=16 logical processors (P) bound to OS threads (M), the netpoller (one runtime epoll instance) parking a G blocked in `recv` and handing it back runnable on readiness, and SIGURG async preemption retiring a G that runs past 10 ms: why Go needed no async rewrite | +| `27-tokio-task-lifecycle` | 27 | tokio's task/Waker cycle for the Rust async engine: `tokio::spawn`ed `async fn` tasks polled by 16 `tokio-rt-worker` threads (= cores), `.await` returning `Poll::Pending` and registering a Waker with the mio reactor, `epoll_wait` calling that Waker on fd readiness to re-enqueue the task, and the re-poll to `Poll::Ready`: 20k tasks over 16 threads | +| `22-connection-state-machine` | 22 | chatterd v1's epoll engine per-connection state machine: recv() drained to EAGAIN into inbuf, take_frame reassembling whole frames, broadcast appending to every conn's outbuf, and the send()/EAGAIN backpressure loop that arms EPOLLOUT and resumes flush() on the next epoll_wait wakeup | +| `22-netpoller-vs-epoll` | 22 | the chapter's key comparison: C++/Rust one thread over a hand-written epoll interest list (4 epoll_wait calls, explicit outbuf+EPOLLOUT backpressure) beside Go's goroutine-per-conn with the runtime netpoller hidden underneath (165 edge-triggered epoll_pwait calls, ~7 OS threads, blocking-channel backpressure) | +| `31-flamegraph-reading` | 31 | a schematic flamegraph annotated with its two axes: x = share of samples (not time order), y = stack depth, bottom the root frame, top the leaf running at each sample tick: with the widest column labeled as spin_hot/hotSpin, the real hot path this chapter's three profilers agree on | +| `31-toolbelt-map` | 31 | one shared `app ` target feeding three native toolbelts: C++'s perf/clang-tidy/-fanalyzer, Go's runtime/pprof+go tool trace+delve, Rust's perf/cargo-flamegraph+clippy: with gdb (Ch. 28) and tokio-console (Ch. 27, not applicable here) noted as dashed, out-of-scope boxes | +| `29-tool-coverage-matrix` | 29 | the five bugfarm defects (leak, uninit, uaf, overflow, race) down the rows against C++/Go/Rust across the columns, each cell backed by a command run this session: valgrind memcheck and ASan both catching uaf/overflow, valgrind's 630-error confusion on the Go binary, Rust's borrow checker preventing four of five outright, and helgrind+TSan+`go -race` all catching the same race | +| `29-shadow-memory` | 29 | ASan's shadow-memory model: one shadow byte per 8 application bytes via `(app_addr >> 3) + offset`: with the real freed-block/redzone shadow bytes (`fa`/`fd`) this chapter's `uaf` run produced, and the measured 0.002s native vs 0.046s TSan vs 1.0s valgrind memcheck gap that the inline-check design explains | +| `30-ebpf-tooling-stack` | 30 | the layered eBPF observation stack on systems-target: kprobe/uprobe/tracepoint/perf_event/BTF at the bottom, bcc-tools/bpftrace/bpftool/c++filt above it (every box exercised live this session), SystemTap's kernel-module vs dyninst backends beside it, and the three target binaries' uprobe arg0 outcome (correct for C++/Rust's SysV ABI, wrong for Go's ABIInternal) | +| `30-uprobe-attachment` | 30 | one uprobe attach walked across all three binaries: C++'s and Rust's mangled `cmd_work` symbols demangled by `c++filt` (Itanium and Rust v0 both auto-detected) then attached by the mangled string, beside Go's plain unmangled `main.cmdWork`: with the real, measured RDI-vs-RAX argument-register mismatch that only the Go column hits | | `35-kvm-virtio-stack` | 35 | VMX root (host kernel + QEMU/virtio-blk backend) versus non-root (guest kernel + overheadbench) modes, the getpid path that never leaves the guest beside the fsync path that really vmexits through the virtqueue back to host NVMe, annotated with the measured overheadbench syscall/mem/io deltas between systems-target and the host | -| `35-isolation-spectrum` | 35 | the four-point isolation spectrum — bare process, podman container (shared kernel), rust-vmm-based microVM (own minimal-device guest kernel), full KVM/QEMU VM (own full-device guest kernel) — each annotated with its escape surface and the measured overheadbench numbers that place container and full-VM on the chart | -| `33-seccomp-filter-flow` | 33 | one syscall's path through fwatch's seccomp-bpf filter — BPF_LD_ABS loading the syscall number, the compiled jump table (26 entries cpp/rust, 39 go), SECCOMP_RET_ALLOW on match, and the two possible default actions (SCMP_ACT_ERRNO, fwatch's own choice, beside the unused SCMP_ACT_KILL_PROCESS) — annotated with the real guest EPERM and SIGSYS transcripts | -| `33-landlock-ruleset` | 33 | the Landlock ruleset/rule model — landlock_create_ruleset probing the ABI (never hardcoded), landlock_add_rule binding READ_FILE\|READ_DIR to one directory fd, and landlock_restrict_self enforcing it irrevocably — with the real ABI split (host 9, systems-target guest 7) and the granted-vs-EACCES filesystem view from the chapter's probes | -| `32-namespace-overview` | 32 | host vs pmon containerize's PID-1 child across all eight namespace types, with the real `/proc//ns/*` inode numbers from systems-target — pid/mnt/uts/net differ (unshared), time/ipc/user/cgroup match the host (deliberately left alone) | -| `32-cgroup-hierarchy` | 32 | the cgroup v2 unified hierarchy from root (`cgroup.subtree_control` delegating +memory +cpu) down to the `pmon-oomdemo` leaf — real `memory.max`/`memory.swap.max`/`cpu.max`/PSI values — into the kernel's own `dmesg` OOM-kill line for pid 27013 this session produced | -| `32-clone3-flow` | 32 | C++/Rust's unshare-then-clone3(flags=0) shape beside Go's two attempts — the first (LockOSThread + raw unshare + os/exec re-exec) hitting a real `ENOMEM` on systems-target, and the shipped fix (Cloneflags on SysProcAttr, one clone(2) for everything) passing 13/13 across all three languages | -| `34-image-layering` | 34 | `app`'s multi-stage Containerfile — the discarded UBI10 builder (220 MB measured) installing a toolchain and statically linking the binary, `COPY --from=builder` into the UBI10-micro runtime stage (24.3 MB base) — with the real measured final image sizes (cpp/go 27.2 MB, rust 24.9 MB) barely above the bare micro base | -| `34-pid1-signal-flow` | 34 | `serve` vs `naive` as a container's PID 1 receiving SIGTERM — serve's signalfd/Notify/Signals wake, stop-spawning, forward-to-worker, reap, graceful exit sequence beside naive's kernel-masked default action that just drops the signal — annotated with the real measured `podman stop` timings (serve: cpp 192ms/go 60ms/rust 101ms; naive: cpp 2108ms/rust 2074ms SIGKILLed, go 60ms but silent) | -| `34-ns-debugging-map` | 34 | the two independent paths that reach the same container PID 1 — `podman exec` from inside the container runtime and a rootless `podman unshare nsenter` from the bare host (plain `nsenter` alone fails EPERM) — both confirming `Name: app` and `/proc/1/exe`, beside the real subuid/subgid mapping and a live zero-zombie scan | -| `39-coordinated-omission` | 39 | benchlab's closed loop against what a fixed-rate caller would have seen — one recorded 1057 ns stall sample on top, the same stall backfilled below into the synthetic queued requests `co_correct` adds, showing why raw p99 buries the stall while `co_p99_ns` (always ≥ `p99_ns`) surfaces it | -| `39-benchmark-pipeline` | 39 | benchlab's real path (warmup discard → per-iteration monotonic timing → sort/percentile and the parallel `co_correct` branch → the printed table) beside `--lie`'s one unwarmed wall-clock call straight to `elapsed_ns` — same codec, same fixed workload, two harnesses telling a different story | -| `38-otlp-pipeline` | 38 | lsp-otel's telemetry path — serve's per-request parent span `request` wrapping `work` + `respond` children plus the `requests_total` counter and `request_duration` histogram, through the OTLP/HTTP exporter (batched ~2s, flushed on SIGINT) posting to the OTel collector on :4318, fanned to Tempo (traces) and Prometheus (metrics) and queried back through Grafana's datasource proxy — with cpp/go/rust each tagging service.name=lsp-otel- so the three never collide in the shared stack | -| `37-use-method-checklist` | 37 | loadmix analyze as a pipeline — four one-shot pre-samples (uptime/dmesg/top/ss) then five interval samplers (vmstat/mpstat/iostat/sar/pidstat) spawned concurrently so an N-second checklist costs ~N seconds not 5N, each parsed by column name from its own header row into the 4×3 USE signal matrix (cpu/mem/io/net × Utilization/Saturation/Errors), and the max-Saturation-ratio verdict — with the saturate side shown as a worker pool the concurrent analyze attributes | -| `41-fleet-topology` | 41 | the capstone's two-VM fleet — pmon on systems-target and systems-peer each supervising fwatch/sysagent/chatterd (cap-dropped + Landlock-sandboxed), the two chatterds bridged across hosts (from=NICK@node), and both guests exporting OTLP over the libvirt gateway to the host LGTM stack | -| `41-supervise-lifecycle` | 41 | pmon's per-child supervise loop — fork+exec → starting → up → wait-on-child, an unexpected exit looping through restarting (+300ms, attempt++) back to up, and SIGTERM forwarding to all children then pmon: shutdown, with a health tick reading each child's state | -| `40-fastpath-datapath` | 40 | one echo round trip, naive versus fastpath: the naive server's per-message heap buffer and blocking `read(2)` that sleeps through the kernel scheduler (one voluntary context switch per message) against the fastpath server's single reused buffer on a `sched_setaffinity`-pinned core busy-polling `recv(2)` over `EAGAIN`, never entering the scheduler (≈ zero voluntary context switches) — the measured 20500-vs-3 contrast that the chapter reads from `/proc//status` | +| `35-isolation-spectrum` | 35 | the four-point isolation spectrum: bare process, podman container (shared kernel), rust-vmm-based microVM (own minimal-device guest kernel), full KVM/QEMU VM (own full-device guest kernel): each annotated with its escape surface and the measured overheadbench numbers that place container and full-VM on the chart | +| `33-seccomp-filter-flow` | 33 | one syscall's path through fwatch's seccomp-bpf filter: BPF_LD_ABS loading the syscall number, the compiled jump table (26 entries cpp/rust, 39 go), SECCOMP_RET_ALLOW on match, and the two possible default actions (SCMP_ACT_ERRNO, fwatch's own choice, beside the unused SCMP_ACT_KILL_PROCESS): annotated with the real guest EPERM and SIGSYS transcripts | +| `33-landlock-ruleset` | 33 | the Landlock ruleset/rule model: landlock_create_ruleset probing the ABI (never hardcoded), landlock_add_rule binding READ_FILE\|READ_DIR to one directory fd, and landlock_restrict_self enforcing it irrevocably: with the real ABI split (host 9, systems-target guest 7) and the granted-vs-EACCES filesystem view from the chapter's probes | +| `32-namespace-overview` | 32 | host vs pmon containerize's PID-1 child across all eight namespace types, with the real `/proc//ns/*` inode numbers from systems-target: pid/mnt/uts/net differ (unshared), time/ipc/user/cgroup match the host (left alone) | +| `32-cgroup-hierarchy` | 32 | the cgroup v2 unified hierarchy from root (`cgroup.subtree_control` delegating +memory +cpu) down to the `pmon-oomdemo` leaf: real `memory.max`/`memory.swap.max`/`cpu.max`/PSI values: into the kernel's own `dmesg` OOM-kill line for pid 27013 this session produced | +| `32-clone3-flow` | 32 | C++/Rust's unshare-then-clone3(flags=0) shape beside Go's two attempts: the first (LockOSThread + raw unshare + os/exec re-exec) hitting a real `ENOMEM` on systems-target, and the shipped fix (Cloneflags on SysProcAttr, one clone(2) for everything) passing 13/13 across all three languages | +| `34-image-layering` | 34 | `app`'s multi-stage Containerfile: the discarded UBI10 builder (220 MB measured) installing a toolchain and statically linking the binary, `COPY --from=builder` into the UBI10-micro runtime stage (24.3 MB base): with the real measured final image sizes (cpp/go 27.2 MB, rust 24.9 MB) barely above the bare micro base | +| `34-pid1-signal-flow` | 34 | `serve` vs `naive` as a container's PID 1 receiving SIGTERM: serve's signalfd/Notify/Signals wake, stop-spawning, forward-to-worker, reap, graceful exit sequence beside naive's kernel-masked default action that just drops the signal: annotated with the real measured `podman stop` timings (serve: cpp 192ms/go 60ms/rust 101ms; naive: cpp 2108ms/rust 2074ms SIGKILLed, go 60ms but silent) | +| `34-ns-debugging-map` | 34 | the two independent paths that reach the same container PID 1: `podman exec` from inside the container runtime and a rootless `podman unshare nsenter` from the bare host (plain `nsenter` alone fails EPERM): both confirming `Name: app` and `/proc/1/exe`, beside the real subuid/subgid mapping and a live zero-zombie scan | +| `39-coordinated-omission` | 39 | benchlab's closed loop against what a fixed-rate caller would have seen: one recorded 1057 ns stall sample on top, the same stall backfilled below into the synthetic queued requests `co_correct` adds, showing why raw p99 buries the stall while `co_p99_ns` (always ≥ `p99_ns`) surfaces it | +| `39-benchmark-pipeline` | 39 | benchlab's real path (warmup discard → per-iteration monotonic timing → sort/percentile and the parallel `co_correct` branch → the printed table) beside `--lie`'s one unwarmed wall-clock call straight to `elapsed_ns`: same codec, same fixed workload, two harnesses telling a different story | +| `38-otlp-pipeline` | 38 | lsp-otel's telemetry path: serve's per-request parent span `request` wrapping `work` + `respond` children plus the `requests_total` counter and `request_duration` histogram, through the OTLP/HTTP exporter (batched ~2s, flushed on SIGINT) posting to the OTel collector on :4318, fanned to Tempo (traces) and Prometheus (metrics) and queried back through Grafana's datasource proxy: with cpp/go/rust each tagging service.name=lsp-otel- so the three never collide in the shared stack | +| `37-use-method-checklist` | 37 | loadmix analyze as a pipeline: four one-shot pre-samples (uptime/dmesg/top/ss) then five interval samplers (vmstat/mpstat/iostat/sar/pidstat) spawned concurrently so an N-second checklist costs ~N seconds not 5N, each parsed by column name from its own header row into the 4×3 USE signal matrix (cpu/mem/io/net × Utilization/Saturation/Errors), and the max-Saturation-ratio verdict: with the saturate side shown as a worker pool the concurrent analyze attributes | +| `41-fleet-topology` | 41 | the final project's two-VM fleet: pmon on systems-target and systems-peer each supervising fwatch/sysagent/chatterd (cap-dropped + Landlock-sandboxed), the two chatterds bridged across hosts (from=NICK@node), and both guests exporting OTLP over the libvirt gateway to the host LGTM stack | +| `41-supervise-lifecycle` | 41 | pmon's per-child supervise loop: fork+exec → starting → up → wait-on-child, an unexpected exit looping through restarting (+300ms, attempt++) back to up, and SIGTERM forwarding to all children then pmon: shutdown, with a health tick reading each child's state | +| `40-fastpath-datapath` | 40 | one echo round trip, naive versus fastpath: the naive server's per-message heap buffer and blocking `read(2)` that sleeps through the kernel scheduler (one voluntary context switch per message) against the fastpath server's single reused buffer on a `sched_setaffinity`-pinned core busy-polling `recv(2)` over `EAGAIN`, never entering the scheduler (≈ zero voluntary context switches): the measured 20500-vs-3 contrast that the chapter reads from `/proc//status` | | `36-proc-datasource-map` | 36 | the six /proc + cgroup PSI sources sysagent reads (stat, loadavg, meminfo, diskstats, net/dev, PSI), counters marked apart from gauges, feeding `take_snapshot`'s t0-read / concurrent-reader / sleep / t1-read / delta sequence that turns two cumulative `/proc/stat` reads into one `cpu_util_pct` | | `36-agent-architecture` | 36 | sysagent's `sample`/`serve` subcommands sharing one procfs reader layer, against the row of cross-check tools run at the same moment (vmstat, mpstat, free -m, ss -s, a direct `/proc/meminfo` read, `kill -INT`), with forward references to Chapter 37 (USE method), 38 (OTLP export), and 45 (PCP pmrep) | | `42-host-script-boundary` | 42 | the three host runtimes (C++/sol2, Go/gopher-lua, Rust/mlua) each calling into one shared `policy.lua` with `on_exit(info)`/`decision{action,delay_ms,reason}`, the `host.log`/`host.now_ms` callbacks bound in, the sandbox boundary blocking os/io/package/debug and nilling the loader globals, and the Lua 5.1-vs-5.4 gap that forces the shared subset | @@ -109,5 +109,5 @@ here as you add them: | `54-scheduler-is-a-choice` | 54 | the same 16 fibers under two schedulers, one line apart -- a left column for the default `algo::round_robin` with one per-thread queue where a fiber never leaves the thread that created it, reporting `distinct_tids = 1`, annotated as ch49's concurrent-but-not-parallel cell and noted as a legitimate choice since no migration means no cross-thread synchronisation; and an amber right column for `algo::shared_work` with one shared queue that 4 threads pull from, reporting `distinct_tids = 4`, reaching ch49's concurrent-and-parallel cell at the price of several threads touching your fiber's data; joined by an amber box holding the single `use_scheduling_algorithm` call and the note that in C++ this is yours to write rather than a runtime's to decide, contrasting ch44's Go | | `55-strand-not-a-mutex` | 55 | the same handler and the same 8 threads posted two ways -- an amber `post(strand, handler)` box where an unsynchronized counter reads 2000 of 2000 with `max_inflight = 1` and `overlaps = 0`, beside a dashed ghost `post(io_context, handler)` box where the same counter reads 1862 of 2000 with `max_inflight = 6` and `overlaps = 1492`, a real data race visible as a wrong number, noting that the lost count is UB and is reported rather than gated while the overlap is what `verify.lua` asserts; over a lower band contrasting `std::mutex` which BLOCKS a thread into `futex(FUTEX_WAIT)` at 1022 futex calls for 20,000 increments with an amber strand which DEFERS the handler and returns the thread to the pool at 52 calls for identical work, closing on the observation that a strand costs no lock and no thread but pays in ordering | | `55-topologies-and-gather` | 55 | two Asio facts measured with earlier chapters' instruments -- an upper band of four shapes of `run()` over the same 400 posts (one thread on one context at `distinct_tids = 1` needing no synchronisation, an amber N-threads-one-context at 8 whose handlers need a strand, one context per thread at 4 where each loop owns its fds, and `asio::thread_pool(4)` at 4 with no `run()` call at all), tids from `gettid()` per ch50's instrument and ch49's vocabulary; and a lower amber band showing `asio::write` with a 4-element `const_buffer` array costing one socket write-family syscall (`sendmsg` carrying 4 iovecs) against four separate `asio::write` calls costing four `sendto`, the same 56 bytes either way, reached over an AF_UNIX socketpair so nothing binds a port | -| `56-one-workload-seven-models` | 56 | the capstone comparison -- one workload (8 tasks x 5000 rounds = 40000 folds into one accumulator, shared verbatim by every model) over a dark header recording that all seven produced the identical total `0xb75768f6610642a0`, then three tiers separated by the two uniform instruments: a top band of single-OS-thread models (`sequential`, `coroutine` at ch53, `fiber` at ch54) each at `distinct_tids = 1` and 1 futex call because one thread has nothing to synchronize; a middle band of lock-based models (`pthreads` at 230 futex calls, `std::jthread` at 427, `Boost.Thread` at 451, and a dashed ghost `P2300 senders` at 562 marked NVIDIA stdexec and NOT the stdlib) all at 8 tids; and a lower amber band holding `Boost.Asio`'s strand at 8 tids and 51 futex calls, an amber arrow marking it at an eighth of the row above, serialized without a lock; footnotes name the instruments (`gettid()` from ch50, `strace -f -c -e trace=futex` from ch51) and record that magnitudes move every run and only the three tiers are gated | +| `56-one-workload-seven-models` | 56 | the final-project comparison -- one workload (8 tasks x 5000 rounds = 40000 folds into one accumulator, shared verbatim by every model) over a dark header recording that all seven produced the identical total `0xb75768f6610642a0`, then three tiers separated by the two uniform instruments: a top band of single-OS-thread models (`sequential`, `coroutine` at ch53, `fiber` at ch54) each at `distinct_tids = 1` and 1 futex call because one thread has nothing to synchronize; a middle band of lock-based models (`pthreads` at 230 futex calls, `std::jthread` at 427, `Boost.Thread` at 451, and a dashed ghost `P2300 senders` at 562 marked NVIDIA stdexec and NOT the stdlib) all at 8 tids; and a lower amber band holding `Boost.Asio`'s strand at 8 tids and 51 futex calls, an amber arrow marking it at an eighth of the row above, serialized without a lock; footnotes name the instruments (`gettid()` from ch50, `strace -f -c -e trace=futex` from ch51) and record that magnitudes move every run and only the three tiers are gated | | `56-two-assembled-axes` | 56 | the two axes ch56 assembles rather than measures -- a left band pricing a paused computation with an arrow chain from a thread at 8388608 bytes (ch50, `pthread_getattr_np`) divided by 64 to an amber fiber at 131072 bytes (ch54, `stack_traits::default_size()`) divided by 4096 to a coroutine frame at 32 bytes (ch53, `operator new` in `promise_type`); and a right band of the four cancellation shapes, ch50's `pthread_cancel` as a forced unwind that aborts the process if swallowed without rethrowing, ch51's `stop_token` as a flag with nothing to swallow, ch52's `thread::interrupt()` as an ordinary exception at defined points, and an amber ch55 `cancellation_signal` as a completion carrying `operation_aborted` where the handler still runs exactly once; footnotes state that neither band is measured in ch56 but carried in as named constants beside the instrument that produced them, that cost and capability move in opposite directions, and that P2300 senders are absent from both bands because `__cpp_lib_senders` is still undefined | diff --git a/assets/diagrams/specs/56.py b/assets/diagrams/specs/56.py index f5feef6..9658cd0 100644 --- a/assets/diagrams/specs/56.py +++ b/assets/diagrams/specs/56.py @@ -3,12 +3,12 @@ import generate_diagram as g g.OUT = "assets/diagrams" -# ── Figure 56.1 — one workload, seven models, two uniform instruments ────── +# ── Figure 56.1: one workload, seven models, two uniform instruments ────── bands = [ dict(x=24, y=40, w=1112, h=96, label="ONE workload, shared verbatim by every model (workload.hpp)", fill="#fbfbfb"), - dict(x=24, y=156, w=1112, h=164, label="one OS thread — concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", fill="#f7faf7"), - dict(x=24, y=340, w=1112, h=176, label="many OS threads + a LOCK — a thread that loses the race is parked, and has to be woken", fill="#faf7f7"), - dict(x=24, y=536, w=1112, h=132, label="many OS threads + a STRAND — the handler is deferred, so no thread ever blocks", fill="#fff8ef"), + dict(x=24, y=156, w=1112, h=164, label="one OS thread: concurrent, not parallel (ch49). No lock anywhere, because there is nothing to race with.", fill="#f7faf7"), + dict(x=24, y=340, w=1112, h=176, label="many OS threads + a LOCK: a thread that loses the race is parked, and has to be woken", fill="#faf7f7"), + dict(x=24, y=536, w=1112, h=132, label="many OS threads + a STRAND: the handler is deferred, so no thread ever blocks", fill="#fff8ef"), ] nodes = [ dict(x=180, y=70, w=800, h=54, style="ink", lines=[ @@ -30,20 +30,20 @@ dict(x1=717, y1=496, x2=717, y2=566, amber=True, label="1/8 the futex traffic of the row above", lx=0, ly=-8), ] notes = [ - dict(x=24, y=692, text="Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models — which is the only thing that makes this a comparison rather than a table of quotations."), + dict(x=24, y=692, text="Instrument 1: gettid(), ch50's. Instrument 2: strace -f -c -e trace=futex, ch51's. Both applied identically to all seven models: which is the only thing that makes this a comparison rather than a table of quotations."), dict(x=24, y=710, text="Futex magnitudes move on every run and are never gated; the three TIERS are. Measured on the Fedora 44 reference host, Boost 1.90.0, GCC 16.1.1.", color="#555555"), ] g.emit("56-one-workload-seven-models", 1160, 726, bands, nodes, edges, notes) -# ── Figure 56.2 — the two assembled axes ────────────────────────────────── +# ── Figure 56.2: the two assembled axes ────────────────────────────────── bands2 = [ dict(x=24, y=40, w=540, h=506, label="what a paused computation costs", fill="#fbfbfb"), dict(x=596, y=40, w=540, h=506, label="how cancellation arrives", fill="#fbfbfb"), ] nodes2 = [ - dict(x=64, y=96, w=460, h=92, lines=["thread — 8388608 bytes", "ch50, pthread_getattr_np", "the kernel schedules it, so it costs kernel state"]), - dict(x=64, y=246, w=460, h=92, style="accent", lines=["fiber — 131072 bytes", "ch54, stack_traits::default_size()", "user-scheduled, but it keeps a real stack"]), - dict(x=64, y=396, w=460, h=92, lines=["coroutine frame — 32 bytes", "ch53, operator new in promise_type", "no stack: only what crosses a suspension"]), + dict(x=64, y=96, w=460, h=92, lines=["thread: 8388608 bytes", "ch50, pthread_getattr_np", "the kernel schedules it, so it costs kernel state"]), + dict(x=64, y=246, w=460, h=92, style="accent", lines=["fiber: 131072 bytes", "ch54, stack_traits::default_size()", "user-scheduled, but it keeps a real stack"]), + dict(x=64, y=396, w=460, h=92, lines=["coroutine frame: 32 bytes", "ch53, operator new in promise_type", "no stack: only what crosses a suspension"]), dict(x=636, y=96, w=460, h=92, lines=["ch50 pthread_cancel", "a FORCED UNWIND", "swallow it without rethrowing and the process aborts"]), dict(x=636, y=206, w=460, h=92, lines=["ch51 std::stop_token", "a FLAG the target polls", "nothing is thrown; there is nothing to swallow"]), @@ -55,8 +55,8 @@ dict(x1=294, y1=338, x2=294, y2=394, amber=True, label="divide by 4096", lx=0, ly=-4), ] notes2 = [ - dict(x=24, y=578, text="NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them — the pattern ch54 established."), + dict(x=24, y=578, text="NEITHER band is measured in ch56. Both are assembled from earlier chapters' own measurements, carried into the table arm as named constants beside the instrument that produced them: the pattern ch54 established."), dict(x=24, y=596, text="Cost and capability move together and in opposite directions: the more a paused computation costs, the fewer restrictions there are on where it may pause.", color="#555555"), - dict(x=24, y=614, text="P2300 senders are absent from both bands on purpose: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", color="#555555"), + dict(x=24, y=614, text="P2300 senders are absent from both bands by design: __cpp_lib_senders is still undefined here, so ch56's seventh arm links NVIDIA's reference implementation, not the standard library.", color="#555555"), ] g.emit("56-two-assembled-axes", 1160, 636, bands2, nodes2, edges2, notes2)