Skip to content

Commit 8e26fd2

Browse files
committed
sched_process_free stuff
1 parent 1d0d1b4 commit 8e26fd2

5 files changed

Lines changed: 57 additions & 12 deletions

File tree

support/ebpf/sched_monitor.ebpf.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,25 @@
77
#include "types.h"
88

99
// See /sys/kernel/debug/tracing/events/sched/sched_process_free/format
10-
// for struct layout.
11-
struct sched_process_free_ctx {
10+
// for struct layout. This is pre-6.16 format which uses a fixed-size
11+
// (TASK_COMM_LEN) array for comm.
12+
struct sched_process_free_ctx_pre616 {
1213
unsigned char skip[24];
1314
pid_t pid;
1415
int prio;
1516
};
1617

17-
// tracepoint__sched_process_free is a tracepoint attached to the scheduler that frees processes.
18-
// Every time a processes exits this hook is triggered.
19-
SEC("tracepoint/sched/sched_process_free")
20-
int tracepoint__sched_process_free(struct sched_process_free_ctx *ctx)
21-
{
22-
u32 pid = ctx->pid;
18+
// This is the newer kernel version 6.16+ format.
19+
// The change was introduced upstream with
20+
// https://github.com/torvalds/linux/commit/155fd6c3e2f02efdc71a9b62888942efc217aff0
21+
struct sched_process_free_ctx {
22+
unsigned char skip[12];
23+
pid_t pid;
24+
int prio;
25+
};
2326

27+
static EBPF_INLINE int do_process_free(void *ctx, u32 pid)
28+
{
2429
if (!bpf_map_lookup_elem(&reported_pids, &pid) && !pid_information_exists(pid)) {
2530
// Only report PIDs that we explicitly track. This avoids sending kernel worker PIDs
2631
// to userspace.
@@ -33,3 +38,17 @@ int tracepoint__sched_process_free(struct sched_process_free_ctx *ctx)
3338
exit:
3439
return 0;
3540
}
41+
42+
// tracepoint__sched_process_free is a tracepoint attached to the scheduler that frees processes.
43+
// Every time a processes exits this hook is triggered.
44+
SEC("tracepoint/sched/sched_process_free/v2")
45+
int tracepoint__sched_process_free(struct sched_process_free_ctx *ctx)
46+
{
47+
return do_process_free(ctx, ctx->pid);
48+
}
49+
50+
SEC("tracepoint/sched/sched_process_free/v1")
51+
int tracepoint__sched_process_free_pre616(struct sched_process_free_ctx_pre616 *ctx)
52+
{
53+
return do_process_free(ctx, ctx->pid);
54+
}

support/ebpf/tracer.ebpf.amd64

5.47 KB
Binary file not shown.

support/ebpf/tracer.ebpf.arm64

5.45 KB
Binary file not shown.

tracer/tracepoints.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ func (t *Tracer) AttachSchedMonitor() error {
3434
if err != nil {
3535
return fmt.Errorf("failed to adjust rlimit: %v", err)
3636
}
37-
defer restoreRlimit()
3837

39-
prog := t.ebpfProgs["tracepoint__sched_process_free"]
40-
return t.attachToTracepoint("sched", "sched_process_free", prog)
38+
defer restoreRlimit()
39+
name := schedProcessFreeHookName(libpf.MapKeysToSet(t.ebpfProgs))
40+
return t.attachToTracepoint("sched", "sched_process_free", t.ebpfProgs[name])
4141
}

tracer/tracer.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ const (
5555
probProfilingDisable = -1
5656
)
5757

58+
// Names of tracepoint hooks for sched_process_free. There are two hooks
59+
// as the tracepoint format has changed for kernel versions 6.16+.
60+
const (
61+
schedProcessFreeV1 = "tracepoint__sched_process_free_pre616"
62+
schedProcessFreeV2 = "tracepoint__sched_process_free"
63+
)
64+
5865
// Intervals is a subset of config.IntervalsAndTimers.
5966
type Intervals interface {
6067
MonitorInterval() time.Duration
@@ -171,6 +178,16 @@ type progLoaderHelper struct {
171178
noTailCallTarget bool
172179
}
173180

181+
// schedProcessFreeHookName returns the name of the tracepoint hook to use.
182+
// This function requires that only one of (schedProcessFreeV1, schedProcessFreeV2)
183+
// be present in progNames.
184+
func schedProcessFreeHookName(progNames libpf.Set[string]) string {
185+
if _, ok := progNames[schedProcessFreeV1]; ok {
186+
return schedProcessFreeV1
187+
}
188+
return schedProcessFreeV2
189+
}
190+
174191
// NewTracer loads eBPF code and map definitions from the ELF module at the configured path.
175192
func NewTracer(ctx context.Context, cfg *Config) (*Tracer, error) {
176193
kernelSymbolizer, err := kallsyms.NewSymbolizer()
@@ -290,6 +307,13 @@ func initializeMapsAndPrograms(kmod *kallsyms.Module, cfg *Config) (ebpfMaps map
290307
return nil, nil, nil, fmt.Errorf("failed to load specification for tracers: %v", err)
291308
}
292309

310+
if major > 6 || (major == 6 && minor >= 16) {
311+
// Tracepoint format for sched_process_free has changed in v6.16+.
312+
delete(coll.Programs, schedProcessFreeV1)
313+
} else {
314+
delete(coll.Programs, schedProcessFreeV2)
315+
}
316+
293317
if cfg.VerboseMode {
294318
if err = coll.Variables["with_debug_output"].Set(uint32(1)); err != nil {
295319
return nil, nil, nil, fmt.Errorf("failed to set debug output: %v", err)
@@ -546,9 +570,11 @@ func loadPerfUnwinders(coll *cebpf.CollectionSpec, ebpfProgs map[string]*cebpf.P
546570

547571
progs := make([]progLoaderHelper, len(tailCallProgs)+2)
548572
copy(progs, tailCallProgs)
573+
574+
schedProcessFree := schedProcessFreeHookName(libpf.MapKeysToSet(coll.Programs))
549575
progs = append(progs,
550576
progLoaderHelper{
551-
name: "tracepoint__sched_process_free",
577+
name: schedProcessFree,
552578
noTailCallTarget: true,
553579
enable: true,
554580
},

0 commit comments

Comments
 (0)