summaryrefslogtreecommitdiff
path: root/integrationtests
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-30 10:49:46 +0300
committerPaul Buetow <paul@buetow.org>2026-05-30 10:49:46 +0300
commitee3a7106a724dc193589ab652ef21503ba291562 (patch)
tree4d5d0f2b75e085880f7f560de1546337aa2c14ce /integrationtests
parent5e334d33b3ddc3e308455262577c461835939bc7 (diff)
fix(sleep): record sentinel for TIMER_ABSTIME clock_nanosleep (a20)
clock_nanosleep with the TIMER_ABSTIME flag passes an ABSOLUTE wakeup time in the request timespec, not a relative duration. The generated BPF sleep handler computed requested_ns = tv_sec*1e9 + tv_nsec unconditionally, so absolute sleeps exported a bogus multi-decade "sleep duration" in CSV/parquet/stream. generateExtraSleep now carries an optional flags-argument expression per sleep syscall. For clock_nanosleep the generated handler checks args[1] & TIMER_ABSTIME (value 1) and only computes the relative duration when the flag is clear; absolute sleeps keep the existing -1 sentinel (same value used for null/unreadable timespec pointers). nanosleep is always relative and stays unconditional (no flags arg). - Regenerated internal/c/generated_tracepoints.c (mage generate idempotent). - Added codegen tests asserting the TIMER_ABSTIME guard for clock_nanosleep and its absence for nanosleep. - Extended the ioworkload sleep scenario to issue an absolute clock_nanosleep and the sleep parquet integration test to assert it is reported as -1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'integrationtests')
-rw-r--r--integrationtests/sleep_test.go29
1 files changed, 24 insertions, 5 deletions
diff --git a/integrationtests/sleep_test.go b/integrationtests/sleep_test.go
index fbd93a7..d7dbdd5 100644
--- a/integrationtests/sleep_test.go
+++ b/integrationtests/sleep_test.go
@@ -38,8 +38,14 @@ func TestSleepRequestedTimespecInParquet(t *testing.T) {
t.Fatalf("expected parquet rows for workload PID %d", pid)
}
+ // The workload issues, per loop iteration: a relative nanosleep (2ms), a
+ // relative clock_nanosleep (3ms), and an ABSOLUTE clock_nanosleep
+ // (TIMER_ABSTIME) whose request is an absolute CLOCK_MONOTONIC timestamp.
+ // The absolute one must be reported as the -1 sentinel, never as a bogus
+ // multi-decade "sleep duration" (task a20).
var sawNanosleep bool
- var sawClockNanosleep bool
+ var sawClockNanosleepRel bool
+ var sawClockNanosleepAbs bool
for _, row := range rows {
switch row.Syscall {
case "nanosleep":
@@ -50,8 +56,18 @@ func TestSleepRequestedTimespecInParquet(t *testing.T) {
t.Fatalf("nanosleep bytes = %d, want 0", row.Bytes)
}
case "clock_nanosleep":
- if row.RequestedSleepNS == 3_000_000 {
- sawClockNanosleep = true
+ switch row.RequestedSleepNS {
+ case 3_000_000:
+ sawClockNanosleepRel = true
+ case -1:
+ // Absolute (TIMER_ABSTIME) sleep: sentinel, not a duration.
+ sawClockNanosleepAbs = true
+ default:
+ // Any large positive value here means the absolute wakeup
+ // timestamp leaked through as a duration — the bug in a20.
+ if row.RequestedSleepNS > 1_000_000_000 {
+ t.Fatalf("clock_nanosleep RequestedSleepNS = %d looks like an absolute timestamp; TIMER_ABSTIME must record -1", row.RequestedSleepNS)
+ }
}
if row.Bytes != 0 {
t.Fatalf("clock_nanosleep bytes = %d, want 0", row.Bytes)
@@ -62,7 +78,10 @@ func TestSleepRequestedTimespecInParquet(t *testing.T) {
if !sawNanosleep {
t.Fatal("expected nanosleep row with RequestedSleepNS=2000000")
}
- if !sawClockNanosleep {
- t.Fatal("expected clock_nanosleep row with RequestedSleepNS=3000000")
+ if !sawClockNanosleepRel {
+ t.Fatal("expected relative clock_nanosleep row with RequestedSleepNS=3000000")
+ }
+ if !sawClockNanosleepAbs {
+ t.Fatal("expected absolute (TIMER_ABSTIME) clock_nanosleep row with RequestedSleepNS=-1")
}
}