Compare commits

..

1 Commits

Author SHA1 Message Date
p2gpamesw 9121a2ac3d qq
1 year ago

@ -0,0 +1,8 @@
{
"files.associations": {
"los_queue_pri.h": "c",
"los_trace.h": "c",
"los_task_pri.h": "c",
"los_mux_debug_pri.h": "c"
}
}

@ -0,0 +1,257 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: Mutex Deadlock Check
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_mux_debug_pri.h"
#include "los_typedef.h"
#include "los_task.h"
#include "arch/exception.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */nbb
typedef struct {
LOS_DL_LIST muxListHead; /* Task-held mutexs list */ //用于管理任务持有的互斥锁列表//
UINT64 lastAccessTime; /* The last operation time */ //记录最后一次操作的时间//
} MuxDLinkCB;
/*管理任务持有的互斥锁列表和跟踪死锁情况*/
typedef struct {
LOS_DL_LIST muxList; /* Insert mutex into the owner task CB */ //用于将互斥锁插入到所属任务的控制块中//
VOID *muxCB; /* The Mutex CB pointer */ //指向互斥锁控制块的指针//
} MuxDLinkNode;
STATIC MuxDLinkCB *g_muxDeadlockCBArray = NULL;
/*
* Mutex deadlock detection time threshold, will print out task information
* that has not been scheduled within this time.
* The unit is tick.
*/
#define OS_MUX_DEADLOCK_CHECK_THRESHOLD 60000 //定义两次检查互斥锁死锁之间的最小时间间隔,单位为毫秒//
UINT32 OsMuxDlockCheckInit(VOID) //用于分配内存并初始化互斥锁控制块列表//
{
UINT32 index;
UINT32 size = (LOSCFG_BASE_CORE_TSK_LIMIT + 1) * sizeof(MuxDLinkCB);
/* system resident memory, don't free */
g_muxDeadlockCBArray = (MuxDLinkCB *)LOS_MemAlloc(m_aucSysMem1, size);
if (g_muxDeadlockCBArray == NULL) {
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
return LOS_NOK;
}
for (index = 0; index < LOSCFG_BASE_CORE_TSK_LIMIT + 1; index++) {
g_muxDeadlockCBArray[index].lastAccessTime = 0;
LOS_ListInit(&g_muxDeadlockCBArray[index].muxListHead);
}
return LOS_OK;
}
VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB) //用于向指定任务的互斥锁链表中插入一个互斥锁节点//
{
MuxDLinkNode *muxDLNode = NULL;
if ((taskId > LOSCFG_BASE_CORE_TSK_LIMIT) || (muxCB == NULL)) {
return;
}
muxDLNode = (MuxDLinkNode *)LOS_MemAlloc(m_aucSysMem1, sizeof(MuxDLinkNode));
if (muxDLNode == NULL) {
return;
}
(VOID)memset_s(muxDLNode, sizeof(MuxDLinkNode), 0, sizeof(MuxDLinkNode));
muxDLNode->muxCB = muxCB;
LOS_ListTailInsert(&g_muxDeadlockCBArray[taskId].muxListHead, &muxDLNode->muxList);
}
VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB) //用于从指定任务的互斥锁链表中删除指定的互斥锁节点//
{
MuxDLinkCB *muxDLCB = NULL;
LOS_DL_LIST *list = NULL;
MuxDLinkNode *muxDLNode = NULL;
if ((taskId > LOSCFG_BASE_CORE_TSK_LIMIT) || (muxCB == NULL)) {
return;
}
muxDLCB = &g_muxDeadlockCBArray[taskId];
LOS_DL_LIST_FOR_EACH(list, &muxDLCB->muxListHead) {
muxDLNode = LOS_DL_LIST_ENTRY(list, MuxDLinkNode, muxList);
if (muxDLNode->muxCB == muxCB) {
LOS_ListDelete(&muxDLNode->muxList);
(VOID)LOS_MemFree(m_aucSysMem1, muxDLNode);
return;
}
}
}
VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount) //用于更新任务的最后访问时间//
{
if (taskId > LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
g_muxDeadlockCBArray[taskId].lastAccessTime = tickCount;
}
STATIC VOID OsDeadlockBackTrace(const LosTaskCB *taskCB) //用于打印任务的函数调用栈信息//
{
TaskContext *context = NULL;
PRINTK("*******backtrace begin*******\n");
context = (TaskContext *)taskCB->stackPointer;
ArchBackTraceWithSp(context);
PRINTK("********backtrace end********\n");
return;
}
STATIC VOID OsMutexPendTaskList(LOS_DL_LIST *list) //用于打印互斥锁等待任务的列表信息//
{
LOS_DL_LIST *listTmp = NULL;
LosTaskCB *pendedTask = NULL;
CHAR *name = NULL;
UINT32 index = 0;
UINT32 id, intSave;
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(list) == TRUE) {
SCHEDULER_UNLOCK(intSave);
PRINTK("Pended Task: null\n");
return;
}
LOS_DL_LIST_FOR_EACH(listTmp, list) {
pendedTask = OS_TCB_FROM_PENDLIST(listTmp);
name = pendedTask->taskName;
id = pendedTask->taskId;
SCHEDULER_UNLOCK(intSave);
if (index == 0) {
PRINTK("Pended task: %u. name:%-15s, id:0x%-5x\n", index, name, id);
} else {
PRINTK(" %u. name:%-15s, id:0x%-5x\n", index, name, id);
}
index++;
SCHEDULER_LOCK(intSave);
}
SCHEDULER_UNLOCK(intSave);
}
STATIC VOID OsTaskHoldMutexList(MuxDLinkCB *muxDLCB) //用于打印任务持有的互斥锁的信息//
{
UINT32 index = 0;
MuxDLinkNode *muxDLNode = NULL;
CHAR *ownerName = NULL;
LosMuxCB *muxCB = NULL;
LOS_DL_LIST *list = NULL;
LOS_DL_LIST *listTmp = NULL;
UINT32 count, intSave;
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&muxDLCB->muxListHead) == TRUE) {
SCHEDULER_UNLOCK(intSave);
PRINTK("null\n");
} else {
LOS_DL_LIST_FOR_EACH(list, &muxDLCB->muxListHead) {
muxDLNode = LOS_DL_LIST_ENTRY(list, MuxDLinkNode, muxList);
muxCB = (LosMuxCB *)muxDLNode->muxCB;
count = muxCB->muxCount;
ownerName = muxCB->owner->taskName;
SCHEDULER_UNLOCK(intSave);
PRINTK("<Mutex%u info>\n", index);
PRINTK("Ptr handle:%p\n", muxCB);
PRINTK("Owner:%s\n", ownerName);
PRINTK("Count:%u\n", count);
listTmp = &muxCB->muxList;
OsMutexPendTaskList(listTmp);
index++;
SCHEDULER_LOCK(intSave);
}
SCHEDULER_UNLOCK(intSave);
}
}
VOID OsMutexDlockCheck(VOID) //用于检测互斥锁死锁情况并输出相关信息//
{
UINT32 loop, intSave;
UINT32 taskId;
CHAR *name = NULL;
LosTaskCB *taskCB = NULL;
MuxDLinkCB *muxDLCB = NULL;
SCHEDULER_LOCK(intSave);
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (LosTaskCB *)g_taskCBArray + loop;
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
continue;
}
muxDLCB = &g_muxDeadlockCBArray[taskCB->taskId];
if ((LOS_TickCountGet() - muxDLCB->lastAccessTime) > OS_MUX_DEADLOCK_CHECK_THRESHOLD) {
name = taskCB->taskName;
taskId = taskCB->taskId;
SCHEDULER_UNLOCK(intSave);
PRINTK("Task_name:%s, ID:0x%x, holds the Mutexs below:\n", name, taskId);
OsTaskHoldMutexList(muxDLCB);
OsDeadlockBackTrace(taskCB);
PRINTK("\n");
SCHEDULER_LOCK(intSave);
}
}
SCHEDULER_UNLOCK(intSave);
}
#ifdef LOSCFG_SHELL //用于在命令行中执行互斥锁死锁检查并输出相关信息//
UINT32 OsShellCmdMuxDeadlockCheck(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {
PRINTK("\nUsage: dlock\n");
return OS_ERROR;
}
PRINTK("Start mutexs deadlock check: \n");
OsMutexDlockCheck();
PRINTK("-----------End-----------\n");
return LOS_OK;
}
SHELLCMD_ENTRY(deadlock_shellcmd, CMD_TYPE_EX, "dlock", 0, (CmdCallBackFunc)OsShellCmdMuxDeadlockCheck);
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

@ -0,0 +1,189 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: Mutex Debug
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_mux_debug_pri.h"
#include "los_typedef.h"
#include "los_task.h"
#include "los_misc_pri.h"
#include "arch/exception.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_MUTEX //用于表示互斥锁的调试信息//
typedef struct {
TSK_ENTRY_FUNC creator; /* The task entry who created this mutex */
UINT64 lastAccessTime; /* The last access time */
} MuxDebugCB;
STATIC MuxDebugCB *g_muxDebugArray = NULL;
//用于比较两个互斥锁调试信息的最后访问时间//
STATIC BOOL MuxCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsMuxDbgInit(VOID) //用于初始化互斥锁调试信息数组//
{
UINT32 size = LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(MuxDebugCB);
/* system resident memory, don't free */
g_muxDebugArray = (MuxDebugCB *)LOS_MemAlloc(m_aucSysMem1, size);
if (g_muxDebugArray == NULL) {
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
return LOS_NOK;
}
(VOID)memset_s(g_muxDebugArray, size, 0, size);
return LOS_OK;
}
VOID OsMuxDbgTimeUpdate(UINT32 muxId) //用于更新指定互斥锁的最后访问时间//
{
MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)];
muxDebug->lastAccessTime = LOS_TickCountGet();
}
VOID OsMuxDbgUpdate(UINT32 muxId, TSK_ENTRY_FUNC creator) //用于更新指定互斥锁的创建者和最后访问时间//
{
MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)];
muxDebug->creator = creator;
muxDebug->lastAccessTime = LOS_TickCountGet();
}
//用于对互斥锁索引数组进行排序,并检查可能存在的互斥锁泄漏//
STATIC VOID SortMuxIndexArray(UINT32 *indexArray, UINT32 count)
{
LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0};
MuxDebugCB muxDebugNode = {0};
UINT32 index, intSave;
SortParam muxSortParam;
muxSortParam.buf = (CHAR *)g_muxDebugArray;
muxSortParam.ctrlBlockSize = sizeof(MuxDebugCB);
muxSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_MUX_LIMIT;
muxSortParam.sortElemOff = LOS_OFF_SET_OF(MuxDebugCB, lastAccessTime);
if (count > 0) {
SCHEDULER_LOCK(intSave);
OsArraySort(indexArray, 0, count - 1, &muxSortParam, MuxCompareValue);
SCHEDULER_UNLOCK(intSave);
for (index = 0; index < count; index++) {
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&muxNode, sizeof(LosMuxCB),
GET_MUX(indexArray[index]), sizeof(LosMuxCB));
(VOID)memcpy_s(&muxDebugNode, sizeof(MuxDebugCB),
&g_muxDebugArray[indexArray[index]], sizeof(MuxDebugCB));
SCHEDULER_UNLOCK(intSave);
/*
* muxStat may be altered after the g_taskSpin is unlocked in OsMutexCheck.
* We should recheck the muxStat before the print.
*/
if ((muxNode.muxStat != LOS_USED) ||
((muxNode.muxStat == LOS_USED) && ((muxDebugNode.creator == NULL) || (muxNode.owner == NULL)))) {
continue;
}
PRINTK("Mutex ID <0x%x> may leak, TaskID of owner:0x%x, TaskEntry of owner: %p,"
"TaskEntry of creator: %p,Latest operation time: 0x%llx\n",
muxNode.muxId, muxNode.owner->taskId, muxNode.owner->taskEntry, muxDebugNode.creator,
muxDebugNode.lastAccessTime);
}
}
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray);
}
VOID OsMutexCheck(VOID) //用于检查互斥锁的状态并对可能存在的互斥锁泄漏进行处理//
{
LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0};
MuxDebugCB muxDebugNode = {0};
UINT32 index, intSave;
UINT32 count = 0;
/*
* This return value does not need to be judged immediately,
* and the following code logic has already distinguished the return value from null and non-empty,
* and there is no case of accessing the null pointer.
*/
UINT32 *indexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(UINT32));
for (index = 0; index < LOSCFG_BASE_IPC_MUX_LIMIT; index++) {
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&muxNode, sizeof(LosMuxCB), GET_MUX(index), sizeof(LosMuxCB));
(VOID)memcpy_s(&muxDebugNode, sizeof(MuxDebugCB), &g_muxDebugArray[index], sizeof(MuxDebugCB));
SCHEDULER_UNLOCK(intSave);
if ((muxNode.muxStat != LOS_USED) ||
((muxNode.muxStat == LOS_USED) && (muxDebugNode.creator == NULL))) {
continue;
} else if ((muxNode.muxStat == LOS_USED) && (muxNode.owner == NULL)) {
PRINTK("Mutex ID <0x%x> may leak, Owner is null, TaskEntry of creator: %p,"
"Latest operation time: 0x%llx\n",
muxNode.muxId, muxDebugNode.creator, muxDebugNode.lastAccessTime);
} else {
if (indexArray != NULL) {
*(indexArray + count) = index;
count++;
} else {
PRINTK("Mutex ID <0x%x> may leak, TaskID of owner:0x%x, TaskEntry of owner: %p,"
"TaskEntry of creator: %p,Latest operation time: 0x%llx\n",
muxNode.muxId, muxNode.owner->taskId, muxNode.owner->taskEntry, muxDebugNode.creator,
muxDebugNode.lastAccessTime);
}
}
}
if (indexArray != NULL) {
SortMuxIndexArray(indexArray, count);
}
}
#ifdef LOSCFG_SHELL
//用于获取互斥锁信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMuxInfoGet(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {
PRINTK("\nUsage: mutex\n");
return OS_ERROR;
}
PRINTK("used mutexs information: \n");
OsMutexCheck();
return LOS_OK;
}
SHELLCMD_ENTRY(mutex_shellcmd, CMD_TYPE_EX, "mutex", 0, (CmdCallBackFunc)OsShellCmdMuxInfoGet);
#endif /* LOSCFG_SHELL */
#endif /* LOSCFG_DEBUG_MUTEX */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

@ -0,0 +1,206 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: Queue Debug
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_queue_debug_pri.h"
#include "los_misc_pri.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_QUEUE //用于保存队列的调试信息//
typedef struct {
TSK_ENTRY_FUNC creator; /* The task entry who created this queue */
UINT64 lastAccessTime; /* The last access time */
} QueueDebugCB;
STATIC QueueDebugCB *g_queueDebugArray = NULL;
//用于比较队列中的元素值//
STATIC BOOL QueueCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsQueueDbgInit(VOID) //用于初始化队列的调试信息//
{
UINT32 size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(QueueDebugCB);
/* system resident memory, don't free */
g_queueDebugArray = (QueueDebugCB *)LOS_MemAlloc(m_aucSysMem1, size);
if (g_queueDebugArray == NULL) {
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
return LOS_NOK;
}
(VOID)memset_s(g_queueDebugArray, size, 0, size);
return LOS_OK;
}
VOID OsQueueDbgTimeUpdate(UINT32 queueId) //用于更新队列的最后访问时间//
{
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)];
queueDebug->lastAccessTime = LOS_TickCountGet();
return;
}
VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry) //用于更新队列的调试信息//
{
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)];
queueDebug->creator = entry;
queueDebug->lastAccessTime = LOS_TickCountGet();
return;
}
STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node) //用于输出队列的信息//
{
PRINTK("Queue ID <0x%x> may leak, queue len is 0x%x, "
"readable cnt:0x%x, writeable cnt:0x%x, ",
node->queueId,
node->queueLen,
node->readWriteableCnt[OS_QUEUE_READ],
node->readWriteableCnt[OS_QUEUE_WRITE]);
}
STATIC INLINE VOID OsQueueOpsOutput(const QueueDebugCB *node) //用于输出队列操作的信息//
{
PRINTK("TaskEntry of creator:0x%p, Latest operation time: 0x%llx\n",
node->creator, node->lastAccessTime);
}
STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count) //用于对队列索引数组进行排序并输出相应的队列信息//
{
LosQueueCB queueNode = {0};
QueueDebugCB queueDebugNode = {0};
UINT32 index, intSave;
SortParam queueSortParam;
queueSortParam.buf = (CHAR *)g_queueDebugArray;
queueSortParam.ctrlBlockSize = sizeof(QueueDebugCB);
queueSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_QUEUE_LIMIT;
queueSortParam.sortElemOff = LOS_OFF_SET_OF(QueueDebugCB, lastAccessTime);
if (count > 0) {
SCHEDULER_LOCK(intSave);
OsArraySort(indexArray, 0, count - 1, &queueSortParam, QueueCompareValue);
SCHEDULER_UNLOCK(intSave);
for (index = 0; index < count; index++) {
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&queueNode, sizeof(LosQueueCB),
GET_QUEUE_HANDLE(indexArray[index]), sizeof(LosQueueCB));
(VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB),
&g_queueDebugArray[indexArray[index]], sizeof(QueueDebugCB));
SCHEDULER_UNLOCK(intSave);
if (queueNode.queueState == LOS_UNUSED) {
continue;
}
OsQueueInfoOutPut(&queueNode);
OsQueueOpsOutput(&queueDebugNode);
}
}
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray);
}
VOID OsQueueCheck(VOID) //用于检查队列的状态并输出相应信息//
{
LosQueueCB queueNode = {0};
QueueDebugCB queueDebugNode = {0};
UINT32 index, intSave;
UINT32 count = 0;
/*
* This return value does not need to be judged immediately,
* and the following code logic has already distinguished the return value from null and non-empty,
* and there is no case of accessing the null pointer.
*/
UINT32 *indexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(UINT32));
for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&queueNode, sizeof(LosQueueCB),
GET_QUEUE_HANDLE(index), sizeof(LosQueueCB));
(VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB),
&g_queueDebugArray[index], sizeof(QueueDebugCB));
SCHEDULER_UNLOCK(intSave);
if ((queueNode.queueState == LOS_UNUSED) ||
((queueNode.queueState == LOS_USED) && (queueDebugNode.creator == NULL))) {
continue;
}
if ((queueNode.queueState == LOS_USED) &&
(queueNode.queueLen == queueNode.readWriteableCnt[OS_QUEUE_WRITE]) &&
LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_READ]) &&
LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_WRITE]) &&
LOS_ListEmpty(&queueNode.memList)) {
PRINTK("Queue ID <0x%x> may leak, No task uses it, "
"QueueLen is 0x%x, ",
queueNode.queueId,
queueNode.queueLen);
OsQueueOpsOutput(&queueDebugNode);
} else {
if (indexArray != NULL) {
*(indexArray + count) = index;
count++;
} else {
OsQueueInfoOutPut(&queueNode);
OsQueueOpsOutput(&queueDebugNode);
}
}
}
if (indexArray != NULL) {
SortQueueIndexArray(indexArray, count);
}
return;
}
#ifdef LOSCFG_SHELL
//当用户输入 "queue" 命令时,会输出已使用队列的信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdQueueInfoGet(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {
PRINTK("\nUsage: queue\n");
return OS_ERROR;
}
PRINTK("used queues information: \n");
OsQueueCheck();
return LOS_OK;
}
SHELLCMD_ENTRY(queue_shellcmd, CMD_TYPE_EX, "queue", 0, (CmdCallBackFunc)OsShellCmdQueueInfoGet);
#endif /* LOSCFG_SHELL */
#endif /* LOSCFG_DEBUG_QUEUE */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

