[RFC 1/8] trace: correct handling of recursive call

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Sun Dec 21 02:58:52 CET 2025


__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 <patrick.rudolph at 9elements.com>
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
---
 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



More information about the U-Boot mailing list