diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-30 10:17:11 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-30 10:17:11 +0300 |
| commit | d7ed10ef5f3d819c7232302317c8ba149922b391 (patch) | |
| tree | c4f46f2384758a99e7dd90a47e088d3952cc84e1 | |
| parent | 768e53d90be2d15242266b898023c9c39dacf47d (diff) | |
family: document Misc-vs-IPC boundary rule; keep robust_list in Misc (task 520)
Resolve the get_robust_list/set_robust_list classification decision: keep
both as FamilyMisc rather than promoting them to FamilyIPC alongside the
recently-moved futex_* syscalls.
Rule (now documented in family.go next to the futex IPC block): a syscall
is IPC only if it PERFORMS the actual IPC/sync operation (futex
wait/wake/requeue on the futex word, or an op on an IPC object). Per-thread
registration/bookkeeping that merely hands the kernel a pointer it consults
later -- rseq and get_robust_list/set_robust_list -- stays Misc. man 2
get_robust_list confirms the robust futex list is 'managed in user space:
the kernel knows only about the location of the head'; these syscalls
register/query that per-thread head pointer and never wait/wake or touch
shared memory, structurally identical to rseq. The split axis is
operation-vs-registration, not name similarity.
No classification change, so mage generate is a no-op (generated artifacts
and docs/syscall-tracing-plan.md unchanged). Strengthened the rseq/
robust_list comments in family_test.go and the TestClassifyGetRobustListPidNotFd
lock-in comment in classify_test.go to cite the rule and mark the decision
resolved.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| -rw-r--r-- | internal/generate/classify_test.go | 14 | ||||
| -rw-r--r-- | internal/generate/family.go | 18 | ||||
| -rw-r--r-- | internal/generate/family_test.go | 10 |
3 files changed, 38 insertions, 4 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index 77e19d1..bebf85e 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -2276,10 +2276,16 @@ func TestClassifySchedGetattrPidNotFd(t *testing.T) { // IPC like the futex_* shared-memory primitives (see family.go / family_test.go), // - return classifies as UNCLASSIFIED (0/-1, no byte transfer). // -// NOTE: get_robust_list/set_robust_list are robust-futex bookkeeping and could -// arguably sit with futex_* under IPC; that grouping question is tracked as a -// follow-up rather than changed here, since the syscalls register/query a -// per-thread pointer (like rseq) rather than operating on shared memory. +// FAMILY DECISION (resolved): get_robust_list/set_robust_list stay FamilyMisc and +// are NOT moved to FamilyIPC for "futex consistency". The boundary rule (spelled +// out next to the futex block in family.go) is operation-vs-registration: a +// syscall is IPC only if it PERFORMS the actual IPC/sync operation (futex +// wait/wake/requeue, or an op on an IPC object). These two only register/query +// the per-thread robust-futex list head pointer — per get_robust_list(2) the list +// is "managed in user space: the kernel knows only about the location of the head" +// — and never wait, wake, or touch the shared futex word. That is per-thread +// bookkeeping, structurally identical to rseq, so they share rseq's Misc family. +// The contrast assertion below (futex == IPC) pins both sides of the boundary. func TestClassifyGetRobustListPidNotFd(t *testing.T) { // Field layout mirrors the actual kernel tracepoint format for // sys_enter_get_robust_list: int pid, struct robust_list_head **head_ptr, diff --git a/internal/generate/family.go b/internal/generate/family.go index fd61961..dafbe13 100644 --- a/internal/generate/family.go +++ b/internal/generate/family.go @@ -49,6 +49,24 @@ var syscallFamilies = map[string]SyscallFamily{ // futex_waitv. The futex word is a userspace pointer, so argument capture // is handled by KindFutex (null_event); the family tag only affects // per-family aggregation/reporting. + // + // Boundary rule for the futex/IPC vs Misc split (keep consistent): a + // syscall is IPC only if it PERFORMS the actual IPC/synchronization + // operation — wait/wake/requeue on the futex word, or an operation on an + // IPC object (semaphore, message queue, shared-memory segment, pipe, etc.). + // By contrast, per-thread registration/bookkeeping that merely hands the + // kernel a pointer it consults LATER (at thread exit) is NOT IPC and stays + // in Misc. get_robust_list/set_robust_list fall in the latter camp: per + // get_robust_list(2), the robust futex list is "managed in user space: the + // kernel knows only about the location of the head of the list." They + // register/query that per-thread head pointer; they never wait, wake, or + // touch the shared futex word themselves. That makes them structurally + // identical to rseq (per-thread restartable-sequences area registration), + // so both deliberately fall through to FamilyMisc (they are absent from this + // explicit table by design — see ClassifySyscallFamily's default and the + // rseq/robust_list assertions in family_test.go / classify_test.go). Do not + // promote them to IPC for "futex consistency": the consistent axis is + // operation-vs-registration, not name similarity. "futex": FamilyIPC, "futex_wait": FamilyIPC, "futex_wake": FamilyIPC, "futex_requeue": FamilyIPC, "futex_waitv": FamilyIPC, diff --git a/internal/generate/family_test.go b/internal/generate/family_test.go index 71f0d0d..7302919 100644 --- a/internal/generate/family_test.go +++ b/internal/generate/family_test.go @@ -152,6 +152,16 @@ func TestClassifySyscallFamily(t *testing.T) { // (also Misc). set_tid_address is Process, but rseq is grouped with the // robust-list pair rather than the tid-address syscall; keep this in sync // with the Misc list in docs/syscall-tracing-plan.md. + // + // Boundary rule (see family.go futex block): a syscall is IPC only if it + // PERFORMS the actual IPC/sync operation (futex wait/wake/requeue, or an + // op on an IPC object). set_robust_list/get_robust_list merely register or + // query the per-thread robust-futex list head pointer — "managed in user + // space: the kernel knows only about the location of the head" + // (get_robust_list(2)) — and never wait/wake or touch the shared futex + // word. That is registration/bookkeeping, exactly like rseq, so they stay + // Misc and are NOT promoted to IPC alongside futex_* (asserted as IPC just + // above). The split axis is operation-vs-registration, not name similarity. {"sys_enter_rseq", FamilyMisc}, {"sys_exit_rseq", FamilyMisc}, {"sys_enter_set_robust_list", FamilyMisc}, |
