@@ -4110,30 +4110,18 @@ void cleanup_bpf_maps(void) {
41104110 let load_function = generate_load_function_with_tail_calls base_name all_usage tail_call_analysis all_setup_code kfunc_dependencies (Ir. get_global_variables ir_multi_prog) in
41114111
41124112 (* Global attachment storage (generated when attach/detach/perf attach/perf read are used) *)
4113- let attachment_storage = if all_usage.uses_attach || all_usage.uses_detach || all_usage. uses_attach_perf || all_usage.uses_perf_read then
4114- { |// Global attachment storage for tracking active program attachments
4115- typedef struct PerfAttachment {
4113+ let uses_perf_state = all_usage.uses_attach_perf || all_usage.uses_perf_read in
4114+ let perf_typedef = if uses_perf_state then
4115+ { | typedef struct PerfAttachment {
41164116 int perf_fd;
41174117 int link_id;
41184118 int prog_fd;
41194119 uint64_t generation;
41204120} PerfAttachment ;
4121-
4122- struct attachment_entry {
4123- int attachment_id;
4124- int prog_fd;
4125- char target[128 ];
4126- uint32_t flags;
4127- struct bpf_link * link; // For kprobe/ tracepoint programs (NULL for XDP )
4128- int ifindex; // For XDP programs (0 for kprobe/ tracepoint)
4129- int perf_fd; // For perf_event programs (- 1 otherwise)
4130- int detaching; // Non - zero while teardown is in progress
4131- uint64_t generation; // PerfAttachment stale- handle token
4132- enum bpf_prog_type type ;
4133- struct attachment_entry * next;
4134- };
4135-
4136- struct perf_attachment_state {
4121+ | }
4122+ else " " in
4123+ let perf_state_decls = if uses_perf_state then
4124+ {| struct perf_attachment_state {
41374125 _Atomic uint64_t generation;
41384126 _Atomic int perf_fd;
41394127 _Atomic unsigned int readers;
@@ -4151,13 +4139,12 @@ typedef struct PerfAttachment {
41514139 #define KS_PERF_STATE_CHUNK_MASK (KS_PERF_STATE_CHUNK_SIZE - 1 u)
41524140 #define KS_PERF_STATE_MAX_CHUNKS 4096 u
41534141
4154- static struct attachment_entry *attached_programs = NULL ;
41554142 static _Atomic (struct perf_attachment_state *) perf_state_chunks [KS_PERF_STATE_MAX_CHUNKS];
4156- static pthread_mutex_t attachment_mutex = PTHREAD_MUTEX_INITIALIZER ;
4157- static int next_attachment_id = 1 ;
41584143 static uint64_t next_perf_attachment_generation = 1 ;
4159-
4160- static struct perf_attachment_state * perf_state_slot_lookup(int perf_fd) {
4144+ | }
4145+ else " " in
4146+ let perf_helpers = if uses_perf_state then
4147+ {| static struct perf_attachment_state * perf_state_slot_lookup(int perf_fd) {
41614148 if (perf_fd < 0 ) {
41624149 return NULL ;
41634150 }
@@ -4254,7 +4241,60 @@ typedef struct PerfAttachment {
42544241 static void perf_attachment_end_read(struct perf_attachment_state *state) {
42554242 atomic_fetch_sub_explicit(&state->readers, 1, memory_order_release);
42564243 }
4244+ |}
4245+ else "" in
4246+ let add_attachment_perf_branch = if uses_perf_state then
4247+ {| if (type == BPF_PROG_TYPE_PERF_EVENT && perf_fd >= 0) {
4248+ struct perf_attachment_state *state = ensure_perf_attachment_state_locked(perf_fd);
4249+ if (!state) {
4250+ pthread_mutex_unlock(&attachment_mutex);
4251+ free(entry);
4252+ return -1;
4253+ }
4254+ entry->generation = next_perf_attachment_generation++;
4255+ if (next_perf_attachment_generation == 0) {
4256+ next_perf_attachment_generation = 1;
4257+ }
4258+ atomic_store_explicit(&state->perf_fd, perf_fd, memory_order_release);
4259+ atomic_store_explicit(&state->generation, entry->generation, memory_order_release);
4260+ }
4261+ |}
4262+ else "" in
4263+ let perf_find_by_id = if uses_perf_state then
4264+ {| static struct attachment_entry *find_attachment_by_id_locked(int attachment_id) {
4265+ struct attachment_entry *entry = attached_programs;
4266+ while (entry) {
4267+ if (entry->attachment_id == attachment_id) {
4268+ return entry;
4269+ }
4270+ entry = entry->next;
4271+ }
4272+ return NULL;
4273+ }
4274+ |}
4275+ else "" in
4276+ let attachment_storage = if all_usage.uses_attach || all_usage.uses_detach || uses_perf_state then
4277+ sprintf {|// Global attachment storage for tracking active program attachments
4278+ %s
4279+ struct attachment_entry {
4280+ int attachment_id;
4281+ int prog_fd;
4282+ char target[128];
4283+ uint32_t flags;
4284+ struct bpf_link *link; // For kprobe/tracepoint programs (NULL for XDP)
4285+ int ifindex; // For XDP programs (0 for kprobe/tracepoint)
4286+ int perf_fd; // For perf_event programs (-1 otherwise)
4287+ int detaching; // Non-zero while teardown is in progress
4288+ uint64_t generation; // PerfAttachment stale-handle token
4289+ enum bpf_prog_type type;
4290+ struct attachment_entry *next;
4291+ };
42574292
4293+ %s static struct attachment_entry *attached_programs = NULL;
4294+ static pthread_mutex_t attachment_mutex = PTHREAD_MUTEX_INITIALIZER;
4295+ static int next_attachment_id = 1;
4296+
4297+ %s
42584298 // Helper function to add attachment entry.
42594299 // Duplicate check is performed atomically under the same lock as insertion.
42604300 static int add_attachment(int prog_fd, const char *target, uint32_t flags,
@@ -4266,7 +4306,7 @@ typedef struct PerfAttachment {
42664306 fprintf(stderr, "Failed to allocate memory for attachment entry\n");
42674307 return -1;
42684308 }
4269-
4309+
42704310 entry->prog_fd = prog_fd;
42714311 entry->attachment_id = 0;
42724312 strncpy(entry->target, target, sizeof(entry->target) - 1);
@@ -4276,7 +4316,7 @@ typedef struct PerfAttachment {
42764316 entry->ifindex = ifindex;
42774317 entry->perf_fd = perf_fd;
42784318 entry->type = type;
4279-
4319+
42804320 entry->detaching = 0;
42814321 entry->generation = 0;
42824322 pthread_mutex_lock(&attachment_mutex);
@@ -4290,27 +4330,13 @@ typedef struct PerfAttachment {
42904330 !existing->detaching) {
42914331 pthread_mutex_unlock(&attachment_mutex);
42924332 free(entry);
4293- fprintf(stderr, "Program with fd %d is already attached. Use detach() first.\n", prog_fd);
4333+ fprintf(stderr, "Program with fd %% d is already attached. Use detach() first.\n", prog_fd);
42944334 return -1;
42954335 }
42964336 existing = existing->next;
42974337 }
42984338 entry->attachment_id = next_attachment_id++;
4299- if (type == BPF_PROG_TYPE_PERF_EVENT && perf_fd >= 0) {
4300- struct perf_attachment_state *state = ensure_perf_attachment_state_locked(perf_fd);
4301- if (!state) {
4302- pthread_mutex_unlock(&attachment_mutex);
4303- free(entry);
4304- return -1;
4305- }
4306- entry->generation = next_perf_attachment_generation++;
4307- if (next_perf_attachment_generation == 0) {
4308- next_perf_attachment_generation = 1;
4309- }
4310- atomic_store_explicit(&state->perf_fd, perf_fd, memory_order_release);
4311- atomic_store_explicit(&state->generation, entry->generation, memory_order_release);
4312- }
4313- entry->next = attached_programs;
4339+ %s entry->next = attached_programs;
43144340 attached_programs = entry;
43154341 if (attachment_id_out) {
43164342 *attachment_id_out = entry->attachment_id;
@@ -4319,21 +4345,11 @@ typedef struct PerfAttachment {
43194345 *generation_out = entry->generation;
43204346 }
43214347 pthread_mutex_unlock(&attachment_mutex);
4322-
4323- return 0;
4324- }
43254348
4326- static struct attachment_entry *find_attachment_by_id_locked(int attachment_id) {
4327- struct attachment_entry *entry = attached_programs;
4328- while (entry) {
4329- if (entry->attachment_id == attachment_id) {
4330- return entry;
4331- }
4332- entry = entry->next;
4333- }
4334- return NULL;
4349+ return 0;
43354350 }
43364351
4352+ %s
43374353 /* Helper: find the bpf_program in the skeleton object for a given fd.
43384354 * Returns NULL if the skeleton is not loaded or no program matches. */
43394355 static struct bpf_program *find_prog_by_fd(int prog_fd) {
@@ -4346,7 +4362,7 @@ typedef struct PerfAttachment {
43464362 }
43474363 return NULL;
43484364 }
4349- |}
4365+ |} perf_typedef perf_state_decls perf_helpers add_attachment_perf_branch perf_find_by_id
43504366 else "" in
43514367
43524368 let attach_function = if all_usage.uses_attach then
@@ -4556,7 +4572,10 @@ typedef struct PerfAttachment {
45564572 break;
45574573 }|}
45584574 else "" in
4559- let detach_function = if all_usage.uses_detach || all_usage.uses_attach_perf then
4575+ let invalidate_call_line = if uses_perf_state then
4576+ " invalidate_perf_attachment_state_locked(entry);\n"
4577+ else "" in
4578+ let detach_entry_dispatch = if all_usage.uses_detach || all_usage.uses_attach_perf then
45604579 sprintf {|static void ks_detach_attachment_entry(struct attachment_entry *entry, int identifier_for_logs) {
45614580 if (!entry) {
45624581 return;
@@ -4613,9 +4632,10 @@ typedef struct PerfAttachment {
46134632 fprintf(stderr, "Unsupported program type for detachment: %%d\n", entry->type);
46144633 break;
46154634 }
4616- }
4617-
4618- void detach_bpf_program_by_fd(int prog_fd) {
4635+ }|} detach_perf_case
4636+ else "" in
4637+ let std_detach_function = if all_usage.uses_detach then
4638+ sprintf {|void detach_bpf_program_by_fd(int prog_fd) {
46194639 if (prog_fd < 0) {
46204640 fprintf(stderr, "Invalid program file descriptor: %%d\n", prog_fd);
46214641 return;
@@ -4629,8 +4649,7 @@ void detach_bpf_program_by_fd(int prog_fd) {
46294649 while (entry) {
46304650 if (entry->prog_fd == prog_fd && !entry->detaching) {
46314651 entry->detaching = 1;
4632- invalidate_perf_attachment_state_locked(entry);
4633- break;
4652+ %s break;
46344653 }
46354654 entry = entry->next;
46364655 }
@@ -4655,11 +4674,12 @@ void detach_bpf_program_by_fd(int prog_fd) {
46554674 pthread_mutex_unlock(&attachment_mutex);
46564675 free(entry);
46574676 }
4658- }
4659-
4660- void ks_detach_perf_attachment(PerfAttachment attachment) {
4677+ }|} invalidate_call_line
4678+ else "" in
4679+ let perf_detach_function = if all_usage.uses_attach_perf then
4680+ {|void ks_detach_perf_attachment(PerfAttachment attachment) {
46614681 if (attachment.link_id <= 0) {
4662- fprintf(stderr, "Invalid perf attachment link id: %% d\n", attachment.link_id);
4682+ fprintf(stderr, "Invalid perf attachment link id: %d\n", attachment.link_id);
46634683 return;
46644684 }
46654685
@@ -4674,7 +4694,7 @@ void ks_detach_perf_attachment(PerfAttachment attachment) {
46744694 pthread_mutex_unlock(&attachment_mutex);
46754695
46764696 if (!entry) {
4677- fprintf(stderr, "No active perf attachment found for link id %% d\n", attachment.link_id);
4697+ fprintf(stderr, "No active perf attachment found for link id %d\n", attachment.link_id);
46784698 return;
46794699 }
46804700
@@ -4691,8 +4711,13 @@ void ks_detach_perf_attachment(PerfAttachment attachment) {
46914711 }
46924712 pthread_mutex_unlock(&attachment_mutex);
46934713 free(entry);
4694- }|} detach_perf_case
4714+ }|}
46954715 else "" in
4716+ let detach_function =
4717+ [detach_entry_dispatch; std_detach_function; perf_detach_function]
4718+ |> List.filter (fun s -> s <> "")
4719+ |> String.concat "\n\n"
4720+ in
46964721
46974722 let bpf_obj_decl = "" in (* Skeleton now handles the BPF object *)
46984723
0 commit comments