#include <subcmd/parse-options.h>
 #include "../builtin.h"
 #include "bench.h"
+#include <linux/compiler.h>
 #include <linux/time64.h>
 
 #include <inttypes.h>
 enum bench_uprobe {
         BENCH_UPROBE__BASELINE,
         BENCH_UPROBE__EMPTY,
+        BENCH_UPROBE__TRACE_PRINTK,
 };
 
 static const struct option options[] = {
 #ifdef HAVE_BPF_SKEL
 #include "bpf_skel/bench_uprobe.skel.h"
 
+#define bench_uprobe__attach_uprobe(prog) \
+       skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \
+                                                          /*pid=*/-1, \
+                                                          /*binary_path=*/"/lib64/libc.so.6", \
+                                                          /*func_offset=*/0, \
+                                                          /*opts=*/&uprobe_opts); \
+       if (!skel->links.prog) { \
+               err = -errno; \
+               fprintf(stderr, "Failed to attach bench uprobe \"%s\": %s\n", #prog, strerror(errno)); \
+               goto cleanup; \
+       }
+
 struct bench_uprobe_bpf *skel;
 
-static int bench_uprobe__setup_bpf_skel(void)
+static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench)
 {
        DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
        int err;
        }
 
        uprobe_opts.func_name = "usleep";
-       skel->links.empty = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.empty,
-                                                           /*pid=*/-1,
-                                                           /*binary_path=*/"/lib64/libc.so.6",
-                                                           /*func_offset=*/0,
-                                                           /*opts=*/&uprobe_opts);
-       if (!skel->links.empty) {
-               err = -errno;
-               fprintf(stderr, "Failed to attach bench uprobe: %s\n", strerror(errno));
+       switch (bench) {
+       case BENCH_UPROBE__BASELINE:                                                    break;
+       case BENCH_UPROBE__EMPTY:        bench_uprobe__attach_uprobe(empty);            break;
+       case BENCH_UPROBE__TRACE_PRINTK: bench_uprobe__attach_uprobe(trace_printk);     break;
+       default:
+               fprintf(stderr, "Invalid bench: %d\n", bench);
                goto cleanup;
        }
 
        }
 }
 #else
-static int bench_uprobe__setup_bpf_skel(void) { return 0; }
+static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench __maybe_unused) { return 0; }
 static void bench_uprobe__teardown_bpf_skel(void) {};
 #endif
 
 
        argc = parse_options(argc, argv, options, bench_uprobe_usage, 0);
 
-       if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel() < 0)
+       if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel(bench) < 0)
                return 0;
 
         clock_gettime(CLOCK_REALTIME, &start);
 {
        return bench_uprobe(argc, argv, BENCH_UPROBE__EMPTY);
 }
+
+int bench_uprobe_trace_printk(int argc, const char **argv)
+{
+       return bench_uprobe(argc, argv, BENCH_UPROBE__TRACE_PRINTK);
+}
 
 static struct bench uprobe_benchmarks[] = {
        { "baseline",   "Baseline libc usleep(1000) call",                              bench_uprobe_baseline,  },
        { "empty",      "Attach empty BPF prog to uprobe on usleep, system wide",       bench_uprobe_empty,     },
+       { "trace_printk", "Attach trace_printk BPF prog to uprobe on usleep syswide",   bench_uprobe_trace_printk,      },
        { NULL, NULL, NULL },
 };