On Tue, 3 Sept 2024 at 06:42, Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx> wrote: > > If we look at perf_trace_##call(), with the conditional guard, it looks > like the following. It is not clear to me that code duplication would > be acceptable here. Sure it is. Admittedly, I think it would look a *lot* better off with that macro creating a helper function for the common part, and then just call that helper function in two places. In fact, I think the existing "perf_trace_##call()" function *is* that helper function already, and all it needs is (a) add the traditional double underscore (or "do_") to that function (b) create the wrapper function. IOW, I think the diff would look something like this: --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -15,7 +15,7 @@ #undef DECLARE_EVENT_CLASS #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ static notrace void \ -perf_trace_##call(void *__data, proto) \ +__perf_trace_##call(void *__data, proto) \ { \ struct trace_event_call *event_call = __data; \ struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ @@ -53,6 +53,17 @@ perf_trace_##call(void *__data, proto) \ perf_trace_run_bpf_submit(entry, __entry_size, rctx, \ event_call, __count, __regs, \ head, __task); \ +} \ +static notrace void \ +perf_trace_##call(void *__data, proto) \ +{ \ + if ((tp_flags) & TRACEPOINT_MAY_FAULT) { \ + might_fault(); \ + guard(preempt_notrace)(); \ + __perf_trace_##call(__data, proto); \ + return; \ + } \ + __perf_trace_##call(__data, proto); \ } /* and notice how there is no actual duplicated code on a source level now (although the compiler may obviously do the inlining and duplication - although I think that the tp_flags are always constant, so what actually hopefully happens is that the compiler doesn't duplicate anything at all, and all the conditionals just go away.). NOTE! The above patch is garbage. I did it as a "like this" patch on my current tree, and it doesn't even have the "tp_class" thing at all, so the patch is obviously not functional. It's just meant as a "look, wrapper function". In fact, I think the wrapping might even be done at a higher level (ie maybe the whole "may_fault" shouldn't be an argument at all, but a static part of the define, in case some event classes can take faults and others cannot?) I dunno. I actually think the whole "TRACEPOINT_MAY_FAULT" thing is an incredibly ugly hack, and SHOULD NOT EXIST. In other words - why make these incredibly ugly macros EVEN MORE UGLY - when there is a single use-case and we sure as hell don't want to add any more? IOW - why not get rid of the stupid TRACE_EVENT_FN_MAY_FAULT thing entirely, and do this trivial wrapping in the *one* place that wants it, instead of making it look like some generic thing with an allegedly generic test, when it is anything but generic, and is in fact just a single special case for system call. Yes, I know. Computer Science classes say that "generic programming is good". Those CS classes are garbage. You want to make your code as specialized as humanly possible, and *not* make some complicated "this handles all cases" code that is complicated and fragile. Linus