__cyg_profile_func_enter() adds timer information to function traces.

Commit 852d4dbd70ba ("trace: Detect an infinite loop") introduced a logic
letting any recursive call to __cyg_profile_func_enter() deactivate
tracing.

This implies that a lot of the DM core and timer drivers functions need to
be marked as `notrace`. This in not desirable as those functions are part
of what we want to trace when not invoked by __cyg_profile_func_enter().

A better approach than switching of tracing is to immediately leave
__cyg_profile_func_enter() when reentered.

Reported-by: Patrick Rudolph <[email protected]>
Signed-off-by: Heinrich Schuchardt <[email protected]>
---
 lib/trace.c | 59 ++++++++++++++++++++++++-----------------------------
 1 file changed, 27 insertions(+), 32 deletions(-)

diff --git a/lib/trace.c b/lib/trace.c
index 3d54dfaddc0..2dea8fc85f2 100644
--- a/lib/trace.c
+++ b/lib/trace.c
@@ -131,32 +131,26 @@ static void notrace add_ftrace(void *func_ptr, void 
*caller, ulong flags)
  */
 void notrace __cyg_profile_func_enter(void *func_ptr, void *caller)
 {
-       if (trace_enabled) {
-               int func;
-
-               if (hdr->trace_locked) {
-                       trace_enabled = 0;
-                       puts("trace: recursion detected, disabling\n");
-                       hdr->trace_locked = false;
-                       return;
-               }
+       int func;
 
-               hdr->trace_locked = true;
-               trace_swap_gd();
-               add_ftrace(func_ptr, caller, FUNCF_ENTRY);
-               func = func_ptr_to_num(func_ptr);
-               if (func < hdr->func_count) {
-                       hdr->call_accum[func]++;
-                       hdr->call_count++;
-               } else {
-                       hdr->untracked_count++;
-               }
-               hdr->depth++;
-               if (hdr->depth > hdr->max_depth)
-                       hdr->max_depth = hdr->depth;
-               trace_swap_gd();
-               hdr->trace_locked = false;
+       if (!trace_enabled || hdr->trace_locked)
+               return;
+
+       hdr->trace_locked = true;
+       trace_swap_gd();
+       add_ftrace(func_ptr, caller, FUNCF_ENTRY);
+       func = func_ptr_to_num(func_ptr);
+       if (func < hdr->func_count) {
+               hdr->call_accum[func]++;
+               hdr->call_count++;
+       } else {
+               hdr->untracked_count++;
        }
+       hdr->depth++;
+       if (hdr->depth > hdr->max_depth)
+               hdr->max_depth = hdr->depth;
+       trace_swap_gd();
+       hdr->trace_locked = false;
 }
 
 /**
@@ -167,14 +161,15 @@ void notrace __cyg_profile_func_enter(void *func_ptr, 
void *caller)
  */
 void notrace __cyg_profile_func_exit(void *func_ptr, void *caller)
 {
-       if (trace_enabled) {
-               trace_swap_gd();
-               hdr->depth--;
-               add_ftrace(func_ptr, caller, FUNCF_EXIT);
-               if (hdr->depth < hdr->min_depth)
-                       hdr->min_depth = hdr->depth;
-               trace_swap_gd();
-       }
+       if (!trace_enabled || hdr->trace_locked)
+               return;
+
+       trace_swap_gd();
+       hdr->depth--;
+       add_ftrace(func_ptr, caller, FUNCF_EXIT);
+       if (hdr->depth < hdr->min_depth)
+               hdr->min_depth = hdr->depth;
+       trace_swap_gd();
 }
 
 /**
-- 
2.51.0

Reply via email to