@ -0,0 +1,347 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
* Description: Schedule Statistics
* Author: Huawei LiteOS Team
* Create: 2018-11-16
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_SCHED_STATISTICS
#define HIGHTASKPRI 16
#define NS_PER_MS 1000000
#define DECIMAL_TO_PERCENTAGE 100
typedef struct {
UINT64 idleRuntime; //空闲任务的运行时间//
UINT64 idleStarttime; //空闲任务的启动时间//
UINT64 highTaskRuntime; //高优先级任务的运行时间//
UINT64 highTaskStarttime; //高优先级任务的启动时间//
UINT64 sumPriority; //任务优先级之和//
UINT32 prioritySwitch; //任务切换次数//
UINT32 highTaskSwitch; //高优先级任务切换次数//
UINT32 contexSwitch; //上下文切换次数//
UINT32 hwiNum; //硬件中断次数//
#ifdef LOSCFG_KERNEL_SMP
UINT32 ipiIrqNum; //中断次数(仅在多核配置下定义)//
#endif
} StatPercpu;
STATIC BOOL g_statisticsStartFlag = FALSE;
STATIC UINT64 g_statisticsStartTime;
STATIC StatPercpu g_statPercpu[LOSCFG_KERNEL_CORE_NUM];
//用于在每个 CPU 核心上进行调度统计//
STATIC VOID OsSchedStatisticsPerCpu(const LosTaskCB *runTask, const LosTaskCB *newTask)
{
UINT32 cpuId;
UINT32 idleTaskId;
UINT64 now, runtime;
if (g_statisticsStartFlag != TRUE) {
return;
}
cpuId = ArchCurrCpuid();
idleTaskId = OsGetIdleTaskId();
now = LOS_CurrNanosec();
g_statPercpu[cpuId].contexSwitch++;
if ((runTask->taskId != idleTaskId) && (newTask->taskId == idleTaskId)) {
g_statPercpu[cpuId].idleStarttime = now;
}
if ((runTask->taskId == idleTaskId) && (newTask->taskId != idleTaskId)) {
runtime = now - g_statPercpu[cpuId].idleStarttime;
g_statPercpu[cpuId].idleRuntime += runtime;
g_statPercpu[cpuId].idleStarttime = 0;
}
if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) {
g_statPercpu[cpuId].highTaskStarttime = now;
}
if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) {
runtime = now - g_statPercpu[cpuId].highTaskStarttime;
g_statPercpu[cpuId].highTaskRuntime += runtime;
g_statPercpu[cpuId].highTaskStarttime = 0;
}
if (newTask->priority < HIGHTASKPRI) {
g_statPercpu[cpuId].highTaskSwitch++;
}
if (newTask->taskId != idleTaskId) {
g_statPercpu[cpuId].sumPriority += newTask->priority;
g_statPercpu[cpuId].prioritySwitch++;
}
return;
}
//用于更新调度统计信息//
LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT64 runtime;
UINT32 cpuId = ArchCurrCpuid();
UINT64 now = LOS_CurrNanosec();
SchedStat *schedRun = &runTask->schedStat;
SchedStat *schedNew = &newTask->schedStat;
SchedPercpu *cpuRun = &schedRun->schedPercpu[cpuId];
SchedPercpu *cpuNew = &schedNew->schedPercpu[cpuId];
/* calculate one chance of running time */
runtime = now - schedRun->startRuntime;
/* add running timer to running task statistics */
cpuRun->runtime += runtime;
schedRun->allRuntime += runtime;
/* add context switch counters and schedule start time */
cpuNew->contexSwitch++;
schedNew->allContextSwitch++;
schedNew->startRuntime = now;
OsSchedStatisticsPerCpu(runTask, newTask);
}
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum) //用于更新硬中断的统计信息//
{
UINT32 cpuId = ArchCurrCpuid();
if ((g_statisticsStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) {
return;
}
g_statPercpu[cpuId].hwiNum++;
#ifdef LOSCFG_KERNEL_SMP
/* 16: 0~15 is ipi interrupts */
if (intNum < 16) {
g_statPercpu[cpuId].ipiIrqNum++;
}
#endif
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID) //用于打印任务的调度统计信息//
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId;
#ifdef LOSCFG_KERNEL_SMP
UINT32 affinity;
#endif
PRINTK("\n");
PRINTK("Task TID Total Time Total CST "
"CPU Time CST\n");
PRINTK("---- --- ------------------ ---------- -"
"--- ------------------ ----------\n");
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
continue;
}
#ifdef LOSCFG_KERNEL_SMP
affinity = (UINT32)taskCB->cpuAffiMask;
#endif
PRINTK("%-30s0x%-6x%+16lf ms %10u\n", taskCB->taskName, taskCB->taskId,
(DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS,
taskCB->schedStat.allContextSwitch);
for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
#ifdef LOSCFG_KERNEL_SMP
if (!((1U << cpuId) & affinity)) {
continue;
}
#endif
PRINTK(" "
"CPU%u %+16lf ms %12u\n", cpuId,
(DOUBLE)(taskCB->schedStat.schedPercpu[cpuId].runtime) / NS_PER_MS,
taskCB->schedStat.schedPercpu[cpuId].contexSwitch);
}
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime) //用于显示系统的统计信息//
{
UINT32 cpuId;
PRINTK("\n");
PRINTK("Passed Time: %+16lf ms\n", ((DOUBLE)statisticsPastTime / NS_PER_MS));
PRINTK("--------------------------------\n");
PRINTK("CPU Idle(%%) ContexSwitch HwiNum "
"Avg Pri HiTask(%%) HiTask SwiNum HiTask P(ms)"
#ifdef LOSCFG_KERNEL_SMP
" MP Hwi\n");
#else
"\n");
#endif
PRINTK("---- --------- ----------- -------- --------- "
"---------- ------------ ----------"
#ifdef LOSCFG_KERNEL_SMP
" ------\n");
#else
"\n");
#endif
for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
#ifdef LOSCFG_KERNEL_SMP
PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf %11u\n", cpuId,
#else
PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf\n", cpuId,
#endif
((DOUBLE)(g_statPercpu[cpuId].idleRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE,
g_statPercpu[cpuId].contexSwitch,
g_statPercpu[cpuId].hwiNum,
(g_statPercpu[cpuId].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST :
((DOUBLE)(g_statPercpu[cpuId].sumPriority) / (g_statPercpu[cpuId].prioritySwitch)),
((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE,
g_statPercpu[cpuId].highTaskSwitch,
(g_statPercpu[cpuId].highTaskSwitch == 0) ? 0 :
((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / (g_statPercpu[cpuId].highTaskSwitch)) / NS_PER_MS
#ifdef LOSCFG_KERNEL_SMP
, g_statPercpu[cpuId].ipiIrqNum);
#else
);
#endif
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID) //用于在多核系统中启动统计功能//
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId = 0;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_statisticsStartFlag) {
SCHEDULER_UNLOCK(intSave);
PRINT_WARN("mp static has started\n");
return;
}
g_statisticsStartTime = LOS_CurrNanosec();
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuId = taskCB->currCpu;
#endif
if ((UINT32)(OS_TASK_INVALID_CPUID) == cpuId) {
continue;
}
if (!strcmp(taskCB->taskName, "IdleCore000")) {
g_statPercpu[cpuId].idleStarttime = g_statisticsStartTime;
}
if (taskCB->priority < HIGHTASKPRI) {
g_statPercpu[cpuId].highTaskStarttime = g_statisticsStartTime;
g_statPercpu[cpuId].highTaskSwitch++;
}
if (strcmp(taskCB->taskName, "IdleCore000")) {
g_statPercpu[cpuId].sumPriority += taskCB->priority;
g_statPercpu[cpuId].prioritySwitch++;
}
}
}
g_statisticsStartFlag = TRUE;
SCHEDULER_UNLOCK(intSave);
PRINTK("mp static start\n");
return;
}
//用于在多核系统中停止统计功能,并进行统计数据的处理和展示//
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStop(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId = 0;
UINT64 statisticsStopTime;
UINT64 statisticsPastTime;
UINT64 runtime;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_statisticsStartFlag != TRUE) {
SCHEDULER_UNLOCK(intSave);
PRINT_WARN("Please set mp static start\n");
return;
}
g_statisticsStartFlag = FALSE;
statisticsStopTime = LOS_CurrNanosec();
statisticsPastTime = statisticsStopTime - g_statisticsStartTime;
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuId = taskCB->currCpu;
#endif
if (cpuId == (UINT32)(OS_TASK_INVALID_CPUID)) {
continue;
}
if (!strcmp(taskCB->taskName, "IdleCore000")) {
runtime = statisticsStopTime - g_statPercpu[cpuId].idleStarttime;
g_statPercpu[cpuId].idleRuntime += runtime;
g_statPercpu[cpuId].idleStarttime = 0;
}
if (taskCB->priority < HIGHTASKPRI) {
runtime = statisticsStopTime - g_statPercpu[cpuId].highTaskStarttime;
g_statPercpu[cpuId].highTaskRuntime += runtime;
g_statPercpu[cpuId].highTaskStarttime = 0;
}
}
}
SCHEDULER_UNLOCK(intSave);
OsStatisticsShow(statisticsPastTime);
(VOID)memset_s(g_statPercpu, sizeof(g_statPercpu), 0, sizeof(g_statPercpu));
g_statisticsStartTime = 0;
return;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,299 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: Sem Debug
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_sem_debug_pri.h"
#include "stdlib.h"
#include "los_typedef.h"
#include "los_task_pri.h"
#include "los_misc_pri.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_SEMAPHORE
#define OS_ALL_SEM_MASK 0xffffffff
STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode) //用于打印等待某个信号量的任务列表//
{
LosTaskCB *tskCB = NULL;
CHAR *nameArr[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
UINT32 i, intSave;
UINT32 num = 0;
SCHEDULER_LOCK(intSave);
if ((semNode->semStat == LOS_UNUSED) || (LOS_ListEmpty(&semNode->semList))) {
SCHEDULER_UNLOCK(intSave);
return;
}
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &semNode->semList, LosTaskCB, pendList) {
nameArr[num++] = tskCB->taskName;
if (num == LOSCFG_BASE_CORE_TSK_LIMIT) {
break;
}
}
SCHEDULER_UNLOCK(intSave);
PRINTK("Pended task list : ");
for (i = 0; i < num; i++) {
if (i == 0) {
PRINTK("%s\n", nameArr[i]);
} else {
PRINTK(", %s", nameArr[i]);
}
}
PRINTK("\n");
}
typedef struct { //用于记录信号量的调试信息//
UINT16 origSemCount; /* Number of original available semaphores */
UINT64 lastAccessTime; /* The last operation time */
TSK_ENTRY_FUNC creator; /* The task entry who created this sem */
} SemDebugCB;
STATIC SemDebugCB *g_semDebugArray = NULL; //用于存储所有信号量的调试信息//
//用于比较两个排序元素的值//
STATIC BOOL SemCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsSemDbgInit(VOID) //用于初始化信号量的调试信息数组//
{
UINT32 size = LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(SemDebugCB);
/* system resident memory, don't free */
g_semDebugArray = (SemDebugCB *)LOS_MemAlloc(m_aucSysMem1, size);
if (g_semDebugArray == NULL) {
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
return LOS_NOK;
}
(VOID)memset_s(g_semDebugArray, size, 0, size);
return LOS_OK;
}
VOID OsSemDbgTimeUpdate(UINT32 semId) //用于更新指定信号量的最后一次访问时间//
{
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)];
semDebug->lastAccessTime = LOS_TickCountGet();
return;
}
VOID OsSemDbgUpdate(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count) //用于更新指定信号量的调试信息//
{
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)];
semDebug->creator = creator;
semDebug->lastAccessTime = LOS_TickCountGet();
semDebug->origSemCount = count;
return;
}
/*用于按照信号量的最后访问时间对当前正在使用的信号量进行排序,*/
/*并打印每个信号量的调试信息和等待该信号量的任务名*/
STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount)
{
UINT32 i, intSave;
LosSemCB *semCB = NULL;
LosSemCB semNode = {0};
SemDebugCB semDebug = {0};
SortParam semSortParam;
semSortParam.buf = (CHAR *)g_semDebugArray;
semSortParam.ctrlBlockSize = sizeof(SemDebugCB);
semSortParam.ctrlBlockCnt = LOSCFG_BASE_IPC_SEM_LIMIT;
semSortParam.sortElemOff = LOS_OFF_SET_OF(SemDebugCB, lastAccessTime);
/* It will Print out ALL the Used Semaphore List. */
PRINTK("Used Semaphore List: \n");
PRINTK("\r\n SemID Count OriginalCount Creater(TaskEntry) LastAccessTime\n");
PRINTK(" ------ ------ ------------- ------------------ -------------- \n");
SCHEDULER_LOCK(intSave);
OsArraySort(semIndexArray, 0, usedCount - 1, &semSortParam, SemCompareValue);
SCHEDULER_UNLOCK(intSave);
for (i = 0; i < usedCount; i++) {
semCB = GET_SEM(semIndexArray[i]);
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
(VOID)memcpy_s(&semDebug, sizeof(SemDebugCB), &g_semDebugArray[semIndexArray[i]], sizeof(SemDebugCB));
SCHEDULER_UNLOCK(intSave);
if ((semNode.semStat != LOS_USED) || (semDebug.creator == NULL)) {
continue;
}
PRINTK(" 0x%-07x0x%-07u0x%-14u%-22p0x%llx\n", semNode.semId, semDebug.origSemCount,
semNode.semCount, semDebug.creator, semDebug.lastAccessTime);
if (!LOS_ListEmpty(&semNode.semList)) {
OsSemPendedTaskNamePrint(semCB);
}
}
}
/*用于获取当前正在使用的信号量信息,并按照信号量的最后访问时间对信号量进行排序*/
UINT32 OsSemInfoGetFullData(VOID)
{
UINT32 usedSemCnt = 0;
LosSemCB *semNode = NULL;
SemDebugCB *semDebug = NULL;
UINT32 i;
UINT32 *semIndexArray = NULL;
UINT32 count, intSave;
SCHEDULER_LOCK(intSave);
/* Get the used semaphore count. */
for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) {
semNode = GET_SEM(i);
semDebug = &g_semDebugArray[i];
if ((semNode->semStat == LOS_USED) && (semDebug->creator != NULL)) {
usedSemCnt++;
}
}
SCHEDULER_UNLOCK(intSave);
if (usedSemCnt > 0) {
semIndexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, usedSemCnt * sizeof(UINT32));
if (semIndexArray == NULL) {
PRINTK("LOS_MemAlloc failed in %s \n", __func__);
return LOS_NOK;
}
/* Fill the semIndexArray with the real index. */
count = 0;
SCHEDULER_LOCK(intSave);
for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) {
semNode = GET_SEM(i);
semDebug = &g_semDebugArray[i];
if ((semNode->semStat != LOS_USED) || (semDebug->creator == NULL)) {
continue;
}
*(semIndexArray + count) = i;
count++;
/* if the count is touched usedSemCnt break. */
if (count >= usedSemCnt) {
break;
}
}
SCHEDULER_UNLOCK(intSave);
OsSemSort(semIndexArray, count);
/* free the index array. */
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, semIndexArray);
}
return LOS_OK;
}
#ifdef LOSCFG_SHELL
STATIC UINT32 OsSemInfoOutput(size_t semId) //用于输出信号量信息//
{
UINT32 loop, semCnt, intSave;
LosSemCB *semCB = NULL;
LosSemCB semNode = {0};
if (semId == OS_ALL_SEM_MASK) {
for (loop = 0, semCnt = 0; loop < LOSCFG_BASE_IPC_SEM_LIMIT; loop++) {
semCB = GET_SEM(loop);
SCHEDULER_LOCK(intSave);
if (semCB->semStat == LOS_USED) {
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
SCHEDULER_UNLOCK(intSave);
semCnt++;
PRINTK("\r\n SemID Count\n ---------- -----\n");
PRINTK(" 0x%08x %u\n", semNode.semId, semNode.semCount);
continue;
}
SCHEDULER_UNLOCK(intSave);
}
PRINTK(" SemUsingNum : %u\n\n", semCnt);
return LOS_OK;
} else {
semCB = GET_SEM(semId);
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
SCHEDULER_UNLOCK(intSave);
if ((semNode.semId != semId) || (semNode.semStat != LOS_USED)) {
PRINTK("\nThe semaphore is not in use!\n");
return LOS_OK;
}
PRINTK("\r\n SemID Count\n ---------- -----\n");
PRINTK(" 0x%08x 0x%u\n", semNode.semId, semNode.semCount);
if (LOS_ListEmpty(&semNode.semList)) {
PRINTK("No task is pended on this semaphore!\n");
return LOS_OK;
} else {
OsSemPendedTaskNamePrint(semCB);
}
}
return LOS_OK;
}
//用于获取信号量信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSemInfoGet(UINT32 argc, const CHAR **argv)
{
size_t semId;
CHAR *endPtr = NULL;
UINT32 ret;
if (argc > 1) {
PRINTK("\nUsage: sem [fulldata|ID]\n");
return OS_ERROR;
}
if (argc == 0) {
semId = OS_ALL_SEM_MASK;
} else {
if (strcmp(argv[0], "fulldata") == 0) {
ret = OsSemInfoGetFullData();
return ret;
}
semId = strtoul(argv[0], &endPtr, 0);
if ((*endPtr != 0) || (GET_SEM_INDEX(semId) >= LOSCFG_BASE_IPC_SEM_LIMIT)) {
PRINTK("\nsem ID can't access %s.\n", argv[0]);
return OS_ERROR;
}
}
ret = OsSemInfoOutput(semId);
return ret;
}
SHELLCMD_ENTRY(sem_shellcmd, CMD_TYPE_EX, "sem", 1, (CmdCallBackFunc)OsShellCmdSemInfoGet);
#endif /* LOSCFG_SHELL */
#endif /* LOSCFG_DEBUG_SEMAPHORE */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -38,17 +38,16 @@
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */nbb
#endif /* __cplusplus */
typedef struct {
LOS_DL_LIST muxListHead; /* Task-held mutexs list */ //用于管理任务持有的互斥锁列表//
UINT64 lastAccessTime; /* The last operation time */ //记录最后一次操作的时间//
LOS_DL_LIST muxListHead; /* Task-held mutexs list */
UINT64 lastAccessTime; /* The last operation time */
} MuxDLinkCB;
/*管理任务持有的互斥锁列表和跟踪死锁情况*/
typedef struct {
LOS_DL_LIST muxList; /* Insert mutex into the owner task CB */ //用于将互斥锁插入到所属任务的控制块中//
VOID *muxCB; /* The Mutex CB pointer */ //指向互斥锁控制块的指针//
LOS_DL_LIST muxList; /* Insert mutex into the owner task CB */
VOID *muxCB; /* The Mutex CB pointer */
} MuxDLinkNode;
STATIC MuxDLinkCB *g_muxDeadlockCBArray = NULL;
@ -58,9 +57,9 @@ STATIC MuxDLinkCB *g_muxDeadlockCBArray = NULL;
* that has not been scheduled within this time.
* The unit is tick.
*/
#define OS_MUX_DEADLOCK_CHECK_THRESHOLD 60000 //定义两次检查互斥锁死锁之间的最小时间间隔,单位为毫秒//
#define OS_MUX_DEADLOCK_CHECK_THRESHOLD 60000
UINT32 OsMuxDlockCheckInit(VOID) //用于分配内存并初始化互斥锁控制块列表//
UINT32 OsMuxDlockCheckInit(VOID)
{
UINT32 index;
UINT32 size = (LOSCFG_BASE_CORE_TSK_LIMIT + 1) * sizeof(MuxDLinkCB);
@ -79,7 +78,7 @@ UINT32 OsMuxDlockCheckInit(VOID) //
return LOS_OK;
}
VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB) //用于向指定任务的互斥锁链表中插入一个互斥锁节点//
VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB)
{
MuxDLinkNode *muxDLNode = NULL;
@ -97,7 +96,7 @@ VOID OsMuxDlockNodeInsert(UINT32 taskId, VOID *muxCB) //
LOS_ListTailInsert(&g_muxDeadlockCBArray[taskId].muxListHead, &muxDLNode->muxList);
}
VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB) //用于从指定任务的互斥锁链表中删除指定的互斥锁节点//
VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB)
{
MuxDLinkCB *muxDLCB = NULL;
LOS_DL_LIST *list = NULL;
@ -118,7 +117,7 @@ VOID OsMuxDlockNodeDelete(UINT32 taskId, const VOID *muxCB) //
}
}
VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount) //用于更新任务的最后访问时间//
VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount)
{
if (taskId > LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
@ -127,7 +126,7 @@ VOID OsTaskTimeUpdate(UINT32 taskId, UINT64 tickCount) //
g_muxDeadlockCBArray[taskId].lastAccessTime = tickCount;
}
STATIC VOID OsDeadlockBackTrace(const LosTaskCB *taskCB) //用于打印任务的函数调用栈信息//
STATIC VOID OsDeadlockBackTrace(const LosTaskCB *taskCB)
{
TaskContext *context = NULL;
@ -138,7 +137,7 @@ STATIC VOID OsDeadlockBackTrace(const LosTaskCB *taskCB) //
return;
}
STATIC VOID OsMutexPendTaskList(LOS_DL_LIST *list) //用于打印互斥锁等待任务的列表信息//
STATIC VOID OsMutexPendTaskList(LOS_DL_LIST *list)
{
LOS_DL_LIST *listTmp = NULL;
LosTaskCB *pendedTask = NULL;
@ -169,7 +168,7 @@ STATIC VOID OsMutexPendTaskList(LOS_DL_LIST *list) //
SCHEDULER_UNLOCK(intSave);
}
STATIC VOID OsTaskHoldMutexList(MuxDLinkCB *muxDLCB) //用于打印任务持有的互斥锁的信息//
STATIC VOID OsTaskHoldMutexList(MuxDLinkCB *muxDLCB)
{
UINT32 index = 0;
MuxDLinkNode *muxDLNode = NULL;
@ -205,7 +204,7 @@ STATIC VOID OsTaskHoldMutexList(MuxDLinkCB *muxDLCB) //
}
}
VOID OsMutexDlockCheck(VOID) //用于检测互斥锁死锁情况并输出相关信息//
VOID OsMutexDlockCheck(VOID)
{
UINT32 loop, intSave;
UINT32 taskId;
@ -235,7 +234,7 @@ VOID OsMutexDlockCheck(VOID) //
SCHEDULER_UNLOCK(intSave);
}
#ifdef LOSCFG_SHELL //用于在命令行中执行互斥锁死锁检查并输出相关信息//
#ifdef LOSCFG_SHELL
UINT32 OsShellCmdMuxDeadlockCheck(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {

@ -41,21 +41,20 @@ extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_MUTEX //用于表示互斥锁的调试信息//
#ifdef LOSCFG_DEBUG_MUTEX
typedef struct {
TSK_ENTRY_FUNC creator; /* The task entry who created this mutex */
UINT64 lastAccessTime; /* The last access time */
} MuxDebugCB;
STATIC MuxDebugCB *g_muxDebugArray = NULL;
//用于比较两个互斥锁调试信息的最后访问时间//
STATIC BOOL MuxCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsMuxDbgInit(VOID) //用于初始化互斥锁调试信息数组//
UINT32 OsMuxDbgInit(VOID)
{
UINT32 size = LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(MuxDebugCB);
/* system resident memory, don't free */
@ -68,20 +67,19 @@ UINT32 OsMuxDbgInit(VOID) //
return LOS_OK;
}
VOID OsMuxDbgTimeUpdate(UINT32 muxId) //用于更新指定互斥锁的最后访问时间//
VOID OsMuxDbgTimeUpdate(UINT32 muxId)
{
MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)];
muxDebug->lastAccessTime = LOS_TickCountGet();
}
VOID OsMuxDbgUpdate(UINT32 muxId, TSK_ENTRY_FUNC creator) //用于更新指定互斥锁的创建者和最后访问时间//
VOID OsMuxDbgUpdate(UINT32 muxId, TSK_ENTRY_FUNC creator)
{
MuxDebugCB *muxDebug = &g_muxDebugArray[GET_MUX_INDEX(muxId)];
muxDebug->creator = creator;
muxDebug->lastAccessTime = LOS_TickCountGet();
}
//用于对互斥锁索引数组进行排序,并检查可能存在的互斥锁泄漏//
STATIC VOID SortMuxIndexArray(UINT32 *indexArray, UINT32 count)
{
LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0};
@ -121,7 +119,7 @@ STATIC VOID SortMuxIndexArray(UINT32 *indexArray, UINT32 count)
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray);
}
VOID OsMutexCheck(VOID) //用于检查互斥锁的状态并对可能存在的互斥锁泄漏进行处理//
VOID OsMutexCheck(VOID)
{
LosMuxCB muxNode = {{0, 0}, 0, 0, 0, 0};
MuxDebugCB muxDebugNode = {0};
@ -167,7 +165,6 @@ VOID OsMutexCheck(VOID) //
}
#ifdef LOSCFG_SHELL
//用于获取互斥锁信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMuxInfoGet(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {

