FastLED 3.9.15
Loading...
Searching...
No Matches
trace.cpp.hpp
Go to the documentation of this file.
1
8
9#include "fl/system/trace.h"
10
11#include "fl/stl/vector.h"
12#include "fl/stl/string.h"
13#include "fl/stl/chrono.h"
14#include "fl/log/log.h"
15#include "fl/stl/singleton.h"
16#include "fl/stl/stdio.h"
17#include "fl/stl/noexcept.h"
18
19// Configuration: Maximum stack depth (can be overridden at compile time)
20#ifndef FL_STACK_TRACE_MAX_DEPTH
21#define FL_STACK_TRACE_MAX_DEPTH 32
22#endif
23
24namespace fl {
25
27struct TraceEntry {
28 const char* function;
29 int line;
30
31 TraceEntry() FL_NOEXCEPT : function(nullptr), line(0) {}
32 TraceEntry(const char* f, int l) FL_NOEXCEPT : function(f), line(l) {}
33};
34
38 // Call stack storage using FixedVector for bounds checking
40
41 // Separate depth counter to track actual stack depth (can exceed capacity)
42 // This allows us to detect overflow conditions without corrupting the stack
43 fl::size stackDepth = 0;
44};
45
46// Thread-local storage for trace data
47// When trace functions are not used, the optimizer can eliminate this entirely
51
52// ScopedTrace static method implementations
53void ScopedTrace::push(const char* function, int line) FL_NOEXCEPT {
54 if (!function) {
55 return; // Ignore null function names
56 }
57
58 auto& storage = getTraceStorage();
59
60 // Always increment depth counter (tracks true depth even on overflow)
61 storage.stackDepth++;
62
63 // Only push to storage if we have capacity
64 if (storage.callStack.size() < FL_STACK_TRACE_MAX_DEPTH) {
65 storage.callStack.push_back(TraceEntry(function, line));
66 }
67 // If size >= MAX_DEPTH, we're in overflow - just track depth
68}
69
71 auto& storage = getTraceStorage();
72
73 // Guard against underflow
74 if (storage.stackDepth == 0) {
75 return;
76 }
77
78 // Decrement depth counter first
79 storage.stackDepth--;
80
81 // Pop from callStack only if:
82 // 1. We have entries in the stack
83 // 2. After decrement, depth matches or is less than callStack size
84 // (this handles both normal operation and overflow recovery)
85 if (!storage.callStack.empty() && storage.stackDepth < storage.callStack.size()) {
86 // Use manual pop since FixedVector doesn't have pop_back
87 storage.callStack.resize(storage.callStack.size() - 1);
88 }
89}
90
94
96 auto& storage = getTraceStorage();
97 fl::string result = "Stack trace (depth ";
98
99 char depth_str[32];
100 fl::sprintf(depth_str, "%zu", (size_t)storage.stackDepth);
101 result += depth_str;
102 result += "):\n";
103
104 if (storage.callStack.empty()) {
105 result += " <empty>\n";
106 return result;
107 }
108
109 // Show overflow warning if depth exceeds capacity
110 if (storage.stackDepth > FL_STACK_TRACE_MAX_DEPTH) {
111 result += " <WARNING: Stack overflow - showing last ";
112 char max_str[32];
114 result += max_str;
115 result += " of ";
116 result += depth_str;
117 result += " entries>\n";
118 }
119
120 // Dump all stored entries in format: functionName(lineNo)
121 for (fl::size i = 0; i < storage.callStack.size(); ++i) {
122 const auto& entry = storage.callStack[i];
123 char line_buf[256];
124 if (entry.line > 0) {
125 fl::sprintf(line_buf, " [%zu] %s(%d)\n", (size_t)i, entry.function, entry.line);
126 } else {
127 fl::sprintf(line_buf, " [%zu] %s\n", (size_t)i, entry.function);
128 }
129 result += line_buf;
130 }
131
132 return result;
133}
134
136 if (!out) {
137 return;
138 }
139
140 auto& storage = getTraceStorage();
141 out->clear();
142
143 // Copy all stored entries to the output vector as TracePoints
144 for (fl::size i = 0; i < storage.callStack.size(); ++i) {
145 const auto& entry = storage.callStack[i];
146 // TracePoint is tuple<const char*, int, fl::u32> (file, line, timestamp)
147 // Since we don't store file or timestamp, we'll use the function name and line
148 out->push_back(fl::make_tuple(entry.function, entry.line, fl::u32(0)));
149 }
150}
151
153 auto& storage = getTraceStorage();
154 storage.callStack.resize(0);
155 storage.stackDepth = 0;
156}
157
158// ScopedTrace RAII implementation
160 push(function, line);
161}
162
166
167} // namespace fl
FastLED chrono implementation - duration types for time measurements.
static void push(const char *function, int line) FL_NOEXCEPT
Push a function name onto the call stack.
Definition trace.cpp.hpp:53
static void pop() FL_NOEXCEPT
Pop the most recent function from the call stack.
Definition trace.cpp.hpp:70
ScopedTrace(const char *function, int line) FL_NOEXCEPT
Construct and push function name onto stack.
static void clear() FL_NOEXCEPT
Clear the entire call stack (primarily for testing)
static fl::size depth() FL_NOEXCEPT
Get the current stack depth.
Definition trace.cpp.hpp:91
~ScopedTrace() FL_NOEXCEPT
Destructor - automatically pops from stack.
static fl::string dump() FL_NOEXCEPT
Dump the current call stack to a string.
Definition trace.cpp.hpp:95
static T & instance() FL_NOEXCEPT
Definition singleton.h:133
Centralized logging categories for FastLED hardware interfaces and subsystems.
static TraceStorage & getTraceStorage() FL_NOEXCEPT
Definition trace.cpp.hpp:48
int sprintf(char(&buffer)[N], const char *format, const Args &... args) FL_NOEXCEPT
Sprintf-like formatting function that writes to a buffer.
Definition stdio.h:712
tuple< typename fl::decay< Ts >::type... > make_tuple(Ts &&... args) FL_NOEXCEPT
Definition tuple.h:104
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
Base definition for an LED controller.
Definition crgb.hpp:179
FixedVector< TraceEntry, FL_STACK_TRACE_MAX_DEPTH > callStack
Definition trace.cpp.hpp:39
fl::size stackDepth
Definition trace.cpp.hpp:43
Internal storage for the trace system Encapsulates call stack and depth tracking per-thread.
Definition trace.cpp.hpp:37
#define FL_NOEXCEPT
TraceEntry() FL_NOEXCEPT
Definition trace.cpp.hpp:31
int line
Definition trace.cpp.hpp:29
const char * function
Definition trace.cpp.hpp:28
TraceEntry(const char *f, int l) FL_NOEXCEPT
Definition trace.cpp.hpp:32
A single stack trace entry with location information.
Definition trace.cpp.hpp:27
#define FL_STACK_TRACE_MAX_DEPTH
Definition trace.cpp.hpp:21