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 tasks.
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 /* Code used for "task address" when no task has started, to indicate "(startup)".
18  * This value was used since NULL/0 was already reserved for the idle task. */
19 #define TRACE_HANDLE_NO_TASK ((void*)2)
20 
21 #define TRC_TASK_STATE_INDEX_PRIORITY		0
22 #define TRC_TASK_STATE_INDEX_UNUSED_STACK	1
23 
24 TraceTaskInfo_t* pxTraceTaskInfo;
25 
xTraceTaskInitialize(TraceTaskInfoBuffer_t * pxBuffer)26 traceResult xTraceTaskInitialize(TraceTaskInfoBuffer_t *pxBuffer)
27 {
28 	uint32_t i;
29 
30 	TRC_ASSERT_EQUAL_SIZE(TraceTaskInfoBuffer_t, TraceTaskInfo_t);
31 
32 	/* This should never fail */
33 	TRC_ASSERT(pxBuffer != 0);
34 
35 	pxTraceTaskInfo = (TraceTaskInfo_t*)pxBuffer;
36 
37 	for (i = 0; i < TRC_CFG_CORE_COUNT; i++)
38 	{
39 		pxTraceTaskInfo->coreTasks[i] = TRACE_HANDLE_NO_TASK;
40 	}
41 
42 	xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_TASK);
43 
44 	return TRC_SUCCESS;
45 }
46 
xTraceTaskUnregister(TraceTaskHandle_t xTaskHandle,TraceUnsignedBaseType_t uxPriority)47 traceResult xTraceTaskUnregister(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority)
48 {
49 	void* pvTask;
50 
51 	/* This should never fail */
52 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xTaskHandle, &pvTask) == TRC_SUCCESS);
53 
54 	xTraceStackMonitorRemove(pvTask);
55 
56 	return xTraceObjectUnregister((TraceObjectHandle_t)xTaskHandle, PSF_EVENT_TASK_DELETE, uxPriority);
57 }
58 
xTraceTaskSetPriority(TraceTaskHandle_t xTaskHandle,TraceUnsignedBaseType_t uxPriority)59 traceResult xTraceTaskSetPriority(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority)
60 {
61 	TraceEventHandle_t xEventHandle = 0;
62 	void *pvTask;
63 
64 	/* This should never fail */
65 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetState((TraceObjectHandle_t)xTaskHandle, uxPriority) == TRC_SUCCESS);
66 
67 	/* This should never fail */
68 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xTaskHandle, &pvTask) == TRC_SUCCESS);
69 
70 	/* We need to check this */
71 	if (xTraceEventBegin(PSF_EVENT_TASK_PRIORITY, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS)
72 	{
73 		xTraceEventAddPointer(xEventHandle, pvTask);
74 		xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority);
75 		xTraceEventEnd(xEventHandle);
76 	}
77 
78 	return TRC_SUCCESS;
79 }
80 
xTraceTaskSetPriorityWithoutHandle(void * pvTask,TraceUnsignedBaseType_t uxPriority)81 traceResult xTraceTaskSetPriorityWithoutHandle(void* pvTask, TraceUnsignedBaseType_t uxPriority)
82 {
83 	TraceEventHandle_t xEventHandle = 0;
84 	TraceEntryHandle_t xEntryHandle;
85 
86 	if (xTraceEntryFind(pvTask, &xEntryHandle) == TRC_FAIL)
87 	{
88 		return TRC_FAIL;
89 	}
90 
91 	/* This should never fail */
92 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetState((TraceObjectHandle_t)xEntryHandle, uxPriority) == TRC_SUCCESS);
93 
94 	/* We need to check this */
95 	if (xTraceEventBegin(PSF_EVENT_TASK_PRIORITY, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS)
96 	{
97 		xTraceEventAddPointer(xEventHandle, pvTask);
98 		xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority);
99 		xTraceEventEnd(xEventHandle);
100 	}
101 
102 	return TRC_SUCCESS;
103 }
104 
xTraceTaskSwitch(void * pvTask,TraceUnsignedBaseType_t uxPriority)105 traceResult xTraceTaskSwitch(void *pvTask, TraceUnsignedBaseType_t uxPriority)
106 {
107 	traceResult xResult = TRC_FAIL;
108 	TraceEventHandle_t xEventHandle = 0;
109 	void* pvCurrent = 0;
110 
111 	TRACE_ALLOC_CRITICAL_SECTION();
112 
113 	(void)pvTask;
114 	(void)uxPriority;
115 
116 	if (xTraceIsRecorderEnabled() == 0)
117 	{
118 		return xResult;
119 	}
120 
121 	TRACE_ENTER_CRITICAL_SECTION();
122 
123 	xTraceStateSet(TRC_STATE_IN_TASKSWITCH);
124 
125 	xTraceTaskGetCurrent(&pvCurrent);
126 	if (pvCurrent != pvTask)
127 	{
128 		xTraceTaskSetCurrent(pvTask);
129 
130 		if (xTraceEventBegin(PSF_EVENT_TASK_ACTIVATE, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS)
131 		{
132 			xTraceEventAddPointer(xEventHandle, pvTask);
133 			xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority);
134 			xTraceEventEnd(xEventHandle);
135 			xResult = TRC_SUCCESS;
136 		}
137 	}
138 
139 	xTraceStateSet(TRC_STATE_IN_APPLICATION);
140 
141 	TRACE_EXIT_CRITICAL_SECTION();
142 
143 	return xResult;
144 }
145 
146 #if (TRC_CFG_INCLUDE_READY_EVENTS == 1)
xTraceTaskReady(void * pvTask)147 traceResult xTraceTaskReady(void *pvTask)
148 {
149 	traceResult xResult = TRC_FAIL;
150 	TraceEventHandle_t xEventHandle = 0;
151 
152 	if (xTraceEventBegin(PSF_EVENT_TASK_READY, sizeof(void*), &xEventHandle) == TRC_SUCCESS)
153 	{
154 		xTraceEventAddPointer(xEventHandle, pvTask);
155 		xTraceEventEnd(xEventHandle);
156 		xResult = TRC_SUCCESS;
157 	}
158 
159 	return xResult;
160 }
161 #endif /* (TRC_CFG_INCLUDE_READY_EVENTS == 1) */
162 
xTraceTaskInstanceFinishedNow(void)163 traceResult xTraceTaskInstanceFinishedNow(void)
164 {
165 	TraceEventHandle_t xEventHandle = 0;
166 
167 	if (xTraceEventBegin(PSF_EVENT_IFE_DIRECT, 0, &xEventHandle) == TRC_FAIL)
168 	{
169 		return TRC_FAIL;
170 	}
171 
172 	xTraceEventEnd(xEventHandle);
173 
174 	return TRC_SUCCESS;
175 }
176 
xTraceTaskInstanceFinishedNext(void)177 traceResult xTraceTaskInstanceFinishedNext(void)
178 {
179 	TraceEventHandle_t xEventHandle = 0;
180 
181 	if (xTraceEventBegin(PSF_EVENT_IFE_NEXT, 0, &xEventHandle) == TRC_FAIL)
182 	{
183 		return TRC_FAIL;
184 	}
185 
186 	xTraceEventEnd(xEventHandle);
187 
188 	return TRC_SUCCESS;
189 }
190 
191 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
192 
193 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
194