1 /*
2 * Percepio Trace Recorder for Tracealyzer v4.6.6
3 * Copyright 2021 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation for the stack monitor.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
16
17 #if (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0))
18
19 typedef struct TraceStackMonitorEntry
20 {
21 void *pvTask;
22 TraceUnsignedBaseType_t uxPreviousLowWaterMark;
23 } TraceStackMonitorEntry_t;
24
25 typedef struct TraceStackMonitor
26 {
27 TraceStackMonitorEntry_t xEntries[TRC_CFG_STACK_MONITOR_MAX_TASKS];
28
29 uint32_t uiEntryCount;
30 } TraceStackMonitor_t;
31
32 static TraceStackMonitor_t* pxStackMonitor;
33
xTraceStackMonitorInitialize(TraceStackMonitorBuffer_t * pxBuffer)34 traceResult xTraceStackMonitorInitialize(TraceStackMonitorBuffer_t *pxBuffer)
35 {
36 uint32_t i;
37
38 TRC_ASSERT_EQUAL_SIZE(TraceStackMonitorBuffer_t, TraceStackMonitor_t);
39
40 /* This should never fail */
41 TRC_ASSERT(pxBuffer != 0);
42
43 pxStackMonitor = (TraceStackMonitor_t*)pxBuffer;
44
45 pxStackMonitor->uiEntryCount = 0;
46
47 for (i = 0; i < (TRC_CFG_STACK_MONITOR_MAX_TASKS); i++)
48 {
49 pxStackMonitor->xEntries[i].pvTask = 0;
50 }
51
52 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR);
53
54 return TRC_SUCCESS;
55 }
56
xTraceStackMonitorAdd(void * pvTask)57 traceResult xTraceStackMonitorAdd(void *pvTask)
58 {
59 TraceUnsignedBaseType_t uxLowMark;
60
61 TRACE_ALLOC_CRITICAL_SECTION();
62
63 /* This should never fail */
64 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR));
65
66 if (pvTask == 0)
67 {
68 /* We don't add null addresses */
69 return TRC_FAIL;
70 }
71
72 TRACE_ENTER_CRITICAL_SECTION();
73
74 if (pxStackMonitor->uiEntryCount >= (TRC_CFG_STACK_MONITOR_MAX_TASKS))
75 {
76 xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_STACK_MONITOR_NO_SLOTS);
77
78 TRACE_EXIT_CRITICAL_SECTION();
79
80 return TRC_FAIL;
81 }
82
83 if (xTraceKernelPortGetUnusedStack(pvTask, &uxLowMark) == TRC_SUCCESS)
84 {
85 pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount].pvTask = pvTask;
86 pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount].uxPreviousLowWaterMark = uxLowMark;
87
88 pxStackMonitor->uiEntryCount++;
89 }
90
91 TRACE_EXIT_CRITICAL_SECTION();
92
93 return TRC_SUCCESS;
94 }
95
xTraceStackMonitorRemove(void * pvTask)96 traceResult xTraceStackMonitorRemove(void* pvTask)
97 {
98 uint32_t i;
99
100 TRACE_ALLOC_CRITICAL_SECTION();
101
102 /* This should never fail */
103 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR));
104
105 if (pvTask == 0)
106 {
107 /* We don't add null addresses */
108 return TRC_FAIL;
109 }
110
111 TRACE_ENTER_CRITICAL_SECTION();
112
113 for (i = 0; i < pxStackMonitor->uiEntryCount; i++)
114 {
115 if (pxStackMonitor->xEntries[i].pvTask == pvTask)
116 {
117 if (pxStackMonitor->uiEntryCount > 1 && i != (pxStackMonitor->uiEntryCount - 1))
118 {
119 /* There are more entries and this is NOT the last entry. Move last entry to this slot. */
120 pxStackMonitor->xEntries[i].pvTask = pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].pvTask;
121 pxStackMonitor->xEntries[i].uxPreviousLowWaterMark = pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].uxPreviousLowWaterMark;
122
123 /* Clear old entry that was moved */
124 pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].pvTask = 0;
125 pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].uxPreviousLowWaterMark = 0;
126 }
127 else
128 {
129 /* No other entries or last entry. */
130 pxStackMonitor->xEntries[i].pvTask = 0;
131 pxStackMonitor->xEntries[i].uxPreviousLowWaterMark = 0;
132 }
133
134 pxStackMonitor->uiEntryCount--;
135
136 TRACE_EXIT_CRITICAL_SECTION();
137
138 return TRC_SUCCESS;
139 }
140 }
141
142 TRACE_EXIT_CRITICAL_SECTION();
143
144 return TRC_FAIL;
145 }
146
xTraceStackMonitorGetAtIndex(uint32_t uiIndex,void ** ppvTask,TraceUnsignedBaseType_t * puxLowWaterMark)147 traceResult xTraceStackMonitorGetAtIndex(uint32_t uiIndex, void **ppvTask, TraceUnsignedBaseType_t *puxLowWaterMark)
148 {
149 /* This should never fail */
150 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR));
151
152 /* This should never fail */
153 TRC_ASSERT(ppvTask != 0);
154
155 /* This should never fail */
156 TRC_ASSERT(puxLowWaterMark != 0);
157
158 /* This should never fail */
159 TRC_ASSERT(uiIndex < (TRC_CFG_STACK_MONITOR_MAX_TASKS));
160
161 *ppvTask = pxStackMonitor->xEntries[uiIndex].pvTask;
162 *puxLowWaterMark = pxStackMonitor->xEntries[uiIndex].uxPreviousLowWaterMark;
163
164 return TRC_SUCCESS;
165 }
166
xTraceStackMonitorReport(void)167 traceResult xTraceStackMonitorReport(void)
168 {
169 TraceUnsignedBaseType_t uxLowWaterMark;
170 TraceEventHandle_t xEventHandle = 0;
171 TraceStackMonitorEntry_t *pxStackMonitorEntry;
172 uint32_t uiToReport;
173 uint32_t i;
174 static uint32_t uiCurrentIndex = 0;
175
176 TRACE_ALLOC_CRITICAL_SECTION();
177
178 /* This should never fail */
179 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR));
180
181 TRACE_ENTER_CRITICAL_SECTION();
182
183 /* Never report more than there are entries */
184 uiToReport = TRC_CFG_STACK_MONITOR_MAX_REPORTS <= pxStackMonitor->uiEntryCount ? TRC_CFG_STACK_MONITOR_MAX_REPORTS : pxStackMonitor->uiEntryCount;
185
186 for (i = 0; i < uiToReport; i++)
187 {
188 /* If uiCurrentIndex is too large, reset it */
189 uiCurrentIndex = uiCurrentIndex < pxStackMonitor->uiEntryCount ? uiCurrentIndex : 0;
190
191 pxStackMonitorEntry = &pxStackMonitor->xEntries[uiCurrentIndex];
192
193 xTraceKernelPortGetUnusedStack(pxStackMonitorEntry->pvTask, &uxLowWaterMark);
194
195 if (uxLowWaterMark < pxStackMonitorEntry->uxPreviousLowWaterMark)
196 {
197 pxStackMonitorEntry->uxPreviousLowWaterMark = uxLowWaterMark;
198 }
199
200 if (xTraceEventBegin(PSF_EVENT_UNUSED_STACK, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS)
201 {
202 xTraceEventAddPointer(xEventHandle, pxStackMonitorEntry->pvTask);
203 xTraceEventAdd32(xEventHandle, (uint32_t)pxStackMonitorEntry->uxPreviousLowWaterMark);
204 xTraceEventEnd(xEventHandle);
205 }
206
207 uiCurrentIndex++;
208 }
209
210 TRACE_EXIT_CRITICAL_SECTION();
211
212 return TRC_SUCCESS;
213 }
214 #endif /* (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) */
215
216 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
217
218 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
219