1*2b4b2621SDave Marchevsky // SPDX-License-Identifier: GPL-2.0
2*2b4b2621SDave Marchevsky /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3*2b4b2621SDave Marchevsky 
4*2b4b2621SDave Marchevsky #include "vmlinux.h"
5*2b4b2621SDave Marchevsky #include <bpf/bpf_helpers.h>
6*2b4b2621SDave Marchevsky #include "bpf_misc.h"
7*2b4b2621SDave Marchevsky 
8*2b4b2621SDave Marchevsky struct {
9*2b4b2621SDave Marchevsky 	__uint(type, BPF_MAP_TYPE_TASK_STORAGE);
10*2b4b2621SDave Marchevsky 	__uint(map_flags, BPF_F_NO_PREALLOC);
11*2b4b2621SDave Marchevsky 	__type(key, int);
12*2b4b2621SDave Marchevsky 	__type(value, int);
13*2b4b2621SDave Marchevsky } task_storage SEC(".maps");
14*2b4b2621SDave Marchevsky 
15*2b4b2621SDave Marchevsky long hits;
16*2b4b2621SDave Marchevsky long gp_hits;
17*2b4b2621SDave Marchevsky long gp_times;
18*2b4b2621SDave Marchevsky long current_gp_start;
19*2b4b2621SDave Marchevsky long unexpected;
20*2b4b2621SDave Marchevsky bool postgp_seen;
21*2b4b2621SDave Marchevsky 
22*2b4b2621SDave Marchevsky SEC("fentry/" SYS_PREFIX "sys_getpgid")
get_local(void * ctx)23*2b4b2621SDave Marchevsky int get_local(void *ctx)
24*2b4b2621SDave Marchevsky {
25*2b4b2621SDave Marchevsky 	struct task_struct *task;
26*2b4b2621SDave Marchevsky 	int idx;
27*2b4b2621SDave Marchevsky 	int *s;
28*2b4b2621SDave Marchevsky 
29*2b4b2621SDave Marchevsky 	idx = 0;
30*2b4b2621SDave Marchevsky 	task = bpf_get_current_task_btf();
31*2b4b2621SDave Marchevsky 	s = bpf_task_storage_get(&task_storage, task, &idx,
32*2b4b2621SDave Marchevsky 				 BPF_LOCAL_STORAGE_GET_F_CREATE);
33*2b4b2621SDave Marchevsky 	if (!s)
34*2b4b2621SDave Marchevsky 		return 0;
35*2b4b2621SDave Marchevsky 
36*2b4b2621SDave Marchevsky 	*s = 3;
37*2b4b2621SDave Marchevsky 	bpf_task_storage_delete(&task_storage, task);
38*2b4b2621SDave Marchevsky 	__sync_add_and_fetch(&hits, 1);
39*2b4b2621SDave Marchevsky 	return 0;
40*2b4b2621SDave Marchevsky }
41*2b4b2621SDave Marchevsky 
42*2b4b2621SDave Marchevsky SEC("fentry/rcu_tasks_trace_pregp_step")
pregp_step(struct pt_regs * ctx)43*2b4b2621SDave Marchevsky int pregp_step(struct pt_regs *ctx)
44*2b4b2621SDave Marchevsky {
45*2b4b2621SDave Marchevsky 	current_gp_start = bpf_ktime_get_ns();
46*2b4b2621SDave Marchevsky 	return 0;
47*2b4b2621SDave Marchevsky }
48*2b4b2621SDave Marchevsky 
49*2b4b2621SDave Marchevsky SEC("fentry/rcu_tasks_trace_postgp")
postgp(struct pt_regs * ctx)50*2b4b2621SDave Marchevsky int postgp(struct pt_regs *ctx)
51*2b4b2621SDave Marchevsky {
52*2b4b2621SDave Marchevsky 	if (!current_gp_start && postgp_seen) {
53*2b4b2621SDave Marchevsky 		/* Will only happen if prog tracing rcu_tasks_trace_pregp_step doesn't
54*2b4b2621SDave Marchevsky 		 * execute before this prog
55*2b4b2621SDave Marchevsky 		 */
56*2b4b2621SDave Marchevsky 		__sync_add_and_fetch(&unexpected, 1);
57*2b4b2621SDave Marchevsky 		return 0;
58*2b4b2621SDave Marchevsky 	}
59*2b4b2621SDave Marchevsky 
60*2b4b2621SDave Marchevsky 	__sync_add_and_fetch(&gp_times, bpf_ktime_get_ns() - current_gp_start);
61*2b4b2621SDave Marchevsky 	__sync_add_and_fetch(&gp_hits, 1);
62*2b4b2621SDave Marchevsky 	current_gp_start = 0;
63*2b4b2621SDave Marchevsky 	postgp_seen = true;
64*2b4b2621SDave Marchevsky 	return 0;
65*2b4b2621SDave Marchevsky }
66*2b4b2621SDave Marchevsky 
67*2b4b2621SDave Marchevsky char _license[] SEC("license") = "GPL";
68