更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
trace_offline.c
浏览该文件的文档.
1/*!
2 * @file trace_offline.c
3 * @brief
4 * @link
5 @verbatim
6 基本概念
7 Trace调测旨在帮助开发者获取内核的运行流程,各个模块、任务的执行顺序,从而可以辅助开发者定位一些时序问题或者了解内核的代码运行过程。
8
9 运行机制
10 内核提供一套Hook框架,将Hook点预埋在各个模块的主要流程中, 在内核启动初期完成Trace功能的初始化,并注册Trace的处理函数到Hook中。
11 当系统触发到一个Hook点时,Trace模块会对输入信息进行封装,添加Trace帧头信息,包含事件类型、运行的cpuid、运行的任务id、运行的相对时间戳等信息;
12
13 Trace提供2种工作模式,离线模式和在线模式。此处为离线模式下的实现
14 @endverbatim
15 * @version
16 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
17 * @date 2021-11-22
18 */
19/*
20 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
21 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without modification,
24 * are permitted provided that the following conditions are met:
25 *
26 * 1. Redistributions of source code must retain the above copyright notice, this list of
27 * conditions and the following disclaimer.
28 *
29 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
30 * of conditions and the following disclaimer in the documentation and/or other materials
31 * provided with the distribution.
32 *
33 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
34 * to endorse or promote products derived from this software without specific prior written
35 * permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
39 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
41 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
44 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 */
49
50#include "los_trace_pri.h"
51#include "trace_pipeline.h"
52
53#define BITS_NUM_FOR_TASK_ID 16
54
55LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder; ///< 离线模式下的记录方式
56LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};///< 记录屏蔽任务情况
57
59{
60 return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */
61}
62/// trace离线模式初始化
64{
65 UINT32 headSize;
66 VOID *buf = NULL;
67 headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM;
68 if (size <= headSize) {
69 TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize);
70 return LOS_ERRNO_TRACE_BUF_TOO_SMALL;
71 }
72
73
74 buf = LOS_MemAlloc(m_aucSysMem0, size);//在内核堆空间中申请内存
75 if (buf == NULL) {
76 return LOS_ERRNO_TRACE_NO_MEMORY;
77 }
78
79 (VOID)memset_s(buf, size, 0, size);
81 g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD;//大小端
82 g_traceRecoder.head->baseInfo.version = TRACE_VERSION(TRACE_MODE_OFFLINE);//离线模式
83 g_traceRecoder.head->baseInfo.clockFreq = OS_SYS_CLOCK;//CPU时钟频率
84 g_traceRecoder.head->objSize = sizeof(ObjData);//对象大小
85 g_traceRecoder.head->frameSize = sizeof(TraceEventFrame);//帧大小
86 g_traceRecoder.head->objOffset = sizeof(OfflineHead);//对象开始位置
87 g_traceRecoder.head->frameOffset = headSize;//帧开始位置
88 g_traceRecoder.head->totalLen = size;//头部大小
89
90 g_traceRecoder.ctrl.curIndex = 0; //当前帧位置
91 g_traceRecoder.ctrl.curObjIndex = 0; //当前对象位置
92 g_traceRecoder.ctrl.maxObjCount = LOSCFG_TRACE_OBJ_MAX_NUM;//最大
93 g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame);//最大记录数
96
97 return LOS_OK;
98}
99/// 添加一个任务
100VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId)
101{
102 UINT32 intSave;
103 UINT32 index;
104 ObjData *obj = NULL;
105
106 TRACE_LOCK(intSave);
107 /* add obj begin */
109 if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */
110 TRACE_UNLOCK(intSave);
111 return;
112 }
113 obj = &g_traceRecoder.ctrl.objBuf[index];
114
115 if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) {
116 g_tidMask[taskId]++;
117 }
118
119 OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId));
120
123 g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */
124 }
125 /* add obj end */
126 TRACE_UNLOCK(intSave);
127}
128/// 离线模式下保存帧数据 @note_thinking 此处未封装好,会懵逼,文件名中体现了对离线模式的保存或对在线模式的发送这样真的好吗? .
130{
131 UINT16 index;
132 UINT32 intSave;
133
134 TRACE_LOCK(intSave);
135 index = g_traceRecoder.ctrl.curIndex;//获取当前位置,离线模式会将trace frame记录到预先申请好的循环buffer中
136 (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame));//保存帧内容至frameBuf中
137
138 g_traceRecoder.ctrl.curIndex++;//当前位置向前滚
139 if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) {//循环写入,这里可以看出,如果循环buffer记录的frame过多则可能出现翻转,
140 g_traceRecoder.ctrl.curIndex = 0;//会覆盖之前的记录,保持记录的信息始终是最新的信息。
141 }
142 TRACE_UNLOCK(intSave);
143}
144/// 重置循环buf
145VOID OsTraceReset(VOID)
146{
147 UINT32 intSave;
148 UINT32 bufLen;
149
150 TRACE_LOCK(intSave);
152 (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen);
154 TRACE_UNLOCK(intSave);
155}
156
157STATIC VOID OsTraceInfoObj(VOID)
158{
159 UINT32 i;
161
163 PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex);
164 PRINTK("Index TaskID TaskPrio TaskName \n");
165 for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) {
166 PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name);
167 }
168 PRINTK("\n");
169 }
170}
171
172STATIC VOID OsTraceInfoEventTitle(VOID)
173{
174 PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex);
175
176 PRINTK("Index Time(cycles) EventType CurPid CurTask Identity ");
177#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
178 PRINTK("cpuid hwiActive taskLockCnt ");
179#endif
180#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
181 PRINTK("eventCount ");
182#endif
183#ifdef LOS_TRACE_FRAME_LR
184 UINT32 i;
185 PRINTK("backtrace ");
186 for (i = 0; i < LOS_TRACE_LR_RECORD; i++) {
187 PRINTK(" ");
188 }
189#endif
190 if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) {
191 PRINTK("params ");
192 }
193 PRINTK("\n");
194}
195
196STATIC VOID OsTraceInfoEventData(VOID)
197{
198 UINT32 i, j;
200
201 for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) {
202 PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-7x 0x%-11x ", i, frame->curTime, frame->eventType,
203 frame->curPid, frame->curTask, frame->identity);
204#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
205 UINT32 taskLockCnt = frame->core.taskLockCnt;
206#ifdef LOSCFG_KERNEL_SMP
207 /*
208 * For smp systems, TRACE_LOCK will requst taskLock, and this counter
209 * will increase by 1 in that case.
210 */
211 taskLockCnt -= 1;
212#endif
213 PRINTK("%-11u %-11u %-11u", frame->core.cpuid, frame->core.hwiActive, taskLockCnt);
214#endif
215#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
216 PRINTK("%-11u", frame->eventCount);
217#endif
218#ifdef LOS_TRACE_FRAME_LR
219 for (j = 0; j < LOS_TRACE_LR_RECORD; j++) {
220 PRINTK("0x%-11x", frame->linkReg[j]);
221 }
222#endif
223 for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) {
224 PRINTK("0x%-11x", frame->params[j]);
225 }
226 PRINTK("\n");
227 }
228}
229
230STATIC VOID OsTraceInfoDisplay(VOID)
231{
233
234 PRINTK("*******TraceInfo begin*******\n");
235 PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq);
236
238
241
242 PRINTK("*******TraceInfo end*******\n");
243}
244
245#ifdef LOSCFG_TRACE_CLIENT_INTERACT
246STATIC VOID OsTraceSendInfo(VOID)
247{
248 UINT32 i;
249 ObjData *obj = NULL;
250 TraceEventFrame *frame = NULL;
251
253
254 obj = &g_traceRecoder.ctrl.objBuf[0];
255 for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) {
256 OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i));
257 }
258
259 frame = &g_traceRecoder.ctrl.frameBuf[0];
260 for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) {
261 OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i));
262 }
263}
264#endif
265
267{
268 if (!toClient) {
270 return;
271 }
272
273#ifdef LOSCFG_TRACE_CLIENT_INTERACT
275#endif
276}
277
279{
280 return g_traceRecoder.head;
281}
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb)
Definition: los_trace.c:161
unsigned short UINT16
Definition: los_typedef.h:56
unsigned char UINT8
Definition: los_typedef.h:55
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
size_t BOOL
Definition: los_typedef.h:88
UINT32 id
Definition: los_trace.h:298
CHAR name[LOSCFG_TRACE_OBJ_MAX_NAME_SIZE]
Definition: los_trace.h:300
UINT32 prio
Definition: los_trace.h:299
TraceBaseHeaderInfo baseInfo
Definition: los_trace.h:308
UINT16 totalLen
Definition: los_trace.h:309
UINT16 objOffset
Definition: los_trace.h:312
UINT16 frameOffset
Definition: los_trace.h:313
UINT16 frameSize
Definition: los_trace.h:311
UINT16 objSize
Definition: los_trace.h:310
UINT32 bigLittleEndian
Definition: los_trace.h:245
UINT64 curTime
Definition: los_trace.h:259
UINT32 eventCount
Definition: los_trace.h:272
UINTPTR params[LOSCFG_TRACE_FRAME_MAX_PARAMS]
Definition: los_trace.h:280
UINTPTR identity
Definition: los_trace.h:260
UINTPTR linkReg[LOS_TRACE_LR_RECORD]
Definition: los_trace.h:276
struct TraceEventFrame::CoreStatus core
UINT32 curTask
Definition: los_trace.h:257
UINT32 eventType
Definition: los_trace.h:256
OfflineHead * head
离线模式头部信息
struct TraceOfflineHeaderInfo::WriteCtrl ctrl
UINT32 OsTraceBufInit(UINT32 size)
trace离线模式初始化
Definition: trace_offline.c:63
STATIC VOID OsTraceInfoEventData(VOID)
LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT]
记录屏蔽任务情况
Definition: trace_offline.c:56
VOID OsTraceReset(VOID)
重置循环buf
UINT32 OsTraceGetMaskTid(UINT32 tid)
Definition: trace_offline.c:58
STATIC VOID OsTraceInfoEventTitle(VOID)
OfflineHead * OsTraceRecordGet(VOID)
LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder
离线模式下的记录方式
Definition: trace_offline.c:55
VOID OsTraceRecordDump(BOOL toClient)
VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId)
添加一个任务
STATIC VOID OsTraceSendInfo(VOID)
STATIC VOID OsTraceInfoObj(VOID)
VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame)
离线模式下保存帧数据 @note_thinking 此处未封装好,会懵逼,文件名中体现了对离线模式的保存或对在线模式的发送这样真的好吗? .
STATIC VOID OsTraceInfoDisplay(VOID)
VOID OsTraceDataSend(UINT8 type, UINT16 len, UINT8 *data)
@ EVENT
指事件(例如:定时器开始) 即发送 TraceEventFrame
@ HEAD
数据头信息, 即发送 TraceBaseHeaderInfo
@ OBJ
指对象(例如:任务) 即发送 ObjData