summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-30 10:17:11 +0300
committerPaul Buetow <paul@buetow.org>2026-05-30 10:17:11 +0300
commitd7ed10ef5f3d819c7232302317c8ba149922b391 (patch)
treec4f46f2384758a99e7dd90a47e088d3952cc84e1
parent768e53d90be2d15242266b898023c9c39dacf47d (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.go14
-rw-r--r--internal/generate/family.go18
-rw-r--r--internal/generate/family_test.go10
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},