new code-reading

pull/9/head
文豪 11 months ago
parent 2bdb3fa4bd
commit 0771df2fb3

@ -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.
Loading…
Cancel
Save