@ -38,21 +38,20 @@ extern "C" {
#endif
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_QUEUE //用于保存队列的调试信息//
#ifdef LOSCFG_DEBUG_QUEUE
typedef struct {
TSK_ENTRY_FUNC creator; /* The task entry who created this queue */
UINT64 lastAccessTime; /* The last access time */
} QueueDebugCB;
STATIC QueueDebugCB *g_queueDebugArray = NULL;
//用于比较队列中的元素值//
STATIC BOOL QueueCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsQueueDbgInit(VOID) //用于初始化队列的调试信息//
UINT32 OsQueueDbgInit(VOID)
{
UINT32 size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(QueueDebugCB);
@ -66,14 +65,14 @@ UINT32 OsQueueDbgInit(VOID) //
return LOS_OK;
}
VOID OsQueueDbgTimeUpdate(UINT32 queueId) //用于更新队列的最后访问时间//
VOID OsQueueDbgTimeUpdate(UINT32 queueId)
{
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)];
queueDebug->lastAccessTime = LOS_TickCountGet();
return;
}
VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry) //用于更新队列的调试信息//
VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry)
{
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueId)];
queueDebug->creator = entry;
@ -81,7 +80,7 @@ VOID OsQueueDbgUpdate(UINT32 queueId, TSK_ENTRY_FUNC entry) //
return;
}
STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node) //用于输出队列的信息//
STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node)
{
PRINTK("Queue ID <0x%x> may leak, queue len is 0x%x, "
"readable cnt:0x%x, writeable cnt:0x%x, ",
@ -91,13 +90,13 @@ STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node) //
node->readWriteableCnt[OS_QUEUE_WRITE]);
}
STATIC INLINE VOID OsQueueOpsOutput(const QueueDebugCB *node) //用于输出队列操作的信息//
STATIC INLINE VOID OsQueueOpsOutput(const QueueDebugCB *node)
{
PRINTK("TaskEntry of creator:0x%p, Latest operation time: 0x%llx\n",
node->creator, node->lastAccessTime);
}
STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count) //用于对队列索引数组进行排序并输出相应的队列信息//
STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count)
{
LosQueueCB queueNode = {0};
QueueDebugCB queueDebugNode = {0};
@ -129,7 +128,7 @@ STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count) //
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray);
}
VOID OsQueueCheck(VOID) //用于检查队列的状态并输出相应信息//
VOID OsQueueCheck(VOID)
{
LosQueueCB queueNode = {0};
QueueDebugCB queueDebugNode = {0};
@ -183,7 +182,6 @@ VOID OsQueueCheck(VOID) //
}
#ifdef LOSCFG_SHELL
//当用户输入 "queue" 命令时,会输出已使用队列的信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdQueueInfoGet(UINT32 argc, const CHAR **argv)
{
if (argc > 0) {

@ -40,17 +40,17 @@ extern "C" {
#define DECIMAL_TO_PERCENTAGE 100
typedef struct {
UINT64 idleRuntime; //空闲任务的运行时间//
UINT64 idleStarttime; //空闲任务的启动时间//
UINT64 highTaskRuntime; //高优先级任务的运行时间//
UINT64 highTaskStarttime; //高优先级任务的启动时间//
UINT64 sumPriority; //任务优先级之和//
UINT32 prioritySwitch; //任务切换次数//
UINT32 highTaskSwitch; //高优先级任务切换次数//
UINT32 contexSwitch; //上下文切换次数//
UINT32 hwiNum; //硬件中断次数//
UINT64 idleRuntime;
UINT64 idleStarttime;
UINT64 highTaskRuntime;
UINT64 highTaskStarttime;
UINT64 sumPriority;
UINT32 prioritySwitch;
UINT32 highTaskSwitch;
UINT32 contexSwitch;
UINT32 hwiNum;
#ifdef LOSCFG_KERNEL_SMP
UINT32 ipiIrqNum; //中断次数(仅在多核配置下定义)//
UINT32 ipiIrqNum;
#endif
} StatPercpu;
@ -58,7 +58,6 @@ STATIC BOOL g_statisticsStartFlag = FALSE;
STATIC UINT64 g_statisticsStartTime;
STATIC StatPercpu g_statPercpu[LOSCFG_KERNEL_CORE_NUM];
//用于在每个 CPU 核心上进行调度统计//
STATIC VOID OsSchedStatisticsPerCpu(const LosTaskCB *runTask, const LosTaskCB *newTask)
{
UINT32 cpuId;
@ -107,7 +106,6 @@ STATIC VOID OsSchedStatisticsPerCpu(const LosTaskCB *runTask, const LosTaskCB *n
return;
}
//用于更新调度统计信息//
LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT64 runtime;
@ -133,7 +131,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *new
OsSchedStatisticsPerCpu(runTask, newTask);
}
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum) //用于更新硬中断的统计信息//
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum)
{
UINT32 cpuId = ArchCurrCpuid();
@ -151,7 +149,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum) //
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID) //用于打印任务的调度统计信息//
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
@ -194,7 +192,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID) //
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime) //用于显示系统的统计信息//
LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime)
{
UINT32 cpuId;
PRINTK("\n");
@ -240,7 +238,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime) //
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID) //用于在多核系统中启动统计功能//
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
@ -287,7 +285,6 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID) //
return;
}
//用于在多核系统中停止统计功能,并进行统计数据的处理和展示//
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStop(VOID)
{
LosTaskCB *taskCB = NULL;

@ -44,7 +44,7 @@ extern "C" {
#ifdef LOSCFG_DEBUG_SEMAPHORE
#define OS_ALL_SEM_MASK 0xffffffff
STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode) //用于打印等待某个信号量的任务列表//
STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode)
{
LosTaskCB *tskCB = NULL;
CHAR *nameArr[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
@ -76,21 +76,20 @@ STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode) //
PRINTK("\n");
}
typedef struct { //用于记录信号量的调试信息//
typedef struct {
UINT16 origSemCount; /* Number of original available semaphores */
UINT64 lastAccessTime; /* The last operation time */
TSK_ENTRY_FUNC creator; /* The task entry who created this sem */
} SemDebugCB;
STATIC SemDebugCB *g_semDebugArray = NULL; //用于存储所有信号量的调试信息//
STATIC SemDebugCB *g_semDebugArray = NULL;
//用于比较两个排序元素的值//
STATIC BOOL SemCompareValue(const SortParam *sortParam, UINT32 left, UINT32 right)
{
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
}
UINT32 OsSemDbgInit(VOID) //用于初始化信号量的调试信息数组//
UINT32 OsSemDbgInit(VOID)
{
UINT32 size = LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(SemDebugCB);
/* system resident memory, don't free */
@ -103,14 +102,14 @@ UINT32 OsSemDbgInit(VOID) //
return LOS_OK;
}
VOID OsSemDbgTimeUpdate(UINT32 semId) //用于更新指定信号量的最后一次访问时间//
VOID OsSemDbgTimeUpdate(UINT32 semId)
{
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)];
semDebug->lastAccessTime = LOS_TickCountGet();
return;
}
VOID OsSemDbgUpdate(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count) //用于更新指定信号量的调试信息//
VOID OsSemDbgUpdate(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count)
{
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semId)];
semDebug->creator = creator;
@ -119,9 +118,7 @@ VOID OsSemDbgUpdate(UINT32 semId, TSK_ENTRY_FUNC creator, UINT16 count) //
return;
}
/*用于按照信号量的最后访问时间对当前正在使用的信号量进行排序,*/
/*并打印每个信号量的调试信息和等待该信号量的任务名*/
STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount)
STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount)
{
UINT32 i, intSave;
LosSemCB *semCB = NULL;
@ -157,7 +154,7 @@ STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount)
}
}
}
/*用于获取当前正在使用的信号量信息,并按照信号量的最后访问时间对信号量进行排序*/
UINT32 OsSemInfoGetFullData(VOID)
{
UINT32 usedSemCnt = 0;
@ -212,7 +209,7 @@ UINT32 OsSemInfoGetFullData(VOID)
}
#ifdef LOSCFG_SHELL
STATIC UINT32 OsSemInfoOutput(size_t semId) //用于输出信号量信息//
STATIC UINT32 OsSemInfoOutput(size_t semId)
{
UINT32 loop, semCnt, intSave;
LosSemCB *semCB = NULL;
@ -257,7 +254,6 @@ STATIC UINT32 OsSemInfoOutput(size_t semId) //
return LOS_OK;
}
//用于获取信号量信息//
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSemInfoGet(UINT32 argc, const CHAR **argv)
{
size_t semId;

@ -62,13 +62,8 @@ extern "C" {
return; \
} \
} while (0)
//这个宏的作用是确保在参数为NULL时能够快速地进行错误处理
//避免在每个需要检查空指针的地方都重复编写相似的代码。
//这样可以提高代码的可读性和可维护性。
/*对内存模块的自旋锁进行定义的注释。它表明这个自旋锁只在SMP对称多处理模式下可用。 */
/* spinlock for mem module, only available on SMP mode */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_memSpin);
UINT8 *m_aucSysMem0 = NULL;
@ -95,18 +90,7 @@ STATIC VOID OsMemNodeSave(LosMemDynNode *node);
#endif
STATIC VOID *OsMemAllocWithCheck(LosMemPoolInfo *pool, UINT32 size);
/*
LITE_OS_SEC_BSS g_memSpin BSS
SPIN_LOCK_INIT(g_memSpin) g_memSpin
m_aucSysMem0 m_aucSysMem1 UINT8 NULL
g_MALLOC_HOOK
g_sys_mem_addr_end UINTPTR
g_excInteractMemSize UINTPTR LOSCFG_EXC_INTERACTION
g_memCheckLevel UINT8 LOSCFG_BASE_MEM_NODE_SIZE_CHECK
g_moduleMemUsedSize UINT32 LOSCFG_MEM_MUL_MODULE 使
OsMemNodeSave
OsMemAllocWithCheck
*/
STATIC INLINE VOID OS_MEM_TASKID_SET(LosMemDynNode *node, UINT32 taskId)
{
node->selfNode.taskId = taskId;
@ -138,12 +122,7 @@ STATIC INLINE UINT32 OS_MEM_MODID_GET(const LosMemDynNode *node)
}
#endif
/*OS_MEM_TASKID_SET 函数用于将给定的任务IDtask ID设置到指定的内存节点 node 中。
OS_MEM_TASKID_GET node IDtask ID
LOSCFG_MEM_MUL_MODULE
OS_MEM_MODID_SET IDmodule ID node
OS_MEM_MODID_GET node IDmodule ID
IDID LOSCFG_MEM_HEAD_BACKUP OsMemNodeSave */
/*
* Description : set magic & taskid
* Input : node -- the node which will be set magic & taskid
@ -160,8 +139,6 @@ STATIC INLINE VOID OsMemSetMagicNumAndTaskID(LosMemDynNode *node)
* or in interrupt, make the value of taskid of node to (TASK_NUM - 1) which is
* the id of the extra task. We can record those memory use with that.
*/
//这段注释是在说明一种情况,即如果在任务初始化之前(即任务的 runTask 还没有被赋值)或在中断中进行操作,将节点的 taskid 值设置为 (TASK_NUM - 1)
//其中 TASK_NUM 是额外任务的 ID。这样可以记录那些在任务初始化之前或在中断中使用的内存。
if ((runTask != NULL) && OS_INT_INACTIVE) {
OS_MEM_TASKID_SET(node, runTask->taskId);
} else {
@ -170,10 +147,7 @@ STATIC INLINE VOID OsMemSetMagicNumAndTaskID(LosMemDynNode *node)
}
#endif
}
//如果宏 LOSCFG_MEM_HEAD_BACKUP 被定义,那么会定义一个名为 CHECKSUM_MAGICNUM 的常量,
//用于计算内存控制节点的校验和。
OS_MEM_NODE_CHECKSUM_CALCULATE
OsMemDispCtlNode
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
const VOID *OsMemFindNodeCtrl(const VOID *pool, const VOID *ptr);
#endif
@ -206,8 +180,6 @@ STATIC INLINE VOID OsMemDispCtlNode(const LosMemCtlNode *ctlNode)
}
STATIC INLINE VOID OsMemDispMoreDetails(const LosMemDynNode *node)
//用于打印关于动态内存节点的更多详细信息。它接受一个 LosMemDynNode 结构体指针作为参数,
//并根据节点的状态打印不同的信息,例如节点是否被使用、分配该节点的任务信息等。
{
UINT32 taskId;
LosTaskCB *taskCB = NULL;
@ -251,7 +223,6 @@ STATIC INLINE VOID OsMemDispMoreDetails(const LosMemDynNode *node)
STATIC INLINE VOID OsMemDispWildPointerMsg(const LosMemDynNode *node, const VOID *ptr)
{
//用于在发现野指针时打印相关信息。它接受一个 LosMemDynNode 结构体指针和一个野指针作为参数,并打印出野指针的详细信息,以及可能的原因。
PRINT_ERR("*****************************************************\n");
PRINT_ERR("find an control block at: %p, gap size: 0x%x, sizeof(LosMemDynNode): 0x%x\n", node,
node->selfNode.gapSize, sizeof(LosMemDynNode));
@ -263,17 +234,17 @@ STATIC INLINE VOID OsMemDispWildPointerMsg(const LosMemDynNode *node, const VOID
PRINT_ERR("*****************************************************\n\n");
}
STATIC INLINE VOID OsMemChecksumSet(LosMemCtlNode *ctlNode)//用于为控制节点计算并设置校验和。
STATIC INLINE VOID OsMemChecksumSet(LosMemCtlNode *ctlNode)
{
ctlNode->checksum = OS_MEM_NODE_CHECKSUM_CALCULATE(ctlNode);
}
STATIC INLINE BOOL OsMemChecksumVerify(const LosMemCtlNode *ctlNode)//验证控制节点的校验和是否正确。
STATIC INLINE BOOL OsMemChecksumVerify(const LosMemCtlNode *ctlNode)
{
return ctlNode->checksum == OS_MEM_NODE_CHECKSUM_CALCULATE(ctlNode);
}
STATIC INLINE VOID OsMemBackupSetup(const LosMemDynNode *node)//为当前节点的前一个节点设置备份信息
STATIC INLINE VOID OsMemBackupSetup(const LosMemDynNode *node)
{
LosMemDynNode *nodePre = node->selfNode.preNode;
if (nodePre != NULL) {
@ -286,7 +257,7 @@ STATIC INLINE VOID OsMemBackupSetup(const LosMemDynNode *node)//为当前节点
}
}
LosMemDynNode *OsMemNodeNextGet(const VOID *pool, const LosMemDynNode *node)//获取指定节点的下一个节点
LosMemDynNode *OsMemNodeNextGet(const VOID *pool, const LosMemDynNode *node)
{
const LosMemPoolInfo *poolInfo = (const LosMemPoolInfo *)pool;
@ -298,7 +269,6 @@ LosMemDynNode *OsMemNodeNextGet(const VOID *pool, const LosMemDynNode *node)//
}
STATIC INLINE UINT32 OsMemBackupSetup4Next(const VOID *pool, LosMemDynNode *node)
//为下一个节点设置备份信息,并检查下一个节点的校验和是否正确。
{
LosMemDynNode *nodeNext = OsMemNodeNextGet(pool, node);
@ -324,8 +294,6 @@ STATIC INLINE UINT32 OsMemBackupSetup4Next(const VOID *pool, LosMemDynNode *node
UINT32 OsMemBackupDoRestore(VOID *pool, const LosMemDynNode *nodePre, LosMemDynNode *node)
{
//从备份中恢复节点。它首先打印出备份信息和原节点信息,然后将备份信息中记录的值恢复到节点中,
//并调用 OsMemBackupSetup4Next 重新设置下一个节点的备份信息。
if (node == NULL) {
PRINT_ERR("the node is NULL.\n");
return LOS_NOK;
@ -347,7 +315,6 @@ UINT32 OsMemBackupDoRestore(VOID *pool, const LosMemDynNode *nodePre, LosMemDynN
}
STATIC LosMemDynNode *OsMemFirstNodePrevGet(const LosMemPoolInfo *poolInfo)
//获取内存池中第一个节点的前一个节点。
{
LosMemDynNode *nodePre = NULL;
@ -368,7 +335,6 @@ STATIC LosMemDynNode *OsMemFirstNodePrevGet(const LosMemPoolInfo *poolInfo)
}
LosMemDynNode *OsMemNodePrevGet(VOID *pool, const LosMemDynNode *node)
//在内存池中查找给定节点的前一个节点。
{
LosMemDynNode *nodeCur = NULL;
LosMemDynNode *nodePre = NULL;
@ -427,7 +393,7 @@ LosMemDynNode *OsMemNodePrevGet(VOID *pool, const LosMemDynNode *node)
}
LosMemDynNode *OsMemNodePrevTryGet(VOID *pool, LosMemDynNode **node, const VOID *ptr)
{//在内存池中尝试获取指向给定地址的节点的前一个节点。
{
UINTPTR nodeShouldBe;
LosMemDynNode *nodeCur = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
@ -481,7 +447,7 @@ LosMemDynNode *OsMemNodePrevTryGet(VOID *pool, LosMemDynNode **node, const VOID
}
STATIC INLINE UINT32 OsMemBackupTryRestore(VOID *pool, LosMemDynNode **node, const VOID *ptr)
{//尝试恢复节点的备份状态。
{
LosMemDynNode *nodeHead = NULL;
LosMemDynNode *nodePre = OsMemNodePrevTryGet(pool, &nodeHead, ptr);
if (nodePre == NULL) {
@ -493,7 +459,7 @@ STATIC INLINE UINT32 OsMemBackupTryRestore(VOID *pool, LosMemDynNode **node, con
}
STATIC INLINE UINT32 OsMemBackupRestore(VOID *pool, LosMemDynNode *node)
{//恢复节点的备份状态
{
LosMemDynNode *nodePre = OsMemNodePrevGet(pool, node);
if (nodePre == NULL) {
return LOS_NOK;
@ -503,7 +469,7 @@ STATIC INLINE UINT32 OsMemBackupRestore(VOID *pool, LosMemDynNode *node)
}
STATIC INLINE UINT32 OsMemBackupCheckAndRetore(VOID *pool, const VOID *ptr, LosMemDynNode *node)
{//检查并恢复节点的备份状态。
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
LosMemDynNode *startNode = OS_MEM_FIRST_NODE(pool);
LosMemDynNode *endNode = OS_MEM_END_NODE(pool, poolInfo->poolSize);
@ -519,26 +485,26 @@ STATIC INLINE UINT32 OsMemBackupCheckAndRetore(VOID *pool, const VOID *ptr, LosM
}
STATIC INLINE VOID OsMemSetGapSize(LosMemCtlNode *ctlNode, UINT32 gapSize)
{//设置节点的间隙大小。
{
ctlNode->gapSize = gapSize;
}
STATIC VOID OsMemNodeSave(LosMemDynNode *node)
{//保存节点的状态信息
{
OsMemSetGapSize(&(node->selfNode), 0);
OsMemChecksumSet(&(node->selfNode));
OsMemBackupSetup(node);
}
STATIC VOID OsMemNodeSaveWithGapSize(LosMemDynNode *node, UINT32 gapSize)
{//保存节点的状态信息,并设置间隙大小。
{
OsMemSetGapSize(&(node->selfNode), gapSize);
OsMemChecksumSet(&(node->selfNode));
OsMemBackupSetup(node);
}
STATIC VOID OsMemListDelete(LOS_DL_LIST *node, const VOID *firstNode)
{//从链表中删除节点
{
LosMemDynNode *dynNode = NULL;
node->pstNext->pstPrev = node->pstPrev;
@ -562,7 +528,7 @@ STATIC VOID OsMemListDelete(LOS_DL_LIST *node, const VOID *firstNode)
}
STATIC VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, const VOID *firstNode)
{//将节点添加到链表中
{
LosMemDynNode *dynNode = NULL;
node->pstNext = listNode->pstNext;
@ -581,7 +547,6 @@ STATIC VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, const VOID *f
}
VOID LOS_MemBadNodeShow(VOID *pool)
//遍历给定内存池中的内存动态节点,检查节点的校验和,然后打印出错的节点以及其前一个节点的信息。
{
LosMemDynNode *nodePre = NULL;
LosMemDynNode *tmpNode = NULL;
@ -619,7 +584,7 @@ VOID LOS_MemBadNodeShow(VOID *pool)
#else /* without LOSCFG_MEM_HEAD_BACKUP */
STATIC VOID OsMemListDelete(LOS_DL_LIST *node, const VOID *firstNode)
{//从双向链表中删除指定的节点
{
(VOID)firstNode;
node->pstNext->pstPrev = node->pstPrev;
node->pstPrev->pstNext = node->pstNext;
@ -628,7 +593,7 @@ STATIC VOID OsMemListDelete(LOS_DL_LIST *node, const VOID *firstNode)
}
STATIC VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, const VOID *firstNode)
{//将节点添加到双向链表中
{
(VOID)firstNode;
node->pstNext = listNode->pstNext;
node->pstPrev = listNode;
@ -639,9 +604,6 @@ STATIC VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, const VOID *f
#endif
#ifdef LOSCFG_MEM_LEAKCHECK
//用于注册内存动态节点并记录它的链路寄存器信息。具体来说,
//该函数会将当前节点的 linkReg 数组清零,并调用 ArchGetFp 函数获取当前栈帧指针,
//然后调用 ArchBackTraceGet 函数获取从当前栈帧开始的函数调用链信息并保存在 linkReg 数组中。
__attribute__((always_inline)) inline VOID OsMemLinkRegisterRecord(LosMemDynNode *node)
{
UINTPTR framePtr;
@ -654,9 +616,6 @@ __attribute__((always_inline)) inline VOID OsMemLinkRegisterRecord(LosMemDynNode
}
#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
//只有在开启了内存节点完整性检查、并且发现了内存节点错误时才会被调用。
//该函数用于打印出错节点和前一个节点的链路寄存器信息,以帮助进行故障排查和修复。
//如果定义了 LOSCFG_SHELL_EXCINFO_DUMP 宏,则还会将信息输出到异常信息缓冲区中。
STATIC VOID OsMemNodeBacktraceInfo(const LosMemDynNode *tmpNode, const LosMemDynNode *preNode)
{
INT32 i;
@ -683,8 +642,6 @@ STATIC VOID OsMemNodeBacktraceInfo(const LosMemDynNode *tmpNode, const LosMemDyn
#endif
LITE_OS_SEC_TEXT_MINOR VOID OsMemUsedNodeShow(VOID *pool)
//打印出使用的内存节点和相关的链接寄存器。
//它接受一个指向内存池的指针作为参数,并遍历内存池中的节点来打印信息。
{
LosMemDynNode *tmpNode = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
@ -740,7 +697,6 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemUsedNodeShow(VOID *pool)
#ifdef LOSCFG_KERNEL_MEM_SLAB_EXTENTION
STATIC VOID *OsMemReallocSlab(VOID *pool, VOID *ptr, BOOL *isSlabMem, UINT32 size)
{
//在扩展内核内存时重新分配用于内存池的内存块。它接受一个指向内存池的指针、一个指向原始内存块的指针以及一个布尔值的指针作为参数,返回重新分配后的内存块指针。
errno_t rc;
UINT32 blkSz;
VOID *newPtr = NULL;
@ -780,15 +736,12 @@ STATIC VOID *OsMemReallocSlab(VOID *pool, VOID *ptr, BOOL *isSlabMem, UINT32 siz
}
VOID *OsMemAlloc(VOID *pool, UINT32 size)
//分配指定大小的内存块。它接受一个指向内存池的指针和一个大小参数,并返回分配的内存块指针。
{
return OsMemAllocWithCheck(pool, size);
}
#else
//与上述函数相同,但只在支持内存泄漏检测的情况下启用。(条件编译)
STATIC VOID *OsMemReallocSlab(VOID *pool, const VOID *ptr, BOOL *isSlabMem, UINT32 size)
{
*isSlabMem = FALSE;
@ -799,7 +752,6 @@ STATIC VOID *OsMemReallocSlab(VOID *pool, const VOID *ptr, BOOL *isSlabMem, UINT
#ifdef LOSCFG_EXC_INTERACTION
LITE_OS_SEC_TEXT_INIT UINT32 OsMemExcInteractionInit(UINTPTR memStart)
//初始化用于异常交互的内存。它接受一个起始内存地址参数,并返回初始化结果。
{
UINT32 ret;
m_aucSysMem0 = (UINT8 *)memStart;
@ -811,7 +763,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsMemExcInteractionInit(UINTPTR memStart)
#endif
LITE_OS_SEC_TEXT_INIT UINT32 OsMemSystemInit(UINTPTR memStart)
//初始化系统堆内存。它接受一个起始内存地址参数,并返回初始化结果。
{
UINT32 ret;
UINT32 poolSize;
@ -834,7 +785,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsMemSystemInit(UINTPTR memStart)
* tmpNode --- pointer a suitable free block
*/
STATIC INLINE LosMemDynNode *OsMemFindSuitableFreeBlock(VOID *pool, UINT32 allocSize)
{//在内存池中查找合适的空闲块以供分配使用的功能
{
LOS_DL_LIST *listNodeHead = NULL;
LosMemDynNode *tmpNode = NULL;
@ -874,17 +825,20 @@ STATIC INLINE LosMemDynNode *OsMemFindSuitableFreeBlock(VOID *pool, UINT32 alloc
return NULL;
}
STATIC INLINE VOID OsMemClearNode(LosMemDynNode *node)//将 LosMemDynNode 结构体清零。
/*
* Description : clear a mem node, set every member to NULL
* Input : node --- Pointer to the mem node which will be cleared up
*/
STATIC INLINE VOID OsMemClearNode(LosMemDynNode *node)
{
(VOID)memset_s((VOID *)node, sizeof(LosMemDynNode), 0, sizeof(LosMemDynNode));
}
STATIC INLINE VOID OsMemMergeNode(LosMemDynNode *node)//合并两个相邻的空闲节点。具体实现是将当前节点和后继节点合并成一个大的空闲节点,然后将当前节点清零。
LosMemDynNode *newFreeNode = NULL;
/*
* Description : merge this node and pre node, then clear this node info
* Input : node --- Pointer to node which will be merged
*/
STATIC INLINE VOID OsMemMergeNode(LosMemDynNode *node)
{
LosMemDynNode *nextNode = NULL;
@ -898,13 +852,18 @@ STATIC INLINE VOID OsMemMergeNode(LosMemDynNode *node)//合并两个相邻的空
OsMemClearNode(node);
}
/*
* Description : split new node from allocNode, and merge remainder mem if necessary
* Input : pool -- Pointer to memory pool
* allocNode -- the source node which the new node will split from it.
* After pick up it's node info, change to point to the new node
* allocSize -- the size of new node
* Output : allocNode -- save new node addr
*/
STATIC INLINE VOID OsMemSplitNode(VOID *pool,
LosMemDynNode *allocNode, UINT32 allocSize)
{//将一个空闲节点分割成两个,并将其中一个分配给需要的内存块。
//具体实现是在当前空闲节点上创建一个新的空闲节点,并将原有空闲节点的部分内存分配给新节点,
//再将新节点添加到对应链表中。
{
LosMemDynNode *newFreeNode = NULL;
LosMemDynNode *nextNode = NULL;
LOS_DL_LIST *listNodeHead = NULL;
const VOID *firstNode = (const VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);
@ -940,7 +899,7 @@ STATIC INLINE VOID OsMemSplitNode(VOID *pool,
* pool -- Pointer to memory pool
*/
STATIC INLINE VOID OsMemFreeNode(LosMemDynNode *node, LosMemPoolInfo *pool)
{//释放内存节点的,它包括了一些内存合并和链表操作
{
LosMemDynNode *nextNode = NULL;
LOS_DL_LIST *listNodeHead = NULL;
const VOID *firstNode = (const VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);
@ -983,7 +942,12 @@ STATIC INLINE VOID OsMemFreeNode(LosMemDynNode *node, LosMemPoolInfo *pool)
}
#ifdef LOSCFG_MEM_DEBUG
//OsMemIsNodeValid 和 OsMemCheckUsedNode 则是用来检查内存节点的有效性的函数
/*
* Description : check the result if pointer memory node belongs to pointer memory pool
* Input : pool -- Pointer to memory pool
* node -- the node which need be checked
* Return : LOS_OK or LOS_NOK
*/
STATIC INLINE BOOL OsMemIsNodeValid(const LosMemDynNode *node, const LosMemDynNode *startNode,
const LosMemDynNode *endNode,
const UINT8 *startPool, const UINT8 *endPool)
@ -1039,7 +1003,7 @@ STATIC INLINE VOID OsMemCheckUsedNode(const VOID *pool, const LosMemDynNode *nod
#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsMemPoolDlinkcheck(const LosMemPoolInfo *pool, LOS_DL_LIST listHead)
{//OsMemPoolDlinkcheck 则是用来检查内存池的双向链表的函数
{
if (((UINTPTR)listHead.pstPrev < (UINTPTR)(pool + 1)) ||
((UINTPTR)listHead.pstPrev >= ((UINTPTR)pool + pool->poolSize)) ||
((UINTPTR)listHead.pstNext < (UINTPTR)(pool + 1)) ||
@ -1057,7 +1021,7 @@ LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsMemPoolDlinkcheck(const LosMemPool
* Input : pool --Pointer to memory pool
*/
LITE_OS_SEC_TEXT_MINOR VOID OsMemPoolHeadInfoPrint(const VOID *pool)
{//打印内存池头部信息poolAddr, poolSize等以及检查内存池的双向链表是否异常如果异常则打印链表头的前后指针
{
const LosMemPoolInfo *poolInfo = (const LosMemPoolInfo *)pool;
UINT32 dlinkNum;
UINT32 flag = 0;
@ -1101,7 +1065,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemPoolHeadInfoPrint(const VOID *pool)
}
STATIC UINT32 OsMemIntegrityCheck(const VOID *pool, LosMemDynNode **tmpNode, LosMemDynNode **preNode)
{//检查整个内存池的完整性,并输出相关信息。具体实现是从第一个节点开始遍历,逐一检查节点的合法性。如果检测到错误,会触发系统崩溃
{
const LosMemPoolInfo *poolInfo = (const LosMemPoolInfo *)pool;
const UINT8 *endPool = (const UINT8 *)pool + poolInfo->poolSize;
@ -1154,7 +1118,7 @@ STATIC UINT32 OsMemIntegrityCheck(const VOID *pool, LosMemDynNode **tmpNode, Los
STATIC VOID OsMemNodeInfo(const LosMemDynNode *tmpNode,
const LosMemDynNode *preNode)
{//这个函数的作用是输出节点信息,包括节点前后指针、节点大小、堆栈信息等。同时还会输出相关的内存数据,方便调试。
{
if (tmpNode == preNode) {
PRINTK("\n the broken node is the first node\n");
#ifdef LOSCFG_SHELL_EXCINFO_DUMP
@ -1194,8 +1158,7 @@ STATIC VOID OsMemNodeInfo(const LosMemDynNode *tmpNode,
STATIC VOID OsMemIntegrityCheckError(const LosMemDynNode *tmpNode,
const LosMemDynNode *preNode)
{//当检测到内存池的完整性出现问题时,输出相关信息,并触发系统崩溃。
//同时,该函数会输出当前节点和前一个节点的信息,以及前一个节点的所属任务的相关信息。
{
LosTaskCB *taskCB = NULL;
UINT32 taskId;
@ -1234,9 +1197,7 @@ STATIC VOID OsMemIntegrityCheckError(const LosMemDynNode *tmpNode,
* Return : LOS_OK --memory pool integrate or LOS_NOK--memory pool impaired
*/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemIntegrityCheck(VOID *pool)
{//用于检查指定内存池的完整性。它首先对传入的参数进行空指针判断,
//然后获取互斥锁调用OsMemIntegrityCheck函数来检查内存池的完整性。
//如果检查失败则调用OsMemIntegrityCheckError函数进行错误处理并释放互斥锁
{
LosMemDynNode *tmpNode = NULL;
LosMemDynNode *preNode = NULL;
UINT32 intSave;
@ -1258,7 +1219,7 @@ ERROR_OUT:
return LOS_NOK;
}
VOID OsMemIntegrityMultiCheck(VOID)//进行多个内存池的完整性检查
VOID OsMemIntegrityMultiCheck(VOID)
{
if (LOS_MemIntegrityCheck(m_aucSysMem1) == LOS_OK) {
PRINTK("system memcheck over, all passed!\n");
@ -1276,7 +1237,6 @@ VOID OsMemIntegrityMultiCheck(VOID)//进行多个内存池的完整性检查
#endif
}
#else
//如果定义了宏LOSCFG_EXC_INTERACTION则调用LOS_MemIntegrityCheck函数来检查异常交互内存池m_aucSysMem0的完整性并输出检查结果。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemIntegrityCheck(VOID *pool)
{
return LOS_OK;
@ -1288,7 +1248,7 @@ VOID OsMemIntegrityMultiCheck(VOID)
#endif
STATIC INLINE VOID OsMemNodeDebugOperate(VOID *pool, LosMemDynNode *allocNode, UINT32 size)
{//用于内存节点的调试操作
{
#ifdef LOSCFG_MEM_HEAD_BACKUP
OsMemNodeSave(allocNode);
#endif
@ -1299,8 +1259,7 @@ STATIC INLINE VOID OsMemNodeDebugOperate(VOID *pool, LosMemDynNode *allocNode, U
}
STATIC UINT32 OsMemInfoGet(const VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)
{//获取指定内存池的信息。它首先对传入的参数进行类型转换和有效性检查,
//然后遍历内存池中的节点,统计已使用和空闲节点的数量、总大小等信息。
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
LosMemDynNode *tmpNode = NULL;
UINT32 totalUsedSize = 0;
@ -1343,7 +1302,7 @@ STATIC UINT32 OsMemInfoGet(const VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)
}
VOID OsMemInfoPrint(const VOID *pool)
{//打印内存池的信息
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
LOS_MEM_POOL_STATUS status = {0};
@ -1392,8 +1351,7 @@ STATIC INLINE VOID OsMemInfoAlert(const VOID *pool, UINT32 allocSize)
* Return : Pointer to allocated memory
*/
STATIC VOID *OsMemAllocWithCheck(LosMemPoolInfo *pool, UINT32 size)
{//分配内存的函数,它首先对要分配的内存大小进行一些处理,然后查找合适大小的空闲块,
//如果找到则进行分割和设置标记等操作,最后返回分配的内存块。
{
LosMemDynNode *allocNode = NULL;
UINT32 allocSize;
@ -1434,9 +1392,16 @@ STATIC VOID *OsMemAllocWithCheck(LosMemPoolInfo *pool, UINT32 size)
return (allocNode + 1);
}
/*
* Description : reAlloc a smaller memory node
* Input : pool --- Pointer to memory pool
* allocSize --- the size of new node which will be alloced
* node --- the node which will be realloced
* nodeSize --- the size of old node
* Output : node --- pointer to the new node after realloc
*/
STATIC INLINE VOID OsMemReAllocSmaller(LosMemPoolInfo *pool, UINT32 allocSize, LosMemDynNode *node, UINT32 nodeSize)
{//重新分配较小内存块的函数,它会判断是否可以将原有内存块进行分割,如果可以则进行相应的操作。
{
if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_ALIGN_SIZE) <= nodeSize) {
node->selfNode.sizeAndFlag = nodeSize;
OsMemSplitNode(pool, node, allocSize);
@ -1452,10 +1417,18 @@ STATIC INLINE VOID OsMemReAllocSmaller(LosMemPoolInfo *pool, UINT32 allocSize, L
#endif
}
/*
* Description : reAlloc a Bigger memory node after merge node and nextNode
* Input : pool --- Pointer to memory pool
* allocSize --- the size of new node which will be alloced
* node --- the node which will be realloced
* nodeSize --- the size of old node
* nextNode --- pointer next node which will be merged
* Output : node --- pointer to the new node after realloc
*/
STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(LosMemPoolInfo *pool, UINT32 allocSize, LosMemDynNode *node,
UINT32 nodeSize, LosMemDynNode *nextNode)
{//重新分配较大内存块的函数,它会判断是否需要合并相邻的内存块,并进行相应的操作。
{
const VOID *firstNode = (const VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);
node->selfNode.sizeAndFlag = nodeSize;
@ -1477,7 +1450,7 @@ STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(LosMemPoolInfo *pool, UINT32 a
}
STATIC UINT32 OsMemInit(VOID *pool, UINT32 size)
{//初始化内存池的函数,它会对内存池进行一些必要的初始化工作,包括设置头结点、尾结点,以及初始化统计信息等。
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
LosMemDynNode *newNode = NULL;
LosMemDynNode *endNode = NULL;
@ -1527,7 +1500,7 @@ STATIC UINT32 OsMemInit(VOID *pool, UINT32 size)
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemInit(VOID *pool, UINT32 size)
{//初始化内存池,其中包括对内存池的大小、对齐等进行检查,并调用相应的内部函数进行内存池的初始化工作。
{
UINT32 intSave;
if ((pool == NULL) || (size < OS_MEM_MIN_POOL_SIZE)) {
@ -1560,8 +1533,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemInit(VOID *pool, UINT32 size)
}
LITE_OS_SEC_TEXT VOID *LOS_MemAlloc(VOID *pool, UINT32 size)
{//从内存池中分配指定大小的内存块,
//其中包括调用 OsSlabMemAlloc 和 OsMemAllocWithCheck 等函数来实现内存的分配。
{
VOID *ptr = NULL;
UINT32 intSave;
@ -1592,7 +1564,7 @@ LITE_OS_SEC_TEXT VOID *LOS_MemAlloc(VOID *pool, UINT32 size)
}
LITE_OS_SEC_TEXT VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary)
{//按照指定的对齐边界来分配内存,其中包括对边界对齐和内存分配的相关处理。
{
UINT32 useSize;
UINT32 gapSize;
VOID *ptr = NULL;
@ -1650,7 +1622,7 @@ LITE_OS_SEC_TEXT VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundar
}
LITE_OS_SEC_TEXT STATIC INLINE VOID OsDoMemFree(VOID *pool, const VOID *ptr, LosMemDynNode *node)
{//释放内存,其中包括内存检查和内存释放等操作。
{
OsMemCheckUsedNode(pool, node);
OsMemFreeNode(node, pool);
@ -1662,7 +1634,7 @@ LITE_OS_SEC_TEXT STATIC INLINE VOID OsDoMemFree(VOID *pool, const VOID *ptr, Los
}
UINT32 OsMemFree(VOID *pool, const VOID *ptr)
{//释放内存,其中包括内存检查和内存释放等操作。
{
UINT32 ret = LOS_OK;
UINT32 gapSize;
LosMemDynNode *node = NULL;
@ -1701,7 +1673,7 @@ OUT:
}
LITE_OS_SEC_TEXT UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
{//判断了传入参数的有效性然后调用OsSlabMemFree和OsMemFree进行内存的释放操作并最终返回相应的状态码
{
UINT32 ret;
UINT32 intSave;
@ -1726,8 +1698,7 @@ OUT:
}
STATIC VOID *OsGetRealPtr(const VOID *pool, VOID *ptr)
{//根据传入的指针获取真正的内存地址,这个地址是动态内存块的起始地址。在获取真实地址之前,
//需要判断相邻内存块的标志位和大小是否正确,以保证获取到的内存地址是正确的。
{
VOID *realPtr = ptr;
UINT32 gapSize = *((UINT32 *)((UINTPTR)ptr - sizeof(UINT32)));
@ -1748,10 +1719,7 @@ STATIC VOID *OsGetRealPtr(const VOID *pool, VOID *ptr)
}
STATIC VOID *OsMemRealloc(VOID *pool, VOID *ptr, UINT32 size)
{//实现内存重新分配的功能。首先,它会根据传入的指针获取真正的内存地址,
//并对节点信息进行一系列的检查。如果需要重新分配的内存大小小于原有内存块的大小
//则直接将原有内存块作为新的内存块返回。
//否则,需要进行内存的合并或者申请新的内存块等操作。
{
LosMemDynNode *node = NULL;
LosMemDynNode *nextNode = NULL;
VOID *tmpPtr = NULL;
@ -1793,8 +1761,7 @@ STATIC VOID *OsMemRealloc(VOID *pool, VOID *ptr, UINT32 size)
}
LITE_OS_SEC_TEXT_MINOR VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size)
{//对OsMemRealloc和OsMemReallocSlab函数的封装。如果传入的内存池是Slab内存池
//则调用OsMemReallocSlab函数进行处理否则则调用OsMemRealloc函数进行处理。
{
UINT32 intSave;
VOID *newPtr = NULL;
BOOL isSlabMem = FALSE;
@ -1831,10 +1798,7 @@ OUT:
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTotalUsedGet(VOID *pool)
{//获取指定内存池已使用的总字节数。它通过遍历内存池中的动态内存节点,判断节点是否被使用,
//并累计已使用的字节数。
{
LosMemDynNode *tmpNode = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
UINT32 memUsed = 0;
@ -1859,8 +1823,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTotalUsedGet(VOID *pool)
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemUsedBlksGet(VOID *pool)
{//获取指定内存池已使用的内存块数量。
//它通过遍历内存池中的动态内存节点,判断节点是否被使用,并累计已使用的内存块数量。
{
LosMemDynNode *tmpNode = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
UINT32 blkNums = 0;
@ -1885,8 +1848,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemUsedBlksGet(VOID *pool)
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTaskIdGet(const VOID *ptr)
{//根据指针获取其所在的任务ID。它首先判断指针是否在系统内存范围内
//然后遍历内存池中的动态内存节点找到指针所在的内存块再获取该内存块所属的任务ID。
{
LosMemDynNode *tmpNode = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)(VOID *)m_aucSysMem1;
UINT32 intSave;
@ -1925,8 +1887,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTaskIdGet(const VOID *ptr)
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeBlksGet(VOID *pool)
{//获取指定内存池中空闲的内存块数量。
//它通过遍历内存池中的动态内存节点,判断节点是否空闲,并累计空闲的内存块数量。
{
LosMemDynNode *tmpNode = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
UINT32 blkNums = 0;
@ -1951,7 +1912,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeBlksGet(VOID *pool)
}
LITE_OS_SEC_TEXT_MINOR UINTPTR LOS_MemLastUsedGet(VOID *pool)
{//获取指定内存池最后一个使用的内存块的地址
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
LosMemDynNode *node = NULL;
@ -1975,8 +1936,7 @@ LITE_OS_SEC_TEXT_MINOR UINTPTR LOS_MemLastUsedGet(VOID *pool)
* Return : the number of free node
*/
LITE_OS_SEC_TEXT_MINOR VOID OsMemResetEndNode(VOID *pool, UINTPTR preAddr)
{//重置内存池的末尾节点。它将末尾节点的大小和标志设置为头节点的大小,并根据 preAddr 的值设置前一个节点的指针。
//然后它将该节点标记为已使用并设置魔术数和任务ID。
{
LosMemDynNode *endNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, ((LosMemPoolInfo *)pool)->poolSize);
endNode->selfNode.sizeAndFlag = OS_MEM_NODE_HEAD_SIZE;
if (preAddr != 0) {
@ -1990,7 +1950,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsMemResetEndNode(VOID *pool, UINTPTR preAddr)
#endif
}
UINT32 LOS_MemPoolSizeGet(const VOID *pool)//获取内存池的大小。如果传入的内存池为空,则返回错误。
UINT32 LOS_MemPoolSizeGet(const VOID *pool)
{
if (pool == NULL) {
return LOS_NOK;
@ -1999,9 +1959,7 @@ UINT32 LOS_MemPoolSizeGet(const VOID *pool)//获取内存池的大小。如果
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)
{//获取内存池的信息。它接受一个内存池指针和一个指向内存池状态结构体的指针作为参数。
//首先,它检查传入的指针是否为空,如果为空则返回错误。
//然后,它获取内存池的信息,并在获取完成后释放内存池的锁。
{
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
UINT32 ret;
UINT32 intSave;
@ -2024,7 +1982,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *po
}
STATIC INLINE VOID OsShowFreeNode(UINT32 index, UINT32 length, const UINT32 *countNum)
{//显示空闲节点的信息。它打印出每个块大小对应的节点数量。
{
UINT32 count = 0;
PRINTK("\n block size: ");
while (count < length) {
@ -2040,8 +1998,7 @@ STATIC INLINE VOID OsShowFreeNode(UINT32 index, UINT32 length, const UINT32 *cou
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeNodeShow(VOID *pool)
{//显示剩余的空闲节点数量。它遍历多重双向链表,
//统计每个链表头节点后面的节点数量,并调用 OsShowFreeNode 函数打印出结果。
{
LOS_DL_LIST *listNodeHead = NULL;
LosMultipleDlinkHead *headAddr = (LosMultipleDlinkHead *)((UINTPTR)pool + sizeof(LosMemPoolInfo));
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
@ -2086,7 +2043,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeNodeShow(VOID *pool)
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemNodeSizeCheck(VOID *pool, VOID *ptr, UINT32 *totalSize, UINT32 *availSize)
{//进行内存节点大小检查的函数
{
const VOID *head = NULL;
LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
UINT8 *endPool = NULL;
@ -2139,7 +2096,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemNodeSizeCheck(VOID *pool, VOID *ptr, UINT32
* attention : this func couldn't ensure the return memCtrl belongs to ptr it just find forward the most nearly one
*/
LITE_OS_SEC_TEXT_MINOR const VOID *OsMemFindNodeCtrl(const VOID *pool, const VOID *ptr)
{//查找内存池中指针所指的动态内存节点控制块,并返回其地址
{
const VOID *head = ptr;
if (ptr == NULL) {
@ -2157,7 +2114,7 @@ LITE_OS_SEC_TEXT_MINOR const VOID *OsMemFindNodeCtrl(const VOID *pool, const VOI
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemCheckLevelSet(UINT8 checkLevel)
{//用于设置内存检查级别,接受一个参数 checkLevel可以是 LOS_MEM_CHECK_LEVEL_LOW、LOS_MEM_CHECK_LEVEL_HIGH 或 LOS_MEM_CHECK_LEVEL_DISABLE
{
if (checkLevel == LOS_MEM_CHECK_LEVEL_LOW) {
PRINTK("%s: LOS_MEM_CHECK_LEVEL_LOW \n", __FUNCTION__);
} else if (checkLevel == LOS_MEM_CHECK_LEVEL_HIGH) {
@ -2173,13 +2130,13 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemCheckLevelSet(UINT8 checkLevel)
}
LITE_OS_SEC_TEXT_MINOR UINT8 LOS_MemCheckLevelGet(VOID)
{//获取当前的内存检查级别,直接返回全局变量 g_memCheckLevel 的值。
{
return g_memCheckLevel;
}
UINT32 OsMemSysNodeCheck(VOID *dstAddr, VOID *srcAddr, UINT32 nodeLength, UINT8 pos)
{//检查动态节点控制块的可用大小是否足够,以保证进行 memcpy 或 memset 操作时不会越界
{
UINT32 ret;
UINT32 totalSize = 0;
UINT32 availSize = 0;
@ -2223,7 +2180,7 @@ UINT32 OsMemSysNodeCheck(VOID *dstAddr, VOID *srcAddr, UINT32 nodeLength, UINT8
#ifdef LOSCFG_MEM_MUL_MODULE
STATIC INLINE UINT32 OsMemModCheck(UINT32 moduleId)
{//检查输入的模块 ID 是否有效
{
if (moduleId > MEM_MODULE_MAX) {
PRINT_ERR("error module ID input!\n");
return LOS_NOK;
@ -2232,7 +2189,7 @@ STATIC INLINE UINT32 OsMemModCheck(UINT32 moduleId)
}
STATIC INLINE VOID *OsMemPtrToNode(VOID *ptr)
{//将指针转换为动态节点控制块的地址
{
UINT32 gapSize;
if ((UINTPTR)ptr & (OS_MEM_ALIGN_SIZE - 1)) {
@ -2259,7 +2216,7 @@ STATIC INLINE VOID *OsMemPtrToNode(VOID *ptr)
}
STATIC INLINE UINT32 OsMemNodeSizeGet(VOID *ptr)
{//获取动态节点控制块中记录的节点大小
{
LosMemDynNode *node = (LosMemDynNode *)OsMemPtrToNode(ptr);
if (node == NULL) {
return 0;
@ -2269,7 +2226,7 @@ STATIC INLINE UINT32 OsMemNodeSizeGet(VOID *ptr)
}
VOID *LOS_MemMalloc(VOID *pool, UINT32 size, UINT32 moduleId)
{//在内存池中分配指定大小的内存,并进行模块 ID 的标记
{
UINT32 intSave;
VOID *ptr = NULL;
VOID *node = NULL;
@ -2290,8 +2247,7 @@ VOID *LOS_MemMalloc(VOID *pool, UINT32 size, UINT32 moduleId)
}
VOID *LOS_MemMallocAlign(VOID *pool, UINT32 size, UINT32 boundary, UINT32 moduleId)
{//与 LOS_MemMalloc 函数类似,区别在于它支持按照指定对齐边界分配内存。
//调用 LOS_MemAllocAlign 分配对齐内存,并执行与 LOS_MemMalloc 相同的操作
{
UINT32 intSave;
VOID *ptr = NULL;
VOID *node = NULL;
@ -2312,7 +2268,7 @@ VOID *LOS_MemMallocAlign(VOID *pool, UINT32 size, UINT32 boundary, UINT32 module
}
UINT32 LOS_MemMfree(VOID *pool, VOID *ptr, UINT32 moduleId)
{//用于释放指定的内存块
{
UINT32 intSave;
UINT32 ret;
UINT32 size;
@ -2345,15 +2301,7 @@ UINT32 LOS_MemMfree(VOID *pool, VOID *ptr, UINT32 moduleId)
}
VOID *LOS_MemMrealloc(VOID *pool, VOID *ptr, UINT32 size, UINT32 moduleId)
{//重新分配指定大小的内存块
//首先检查模块 ID 和内存池是否有效,如果无效则返回空指针。
//然后判断传入的指针是否为空,如果为空则调用 LOS_MemMalloc 分配新的内存块。
//接着将指针转换为动态节点控制块的地址,并判断节点的模块 ID 是否与传入的模块 ID 匹配,
//如果不匹配则打印错误信息并使用节点中记录的模块 ID 进行重新分配操作。如果新的大小为 0
//则调用 LOS_MemMfree 释放原来的内存块并返回空指针。
//最后调用 LOS_MemRealloc 进行内存块的重新分配,并更新模块使用的内存大小。
{
VOID *newPtr = NULL;
UINT32 oldNodeSize;
UINT32 intSave;
@ -2398,7 +2346,7 @@ VOID *LOS_MemMrealloc(VOID *pool, VOID *ptr, UINT32 size, UINT32 moduleId)
}
UINT32 LOS_MemMusedGet(UINT32 moduleId)
{//获取指定模块使用的内存大小
{
if (OsMemModCheck(moduleId) == LOS_NOK) {
return OS_NULL_INT;
}

@ -220,7 +220,7 @@ INT32 OsShellCmdSystemInfo(INT32 argc, const CHAR **argv)
}
#ifdef LOSCFG_SHELL
//注册Shell命令systeminfo调用OsShellCmdSystemInfo根据参数输出当前系统的程数量、信号量数量、互斥锁数量、消息队列数量和软件定时器数量。。
//注册Shell命令systeminfo调用OsShellCmdSystemInfo根据参数输出当前系统的程数量、信号量数量、互斥锁数量、消息队列数量和软件定时器数量。。
SHELLCMD_ENTRY(systeminfo_shellcmd, CMD_TYPE_EX, "systeminfo", 1, (CmdCallBackFunc)OsShellCmdSystemInfo);
#endif /* LOSCFG_SHELL */

@ -54,7 +54,7 @@ enum LOAD_STRATEGY {
ZIP,
NOZIP
};
/*这是一个枚举类型的定义名称为LOAD_STRATEGY。它包含两个成员ZIP和NOZIP。*/
/**
* @ingroup los_dynload
* Define the structure of the parameters used for dynamic.
@ -64,9 +64,7 @@ enum LOAD_STRATEGY {
typedef struct tagDynloadParam {
enum LOAD_STRATEGY enLoadStrategy;
} DYNLOAD_PARAM_S;
/*这个结构体可以用来存储动态加载的参数信息,
enLoadStrategyZIPNOZIP使
*/
/**
* @ingroup los_dynload
* @brief Register the dynamic parameters.
@ -86,8 +84,7 @@ typedef struct tagDynloadParam {
* @since Huawei LiteOS V100R001C00
*/
extern VOID LOS_DynParamReg(DYNLOAD_PARAM_S *dynloadParam);
/*通过调用LOS_DynParamReg函数并传递一个指向DYNLOAD_PARAM_S类型对象的指针
*/
/**
* @ingroup los_dynload
* @brief Load a shared object file.
@ -139,7 +136,7 @@ extern VOID *LOS_MemLoad(const CHAR *elfFileName, UINT32 fileNameLen,
const CHAR *elfFileBuf, UINT32 bufLen);
#endif /* LOSCFG_DYNLOAD_DYN_FROM_MEM */
#endif /* LOSCFG_KERNEL_DYNLOAD_DYN */
/*这段代码中使用了条件编译指令#ifdef和#endif用于在不同的编译环境下选择是否启用动态加载功能。*/
#ifdef LOSCFG_KERNEL_DYNLOAD_REL
/**
* @ingroup los_dynload
@ -163,9 +160,7 @@ extern VOID *LOS_MemLoad(const CHAR *elfFileName, UINT32 fileNameLen,
*/
extern VOID *LOS_ObjLoad(CHAR *elfFileName);
#endif /* LOSCFG_KERNEL_DYNLOAD_REL */
/*如果宏定义LOSCFG_KERNEL_DYNLOAD_REL被定义
LOS_ObjLoad
CHARVOID*/
/**
* @ingroup los_dynload
* @brief Unload a module.
@ -187,8 +182,7 @@ extern VOID *LOS_ObjLoad(CHAR *elfFileName);
* @since Huawei LiteOS V100R001C00
*/
extern INT32 LOS_ModuleUnload(VOID *handle);
/*通过调用LOS_ModuleUnload函数并传递一个动态库的句柄
*/
/**
* @ingroup los_dynload
* @brief Destroy a dynamic loader.
@ -209,9 +203,7 @@ extern INT32 LOS_ModuleUnload(VOID *handle);
* @since Huawei LiteOS V100R001C00
*/
extern VOID LOS_LdDestroy(VOID);
/*这段代码声明了一个外部函数LOS_LdDestroy该函数没有参数和返回值。
LOS_LdDestroyLoader*/
/**
* @ingroup los_dynload
* @brief Search for a symbol address.
@ -258,8 +250,7 @@ extern VOID *LOS_FindSymByName(VOID *handle, CHAR *name);
* @since Huawei LiteOS V100R001C00
*/
extern INT32 LOS_PathAdd(CHAR *path);
/*通过调用LOS_PathAdd函数并传递一个路径可以将该路径添加到动态库搜索路径中。
*/
/**
* @ingroup los_dynload
* @brief Set the memory pool address used by dynload
@ -282,9 +273,7 @@ extern INT32 LOS_PathAdd(CHAR *path);
* @since Huawei LiteOS V200R002C00
*/
extern BOOL LOS_DynMemPoolSet(VOID *memPool);
/*通过调用LOS_DynMemPoolSet函数并传递一个内存池指针
*/
#ifdef __cplusplus
#if __cplusplus
}

@ -50,10 +50,6 @@ typedef struct LOS_DL_LIST {
struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node */
struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node */
} LOS_DL_LIST;
/*这种结构体通常用于实现双向链表数据结构。
LOS_DL_LIST
*/
/**
* @ingroup los_list
@ -78,11 +74,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
list->pstNext = list;
list->pstPrev = list;
}
/*这段代码定义了一个静态内联函数LOS_ListInit
LOS_DL_LISTlist
pstNextpstPrev
*/
/**
* @ingroup los_list
* @brief Point to the next node of the current node.
@ -101,12 +93,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @since Huawei LiteOS V100R001C00
*/
#define LOS_DL_LIST_FIRST(object) ((object)->pstNext)
/*这段代码定义了一个宏LOS_DL_LIST_FIRST(object)
LOS_DL_LISTobject
object
便
访*/
/**
* @ingroup los_list
* @brief Point to the previous node of the current node.
@ -125,10 +112,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
* @since Huawei LiteOS V100R001C00
*/
#define LOS_DL_LIST_LAST(object) ((object)->pstPrev)
/*这段代码是一个宏定义,用于获取双向链表中指定节点的前一个节点。
object
pstPrev
*/
/**
* @ingroup los_list
* @brief Insert a new node to a doubly linked list.
@ -154,13 +138,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_
list->pstNext->pstPrev = node;
list->pstNext = node;
}
/*该函数将新节点插入到链表头部,具体步骤如下:
next
prev
prev
next
*/
/**
* @ingroup los_list
* @brief Insert a node to a doubly linked list.
@ -183,10 +161,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list,
{
LOS_ListAdd(list->pstPrev, node);
}
/*在该函数中,使用了宏定义 LOS_DL_LIST 来表示链表节点,
使 STATIC INLINE
LOS_ListAdd
*/
/**
* @ingroup los_list
* @brief Insert a node to a doubly linked list.
@ -235,12 +210,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
node->pstNext = NULL;
node->pstPrev = NULL;
}
/*该函数的实现非常简单,具体步骤如下:
next prev prev
prev next next
next prev
*/
/**
* @ingroup los_list
* @brief Identify whether a specified doubly linked list is empty or not.
@ -263,12 +233,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
{
return (BOOL)(list->pstNext == list);
}
/*具体步骤如下:
pstNext
TRUE
FALSE
*/
/**
* @ingroup los_list
* @brief Obtain the offset of a structure member relative to the structure start address.
@ -291,10 +256,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
/* Obsolete API, please use LOS_OFF_SET_OF instead */
#define OFFSET_OF_FIELD(type, field) LOS_OFF_SET_OF(type, field)
/*这些宏的作用是帮助程序员在编写代码时可以方便地获取结构体成员的偏移量。
*/
/**
* @ingroup los_list
* @brief Obtain the pointer to a structure that contains a doubly linked list.
@ -347,12 +309,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member); \
&(item)->member != (list); \
item = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member))
/*宏的实现通过 for 循环来实现链表的遍历,具体步骤如下:
使 LOS_DL_LIST_ENTRY item
&(item)->member != (list)
使 LOS_DL_LIST_ENTRY
便*/
/**
* @ingroup los_list
* @brief Traverse a doubly linked list which is included in a given type structure. And
@ -386,13 +343,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
next = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member); \
&(item)->member != (list); \
item = next, next = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member))
/*该宏的功能是按顺序遍历链表中的每个节点,并对每个节点执行指定的操作。其参数包括:
item
next
list
type
member*/
/**
* @ingroup los_list
* @brief Iterate over a doubly linked list of given type, and call hook for any extra procedures every time.
@ -419,13 +370,7 @@ member
for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member), hook; \
&(item)->member != (list); \
item = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member), hook)
/*该宏的功能是按顺序遍历链表中的每个节点,并在每个节点遍历之前执行指定的钩子函数。其参数包括:
item
list
type
member
hook*/
/**
* @ingroup los_list
* @brief Delete a specified node from a doubly linked list and reinitialize the node.
@ -451,7 +396,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
list->pstPrev->pstNext = list->pstNext;
LOS_ListInit(list);
}
/**/
/**
* @ingroup los_list
* @brief Traverse a doubly linked list.
@ -478,12 +423,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
for (item = (list)->pstNext; \
(item) != (list); \
item = (item)->pstNext)
/*宏的实现通过 for 循环来实现链表的遍历,具体步骤如下:
item (list)->pstNext
(item) != (list) item
item (item)->pstNext
便*/
/**
* @ingroup los_list
* @brief Traverse a doubly linked list safe against removal of list entry.
@ -535,7 +475,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list)
* @since Huawei LiteOS V100R001C00
*/
#define LOS_DL_LIST_HEAD(list) LOS_DL_LIST list = { &(list), &(list) }
/*通过这个宏,可以方便地定义和初始化一个双向链表的头部节点,为链表的后续操作提供了便利。*/
#ifdef __cplusplus
#if __cplusplus
}

@ -51,30 +51,18 @@ extern "C" {
#define memmove_s KasanMemmoveSec
#define strcat_s KasanStrcatSec
#define strcpy_s KasanStrcpySec
/*使用#define预处理指令来重新定义标准库函数的名称。这种技术通常用于调试或测试目的或者提供这些函数的自定义实现。
memcpymemmovestrcatstrcpyKasanMemcpy
KasanMemmoveKasanStrcatKasanStrcpymemcpy_smemmove_sstrcat_sstrcpy_s
KasanMemcpySecKasanMemmoveSecKasanStrcatSecKasanStrcpySec*/
// End: Kernel Address Sanitizer(KASAN) for LiteOS
VOID *KasanMemcpy(VOID *__restrict dest, const VOID *__restrict src, size_t copyAmount);
VOID *KasanMemmove(VOID *dest, const VOID *src, size_t len);
CHAR *KasanStrcat(CHAR *s, const CHAR *append);
CHAR *KasanStrcpy(CHAR *dest, const CHAR *src);
/*KasanMemcpy类似于标准库中的memcpy用于在内存中复制一定数量的数据。可能会包含额外的内存访问检查。
KasanMemmovememmove访
KasanStrcatstrcat访
KasanStrcpystrcpy访*/
errno_t KasanMemcpySec(VOID *dest, size_t destMax, const VOID *src, size_t copyAmount);
errno_t KasanMemmoveSec(VOID *dest, size_t destMax, const VOID *src, size_t len);
errno_t KasanStrcatSec(CHAR *s, size_t destMax, const CHAR *append);
errno_t KasanStrcpySec(CHAR *dest, size_t destMax, const CHAR *src);
/*主要是用于处理字符串和内存拷贝操作。这里的 destMax 参数通常表示目标缓冲区的最大长度,以防止缓冲区溢出等安全问题。
KasanMemcpySecmemcpy
KasanMemmoveSecmemmove
KasanStrcatSecstrcat
KasanStrcpySecstrcpy*/
#endif /* LOSCFG_KERNEL_LMS */
#ifdef __cplusplus

@ -55,33 +55,20 @@ enum LockDepErrType {
/* overflow, needs expand */
LOCKDEP_ERR_OVERFLOW,
};
/*这是一个枚举类型 LockDepErrType用于表示在锁依赖性检查中可能发生的不同错误类型。下面是该枚举类型定义的各个取值及其含义
LOCKDEP_SUCCESS
LOCKDEP_ERR_DOUBLE_LOCK线
LOCKDEP_ERR_DEAD_LOCK线
LOCKDEP_ERR_UNLOCK_WITHOUT_LOCK线线
LOCKDEP_ERR_OVERFLOW*/
typedef struct {
VOID *lockPtr;
VOID *lockAddr;
UINT64 waitTime;
UINT64 holdTime;
} HeldLocks;
/*这个结构体主要用于在锁依赖性分析和调试过程中记录当前线程持有的锁的相关信息。通过记录这些信息,
使便
lockPtr VOID*
lockAddr VOID*
waitTime UINT64 线
holdTime UINT64 线*/
typedef struct {
VOID *waitLock;
INT32 lockDepth;
HeldLocks heldLocks[MAX_LOCK_DEPTH];
} LockDep;
/*这个结构体主要用于在锁依赖性分析和调试过程中记录当前线程的锁依赖关系。
线
使便*/
/**
* @ingroup los_lockdep
*
@ -101,8 +88,7 @@ typedef struct {
* @since Huawei LiteOS V200R003C00
*/
extern VOID OsLockDepCheckIn(const SPIN_LOCK_S *lock);
/*函数名称为 OsLockDepCheckIn参数类型为 const SPIN_LOCK_S* lock返回类型为 VOID。该函数的作用是将指定
lock */
/**
* @ingroup los_lockdep
*
@ -142,8 +128,7 @@ extern VOID OsLockDepRecord(SPIN_LOCK_S *lock);
* @since Huawei LiteOS V200R003C00
*/
extern VOID OsLockDepCheckOut(SPIN_LOCK_S *lock);
/*函数名称为 OsLockDepCheckOut参数类型为 SPIN_LOCK_S* lock返回类型为 VOID。该函数的作用
lock*/
/**
* @ingroup los_lockdep
*

@ -57,14 +57,7 @@ typedef enum LOS_INTERMIT_MODE {
LOS_INTERMIT_SHUTDOWN, /**< Shutdown mode */
LOS_INTERMIT_MAX,
} LosIntermitMode;
/*这是一个枚举类型 LOS_INTERMIT_MODE 的定义,包含了几个枚举常量:
LOS_INTERMIT_NONE
LOS_INTERMIT_LIGHT_SLEEP
LOS_INTERMIT_DEEP_SLEEP
LOS_INTERMIT_STANDBY
LOS_INTERMIT_SHUTDOWN
LOS_INTERMIT_MAX*/
/**
* @ingroup los_lowpower
*
@ -77,13 +70,7 @@ typedef enum LOS_FREQ_MODE {
LOS_SYS_FREQ_LOW, /**< Low freq */
LOS_SYS_FREQ_MAX,
} LosFreqMode;
/*这是另一个枚举类型 LOS_FREQ_MODE 的定义,包含了几个枚举常量:
LOS_SYS_FREQ_SUPER
LOS_SYS_FREQ_HIGH
LOS_SYS_FREQ_NORMAL
LOS_SYS_FREQ_LOW
LOS_SYS_FREQ_MAX*/
typedef UINT32 (*LowpowerExternalVoterHandle)(VOID);
STATIC INLINE BOOL FreqHigher(LosFreqMode freq1, LosFreqMode freq2)
@ -109,19 +96,7 @@ typedef struct {
UINT32 (*getSleepMode)(VOID); /**< Get sleep mode interface, the retval type is LosIntermitMode */
VOID (*setSleepMode)(UINT32 mode); /**< Set sleep mode interface, the param type is LosIntermitMode */
} PowerMgrOps;
/*这是一个结构体类型 PowerMgrOps 的定义,包含了多个函数指针成员:
process
wakeupFromReset
resumeFromInterrupt
changeFreq LosFreqMode
deepSleepVoteBegin
deepSleepVoteEnd
deepSleepVoteDelay
registerExternalVoter UINT32
getDeepSleepVoteCount UINT32
getSleepMode LosIntermitMode
setSleepMode UINT32 LosIntermitMode*/
/**
* @ingroup los_lowpower
* @brief System main frequency tuning.
@ -140,9 +115,7 @@ setSleepMode
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_PowerMgrChangeFreq(LosFreqMode freq);
/*这是一个外部声明extern的函数 LOS_PowerMgrChangeFreq
LosFreqMode freq
*/
/**
* @ingroup los_lowpower
* @brief Vote to enter deep sleep.
@ -180,8 +153,7 @@ extern VOID LOS_PowerMgrDeepSleepVoteBegin(VOID);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_PowerMgrDeepSleepVoteEnd(VOID);
/*这是一个外部声明extern的函数 LOS_PowerMgrDeepSleepVoteEnd它没有任何参数返回类型为 VOID。根据函数名来看
*/
/**
* @ingroup los_lowpower
* @brief Sleep delay vote.
@ -200,8 +172,7 @@ extern VOID LOS_PowerMgrDeepSleepVoteEnd(VOID);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_PowerMgrSleepDelay(UINT32 tick);
/*这是一个外部声明extern的函数 LOS_PowerMgrSleepDelay它接受一个 UINT32 类型的参数 tick
*/
/**
* @ingroup los_lowpower
* @brief Register the external voter.
@ -220,9 +191,7 @@ extern VOID LOS_PowerMgrSleepDelay(UINT32 tick);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_PowerMgrRegisterExtVoter(UINT32 (*)(VOID));
/*这是一个外部声明extern的函数 LOS_PowerMgrRegisterExtVoter
UINT32
*/
/**
* @ingroup los_lowpower
* @brief Get the sleep mode.
@ -281,9 +250,7 @@ extern UINT32 LOS_PowerMgrGetDeepSleepVoteCount(VOID);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_LowpowerInit(const PowerMgrOps *pmOps);
/*这是一个外部声明extern的函数 LOS_LowpowerInit
const PowerMgrOps * pmOps
便*/
/**
* @ingroup los_lowpower
* @brief Define the lowpower framework process function type.
@ -302,10 +269,7 @@ extern VOID LOS_LowpowerInit(const PowerMgrOps *pmOps);
* @since Huawei LiteOS V200R005C10
*/
typedef VOID (*LowPowerHookFn)(VOID);
/*这是一个类型定义语句,定义了一个名为 LowPowerHookFn 的函数指针类型。
VOID
便退*/
/**
* @ingroup los_lowpower
* @brief Register a hook to enter lowpower framework process.
@ -324,10 +288,7 @@ typedef VOID (*LowPowerHookFn)(VOID);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_LowpowerHookReg(LowPowerHookFn hook);
/*这是一个外部声明extern的函数 LOS_LowpowerHookReg
LowPowerHookFn hook
便退*/
/**
* @ingroup los_lowpower
* @brief Define the lowpower framework wakup function type.
@ -346,10 +307,7 @@ extern VOID LOS_LowpowerHookReg(LowPowerHookFn hook);
* @since Huawei LiteOS V200R005C10
*/
typedef VOID (*IntWakeupHookFn)(HWI_HANDLE_T hwiNum);
/*这是一个类型定义语句,定义了一个名为 IntWakeupHookFn 的函数指针类型。
HWI_HANDLE_T VOID
便
*/
/**
* @ingroup los_lowpower
* @brief Register a hook to wakeup from interrupt.
@ -368,11 +326,7 @@ typedef VOID (*IntWakeupHookFn)(HWI_HANDLE_T hwiNum);
* @since Huawei LiteOS V200R005C10
*/
extern VOID LOS_IntWakeupHookReg(IntWakeupHookFn hook);
/*这是一个外部声明extern的函数 LOS_IntWakeupHookReg
IntWakeupHookFn hook
便
*/
#ifdef __cplusplus
#if __cplusplus
}

@ -59,22 +59,7 @@ typedef struct {
UINT32 (*getSleepMode)(VOID); /**< Get sleep mode */
VOID (*setSleepMode)(UINT32 mode); /**< Set sleep mode */
} PowerMgrRunOps;
/*具体来说,该结构体包含以下函数指针成员:
changeFreq
enterLightSleeplight sleep
enterDeepSleepdeep sleep
setWakeUpTimer
withdrawWakeUpTimer
getSleepTime
selectSleepMode
preConfig
postConfig
contextSave
contextRestore
getDeepSleepVoteCount
getSleepMode
setSleepMode*/
/**
* @ingroup los_lowpower
*
@ -85,11 +70,7 @@ typedef struct {
UINT32 minDeepSleepTicks; /**< Min deep sleep ticks */
UINT32 maxDeepSleepTicks; /**< Max deep sleep ticks */
} PowerMgrConfig;
/*minLightSleepTicks最小轻度睡眠light sleep时钟周期数。
minDeepSleepTicksdeep sleep
maxDeepSleepTicksdeep sleep
使*/
/**
* @ingroup los_lowpower
*
@ -107,16 +88,7 @@ typedef struct {
VOID (*otherCoreResume)(VOID); /**< Other core Resume for multi-core scenes */
VOID (*resumeFromReset)(VOID); /**< Resume from image */
} PowerMgrDeepSleepOps;
/*couldDeepSleep检查系统是否可以进入深度睡眠状态。
systemWakeup
suspendPreConfig
suspendDevice
rollback
resumeDevice
resumePostConfig
resumeCallBack
otherCoreResume
resumeFromReset*/
/**
* @ingroup los_lowpower
*
@ -127,10 +99,7 @@ typedef struct {
PowerMgrDeepSleepOps deepSleepOps; /**< power manager deep sleep operations */
PowerMgrConfig config; /**< power manager config */
} PowerMgrParameter;
/*runOps类型为 PowerMgrRunOps 的结构体变量,用于描述系统运行状态下的功耗管理操作集合。
deepSleepOps PowerMgrDeepSleepOps
config PowerMgrConfig
PowerMgrParameter */
/**
* @ingroup los_lowpower
* @brief Init the power manager framework.

@ -75,17 +75,7 @@ extern "C" {
* Head size of each node in staic memory pool
*/
#define OS_MEMBOX_NODE_HEAD_SIZE sizeof(LOS_MEMBOX_NODE)
/*LOS_MEMBOX_ALLIGNED(memAddr) 宏用于对内存地址进行对齐操作。
memAddr UINTPTR sizeof(UINTPTR) -
1 ~(sizeof(UINTPTR) - 1)
sizeof(UINTPTR)
OS_MEMBOX_NEXT(addr, blkSize)
addr UINT8* blkSize
OS_MEMBOX_NODE_HEAD_SIZE LOS_MEMBOX_NODE
*/
/**
* @ingroup los_membox
* @brief Obtain the size of the static memory pool.
@ -108,10 +98,7 @@ OS_MEMBOX_NODE_HEAD_SIZE
*/
#define LOS_MEMBOX_SIZE(blkSize, blkNum) \
(sizeof(LOS_MEMBOX_INFO) + (LOS_MEMBOX_ALLIGNED((blkSize) + OS_MEMBOX_NODE_HEAD_SIZE) * (blkNum)))
/*该宏首先使用 LOS_MEMBOX_ALLIGNED 宏对 (blkSize) + OS_MEMBOX_NODE_HEAD_SIZE 进行对齐操作,确保每个内存块都按照节点大小对齐。然后将对齐后的大小乘以 blkNum并加上 sizeof(LOS_MEMBOX_INFO),得到静态内存池的总大小。
sizeof(LOS_MEMBOX_INFO)
*/
/**
* @ingroup los_membox
* Structure of a free node in a static memory pool
@ -137,11 +124,7 @@ typedef struct {
} LOS_MEMBOX_INFO;
typedef LOS_MEMBOX_INFO OS_MEMBOX_S;
/*LOS_MEMBOX_INFO静态内存池的元信息结构体。包含了静态内存池的起始地址、
uwBlkCnt
stFreeList LOSCFG_KERNEL_MEMBOX_STATIC
OS_MEMBOX_S LOS_MEMBOX_INFO */
/**
* @ingroup los_membox
* @brief Initialize a static memory pool.
@ -170,8 +153,7 @@ OS_MEMBOX_S
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize);
/*该函数会使用提供的内存池起始地址和大小来初始化静态内存池,并指定每个内存块的大小。
*/
/**
* @ingroup los_membox
* @brief Request a static memory block.
@ -220,7 +202,7 @@ extern VOID *LOS_MemboxAlloc(VOID *pool);
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemboxFree(VOID *pool, VOID *box);
/*调用该函数将会释放 box 所指向的内存块,并将其重新加入到内存池的空闲内存块链表中,以便下次分配使用。*/
/**
* @ingroup los_membox
* @brief Clear a static memory block.
@ -244,8 +226,7 @@ extern UINT32 LOS_MemboxFree(VOID *pool, VOID *box);
* @since Huawei LiteOS V100R001C00
*/
extern VOID LOS_MemboxClr(VOID *pool, VOID *box);
/*调用该函数将会将 box 所指向的内存块的数据内容清零,使其变为初始状态。
使*/
/**
* @ingroup los_membox
* @brief show static memory pool information.
@ -296,9 +277,7 @@ extern VOID LOS_ShowBox(VOID *pool);
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemboxStatisticsGet(const VOID *boxMem, UINT32 *maxBlk, UINT32 *blkCnt, UINT32 *blkSize);
/*调用该函数将会获取静态内存池的统计信息,包括最大可分配内存块数量、
使*/
#ifdef __cplusplus
#if __cplusplus
}

@ -155,12 +155,7 @@ extern UINTPTR g_excInteractMemSize;
* @since Huawei LiteOS V100R001C00
*/
extern VOID *LOS_MemMalloc(VOID *pool, UINT32 size, UINT32 moduleId);
/*pool指向内存池起始地址的指针。
size
moduleId ID
size
NULL
ID moduleId 使*/
/**
* @ingroup los_memory
* @brief Allocate aligned memory.
@ -190,10 +185,7 @@ moduleId
* @since Huawei LiteOS V100R001C00
*/
extern VOID *LOS_MemMallocAlign(VOID *pool, UINT32 size, UINT32 boundary, UINT32 moduleId);
/*调用该函数将会在指定的内存池中按照指定的对齐边界boundary分配大小为 size 的内存块,并将其地址返回给调用者。
boundary
NULL
ID moduleId 使*/
/**
* @ingroup los_memory
* @brief Free dynamic memory.
@ -220,9 +212,7 @@ extern VOID *LOS_MemMallocAlign(VOID *pool, UINT32 size, UINT32 boundary, UINT32
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemMfree(VOID *pool, VOID *ptr, UINT32 moduleId);
/*调用该函数将会释放由 ptr 指向的内存块,并将其归还给指定的内存池。同时,通过 moduleId 参数指定要释放的内存块所属的模块 ID以便进行相关的内存管理操作。
LOS_MemMalloc LOS_MemMallocAlign */
/**
* @ingroup los_memory
* @brief Re-allocate a memory block.
@ -334,14 +324,7 @@ typedef struct {
UINT32 uwUsageWaterLine; /**< this structure member is defined only when LOSCFG_MEM_TASK_STAT is defined. */
#endif
} LOS_MEM_POOL_STATUS;
/*uwTotalUsedSize内存池中已使用的总大小单位字节
uwTotalFreeSize使
uwMaxFreeNodeSize
uwUsedNodeNum使
uwFreeNodeNum使
uwUsageWaterLine LOSCFG_MEM_TASK_STAT 使线使
使使使
LOSCFG_MEM_TASK_STAT使线*/
/**
* @ingroup los_memory
* @brief Initialize dynamic memory.
@ -370,8 +353,7 @@ uwUsageWaterLine
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemInit(VOID *pool, UINT32 size);
/*调用该函数将会对指定的内存池进行初始化操作,使其具备可用于分配和管理内存块的能力。
*/
/**
* @ingroup los_memory
* @brief Allocate dynamic memory.
@ -398,8 +380,7 @@ extern UINT32 LOS_MemInit(VOID *pool, UINT32 size);
* @since Huawei LiteOS V100R001C00
*/
extern VOID *LOS_MemAlloc(VOID *pool, UINT32 size);
/*通过该函数可以动态地从内存池中获取一块指定大小的内存块,以满足程序运行时的内存需求。分配的内存块可以根据实际需要进行读写操作
*/
/**
* @ingroup los_memory
* @brief Free dynamic memory.
@ -463,7 +444,7 @@ extern UINT32 LOS_MemFree(VOID *pool, VOID *ptr);
* @since Huawei LiteOS V100R001C00
*/
extern VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size);
//通过该函数可以动态地调整已分配内存块的大小,以满足程序运行时动态变化的内存需求。
/**
* @ingroup los_memory
* @brief Allocate aligned memory.
@ -491,9 +472,7 @@ extern VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size);
* @since Huawei LiteOS V100R001C00
*/
extern VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary);
/*通过该函数可以动态地从内存池中获取一块指定大小并满足对齐要求的内存块,
*/
/**
* @ingroup los_memory
* @brief Get the size of memory pool's size.
@ -634,9 +613,7 @@ extern UINTPTR LOS_MemLastUsedGet(VOID *pool);
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus);
/*调用该函数将会获取指定内存池的状态信息,并将其保存到指定的 LOS_MEM_POOL_STATUS 结构体中。如果获取成功,返回 LOS_OK否则返回错误码。
使便*/
/**
* @ingroup los_memory
* @brief Get the number of free node in every size.
@ -681,10 +658,6 @@ extern UINT32 LOS_MemFreeNodeShow(VOID *pool);
extern UINT32 LOS_MemIntegrityCheck(VOID *pool);
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
/*调用该函数将会对指定的内存池进行完整性检查,以确保内存池中分配的内存块没有损坏或越界等问题。如果检查通过,返回 LOS_OK否则返回错误码。
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
*/
/**
* @ingroup los_memory
* @brief Check the size of the specified memory node.
@ -717,9 +690,7 @@ extern UINT32 LOS_MemIntegrityCheck(VOID *pool);
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MemNodeSizeCheck(VOID *pool, VOID *ptr, UINT32 *totalSize, UINT32 *availSize);
/*调用该函数将会检查指定内存池中给定内存节点的大小,并将总大小和可用大小分别保存到指定的变量中。如果检查成功,返回 LOS_OK否则返回错误码。
使使*/
/**
* @ingroup los_memory
* @brief Set the memory check level.

@ -54,10 +54,7 @@ extern "C" {
* Solution: Decrease the number of mutexes defined by LOSCFG_BASE_IPC_MUX_LIMIT.
*/
#define LOS_ERRNO_MUX_NO_MEMORY LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x00)
/*这段代码定义了一个名为 LOS_ERRNO_MUX_NO_MEMORY 的宏,用于表示互斥锁分配内存失败的错误码。
LOS_ERRNO_OS_ERROR LOS_MOD_MUX
0x00 */
/**
* @ingroup los_mux
* Mutex error code: The mutex is not usable.
@ -67,7 +64,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Check whether the mutex ID and the mutex state are applicable for the current operation.
*/
#define LOS_ERRNO_MUX_INVALID LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x01)
//LOS_ERRNO_OS_ERROR 是一个宏用于生成具有模块和错误码的错误码值。在这里LOS_MOD_MUX 表示错误所属的模块是互斥锁模块0x01 是该错误码在该模块中的具体数值。
/**
* @ingroup los_mux
* Mutex error code: Null pointer.
@ -77,8 +74,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Check whether the input parameter is usable.
*/
#define LOS_ERRNO_MUX_PTR_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x02)
//这段代码定义了一个名为 LOS_ERRNO_MUX_PTR_NULL 的宏,用于表示互斥锁指针为空的错误码。
//LOS_ERRNO_OS_ERROR 是一个宏用于生成具有模块和错误码的错误码值。在这里LOS_MOD_MUX 表示错误所属的模块是互斥锁模块0x02 是该错误码在该模块中的具体数值。
/**
* @ingroup los_mux
* Mutex error code: No mutex is available and the mutex request fails.
@ -88,9 +84,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Increase the number of mutexes defined by LOSCFG_BASE_IPC_MUX_LIMIT.
*/
#define LOS_ERRNO_MUX_ALL_BUSY LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x03)
/*这段代码定义了一个名为 LOS_ERRNO_MUX_ALL_BUSY 的宏,用于表示互斥锁已全部被占用的错误码。
LOS_ERRNO_OS_ERROR LOS_MOD_MUX 0x03 */
/**
* @ingroup los_mux
* Mutex error code: The mutex fails to be locked in non-blocking mode because it is locked by another thread.
@ -100,9 +94,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Lock the mutex after it is unlocked by the thread that owns it, or set a waiting time.
*/
#define LOS_ERRNO_MUX_UNAVAILABLE LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x04)
/*这段代码定义了一个名为 LOS_ERRNO_MUX_UNAVAILABLE 的宏,用于表示互斥锁不可用的错误码。
LOS_ERRNO_OS_ERROR LOS_MOD_MUX 0x04 */
/**
* @ingroup los_mux
* Mutex error code: The mutex is being locked during an interrupt.
@ -112,9 +104,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Check whether the mutex is being locked during an interrupt.
*/
#define LOS_ERRNO_MUX_PEND_INTERR LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x05)
/*这段代码定义了一个名为 LOS_ERRNO_MUX_PEND_INTERR 的宏,用于表示互斥锁等待被阻塞时发生中断错误的错误码。
LOS_ERRNO_OS_ERROR LOS_MOD_MUX 0x05 */
/**
* @ingroup los_mux
* Mutex error code: A thread locks a mutex after waiting for the mutex to be unlocked by another thread
@ -126,9 +116,7 @@ LOS_ERRNO_OS_ERROR
* thread will not wait for the mutex to become available.
*/
#define LOS_ERRNO_MUX_PEND_IN_LOCK LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x06)
/*这段代码定义了一个名为 LOS_ERRNO_MUX_PEND_IN_LOCK 的宏,用于表示在互斥锁上等待时发生死锁错误的错误码。
LOS_ERRNO_OS_ERROR LOS_MOD_MUX 0x06 */
/**
* @ingroup los_mux
* Mutex error code: The mutex locking times out.
@ -138,7 +126,7 @@ LOS_ERRNO_OS_ERROR
* Solution: Increase the waiting time or set the waiting time to LOS_WAIT_FOREVER (forever-blocking mode).
*/
#define LOS_ERRNO_MUX_TIMEOUT LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x07)
//LOS_ERRNO_OS_ERROR 是一个宏用于生成具有模块和错误码的错误码值。在这里LOS_MOD_MUX 表示错误所属的模块是互斥锁模块0x07 是该错误码在该模块中的具体数值。
/**
* @ingroup los_mux
* The error code is not in use temporarily.
@ -187,9 +175,7 @@ LOS_ERRNO_OS_ERROR
* @deprecated This error code is obsolete since LiteOS 5.0.0.
*/
#define LOS_ERRNO_MUX_PEND_IN_SYSTEM_TASK LOS_ERRNO_OS_ERROR(LOS_MOD_MUX, 0x0C)
/*其中 LOS_ERRNO_OS_ERROR 是一个宏函数,用于生成错误码。该宏函数接受两个参数:模块号和错误码。在这里,模块号为 LOS_MOD_MUX错误码为 0x0C。
便使*/
/**
* @ingroup los_mux
* @brief Create a mutex.
@ -275,14 +261,7 @@ extern UINT32 LOS_MuxDelete(UINT32 muxHandle);
* @since Huawei LiteOS V100R001C00
*/
extern UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout);
/*参数说明:
muxHandle
timeout0
LOS_OK
*/
/**
* @ingroup los_mux
* @brief Release a mutex.

@ -75,12 +75,7 @@ enum PerfStatus {
PERF_STARTED, /**< perf is started */
PERF_STOPED, /**< perf is stopped */
};
/*枚举类型 PerfStatus 包含了三个枚举常量:
PERF_UNINIT
PERF_STARTED
PERF_STOPED
使便*/
/**
* @ingroup los_perf
* Define the type of the perf sample data buffer water mark hook function.
@ -187,13 +182,7 @@ enum PerfEventType {
PERF_EVENT_TYPE_MAX
};
/*枚举类型 PerfEventType 包含了四个枚举常量:
PERF_EVENT_TYPE_HW
PERF_EVENT_TYPE_TIMED
PERF_EVENT_TYPE_SW
PERF_EVENT_TYPE_RAW PmuEventType
使便便*/
/**
* @ingroup los_perf
* Common hardware pmu events
@ -210,17 +199,7 @@ enum PmuHwId {
PERF_COUNT_HW_MAX,
};
/*枚举类型 PmuHwId 包含了多个枚举常量,每个常量代表一个具体的硬件事件:
PERF_COUNT_HW_CPU_CYCLES CPU
PERF_COUNT_HW_INSTRUCTIONS
PERF_COUNT_HW_DCACHE_REFERENCES访
PERF_COUNT_HW_DCACHE_MISSES
PERF_COUNT_HW_ICACHE_REFERENCES访
PERF_COUNT_HW_ICACHE_MISSES
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
PERF_COUNT_HW_BRANCH_MISSES
使便*/
/**
* @ingroup los_perf
* Common hrtimer timed events
@ -241,13 +220,7 @@ enum PmuSwId {
PERF_COUNT_SW_MAX,
};
/*枚举类型 PmuSwId 包含了多个枚举常量,每个常量代表一个具体的软件事件:
PERF_COUNT_SW_TASK_SWITCH
PERF_COUNT_SW_IRQ_RESPONSE
PERF_COUNT_SW_MEM_ALLOC
PERF_COUNT_SW_MUX_PEND
使便*/
/**
* @ingroup los_perf
* perf sample data types
@ -262,16 +235,7 @@ enum PerfSampleType {
PERF_RECORD_IP = 1U << 5, /**< record instruction pointer */
PERF_RECORD_CALLCHAIN = 1U << 6, /**< record backtrace */
};
/*枚举类型 PerfSampleType 包含了多个枚举常量,每个常量代表一个具体的采样数据类型:
PERF_RECORD_CPU CPU ID
PERF_RECORD_TID ID
PERF_RECORD_TYPE
PERF_RECORD_PERIOD
PERF_RECORD_TIMESTAMP
PERF_RECORD_IP
PERF_RECORD_CALLCHAIN
使便便*/
/**
* @ingroup los_perf
* perf configuration sub event information
@ -289,12 +253,7 @@ typedef struct {
BOOL predivided; /**< whether to prescaler (once every 64 counts),
which only take effect on cpu cycle hardware event */
} PerfEventConfig;
/*type表示性能事件类型是一个 UINT32 类型的值,对应于 PerfEventType 枚举。
events
eventId UINT32
period UINT32
eventsNr UINT32
predivided64CPU BOOL */
/**
* @ingroup los_perf
* perf configuration main information
@ -320,17 +279,7 @@ extern VOID OsPerfHook(UINT32 event);
#else
#define LOS_PERF(EVENT)
#endif
/*PerfConfigAttr 结构体包含以下成员变量:
eventsCfg PerfEventConfig
taskIds ID UINT32 PERF_MAX_FILTER_TSKS ID
taskIdsNr ID UINT32
sampleType UINT32 PerfSampleType
needSample BOOL
taskFilterEnable BOOL
OsPerfHook UINT32 event
LOS_PERF LOSCFG_KERNEL_PERF LOSCFG_PERF_SW_PMU OsPerfHook */
/**
* @ingroup los_perf
* @brief Init perf.

@ -46,14 +46,7 @@ extern "C" {
#ifdef LOSCFG_SHELL_LK
extern void LOS_LkPrint(int level, const char *func, int line, const char *fmt, ...);
#endif
/*LOS_LkPrint 函数接受以下参数:
level
func
line
fmt
...
*/
/**
* @ingroup los_printf
* log print level definition, LOS_EMG_LEVEL is set to 0, it means the log is emergency.
@ -104,14 +97,7 @@ fmt
#endif
typedef VOID (*pf_OUTPUT)(const CHAR *fmt, ...);
/*这段代码定义了一个名为 PRINT_LEVEL 的宏以及一个名为 pf_OUTPUT 的函数指针类型。
PRINT_LEVEL LOS_DEBUG_LEVEL LOS_ERR_LEVEL
LOSCFG_SHELL_LK PRINT_LEVEL LOS_DEBUG_LEVEL
PRINT_LEVEL LOS_ERR_LEVEL
pf_OUTPUT VOID
fmt ...使*/
/**
* @ingroup los_printf
* @brief Format and print data.
@ -167,15 +153,7 @@ extern void dprintf(const char *fmt, ...);
#endif
#endif
#endif
/*当宏 PRINT_DEBUG 未被定义时,通过条件编译判断 PRINT_LEVEL 是否小于 LOS_DEBUG_LEVEL。如果是则将 PRINT_DEBUG 宏定义为空操作;否则,进入下一层条件编译。
LOSCFG_SHELL_LK PRINT_DEBUG LOS_LkPrint
[DEBUG] LOS_DEBUG_LEVEL
__FUNCTION__ __LINE__
fmt ...
PRINT_DEBUG [DEBUG] */
/**
* @ingroup los_printf
* @brief Format and print information log.
@ -209,15 +187,7 @@ extern void dprintf(const char *fmt, ...);
#endif
#endif
#endif
/*当宏 PRINT_INFO 未被定义时,通过条件编译判断 PRINT_LEVEL 是否小于 LOS_INFO_LEVEL。
PRINT_INFO
LOSCFG_SHELL_LK PRINT_INFO LOS_LkPrint
[INFO] LOS_INFO_LEVEL
__FUNCTION__ __LINE__
fmt ...
PRINT_INFO [INFO] */
/**
* @ingroup los_printf
* @brief Format and print warning log.
@ -251,14 +221,7 @@ extern void dprintf(const char *fmt, ...);
#endif
#endif
#endif
/*当宏 PRINT_WARN 未被定义时,通过条件编译判断 PRINT_LEVEL 是否小于 LOS_WARN_LEVEL。如果是则将 PRINT_WARN 宏定义为空操作;否则,进入下一层条件编译。
LOSCFG_SHELL_LK PRINT_WARN LOS_LkPrint
[WARN] LOS_WARN_LEVEL
__FUNCTION__ __LINE__
fmt ...
PRINT_WARN [WARN] */
/**
* @ingroup los_printf
* @brief Format and print error log.
@ -292,14 +255,7 @@ extern void dprintf(const char *fmt, ...);
#endif
#endif
#endif
/*当宏 PRINT_ERR 未被定义时,通过条件编译判断 PRINT_LEVEL 是否小于 LOS_ERR_LEVEL。如果是则将 PRINT_ERR 宏定义为空操作;否则,进入下一层条件编译。
LOSCFG_SHELL_LK PRINT_ERR LOS_LkPrint
[ERR] LOS_ERR_LEVEL
__FUNCTION__ __LINE__
fmt ...
PRINT_ERR [ERR] */
/**
* @ingroup los_printf
* @brief Format and print common log.
@ -331,16 +287,7 @@ extern void dprintf(const char *fmt, ...);
#endif
#endif
#endif
/*这段代码定义了一个名为 PRINTK 的宏。
PRINTK PRINT_LEVEL LOS_COMMOM_LEVEL PRINTK
LOSCFG_SHELL_LK PRINTK LOS_LkPrint
[COMM] LOS_COMMOM_LEVEL
__FUNCTION__ __LINE__
fmt ...
PRINTK */
/**
* @ingroup los_printf
* @brief Format and print emergency log.
@ -370,11 +317,7 @@ extern void dprintf(const char *fmt, ...);
} while (0)
#endif
#endif
/*这段代码定义了一个名为 PRINT_EMG 的宏。
PRINT_EMG PRINT_LEVEL LOS_EMG_LEVEL PRINT_EMG
PRINT_LEVEL LOS_EMG_LEVEL PRINT_EMG [EMG] */
/**
* @ingroup los_printf
* @brief Format and print log.

@ -55,9 +55,7 @@ extern "C" {
* @deprecated This error code is obsolete since LiteOS 5.0.0.
*/
#define LOS_ERRNO_QUEUE_MAXNUM_ZERO LOS_ERRNO_OS_ERROR(LOS_MOD_QUE, 0x00)
/*宏的定义使用了 LOS_ERRNO_OS_ERROR 宏,并指定了参数 LOS_MOD_QUE 和 0x00。根据上下文推测LOS_MOD_QUE 可能是表示与队列相关的模块。
*/
/**
* @ingroup los_queue
* Queue error code: The queue block memory fails to be initialized.
@ -68,11 +66,7 @@ extern "C" {
* number of queue resources.
*/
#define LOS_ERRNO_QUEUE_NO_MEMORY LOS_ERRNO_OS_ERROR(LOS_MOD_QUE, 0x01)
/*这段代码定义了一个名为 LOS_ERRNO_QUEUE_NO_MEMORY 的宏,用于表示队列分配内存失败时的错误码。
使 LOS_ERRNO_OS_ERROR LOS_MOD_QUE 0x01LOS_MOD_QUE
*/
/**
* @ingroup los_queue
* Queue error code: The memory for queue creation fails to be requested.
@ -83,11 +77,7 @@ extern "C" {
* the number of nodes in the queue to be created.
*/
#define LOS_ERRNO_QUEUE_CREATE_NO_MEMORY LOS_ERRNO_OS_ERROR(LOS_MOD_QUE, 0x02)
/*这段代码定义了一个名为 LOS_ERRNO_QUEUE_CREATE_NO_MEMORY 的宏,用于表示创建队列时内存分配失败的错误码。
使 LOS_ERRNO_OS_ERROR LOS_MOD_QUE 0x02LOS_MOD_QUE
*/
/**
* @ingroup los_queue
* Queue error code: The size of the biggest message in the created queue is too big.
@ -97,9 +87,6 @@ extern "C" {
* Solution: Change the size of the biggest message in the created queue.
*/
#define LOS_ERRNO_QUEUE_SIZE_TOO_BIG LOS_ERRNO_OS_ERROR(LOS_MOD_QUE, 0x03)
/*宏的定义使用了 LOS_ERRNO_OS_ERROR 宏,并指定了参数 LOS_MOD_QUE 和 0x00。根据上下文推测LOS_MOD_QUE 可能是表示与队列相关的模块。
*/
/**
* @ingroup los_queue
@ -110,11 +97,6 @@ extern "C" {
* Solution: Increase the configured number of resources for queues.
*/
#define LOS_ERRNO_QUEUE_CB_UNAVAILABLE LOS_ERRNO_OS_ERROR(LOS_MOD_QUE, 0x04)
/*这段代码定义了一个名为 LOS_ERRNO_QUEUE_NO_MEMORY 的宏,用于表示队列分配内存失败时的错误码。
使 LOS_ERRNO_OS_ERROR LOS_MOD_QUE 0x01LOS_MOD_QUE
*/
/**
* @ingroup los_queue
@ -374,21 +356,6 @@ typedef struct tagQueueInfo {
} QUEUE_INFO_S;
#ifdef LOSCFG_QUEUE_STATIC_ALLOCATION
/*这段代码定义了一个结构体 QUEUE_INFO_S用于描述队列Queue的信息。
uwQueueID ID
usQueueLen
usQueueSize
usQueueHead
usQueueTail
usWritableCnt
usReadableCnt
uwWaitReadTask 64 ID 64 ID 63
uwWaitWriteTask uwWaitReadTask
uwWaitMemTask uwWaitReadTask
LOSCFG_QUEUE_STATIC_ALLOCATION */
/**
* @ingroup los_queue
* @brief Create a message queue.
@ -430,16 +397,7 @@ extern UINT32 LOS_QueueCreateStatic(const CHAR *queueName,
VOID *queueMem,
UINT16 memSize);
#endif
/*该函数用于静态创建一个队列Queue具体参数如下
queueName const CHAR*
len UINT16
queueId UINT32 ID
flags UINT32
maxMsgSize UINT16
queueMem VOID*
memSize UINT16
ID*/
/**
* @ingroup los_queue
* @brief Create a message queue.
@ -473,14 +431,7 @@ extern UINT32 LOS_QueueCreate(const CHAR *queueName,
UINT32 *queueId,
UINT32 flags,
UINT16 maxMsgSize);
/*该函数用于动态创建一个队列Queue具体参数如下
queueName const CHAR*
len UINT16
queueId UINT32 ID
flags UINT32
maxMsgSize UINT16
ID*/
/**
* @ingroup los_queue
* @brief Read a queue.
@ -530,7 +481,7 @@ extern UINT32 LOS_QueueReadCopy(UINT32 queueId,
VOID *bufferAddr,
UINT32 *bufferSize,
UINT32 timeout);
/*该函数的作用是从队列中读取数据,并将数据复制到指定的缓冲区中。如果队列中没有数据可读,则根据超时时间等待数据可读,如果在超时时间内仍然没有数据可读,则返回错误码。*/
/**
* @ingroup los_queue
* @brief Write data into a queue.
@ -578,13 +529,7 @@ extern UINT32 LOS_QueueWriteCopy(UINT32 queueId,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout);
/*该函数用于向指定的队列中写入数据,具体参数如下:
queueId ID UINT32
bufferAddr VOID*
bufferSize UINT32
timeout Tick 0 LOS_WAIT_FOREVER UINT32
*/
/**
* @ingroup los_queue
* @brief Read a queue.
@ -636,13 +581,7 @@ extern UINT32 LOS_QueueRead(UINT32 queueId,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout);
/*该函数用于从指定的队列中读取数据,具体参数如下:
queueId ID UINT32
bufferAddr VOID*
bufferSize UINT32
timeout Tick 0 LOS_WAIT_FOREVER UINT32
*/
/**
* @ingroup los_queue
* @brief Write data into a queue.
@ -691,13 +630,7 @@ extern UINT32 LOS_QueueWrite(UINT32 queueId,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout);
/*该函数用于向指定的队列中写入数据,具体参数如下:
queueId ID UINT32
bufferAddr VOID*
bufferSize UINT32
timeout Tick 0 LOS_WAIT_FOREVER UINT32
*/
/**
* @ingroup los_queue
* @brief Write data into a queue header.
@ -746,13 +679,7 @@ extern UINT32 LOS_QueueWriteHead(UINT32 queueId,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout);
/*该函数用于向指定队列的队首写入数据,具体参数如下:
queueId ID UINT32
bufferAddr VOID*
bufferSize UINT32
timeout Tick 0 LOS_WAIT_FOREVER UINT32
*/
/**
* @ingroup los_queue
* @brief Write data into a queue header.

@ -51,14 +51,7 @@ typedef enum {
RBUF_UNINIT, /**< Ringbuf is not inited. */
RBUF_INITED /**< Ringbuf is inited. */
} RingbufStatus;
/*这段代码定义了一个名为 RingbufStatus 的枚举类型,表示环形缓冲区的状态。
RBUF_UNINIT
RBUF_INITED
使便
使*/
/**
* @ingroup los_ringbuf
* Ringbuf information structure.
@ -73,18 +66,7 @@ typedef struct {
RingbufStatus status; /**< Ringbuf status */
CHAR *fifo; /**< Buf to store data */
} Ringbuf;
/*这段代码定义了一个名为 Ringbuf 的结构体,用于表示环形缓冲区的属性和状态。
startIdx
endIdx
size
remain
lock
status RingbufStatus
fifo
便*/
/**
* @ingroup los_ringbuf
* @brief Init a ringbuf.
@ -107,8 +89,7 @@ fifo
* @since Huawei LiteOS V200R005C00
*/
extern UINT32 LOS_RingbufInit(Ringbuf *ringbuf, CHAR *fifo, UINT32 size);
/*该函数的作用是根据给定的参数初始化环形缓冲区对象,并分配必要的资源。通过调用这个函数,可以将一个已经定义的 Ringbuf
*/
/**
* @ingroup los_ringbuf
* @brief Reset a ringbuf.
@ -150,9 +131,7 @@ extern VOID LOS_RingbufReset(Ringbuf *ringbuf);
* @since Huawei LiteOS V200R005C00
*/
extern UINT32 LOS_RingbufWrite(Ringbuf *ringbuf, const CHAR *buf, UINT32 size);
/*该函数的作用是将指定大小的数据从源缓冲区写入到目标环形缓冲区中。写入操作会更新环形缓冲区的写入索引,并根据需要循环覆盖已有数据。如果环形缓冲区的空间不足以容纳全部数据,只会写入部分数据。
便*/
/**
* @ingroup los_ringbuf
* @brief Read data from ringbuf.
@ -174,9 +153,7 @@ extern UINT32 LOS_RingbufWrite(Ringbuf *ringbuf, const CHAR *buf, UINT32 size);
* @since Huawei LiteOS V200R005C00
*/
extern UINT32 LOS_RingbufRead(Ringbuf *ringbuf, CHAR *buf, UINT32 size);
/*该函数的作用是从指定大小的数据中读取数据,并将其存储到目标缓冲区。读取操作会更新环形缓冲区的读取索引,并根据需要循环读取已有数据。如果环形缓冲区中的数据不足以满足全部读取请求,只会读取部分数据。
便*/
/**
* @ingroup los_ringbuf
* @brief Get a ringbuf's used size.

Binary file not shown.

@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: LiteOS Cpp Support Implementation
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_cppsupport_pri.h"
#include "los_printf.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef VOID (*InitFunc)(VOID);
/*-------------------------------------------
*`LITE_OS_SEC_TEXT_MINOR``UINTPTR`
*`LOS_CppSystemInit`
*`flag`
*
*--------------------------------------------*/
LITE_OS_SEC_TEXT_MINOR INT32 LOS_CppSystemInit(UINTPTR initArrayStart, UINTPTR initArrayEnd, INT32 flag)
{
UINTPTR fastEnd = (UINTPTR)&__fast_end;
UINTPTR *start = (UINTPTR *)initArrayStart;
InitFunc initFunc = NULL;
#ifdef LOSCFG_AARCH64
__register_frame(__EH_FRAME_BEGIN__);
#endif
for (; start != (UINTPTR *)initArrayEnd; ++start) {
if ((flag == BEFORE_SCATTER) && ((UINTPTR)*start > fastEnd)) {
continue;
} else if ((flag == AFTER_SCATTER) && ((UINTPTR)*start <= fastEnd)) {
continue;
}
initFunc = (InitFunc)(*start);
initFunc();
}
return 0;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,134 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved.
* Description: ShellCmd Cpup
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_config.h"
#ifdef LOSCFG_SHELL
#include "stdio.h"
#include "stdlib.h"
#include "los_cpup_pri.h"
#include "los_task_pri.h"
#include "shcmd.h"
#include "shell.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
VOID OsCmdCpupOperateOneParam(UINT32 mode) //根据参数mode获取系统CPU使用率的历史数据//
{
UINT32 ret;
if (mode == CPUP_LAST_TEN_SECONDS) { //过去10s内//
PRINTK("\nSysCpuUsage in 10s: ");
} else if (mode == CPUP_LAST_ONE_SECONDS) { //过去1s内//
PRINTK("\nSysCpuUsage in 1s: ");
} else { //历史平均CPU使用率//
PRINTK("\nSysCpuUsage in all time: ");
}
ret = LOS_HistorySysCpuUsage(mode); //获取CPU使用率的数值//
PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
}
VOID OsCmdCpupOperateTwoParam(UINT32 mode, UINT32 taskId) //根据参数mode获取参数taskId所指定//
{ //的任务的CPU使用率的历史数据//
UINT32 ret;
if (mode == CPUP_LAST_TEN_SECONDS) { //过去10s内//
PRINTK("\nTaskId %u CpuUsage in 10s: ", taskId);
} else if (mode == CPUP_LAST_ONE_SECONDS) { //过去1s内//
PRINTK("\nTaskId %u CpuUsage in 1s: ", taskId);
} else { //历史平均CPU使用率//
PRINTK("\nTaskId %u CpuUsage in all time: ", taskId);
}
ret = LOS_HistoryTaskCpuUsage(taskId, mode); //获取CPU使用率的数值//
PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdCpup(INT32 argc, const CHAR **argv) //根据输入的参数来获取系统或指定任务的CPU使用率//
{
size_t mode, taskId;
CHAR *bufMode = NULL;
CHAR *bufId = NULL;
LosTaskCB *taskCB = NULL;
UINT32 ret;
if (argc <= 0) { //检查参数个数如果没有参数则获取系统过去10秒的CPU使用率并打印输出//
ret = LOS_HistorySysCpuUsage(CPUP_LAST_TEN_SECONDS);
PRINTK("\nSysCpuUsage in 10s: %u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
return 0;
}
mode = strtoul(argv[0], &bufMode, 0); //将第一个参数转换为无符号整型数mode表示CPU使用率的获取模式//
/*------------------------------------------------------------------*/
//判断输入的mode是否有效//
if ((bufMode == NULL) || (*bufMode != 0)) {
PRINTK("\nThe input mode is invalid. Please try again.\n");
return 0;
}
if (mode > CPUP_ALL_TIME) {
mode = CPUP_ALL_TIME;
}
/*------------------------------------------------------------------*/
//如果只有一个参数则调用OsCmdCpupOperateOneParam函数来获取系统CPU使用率//
if (argc == 1) {
OsCmdCpupOperateOneParam((UINT32)mode);
return 0;
}
/*------------------------------------------------------------------*/
//判断输入的taskId是否有效//
taskId = strtoul(argv[1], &bufId, 0);
if ((taskId >= g_taskMaxNum) || (*bufId != 0)) {
PRINTK("\nThe input taskId is invalid. Please try again.\n");
return 0;
}
taskCB = OS_TCB_FROM_TID(taskId);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
PRINTK("\nThe task is unused. Please try again.\n");
return 0;
}
/*-----------------------------------------------------------------*/
//如果有两个参数则第二个参数为任务ID然后调用OsCmdCpupOperateTwoParam函数来获取指定任务的CPU使用率//
if (argc == 2) {
OsCmdCpupOperateTwoParam((UINT32)mode, (UINT32)taskId);
return 0;
}
PRINTK("cpup [MODE] \ncpup [MODE] [TASKID] \n");
return 0;
}
//通过在Shell终端输入cpup命令根据输入相应的参数来获取CPU使用率的历史数据//
SHELLCMD_ENTRY(cpup_shellcmd, CMD_TYPE_EX, "cpup", XARGS, (CmdCallBackFunc)OsShellCmdCpup);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* LOSCFG_SHELL */

@ -0,0 +1,593 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved.
* Description : LiteOS Cpu Usage Calculation Module Implementation
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_cpup_pri.h"
#include "los_task_pri.h"
#include "los_base.h"
#include "los_swtmr.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_KERNEL_CPUP
LITE_OS_SEC_BSS STATIC UINT16 g_cpupSwtmrId; //用于记录CPU使用率统计定时器的ID//
LITE_OS_SEC_BSS STATIC UINT16 g_cpupInitFlg = 0; //用于标记CPU使用率模块是否已经初始化//
LITE_OS_SEC_BSS OsCpupCB *g_cpup = NULL; //用于保存CPU使用率相关的信息//
LITE_OS_SEC_BSS STATIC UINT16 g_cpupMaxNum; //表示CPU使用率统计信息的最大数量//
LITE_OS_SEC_BSS STATIC UINT16 g_cpupTaskMaxNum; //表示CPU使用率统计信息的最大任务数量//
LITE_OS_SEC_BSS STATIC UINT16 g_hisPos = 0; /* current Sampling point of historyTime */
LITE_OS_SEC_DATA_INIT STATIC UINT32 runningTasks[LOSCFG_KERNEL_CORE_NUM] = {
[0 ... (LOSCFG_KERNEL_CORE_NUM - 1)] = (UINT32)-1
}; //用于记录每个核心上正在运行的任务的ID//
LITE_OS_SEC_BSS STATIC UINT64 cpuHistoryTime[OS_CPUP_HISTORY_RECORD_NUM + 1];
//用于保存CPU历史时间记录//
LITE_OS_SEC_BSS STATIC UINT64 g_startCycles = 0; //用于记录任务切换前的时钟周期数//
#ifdef LOSCFG_CPUP_INCLUDE_IRQ //用于判断是否包含中断相关的功能//
//若满足条件编译//
LITE_OS_SEC_BSS UINT64 g_timeInIrqPerTskSwitch[LOSCFG_KERNEL_CORE_NUM]; //用于记录每个核心上任务切换期间发生的中断的时间//
LITE_OS_SEC_BSS STATIC UINT64 g_intTimeStart[LOSCFG_KERNEL_CORE_NUM]; //用于记录每个核心上中断开始的时间//
#endif
#define HIGH_BITS 32
#define CPUP_PRE_POS(pos) (((pos) == 0) ? (OS_CPUP_HISTORY_RECORD_NUM - 1) : ((pos) - 1))
#define CPUP_POST_POS(pos) (((pos) == (OS_CPUP_HISTORY_RECORD_NUM - 1)) ? 0 : ((pos) + 1))
LITE_OS_SEC_TEXT_INIT OsCpupCB *OsCpupCBGet(UINT32 index)
{
return &g_cpup[index];
}
/*定期更新历史时间采样点和任务的历史运行时间以便后续计算CPU使用率*/
LITE_OS_SEC_TEXT_INIT VOID OsCpupGuard(VOID)
{
UINT16 prevPos = g_hisPos;
UINT16 loop;
UINT16 runTaskId;
UINT64 curCycle;
UINT32 intSave;
if (g_cpupInitFlg == 0) { //表示CPU使用率模块尚未初始化直接返回//
return;
}
//若已初始化,则禁止中断,并获取当前时钟周期数//
intSave = LOS_IntLock();
curCycle = OsCpupGetCycle();
g_hisPos = CPUP_POST_POS(g_hisPos); //更新历史时间采样点的位置//
cpuHistoryTime[prevPos] = curCycle; //记录本次采样的时钟周期数//
/*更新每个任务和CPU核心的历史运行时间*/
for (loop = 0; loop < g_cpupMaxNum; loop++) {
g_cpup[loop].historyTime[prevPos] = g_cpup[loop].allTime;
}
for (loop = 0; loop < LOSCFG_KERNEL_CORE_NUM; loop++) {
runTaskId = runningTasks[loop]; //获取该任务在当前核心上的ID//
/* reacquire the cycle to prevent flip */
curCycle = OsCpupGetCycle();
/*将该任务从开始到当前时刻所用的时钟周期数加入该任务在历史时间采样点上的历史运行时间中*/
g_cpup[runTaskId].historyTime[prevPos] += curCycle - g_cpup[runTaskId].startTime;
#ifdef LOSCFG_CPUP_INCLUDE_IRQ //判断中断功能是否被包含在配置中//
/*从该任务的历史运行时间中减去该任务在任务切换期间发生的中断所用的时间*/
g_cpup[runTaskId].historyTime[prevPos] -= g_timeInIrqPerTskSwitch[loop];
#endif
}
LOS_IntRestore(intSave); //恢复中断状态//
}
/*创建一个软件定时器以便定期更新历史时间采样点和任务的历史运行时间从而实现CPU使用率的统计*/
LITE_OS_SEC_TEXT_INIT VOID OsCpupGuardCreator(VOID)
{
/*下面函数的参数分别为*/
//设定定时器的周期是每秒钟的基本核心时钟滴答数//
//工作模式为周期模式//
//回调函数//
//定时器ID保存在g_cpupSwtmrId变量中//
//最后一个参数为0表示不携带额外参数//
(VOID)LOS_SwtmrCreate(LOSCFG_BASE_CORE_TICK_PER_SECOND, LOS_SWTMR_MODE_PERIOD,
(SWTMR_PROC_FUNC)OsCpupGuard, &g_cpupSwtmrId, 0);
(VOID)LOS_SwtmrStart(g_cpupSwtmrId); //启动该软件定时器//
}
/*初始化CPU使用率统计模块其中包括创建一个最高优先级的任务
OsCpupGuardCreator
OsCpupGuard()*/
LITE_OS_SEC_TEXT_INIT VOID OsCpupGuardInit(VOID)
{
TSK_INIT_PARAM_S taskInitParam;
UINT32 tempId;
//初始化taskInitParam并将其内容清零//
(VOID)memset_s((void *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsCpupGuardCreator; //指定任务入口函数为OsCpupGuardCreator即创建和启动软件定时器的函数//
taskInitParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; //指定任务栈的大小为最小任务栈大小//
taskInitParam.pcName = "CpupGuardCreator"; //指定任务的名称为"CpupGuardCreator"//
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_HIGHEST; //指定任务的优先级为最高优先级//
taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED; //指定任务状态为LOS_TASK_STATUS_DETACHED//
#ifdef LOSCFG_KERNEL_SMP //判断操作系统是否支持多核//
taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); //设置任务的CPU亲和性掩码//
#endif
/*传入上述初始化好的参数taskInitParam并将任务ID保存在tempId中*/
(VOID)LOS_TaskCreate(&tempId, &taskInitParam);
}
/*
* Description: initialization of CPUP
* Return : LOS_OK or Error Information
*/
LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit(VOID)
{
UINT32 size;
g_cpupTaskMaxNum = g_taskMaxNum;
g_cpupMaxNum = g_cpupTaskMaxNum;
/*如果配置了包含中断的CPU使用率统计LOSCFG_CPUP_INCLUDE_IRQ
g_cpupMaxNumLOSCFG_PLATFORM_HWI_LIMIT*/
#ifdef LOSCFG_CPUP_INCLUDE_IRQ
g_cpupMaxNum += LOSCFG_PLATFORM_HWI_LIMIT;
#endif
/* every task has only one record, and it won't operated at the same time */
size = g_cpupMaxNum * sizeof(OsCpupCB); //计算需要分配的内存空间大小//
g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size); //分配内存用于存储OsCpupCB结构体数组//
if (g_cpup == NULL) { //内存分配失败//
return LOS_ERRNO_CPUP_NO_MEMORY;
}
OsCpupGuardInit(); //初始化CPU使用率统计模块//
(VOID)memset_s(g_cpup, size, 0, size); //将分配的内存空间清零//
g_cpupInitFlg = 1; //表示CPU使用率统计模块已经初始化完成//
return LOS_OK; //初始化成功//
}
LITE_OS_SEC_TEXT_INIT VOID LOS_CpupReset(VOID) //用于重置CPU使用率统计模块//
{
UINT32 cpupIndex;
UINT32 maxNum = g_cpupMaxNum;
UINT64 curCycle;
UINT16 loop;
UINT32 intSave;
/*检查全局变量g_cpup是否为NULL如果是则直接返回不执行任何操作*/
if (g_cpup == NULL) {
return;
}
g_cpupInitFlg = 0; //表示CPU使用率统计模块未初始化//
intSave = LOS_IntLock(); //锁定中断,防止在重置过程中发生中断//
(VOID)LOS_SwtmrStop(g_cpupSwtmrId); //停止CPU使用率统计定时器//
curCycle = OsCpupGetCycle(); //获取当前的CPU周期数//
/*将cpuHistoryTime数组中的所有元素都设置为curCycle清空历史时间记录*/
for (loop = 0; loop < (OS_CPUP_HISTORY_RECORD_NUM + 1); loop++) {
cpuHistoryTime[loop] = curCycle;
}
/*遍历每个CPU使用率统计结构体
curCycle
*/
for (cpupIndex = 0; cpupIndex < maxNum; cpupIndex++) {
g_cpup[cpupIndex].startTime = curCycle;
g_cpup[cpupIndex].allTime = curCycle;
for (loop = 0; loop < (OS_CPUP_HISTORY_RECORD_NUM + 1); loop++) {
g_cpup[cpupIndex].historyTime[loop] = curCycle;
}
}
/*如果配置了包含中断的CPU使用率统计
g_timeInIrqPerTskSwitch0
*/
#ifdef LOSCFG_CPUP_INCLUDE_IRQ
for (loop = 0; loop < LOSCFG_KERNEL_CORE_NUM; loop++) {
g_timeInIrqPerTskSwitch[loop] = 0;
}
#endif
(VOID)LOS_SwtmrStart(g_cpupSwtmrId); //重新启动CPU使用率统计定时器//
LOS_IntRestore(intSave); //恢复中断状态//
g_cpupInitFlg = 1; //表示CPU使用率统计模块已经重新初始化完成//
return;
}
/*用于设置CPU周期数起始值以便后面记录时间时
CPU*/
LITE_OS_SEC_TEXT_MINOR VOID OsCpupSetCycle(UINT64 startCycles)
{
g_startCycles = startCycles;
return;
}
/*
* Description: get current cycles count
* Return : current cycles count
*/
LITE_OS_SEC_TEXT_MINOR UINT64 OsCpupGetCycle(VOID)
{
UINT32 high;
UINT32 low;
UINT64 cycles;
LOS_GetCpuCycle(&high, &low);
cycles = ((UINT64)high << HIGH_BITS) + low; //将高位和低位的计数值合并成一个64位计数值//
if (g_startCycles == 0) {
g_startCycles = cycles;
}
/*
* The cycles should keep growing, if the checking failed,
* it mean LOS_GetCpuCycle has the problem which should be fixed.
*/
LOS_ASSERT(cycles >= g_startCycles);
return (cycles - g_startCycles);
}
/*
* Description: start task to get cycles count in current task beginning
*/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleStart(VOID) //用于在任务开始时获取CPU周期计数//
{
UINT32 taskId;
LosTaskCB *runTask = NULL;
if (g_cpupInitFlg == 0) { //如果为0则表示还未进行CPU周期计数的初始化直接返回//
return;
}
runTask = OsCurrTaskGet(); //获取当前正在运行的任务//
taskId = runTask->taskId; //获取当前任务的ID//
g_cpup[taskId].id = taskId;
g_cpup[taskId].startTime = OsCpupGetCycle();
return;
}
/*
* Description: quit task and get cycle count
*/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleEnd(VOID)
{
UINT32 taskId;
UINT64 cpuCycle;
LosTaskCB *runTask = NULL;
if (g_cpupInitFlg == 0) {
return;
}
runTask = OsCurrTaskGet();
taskId = runTask->taskId;
if (g_cpup[taskId].startTime == 0) { //判断是否已经记录了任务的开始时间,//
return; //若为0则表示未记录开始时间直接返回//
}
cpuCycle = OsCpupGetCycle();
g_cpup[taskId].allTime += cpuCycle - g_cpup[taskId].startTime; //获取任务从开始到结束的CPU周期数//
#ifdef LOSCFG_CPUP_INCLUDE_IRQ //如果开启了包含中断处理时间的统计,需要对任务的总运行时间进行修正//
UINT32 cpuId = ArchCurrCpuid();
g_cpup[taskId].allTime -= g_timeInIrqPerTskSwitch[cpuId]; //减去当前CPU核心上中断处理所占用的时间
g_timeInIrqPerTskSwitch[cpuId] = 0;
#endif
g_cpup[taskId].startTime = 0; //表示任务的运行时间统计结束//
return;
}
/*
* Description: start task to get cycles count in current task ending
*/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskCycleEndStart(const LosTaskCB *newTask)
{
UINT64 cpuCycle;
LosTaskCB *runTask = NULL;
OsCpupCB *cpup = NULL;
UINT32 cpuId = ArchCurrCpuid();
if ((g_cpupInitFlg == 0) || (newTask == NULL)) {
return;
}
runTask = OsCurrTaskGet();
cpuCycle = OsCpupGetCycle();
cpup = &g_cpup[runTask->taskId];
if (cpup->startTime != 0) {
cpup->allTime += cpuCycle - cpup->startTime; //表示该任务之前已经开始了CPU周期计数需要对其总运行时间进行更新//
#ifdef LOSCFG_CPUP_INCLUDE_IRQ //根据是否满足条件配置,对总运行时间进行修正//
cpup->allTime -= g_timeInIrqPerTskSwitch[cpuId];
g_timeInIrqPerTskSwitch[cpuId] = 0;
#endif
}
cpup = &g_cpup[newTask->taskId];
/*将新任务的ID和当前CPU周期计数值保存表示新任务的CPU周期计数开始*/
cpup->id = newTask->taskId;
cpup->startTime = cpuCycle;
runningTasks[cpuId] = newTask->taskId; //更新当前CPU核心上正在运行的任务ID//
return;
}
/*用于获取CPU周期计数数据在数组中的位置*/
LITE_OS_SEC_TEXT_MINOR STATIC VOID OsCpupGetPos(UINT32 mode, UINT16 *curPosPointer, UINT16 *prePosPointer)
{
UINT16 curPos;
UINT16 tmpPos;
UINT16 prePos;
tmpPos = g_hisPos; //获取当前位置//
curPos = CPUP_PRE_POS(tmpPos); //获取前一个位置//
/*
* The current position has nothing to do with the CPUP modes,
* however, the previous position differs.
*/
switch (mode) {
/*表示需要获取最近一秒内的CPU周期计数数据
*/
case CPUP_LAST_ONE_SECONDS:
prePos = CPUP_PRE_POS(curPos);
break;
/*表示需要获取最近十秒内的CPU周期计数数据
*/
case CPUP_LAST_TEN_SECONDS:
prePos = tmpPos;
break;
/*表示需要获取所有时间内的CPU周期计数数据
*/
case CPUP_ALL_TIME:
/* fall-through */
default:
prePos = OS_CPUP_HISTORY_RECORD_NUM;
break;
}
*curPosPointer = curPos; //保存当前位置//
*prePosPointer = prePos; //保存前一个位置//
return;
}
/*用于检查CPU使用率统计参数的合法性*/
LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsCpuUsageParaCheck(UINT32 taskId)
{
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (OS_TSK_GET_INDEX(taskId) >= g_taskMaxNum) { //任务ID索引值超过了最大任务数//
return LOS_ERRNO_CPUP_TSK_ID_INVALID; //表示任务ID无效返回错误码//
}
/* weather the task is created */
if (g_cpup[taskId].id != taskId) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED; //表示该任务尚未创建,返回错误码//
}
if ((g_cpup[taskId].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskId].status == 0)) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED; //表示该任务尚未创建,返回错误码//
}
return LOS_OK; //表示通过检查//
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT32 mode) //用于获取历史系统CPU使用率//
{
UINT64 cpuCycleAll;
UINT64 idleCycleAll = 0;
UINT32 cpup = 0;
UINT16 pos;
UINT16 prePos;
UINT32 intSave;
UINT32 idleTaskId;
#ifdef LOSCFG_KERNEL_SMP
UINT32 cpuId = 0;
#endif
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
/* get end time of current task */
intSave = LOS_IntLock(); //锁定中断状态//
OsTaskCycleEnd(); //获取当前任务的结束时间//
OsCpupGetPos(mode, &pos, &prePos); //获取历史CPU使用率数据的位置信息//
cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //计算CPU的总周期数//
#ifdef LOSCFG_KERNEL_SMP //判断是否为SMP系统//
/* For SMP system, each idle task needs to be accounted */
while (cpuId < LOSCFG_KERNEL_CORE_NUM) {
idleTaskId = g_percpu[cpuId].idleTaskId;
//累加各核心的空闲任务的周期数到idleCycleAll中//
idleCycleAll += g_cpup[idleTaskId].historyTime[pos] - g_cpup[idleTaskId].historyTime[prePos];
cpuId++;
}
cpuCycleAll *= LOSCFG_KERNEL_CORE_NUM;
#else
idleTaskId = OsGetIdleTaskId(); //直接获取空闲任务的周期数。//
idleCycleAll = g_cpup[idleTaskId].historyTime[pos] - g_cpup[idleTaskId].historyTime[prePos];
#endif
if (cpuCycleAll) {
cpup = (LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll));
} //得出CPU使用率//
OsTaskCycleStart(); //重新开始任务的时间统计//
LOS_IntRestore(intSave); //恢复中断状态//
return cpup;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskId, UINT32 mode)
{
UINT64 cpuCycleAll;
UINT64 cpuCycleCurTask;
UINT16 pos;
UINT16 prePos;
UINT32 intSave;
UINT32 cpup = 0;
UINT32 ret;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
//对传入的任务ID进行参数检查检查结果不等于LOS_OK则返回相应的错误码//
ret = OsCpuUsageParaCheck(taskId);
if (ret != LOS_OK) {
return ret;
}
OsCpupCB *taskCpup = &g_cpup[taskId];
intSave = LOS_IntLock();
OsTaskCycleEnd();
OsCpupGetPos(mode, &pos, &prePos); //获取历史CPU使用率数据的位置信息//
cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //计算CPU的总周期数//
cpuCycleCurTask = taskCpup->historyTime[pos] - taskCpup->historyTime[prePos]; //计算当前任务的CPU周期数//
if (cpuCycleAll) {
cpup = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTask) / cpuCycleAll);
} //计算得出CPU使用率//
OsTaskCycleStart();
LOS_IntRestore(intSave);
return cpup;
}
//用于获取所有任务历史CPU使用率//
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllCpuUsage(UINT16 maxNum, CPUP_INFO_S *cpupInfo, UINT32 mode, UINT16 flag)
{
UINT16 loop;
UINT16 pos;
UINT16 prePos;
UINT32 intSave;
UINT64 cpuCycleAll;
UINT64 cpuCycleCurTask;
UINT16 numTmpMax = maxNum;
UINT16 numTmpMin = 0;
UINT16 numMax = g_cpupTaskMaxNum;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (cpupInfo == NULL) { //检查传入的指针cpupInfo是否为空如果为空返回错误码//
return LOS_ERRNO_CPUP_TASK_PTR_NULL;
}
if (maxNum == 0) { //检查传入的maxNum是否等于0如果等于0返回错误码//
return LOS_ERRNO_CPUP_MAXNUM_INVALID;
}
#ifdef LOSCFG_CPUP_INCLUDE_IRQ //如果宏被定义//
if (flag == 0) {
numTmpMax += g_cpupTaskMaxNum;
numTmpMin += g_cpupTaskMaxNum;
numMax = g_cpupMaxNum;
}
#endif
if (numTmpMax > numMax) {
numTmpMax = numMax;
}
intSave = LOS_IntLock();
OsTaskCycleEnd();
OsCpupGetPos(mode, &pos, &prePos); //获取历史CPU使用率数据的位置信息//
cpuCycleAll = cpuHistoryTime[pos] - cpuHistoryTime[prePos]; //计算CPU的总周期数//
/*通过循环遍历所有任务的CPU使用率数据计算当前任务的CPU周期数并保存*/
for (loop = numTmpMin; loop < numTmpMax; loop++) {
if ((g_cpup[loop].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loop].status == 0)) {
continue;
}
cpuCycleCurTask = g_cpup[loop].historyTime[pos] - g_cpup[loop].historyTime[prePos];
cpupInfo[loop - numTmpMin].usStatus = g_cpup[loop].status;
if (cpuCycleAll) {
cpupInfo[loop - numTmpMin].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTask) / cpuCycleAll);
}
}
OsTaskCycleStart();
LOS_IntRestore(intSave);
return LOS_OK;
}
#ifdef LOSCFG_CPUP_INCLUDE_IRQ
/*用于在中断开始时记录当前的时钟周期数,以便于后续做中断处理时间的统计和分析*/
LITE_OS_SEC_TEXT_MINOR VOID OsCpupIrqStart(VOID)
{
g_intTimeStart[ArchCurrCpuid()] = OsCpupGetCycle();
return;
}
/*在中断结束时进行统计操作,
*/
LITE_OS_SEC_TEXT_MINOR VOID OsCpupIrqEnd(UINT32 intNum)
{
UINT64 intTimeEnd = OsCpupGetCycle(); //获取当前的时钟周期数//
UINT32 cpuId = ArchCurrCpuid(); //获取当前CPU的ID//
if (g_cpupInitFlg == 0) {
return;
}
g_cpup[g_taskMaxNum + intNum].id = intNum;
g_cpup[g_taskMaxNum + intNum].status = OS_TASK_STATUS_RUNNING; //将中断状态设为运行中//
g_timeInIrqPerTskSwitch[cpuId] += (intTimeEnd - g_intTimeStart[cpuId]); //增加中断期间任务切换所消耗的时间//
g_cpup[g_taskMaxNum + intNum].allTime += (intTimeEnd - g_intTimeStart[cpuId]);
return;
}
#endif
#endif /* LOSCFG_KERNEL_CPUP */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,53 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
* Description: Cpp Support HeadFile
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _LOS_CPPSUPPORT_PRI_H
#define _LOS_CPPSUPPORT_PRI_H //防止多次包含同一个头文件//
#include "los_cppsupport.h"
#ifdef __cplusplus //根据编译器是否为C++//
#if __cplusplus //来使用“extern 'C'”//
extern "C" { //对以下代码块内容进行//
#endif /* __cplusplus */ //正确处理函数名//
#endif /* __cplusplus */
extern CHAR __fast_end; //声明一个_fast_end的CHAR类型变量//
#ifdef LOSCFG_AARCH64 //条件编译//
extern UINT8 __EH_FRAME_BEGIN__[]; //声明一个UINT8类型的数组//
VOID __register_frame(VOID *begin);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */ //关闭extern'C'作用域//
#endif /* __cplusplus */
#endif /* _LOS_CPPSUPPORT_PRI_H */

@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved.
* Description: Cpup HeadFile
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _LOS_CPUP_PRI_H
#define _LOS_CPUP_PRI_H //防止多次包含同一个头文件//
#include "los_cpup.h" //可能包含了一些与CPU使用率//
#include "los_task_pri.h" //统计相关的公共声明和定义//
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_CPUP_HISTORY_RECORD_NUM 11 //定义历史记录的数量为11//
#define LOS_CPUP_PRECISION 1000 //定义CPU使用率的精度为1000//
#define LOS_CPUP_PRECISION_MULT (LOS_CPUP_PRECISION / 100) //可能用于计算CPU使用率//
typedef struct {
UINT32 id; /* Task ID */
UINT16 status; /* Task status */
UINT64 allTime; /* Total running time */
UINT64 startTime; /* Time before a task is invoked */
UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM + 1]; /* Historical running time, the last one saves zero */
} OsCpupCB;
extern OsCpupCB *OsCpupCBGet(UINT32 index); //根据索引获取 `OsCpupCB` 结构体指针//
extern UINT32 OsCpupInit(VOID); //CPU使用率统计模块的初始化函数//
extern VOID OsCpupSetCycle(UINT64 startCycles); //设置CPU周期计数//
extern UINT64 OsCpupGetCycle(VOID); //获取CPU周期计数//
extern VOID OsTaskCycleStart(VOID); //任务运行周期的起始//
extern VOID OsTaskCycleEnd(VOID); //任务运行周期的结束//
extern VOID OsTaskCycleEndStart(const LosTaskCB *newTask); //更新任务运行周期,并开始新的任务周期//
#ifdef LOSCFG_CPUP_INCLUDE_IRQ
VOID OsCpupIrqStart(VOID); //在前一条条件定义下,用于处理//
VOID OsCpupIrqEnd(UINT32); //中断的CPU使用率统计函数//
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_CPUP_PRI_H */
/*这段代码定义了一些用于CPU使用率统计的数据结构和函数声明
CPU*/

@ -0,0 +1,150 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: LiteOS Trace Module Private HeadFile
* Author: Huawei LiteOS Team
* Create: 2019-08-30
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _LOS_TRACE_PRI_H
#define _LOS_TRACE_PRI_H
#include "los_trace.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_TRACE_CONTROL_AGENT
#define TRACE_CMD_END_CHAR 0xD
#endif
#define TRACE_ERROR PRINT_ERR
#define TRACE_MODE_OFFLINE 0
#define TRACE_MODE_ONLINE 1
/* just task and hwi were traced */
#define TRACE_DEFAULT_MASK (TRACE_HWI_FLAG | TRACE_TASK_FLAG)
#define TRACE_CTL_MAGIC_NUM 0xDEADBEEF
#define TRACE_BIGLITTLE_WORD 0x12345678
#define TRACE_VERSION(MODE) (0xFFFFFFFF & (MODE))
#define TRACE_MASK_COMBINE(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
#define TRACE_GET_MODE_FLAG(type) ((type) & 0xFFFFFFF0)
extern SPIN_LOCK_S g_traceSpin;
#define TRACE_LOCK(state) LOS_SpinLockSave(&g_traceSpin, &(state))
#define TRACE_UNLOCK(state) LOS_SpinUnlockRestore(&g_traceSpin, (state))
typedef VOID (*TRACE_DUMP_HOOK)(BOOL toClient);
extern TRACE_DUMP_HOOK g_traceDumpHook;
enum TraceCmd {
TRACE_CMD_START = 1,
TRACE_CMD_STOP,
TRACE_CMD_SET_EVENT_MASK,
TRACE_CMD_RECODE_DUMP,
TRACE_CMD_MAX_CODE,
};
/**
* @ingroup los_trace
* struct to store the trace cmd from traceClient.
*/
typedef struct {
UINT8 cmd;
UINT8 param1;
UINT8 param2;
UINT8 param3;
UINT8 param4;
UINT8 param5;
UINT8 end;
} TraceClientCmd;
/**
* @ingroup los_trace
* struct to store the event infomation
*/
typedef struct {
UINT32 cmd; /* trace start or stop cmd */
UINT32 param; /* magic numb stand for notify msg */
} TraceNotifyFrame;
/**
* @ingroup los_trace
* struct to store the trace config information.
*/
typedef struct {
struct WriteCtrl {
UINT16 curIndex; /* The current record index */
UINT16 maxRecordCount; /* The max num of track items */
UINT16 curObjIndex; /* The current obj index */
UINT16 maxObjCount; /* The max num of obj index */
ObjData *objBuf; /* Pointer to obj info data */
TraceEventFrame *frameBuf; /* Pointer to the track items */
} ctrl;
OfflineHead *head;
} TraceOfflineHeaderInfo;
extern UINT32 OsTraceGetMaskTid(UINT32 taskId);
extern VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb);
extern VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame);
extern UINT32 OsTraceBufInit(VOID *buf, UINT32 size);
extern VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId);
extern BOOL OsTraceIsEnable(VOID);
extern OfflineHead *OsTraceRecordGet(VOID);
#ifdef LOSCFG_RECORDER_MODE_ONLINE
extern VOID OsTraceSendHead(VOID);
extern VOID OsTraceSendObjTable(VOID);
extern VOID OsTraceSendNotify(UINT32 type, UINT32 value);
#define OsTraceNotifyStart() do { \
OsTraceSendNotify(SYS_START, TRACE_CTL_MAGIC_NUM); \
OsTraceSendHead(); \
OsTraceSendObjTable(); \
} while (0)
#define OsTraceNotifyStop() do { \
OsTraceSendNotify(SYS_STOP, TRACE_CTL_MAGIC_NUM); \
} while (0)
#define OsTraceReset()
#define OsTraceRecordDump(toClient)
#else
extern VOID OsTraceReset(VOID);
extern VOID OsTraceRecordDump(BOOL toClient);
#define OsTraceNotifyStart()
#define OsTraceNotifyStop()
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_TRACE_PRI_H */

@ -0,0 +1,424 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: LiteOS Trace Implementation
* Author: Huawei LiteOS Team
* Create: 2019-08-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "uart.h"
#include "los_trace_pri.h"
#include "trace_pipeline.h"
#ifdef LOSCFG_KERNEL_SMP
#include "los_mp_pri.h"
#endif
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_KERNEL_TRACE
LITE_OS_SEC_BSS STATIC UINT32 g_traceEventCount; //追踪事件计数//
LITE_OS_SEC_BSS STATIC volatile enum TraceState g_traceState = TRACE_UNINIT; //追踪状态//
LITE_OS_SEC_DATA_INIT STATIC volatile BOOL g_enableTrace = FALSE; //是否启用追踪功能//
LITE_OS_SEC_BSS STATIC UINT32 g_traceMask = TRACE_DEFAULT_MASK; //追踪掩码,用于过滤追踪事件//
#ifdef LOSCFG_TRACE_CONTROL_AGENT
LITE_OS_SEC_BSS STATIC UINT32 g_traceTaskId; //追踪任务的ID//
#endif
#define EVENT_MASK 0xFFFFFFF0
#define MIN(x, y) ((x) < (y) ? (x) : (y))
LITE_OS_SEC_BSS STATIC TRACE_HWI_FILTER_HOOK g_traceHwiFliterHook = NULL;
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin);
STATIC_INLINE BOOL OsTraceHwiFilter(UINT32 hwiNum) //用于判断是否需要过滤某个硬件中断//
{
BOOL ret = ((hwiNum == NUM_HAL_INTERRUPT_UART) || (hwiNum == OS_TICK_INT_NUM));
#ifdef LOSCFG_KERNEL_SMP
ret |= (hwiNum == LOS_MP_IPI_SCHEDULE);
#endif
if (g_traceHwiFliterHook != NULL) {
ret |= g_traceHwiFliterHook(hwiNum);
}
return ret;
}
//用于设置追踪事件的帧信息//
STATIC VOID OsTraceSetFrame(TraceEventFrame *frame, UINT32 eventType, UINTPTR identity, const UINTPTR *params,
UINT16 paramCount)
{
INT32 i;
UINT32 intSave;
(VOID)memset_s(frame, sizeof(TraceEventFrame), 0, sizeof(TraceEventFrame));
if (paramCount > LOSCFG_TRACE_FRAME_MAX_PARAMS) {
paramCount = LOSCFG_TRACE_FRAME_MAX_PARAMS;
}
TRACE_LOCK(intSave);
frame->curTask = OsTraceGetMaskTid(OsCurrTaskGet()->taskId);
frame->identity = identity;
frame->curTime = HalClockGetCycles();
frame->eventType = eventType;
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
frame->core.cpuId = ArchCurrCpuid(); //CPU的ID//
frame->core.hwiActive = OS_INT_ACTIVE ? TRUE : FALSE; //硬件中断活动状态//
frame->core.taskLockCnt = MIN(OsPercpuGet()->taskLockCnt, 0xF); /* taskLockCnt is 4 bits, max vaule = 0xF */ //任务锁计数//
frame->core.paramCount = paramCount; //参数数目//
#endif
#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
frame->eventCount = g_traceEventCount; //追踪事件的计数//
g_traceEventCount++;
#endif
TRACE_UNLOCK(intSave);
for (i = 0; i < paramCount; i++) {
frame->params[i] = params[i];
}
}
VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb) //设置对象的追踪信息//
{
errno_t ret;
(VOID)memset_s(obj, sizeof(ObjData), 0, sizeof(ObjData));
obj->id = OsTraceGetMaskTid(tcb->taskId); //获取任务ID//
obj->prio = tcb->priority; //获取任务优先级//
ret = strncpy_s(obj->name, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE, tcb->taskName, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE - 1);
if (ret != EOK) {
TRACE_ERROR("Task name copy failed!\n");
}
}
//处理追踪事件钩子//
VOID OsTraceHook(UINT32 eventType, UINTPTR identity, const UINTPTR *params, UINT16 paramCount)
{
if ((eventType == TASK_CREATE) || (eventType == TASK_PRIOSET)) {
OsTraceObjAdd(eventType, identity); /* handle important obj info, these can not be filtered */
}
if ((g_enableTrace == TRUE) && (eventType & g_traceMask)) {
UINTPTR id = identity;
if (TRACE_GET_MODE_FLAG(eventType) == TRACE_HWI_FLAG) {
if (OsTraceHwiFilter(identity)) {
return;
}
} else if (TRACE_GET_MODE_FLAG(eventType) == TRACE_TASK_FLAG) {
id = OsTraceGetMaskTid(identity);
} else if (eventType == MEM_INFO_REQ) {
LOS_MEM_POOL_STATUS status;
LOS_MemInfoGet((VOID *)identity, &status);
LOS_TRACE(MEM_INFO, identity, status.uwTotalUsedSize, status.uwTotalFreeSize);
return;
}
TraceEventFrame frame;
OsTraceSetFrame(&frame, eventType, id, params, paramCount);
OsTraceWriteOrSendEvent(&frame); //将追踪事件信息写入或发送出去//
}
}
BOOL OsTraceIsEnable(VOID) //判断追踪是否处于启用状态//
{
return g_enableTrace == TRUE;
}
STATIC VOID OsTraceHookInstall(VOID) //安装追踪钩子//
{
g_traceEventHook = OsTraceHook;
#ifdef LOSCFG_RECORDER_MODE_OFFLINE
g_traceDumpHook = OsTraceRecordDump; //在离线记录模式下设置追踪转储钩子//
#endif
}
#ifdef LOSCFG_TRACE_CONTROL_AGENT
STATIC BOOL OsTraceCmdIsValid(const TraceClientCmd *msg) //判断传入的TraceClientCmd结构体是否有效//
{
return ((msg->end == TRACE_CMD_END_CHAR) && (msg->cmd < TRACE_CMD_MAX_CODE));
}
STATIC VOID OsTraceCmdHandle(const TraceClientCmd *msg) //处理传入的TraceClientCmd结构体//
{
if (!OsTraceCmdIsValid(msg)) {
return;
}
switch (msg->cmd) {
case TRACE_CMD_START: //启动追踪//
LOS_TraceStart();
break;
case TRACE_CMD_STOP: //停止追踪//
LOS_TraceStop();
break;
case TRACE_CMD_SET_EVENT_MASK: //设置事件掩码//
/* 4 params(UINT8) composition the mask(UINT32) */
LOS_TraceEventMaskSet(TRACE_MASK_COMBINE(msg->param1, msg->param2, msg->param3, msg->param4));
break;
case TRACE_CMD_RECODE_DUMP: //追踪记录转储//
LOS_TraceRecordDump(TRUE);
break;
default:
break;
}
}
VOID TraceAgent(VOID) //不断等待追踪数据的到达,并处理接收到的追踪命令//
{
UINT32 ret;
TraceClientCmd msg;
while (1) {
(VOID)memset_s(&msg, sizeof(TraceClientCmd), 0, sizeof(TraceClientCmd));
ret = OsTraceDataWait();
if (ret == LOS_OK) {
OsTraceDataRecv((UINT8 *)&msg, sizeof(TraceClientCmd), 0);
OsTraceCmdHandle(&msg);
}
}
}
STATIC UINT32 OsCreateTraceAgentTask(VOID) //创建一个追踪代理任务,用于执行追踪逻辑//
{
UINT32 ret;
TSK_INIT_PARAM_S taskInitParam;
(VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)TraceAgent;
taskInitParam.usTaskPrio = LOSCFG_TRACE_TASK_PRIORITY;
taskInitParam.pcName = "TraceAgent";
taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
#ifdef LOSCFG_KERNEL_SMP
taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
#endif
ret = LOS_TaskCreate(&g_traceTaskId, &taskInitParam);
return ret;
}
#endif
UINT32 LOS_TraceInit(VOID *buf, UINT32 size) //初始化追踪功能//
{
UINT32 intSave;
UINT32 ret;
TRACE_LOCK(intSave);
if (g_traceState != TRACE_UNINIT) {
TRACE_ERROR("trace has been initialized already, the current state is :%d\n", g_traceState);
ret = LOS_ERRNO_TRACE_ERROR_STATUS;
goto LOS_ERREND;
}
#ifdef LOSCFG_TRACE_CLIENT_INTERACT //判断是否需要初始化追踪管道//
ret = OsTracePipelineInit();
if (ret != LOS_OK) {
goto LOS_ERREND;
}
#endif
#ifdef LOSCFG_TRACE_CONTROL_AGENT //判断是否需要创建追踪代理任务//
ret = OsCreateTraceAgentTask();
if (ret != LOS_OK) {
TRACE_ERROR("trace init create agentTask error :0x%x\n", ret);
goto LOS_ERREND;
}
#endif
ret = OsTraceBufInit(buf, size); //初始化追踪缓冲区//
if (ret != LOS_OK) {
goto LOS_RELEASE;
}
OsTraceHookInstall(); //安装追踪钩子//
g_traceEventCount = 0;
/*判断是否需要等待追踪客户端启动追踪*/
#ifdef LOSCFG_RECORDER_MODE_ONLINE /* Wait trace client to start trace */
g_enableTrace = FALSE;
g_traceState = TRACE_INITED;
#else
g_enableTrace = TRUE;
g_traceState = TRACE_STARTED;
#endif
TRACE_UNLOCK(intSave);
return LOS_OK;
LOS_RELEASE:
#ifdef LOSCFG_TRACE_CONTROL_AGENT //判断是否需要删除追踪代理任务//
LOS_TaskDelete(g_traceTaskId);
#endif
LOS_ERREND:
TRACE_UNLOCK(intSave);
return ret;
}
UINT32 LOS_TraceStart(VOID) //用于启动追踪功能//
{
UINT32 intSave;
UINT32 ret = LOS_OK;
TRACE_LOCK(intSave);
if (g_traceState == TRACE_STARTED) {
goto START_END;
}
if (g_traceState == TRACE_UNINIT) {
TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n");
ret = LOS_ERRNO_TRACE_ERROR_STATUS;
goto START_END;
}
OsTraceNotifyStart(); //通知追踪功能开始工作//
g_enableTrace = TRUE;
g_traceState = TRACE_STARTED;
TRACE_UNLOCK(intSave);
LOS_TRACE(MEM_INFO_REQ, m_aucSysMem0); //发送追踪信息//
return ret;
START_END:
TRACE_UNLOCK(intSave);
return ret;
}
VOID LOS_TraceStop(VOID) //用于停止追踪功能//
{
UINT32 intSave;
TRACE_LOCK(intSave);
if (g_traceState != TRACE_STARTED) {
goto STOP_END;
}
g_enableTrace = FALSE;
g_traceState = TRACE_STOPED;
OsTraceNotifyStop(); //通知追踪功能停止工作//
STOP_END:
TRACE_UNLOCK(intSave);
}
VOID LOS_TraceEventMaskSet(UINT32 mask) //设置追踪事件掩码//
{
g_traceMask = mask & EVENT_MASK;
}
VOID LOS_TraceRecordDump(BOOL toClient) //转储追踪记录//
{
if (g_traceState != TRACE_STOPED) {
TRACE_ERROR("trace dump must after trace stopped , the current state is : %d\n", g_traceState);
return;
}
OsTraceRecordDump(toClient);
}
OfflineHead *LOS_TraceRecordGet(VOID) //获取追踪记录//
{
return OsTraceRecordGet();
}
VOID LOS_TraceReset(VOID) //重置追踪功能//
{
if (g_traceState == TRACE_UNINIT) {
TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n");
return;
}
OsTraceReset();
}
VOID LOS_TraceHwiFilterHookReg(TRACE_HWI_FILTER_HOOK hook) //注册中断过滤钩子//
{
UINT32 intSave;
TRACE_LOCK(intSave);
g_traceHwiFliterHook = hook;
TRACE_UNLOCK(intSave);
}
#ifdef LOSCFG_SHELL
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceSetMask(INT32 argc, const CHAR **argv) //设置追踪事件掩码//
{
size_t mask;
CHAR *endPtr = NULL;
if (argc >= 2) { /* 2:Just as number of parameters */
PRINTK("\nUsage: trace_mask or trace_mask ID\n");
return OS_ERROR;
}
if (argc == 0) {
mask = TRACE_DEFAULT_MASK;
} else {
mask = strtoul(argv[0], &endPtr, 0);
}
LOS_TraceEventMaskSet((UINT32)mask);
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceDump(INT32 argc, const CHAR **argv) //进行追踪记录的转储//
{
BOOL toClient;
CHAR *endPtr = NULL;
if (argc >= 2) { /* 2:Just as number of parameters */
PRINTK("\nUsage: trace_dump or trace_dump [1/0]\n");
return OS_ERROR;
}
if (argc == 0) {
toClient = FALSE;
} else {
toClient = strtoul(argv[0], &endPtr, 0) != 0 ? TRUE : FALSE;
}
LOS_TraceRecordDump(toClient);
return LOS_OK;
}
/*命令行函数的注册*/
SHELLCMD_ENTRY(tracestart_shellcmd, CMD_TYPE_EX, "trace_start", 0, (CmdCallBackFunc)LOS_TraceStart); //追踪功能的启动//
SHELLCMD_ENTRY(tracestop_shellcmd, CMD_TYPE_EX, "trace_stop", 0, (CmdCallBackFunc)LOS_TraceStop); //追踪功能的停止//
SHELLCMD_ENTRY(tracesetmask_shellcmd, CMD_TYPE_EX, "trace_mask", 1, (CmdCallBackFunc)OsShellCmdTraceSetMask); //设置追踪事件掩码//
SHELLCMD_ENTRY(tracereset_shellcmd, CMD_TYPE_EX, "trace_reset", 0, (CmdCallBackFunc)LOS_TraceReset); //重置追踪记录//
SHELLCMD_ENTRY(tracedump_shellcmd, CMD_TYPE_EX, "trace_dump", 1, (CmdCallBackFunc)OsShellCmdTraceDump); //转储追踪记录//
#endif
#endif /* LOSCFG_KERNEL_TRACE */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,98 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Pipeline of Serial Implementation
* Author: Huawei LiteOS Team
* Create: 2020-03-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "trace_pipeline_serial.h"
#include "trace_pipeline.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_TRACE_CONTROL_AGENT
UINT32 SerialPipelineInit(VOID) //用于初始化串行管道//
{
return uart_hwiCreate();
}
UINT32 SerialDataReceive(UINT8 *data, UINT32 size, UINT32 timeout) //用于从串行管道接收数据//
{
return uart_read(data, size, timeout);
}
UINT32 SerialWait(VOID) //用于等待串行管道准备就绪//
{
return uart_wait_adapt();
}
#else//4号车密码2930
UINT32 SerialPipelineInit(VOID) //表示初始化成功//
{
return LOS_OK;
}
UINT32 SerialDataReceive(UINT8 *data, UINT32 size, UINT32 timeout) //表示接收到了数据//
{
return LOS_OK;
}
UINT32 SerialWait(VOID) //表示已经准备就绪//
{
return LOS_OK;
}
#endif
VOID SerialDataSend(UINT16 len, UINT8 *data) //用于向串行管道发送数据//
{
UINT32 i;
for (i = 0; i < len; i++) {
UART_PUTC(data[i]);
}
}
STATIC const TracePipelineOps g_serialOps = {
.init = SerialPipelineInit,
.dataSend = SerialDataSend,
.dataRecv = SerialDataReceive,
.wait = SerialWait,
};
UINT32 OsTracePipelineInit(VOID) //用于初始化追踪管道并注册与之相关的操作接口//
{
OsTracePipelineReg(&g_serialOps);
return g_serialOps.init();
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,50 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Pipeline of Serial Implementation HeadFile
* Author: Huawei LiteOS Team
* Create: 2020-03-16
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _TRACE_PIPELINE_SERIAL_H
#define _TRACE_PIPELINE_SERIAL_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern INT32 uart_putc(CHAR c); //用于向串口发送一个字符//
#define UART_PUTC(c) uart_putc((c)) //调用uart_putc函数//
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _TRACE_PIPELINE_SERIAL_H */

@ -0,0 +1,156 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Pipeline Implementation
* Author: Huawei LiteOS Team
* Create: 2020-03-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "trace_pipeline.h"
#include "trace_tlv.h"
#include "los_trace_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
//防止缓冲区溢出//
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_pipeSpin); //初始化一个自旋锁//
#define PIPE_LOCK(state) LOS_SpinLockSave(&g_pipeSpin, &(state)) //对自旋锁加锁操作//
#define PIPE_UNLOCK(state) LOS_SpinUnlockRestore(&g_pipeSpin, (state)) //对自旋锁解锁操作//
STATIC TlvTable g_traceTlvTblNotify[] = { //定义结构体的成员变量类型和大小//
{ CMD, LOS_OFF_SET_OF(TraceNotifyFrame, cmd), sizeof(UINT32) },
{ PARAMS, LOS_OFF_SET_OF(TraceNotifyFrame, param), sizeof(UINT32) },
{ TRACE_TLV_TYPE_NULL, 0, 0 },
};
STATIC TlvTable g_traceTlvTblHead[] = { //定义结构体的成员变量类型和大小//
{ ENDIAN, LOS_OFF_SET_OF(TraceBaseHeaderInfo, bigLittleEndian), sizeof(UINT32) },
{ VERSION, LOS_OFF_SET_OF(TraceBaseHeaderInfo, version), sizeof(UINT32) },
{ CLOCK_FREQ, LOS_OFF_SET_OF(TraceBaseHeaderInfo, clockFreq), sizeof(UINT32) },
{ TRACE_TLV_TYPE_NULL, 0, 0 },
};
STATIC TlvTable g_traceTlvTblObj[] = { //定义结构体的成员变量类型、偏移位置和大小//
{ ADDR, LOS_OFF_SET_OF(ObjData, id), sizeof(UINT32) },
{ PRIO, LOS_OFF_SET_OF(ObjData, prio), sizeof(UINT32) },
{ NAME, LOS_OFF_SET_OF(ObjData, name), sizeof(CHAR) * LOSCFG_TRACE_OBJ_MAX_NAME_SIZE },
{ TRACE_TLV_TYPE_NULL, 0, 0 },
};
STATIC TlvTable g_traceTlvTblEvent[] = { //定义结构体的成员变量类型和大小//
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
{ CORE, LOS_OFF_SET_OF(TraceEventFrame, core), sizeof(UINT32) },
#endif
{ EVENT_CODE, LOS_OFF_SET_OF(TraceEventFrame, eventType), sizeof(UINT32) },
{ CUR_TIME, LOS_OFF_SET_OF(TraceEventFrame, curTime), sizeof(UINT64) },
#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
{ EVENT_COUNT, LOS_OFF_SET_OF(TraceEventFrame, eventCount), sizeof(UINT32) },
#endif
{ CUR_TASK, LOS_OFF_SET_OF(TraceEventFrame, curTask), sizeof(UINT32) },
{ IDENTITY, LOS_OFF_SET_OF(TraceEventFrame, identity), sizeof(UINTPTR) },
{ EVENT_PARAMS, LOS_OFF_SET_OF(TraceEventFrame, params), sizeof(UINTPTR) * LOSCFG_TRACE_FRAME_MAX_PARAMS },
{ TRACE_TLV_TYPE_NULL, 0, 0 },
};
STATIC TlvTable *g_traceTlvTbl[] = {
g_traceTlvTblNotify,
g_traceTlvTblHead,
g_traceTlvTblObj,
g_traceTlvTblEvent
};
STATIC UINT32 DefaultPipelineInit(VOID)
{
return LOS_OK;
}
STATIC VOID DefaultDataSend(UINT16 len, UINT8 *data)
{ //将len和data参数标记为"未使用"//
(VOID)len; //避免编译器产生警告//
(VOID)data;
}
STATIC UINT32 DefaultDataReceive(UINT8 *data, UINT32 size, UINT32 timeout)
{
(VOID)data; //将data、size和timeout参数标记为"未使用"//
(VOID)size;
(VOID)timeout;
return LOS_OK;
}
STATIC UINT32 DefaultWait(VOID)
{
return LOS_OK;
}
STATIC TracePipelineOps g_defaultOps = {
.init = DefaultPipelineInit,
.dataSend = DefaultDataSend,
.dataRecv = DefaultDataReceive,
.wait = DefaultWait,
};
STATIC const TracePipelineOps *g_tracePipelineOps = &g_defaultOps;
VOID OsTracePipelineReg(const TracePipelineOps *ops)
{
g_tracePipelineOps = ops; //用于注册一个TracePipelineOps结构体指针//
}
VOID OsTraceDataSend(UINT8 type, UINT16 len, UINT8 *data) //用于发送追踪数据//
{
UINT32 intSave;
UINT8 outBuf[LOSCFG_TRACE_TLV_BUF_SIZE] = {0};
if ((type > TRACE_MSG_MAX) || (len > LOSCFG_TRACE_TLV_BUF_SIZE)) { //输入参数的合法性检查//
return;
}
//对数据进行编码//
len = OsTraceDataEncode(type, g_traceTlvTbl[type], data, &outBuf[0], sizeof(outBuf));
PIPE_LOCK(intSave); //获取管道锁,防止多线程并发访问//
g_tracePipelineOps->dataSend(len, &outBuf[0]); //发送编码后的数据//
PIPE_UNLOCK(intSave); //释放管道锁//
}
UINT32 OsTraceDataRecv(UINT8 *data, UINT32 size, UINT32 timeout) //用于接收追踪数据//
{
return g_tracePipelineOps->dataRecv(data, size, timeout);
}
UINT32 OsTraceDataWait(VOID) //用于等待追踪数据//
{
return g_tracePipelineOps->wait();
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,104 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Pipeline Implementation HeadFile
* Author: Huawei LiteOS Team
* Create: 2020-03-16
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _TRACE_PIPELINE_H
#define _TRACE_PIPELINE_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*用于实现追踪流水线的功能*/
typedef struct {
UINT32 (*init)(VOID); //用于初始化//
VOID (*dataSend)(UINT16 len, UINT8 *data); //用于发送数据//
UINT32 (*dataRecv)(UINT8 *data, UINT32 size, UINT32 timeout); //用于接收数据//
UINT32 (*wait)(VOID); //用于等待操作//
} TracePipelineOps;
/* used as tlv's tag */
enum TraceMsgType { //用于表示追踪消息的类型//
//类型如下//
NOTIFY, //通知//
HEAD, //头部//
OBJ, //对象//
EVENT, //事件//
TRACE_MSG_MAX, //最大值//
};
enum TraceNotifySubType { //用于表示通知消息的子类型//
CMD = 0x1,
PARAMS,
};
enum TraceHeadSubType { //用于表示追踪头部信息的子类型//
ENDIAN = 0x1, //字节序//
VERSION, //版本//
OBJ_SIZE, //对象大小//
OBJ_COUNT, //对象计数//
CUR_INDEX, //当前索引//
MAX_RECODE,
CUR_OBJ_INDEX,
CLOCK_FREQ,
};
enum TraceObjSubType { //用于表示追踪对象的子类型//
ADDR = 0x1, //地址//
PRIO, //优先级/
NAME, //名称//
};
enum TraceEvtSubType { //用于表示追踪事件的子类型//
CORE = 0x1, //核心编号//
EVENT_CODE, //事件码//
CUR_TIME, //当前时间//
EVENT_COUNT, //事件计数//
CUR_TASK, //当前任务//
IDENTITY, //身份信息//
EVENT_PARAMS, //事件参数//
};
extern VOID OsTracePipelineReg(const TracePipelineOps *ops); //用于注册追踪管道操作//
extern UINT32 OsTracePipelineInit(VOID); //用于初始化追踪管道//
extern VOID OsTraceDataSend(UINT8 type, UINT16 len, UINT8 *data); //用于发送追踪数据//
extern UINT32 OsTraceDataRecv(UINT8 *data, UINT32 size, UINT32 timeout); //用于接收追踪数据//
extern UINT32 OsTraceDataWait(VOID); //用于等待追踪数据//
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _TRACE_PIPELINE_H */

@ -0,0 +1,121 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Tlv Implementation
* Author: Huawei LiteOS Team
* Create: 2020-03-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "trace_tlv.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define CRC_WIDTH 8 //CRC的位宽//
#define CRC_POLY 0x1021 //CRC多项式//
#define CRC_TOPBIT 0x8000 //CRC计算中的最高位//
STATIC UINT16 CalcCrc16(const UINT8 *buf, UINT32 len) //用于计算16位CRC校验值//
{
UINT32 i;
UINT16 crc = 0;
for (; len > 0; len--) {
crc = crc ^ (*buf++ << CRC_WIDTH);
for (i = 0; i < CRC_WIDTH; i++) {
if (crc & CRC_TOPBIT) {
crc = (crc << 1) ^ CRC_POLY;
} else {
crc <<= 1;
}
}
}
return crc;
}
STATIC UINT32 OsWriteTlv(UINT8 *tlvBuf, UINT8 type, UINT8 len, UINT8 *value) //将TLV数据写入TLV缓冲区//
{
TraceMsgTlvBody *body = (TraceMsgTlvBody *)tlvBuf;
if (len == 0) {
return 0;
}
body->type = type;
body->len = len;
/* Do not check return value for performance, if copy failed, only this package will be discarded */
(VOID)memcpy_s(body->value, len, value, len);
return len + sizeof(body->type) + sizeof(body->len); //返回实际写入的字节数//
}
/*根据TLV表中的定义将源数据编码成TLV格式并写入TLV缓冲区*/
STATIC UINT32 OsTlvEncode(const TlvTable *table, UINT8 *srcBuf, UINT8 *tlvBuf, INT32 tlvBufLen)
{
UINT32 len = 0;
const TlvTable *tlvTableItem = table;
while (tlvTableItem->tag != TRACE_TLV_TYPE_NULL) {
if ((len + tlvTableItem->elemSize + sizeof(UINT8) + sizeof(UINT8)) > tlvBufLen) {
break;
}
len += OsWriteTlv(tlvBuf + len, tlvTableItem->tag, tlvTableItem->elemSize, srcBuf + tlvTableItem->elemOffset);
tlvTableItem++;
}
return len;
}
/*将源数据按照TLV表的定义编码并写入目标缓冲区*/
UINT32 OsTraceDataEncode(UINT8 type, const TlvTable *table, UINT8 *src, UINT8 *dest, INT32 destLen)
{
UINT16 crc;
INT32 len;
INT32 tlvBufLen;
UINT8 *tlvBuf = NULL;
TraceMsgTlvHead *head = (TraceMsgTlvHead *)dest;
tlvBufLen = destLen - sizeof(TraceMsgTlvHead);
if ((tlvBufLen <= 0) || (table == NULL)) {
return 0;
}
tlvBuf = dest + sizeof(TraceMsgTlvHead);
len = OsTlvEncode(table, src, tlvBuf, tlvBufLen);
crc = CalcCrc16(tlvBuf, len);
head->magicNum = TRACE_TLV_MSG_HEAD;
head->msgType = type;
head->len = len;
head->crc = crc;
return len + sizeof(TraceMsgTlvHead);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,95 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Tlv Implementation HeadFile
* Author: Huawei LiteOS Team
* Create: 2020-03-16
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#ifndef _TRACE_TLV_H
#define _TRACE_TLV_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define TRACE_TLV_MSG_HEAD 0xFF
#define TRACE_TLV_TYPE_NULL 0xFF
typedef struct {
UINT8 magicNum; //魔术数字//
UINT8 msgType; //消息类型//
UINT16 len; //消息长度//
UINT16 crc; //CRC校验码//
} TraceMsgTlvHead; //TLV消息的头部//
typedef struct {
UINT8 type; //消息类型///
UINT8 len; //消息长度//
UINT8 value[]; //数据内容//
} TraceMsgTlvBody; //TLV消息的消息体//
typedef struct {
UINT8 tag; //标签//
UINT8 elemOffset; //元素偏移//
UINT8 elemSize; //元素大小//
} TlvTable; //TLV表项//
/**
* @ingroup los_trace
* @brief Encode trace raw data.
*
* @par Description:
* This API is used to encode trace raw data to tlv data.
* @attention
* <ul>
* <li>Encade trace data</li>
* </ul>
*
* @param type [IN] Type #UINT8. The type stands for different struct of src data.
* @param src [IN] Type #UINT8 *. The raw trace data.
* @param table [IN] Type #const TlvTable *. The tlv table descript elemOffset and elemSize.
* @param dest [OUT] Type #UINT8 *. The tlv data.
* @param destLen [IN] Type #UINT8 *. The tlv buf max len.
* @retval #0 convert failed.
* @retval #UINT32 convert success bytes.
*
* @par Dependency:
* <ul><li>trace_tlv.h: the header file that contains the API declaration.</li></ul>
* @see LOS_TraceDataEncode
* @since Huawei LiteOS V200R005C00
*/
extern UINT32 OsTraceDataEncode(UINT8 type, const TlvTable *table, UINT8 *src, UINT8 *dest, INT32 destLen);
/*根据TLV表的描述信息将原始追踪数据进行编码生成相应的TLV数据*/
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _TRACE_TLV_H */

@ -0,0 +1,264 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Offline Mode Implementation
* Author: Huawei LiteOS Team
* Create: 2020-03-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_trace_pri.h"
#include "trace_pipeline.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_RECORDER_MODE_OFFLINE
#define BITS_NUM_FOR_TASK_ID 16 //指定了任务ID的位数//
LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder; //用来记录离线跟踪记录的相关信息//
LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0}; //用于存储任务ID的掩码//
UINT32 OsTraceGetMaskTid(UINT32 tid) //用于获取掩码后的任务ID//
{
return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */
}
UINT32 OsTraceBufInit(VOID *buf, UINT32 size) //用于初始化离线跟踪缓冲区//
{
UINT32 headSize;
headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM; //用于存储离线跟踪记录头部信息//
if (size <= headSize) {
TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize);
return LOS_ERRNO_TRACE_BUF_TOO_SMALL;
}
if (buf == NULL) {
buf = LOS_MemAlloc(m_aucSysMem1, size);
if (buf == NULL) {
return LOS_ERRNO_TRACE_NO_MEMORY;
}
}
(VOID)memset_s(buf, size, 0, size);
g_traceRecoder.head = (OfflineHead *)buf;
g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD;
g_traceRecoder.head->baseInfo.version = TRACE_VERSION(TRACE_MODE_OFFLINE);
g_traceRecoder.head->baseInfo.clockFreq = GET_SYS_CLOCK();
g_traceRecoder.head->objSize = sizeof(ObjData);
g_traceRecoder.head->frameSize = sizeof(TraceEventFrame);
g_traceRecoder.head->objOffset = sizeof(OfflineHead);
g_traceRecoder.head->frameOffset = headSize;
g_traceRecoder.head->totalLen = size;
g_traceRecoder.ctrl.curIndex = 0;
g_traceRecoder.ctrl.curObjIndex = 0;
g_traceRecoder.ctrl.maxObjCount = LOSCFG_TRACE_OBJ_MAX_NUM;
g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame);
g_traceRecoder.ctrl.objBuf = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset);
g_traceRecoder.ctrl.frameBuf = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset);
return LOS_OK;
}
VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId) //用于向离线跟踪缓冲区中添加对象数据//
{
UINT32 intSave;
UINT32 index;
ObjData *obj = NULL;
TRACE_LOCK(intSave);
/* add obj begin */
index = g_traceRecoder.ctrl.curObjIndex;
if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */
TRACE_UNLOCK(intSave);
return;
}
obj = &g_traceRecoder.ctrl.objBuf[index];
if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) {
g_tidMask[taskId]++;
}
OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId));
g_traceRecoder.ctrl.curObjIndex++;
if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) {
g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */
}
/* add obj end */
TRACE_UNLOCK(intSave);
}
VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame) //用于向离线跟踪缓冲区中写入或发送事件帧数据//
{
UINT16 index;
UINT32 intSave;
TRACE_LOCK(intSave);
index = g_traceRecoder.ctrl.curIndex;
(VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame));
g_traceRecoder.ctrl.curIndex++;
if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) {
g_traceRecoder.ctrl.curIndex = 0;
}
TRACE_UNLOCK(intSave);
}
VOID OsTraceReset(VOID) //用于重置离线跟踪缓冲区//
{
UINT32 intSave;
UINT32 bufLen;
TRACE_LOCK(intSave);
bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount;
(VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen);
g_traceRecoder.ctrl.curIndex = 0;
TRACE_UNLOCK(intSave);
}
STATIC VOID OsTraceInfoObj(VOID) //用于打印离线跟踪对象信息//
{
UINT32 i;
ObjData *obj = &g_traceRecoder.ctrl.objBuf[0];
if (g_traceRecoder.ctrl.maxObjCount > 0) {
PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex);
PRINTK("Index TaskID TaskPrio TaskName \n");
for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) {
PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name);
}
PRINTK("\n");
}
}
STATIC VOID OsTraceInfoEventTitle(VOID) //用于打印离线跟踪事件标题//
{
PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex);
PRINTK("Index Time(cycles) EventType CurTask Identity ");
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
PRINTK("cpuId hwiActive taskLockCnt ");
#endif
#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
PRINTK("eventCount ");
#endif
if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) {
PRINTK("params ");
}
PRINTK("\n");
}
STATIC VOID OsTraceInfoEventData(VOID) //用于打印离线跟踪事件数据//
{
UINT32 i, j;
TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0];
for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) {
PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-11x ", i, frame->curTime, frame->eventType,
frame->curTask, frame->identity);
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
UINT32 taskLockCnt = frame->core.taskLockCnt;
#ifdef LOSCFG_KERNEL_SMP
/*
* For smp systems, TRACE_LOCK will requst taskLock, and this counter
* will increase by 1 in that case.
*/
taskLockCnt -= 1;
#endif
PRINTK("%-11u %-11u %-11u", frame->core.cpuId, frame->core.hwiActive, taskLockCnt);
#endif
#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
PRINTK("%-11u", frame->eventCount);
#endif
for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) {
PRINTK("0x%-11x", frame->params[j]);
}
PRINTK("\n");
}
}
STATIC VOID OsTraceInfoDisplay(VOID) //用于显示离线跟踪信息//
{
OfflineHead *head = g_traceRecoder.head;
PRINTK("*******TraceInfo begin*******\n");
PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq);
OsTraceInfoObj();
OsTraceInfoEventTitle();
OsTraceInfoEventData();
PRINTK("*******TraceInfo end*******\n");
}
#ifdef LOSCFG_TRACE_CLIENT_INTERACT
STATIC VOID OsTraceSendInfo(VOID) //用于发送离线跟踪信息//
{
UINT32 i;
ObjData *obj = NULL;
TraceEventFrame *frame = NULL;
OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head);
obj = &g_traceRecoder.ctrl.objBuf[0];
for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) {
OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i));
}
frame = &g_traceRecoder.ctrl.frameBuf[0];
for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) {
OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i));
}
}
#endif
VOID OsTraceRecordDump(BOOL toClient) //用于输出或发送离线跟踪信息//
{
if (!toClient) { //用于指示是输出还是发送离线跟踪信息//
OsTraceInfoDisplay();
return;
}
#ifdef LOSCFG_TRACE_CLIENT_INTERACT
OsTraceSendInfo();
#endif
}
OfflineHead *OsTraceRecordGet(VOID) //用于获取离线跟踪记录的头信息//
{
return g_traceRecoder.head;
}
#endif /* LOSCFG_RECORDER_MODE_OFFLINE */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

@ -0,0 +1,117 @@
/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: LiteOS Trace Online Mode Implementation
* Author: Huawei LiteOS Team
* Create: 2020-03-31
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
#include "los_trace_pri.h"
#include "trace_pipeline.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_RECORDER_MODE_ONLINE
UINT32 OsTraceGetMaskTid(UINT32 taskId) //用于获取任务ID的掩码//
{
return taskId;
}
UINT32 OsTraceBufInit(VOID *buf, UINT32 size) //初始化跟踪缓冲区//
{
(VOID)buf;
(VOID)size;
return LOS_OK;
}
VOID OsTraceSendHead(VOID) //发送跟踪数据的头信息//
{
TraceBaseHeaderInfo head = {
.bigLittleEndian = TRACE_BIGLITTLE_WORD,
.version = TRACE_VERSION(TRACE_MODE_ONLINE),
.clockFreq = GET_SYS_CLOCK(),
};
OsTraceDataSend(HEAD, sizeof(TraceBaseHeaderInfo), (UINT8 *)&head);
}
VOID OsTraceSendNotify(UINT32 type, UINT32 value) //发送通知类型的跟踪数据//
{
TraceNotifyFrame frame = {
.cmd = type,
.param = value,
};
OsTraceDataSend(NOTIFY, sizeof(TraceNotifyFrame), (UINT8 *)&frame);
}
STATIC VOID OsTraceSendObj(const LosTaskCB *tcb) //发送对象类型为obj的跟踪数据//
{
ObjData obj;
OsTraceSetObj(&obj, tcb);
OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)&obj);
}
VOID OsTraceSendObjTable(VOID) //发送对象表类型的跟踪数据//
{
UINT32 loop;
LosTaskCB *tcb = NULL;
for (loop = 0; loop < g_taskMaxNum; ++loop) {
tcb = g_taskCBArray + loop;
if (tcb->taskStatus & OS_TASK_STATUS_UNUSED) {
continue;
}
OsTraceSendObj(tcb);
}
}
VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId) //向跟踪记录中添加对象//
{
if (OsTraceIsEnable()) {
OsTraceSendObj(OS_TCB_FROM_TID(taskId));
}
}
VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame) //发送事件数据//
{
OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)frame);
}
OfflineHead *OsTraceRecordGet(VOID) //获取离线跟踪记录头//
{
return NULL; //表示没有离线跟踪记录可用//
}
#endif /* LOSCFG_RECORDER_MODE_ONLINE */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
Loading…
Cancel
Save