commit
3370bcc0b2
@ -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.
Binary file not shown.
@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "windows-gcc-x64",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"compilerPath": "D:/mingw64/bin/gcc.exe",
|
||||
"cStandard": "${default}",
|
||||
"cppStandard": "${default}",
|
||||
"intelliSenseMode": "windows-gcc-x64",
|
||||
"compilerArgs": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C/C++ Runner: Debug Session",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": true,
|
||||
"cwd": "h:/ruanjian/LiteOS-Reading/src/kernel/extended/perf/pmu",
|
||||
"program": "h:/ruanjian/LiteOS-Reading/src/kernel/extended/perf/pmu/build/Debug/outDebug",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
{
|
||||
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||
"C_Cpp_Runner.cStandard": "",
|
||||
"C_Cpp_Runner.cppStandard": "",
|
||||
"C_Cpp_Runner.msvcBatchPath": "",
|
||||
"C_Cpp_Runner.useMsvc": false,
|
||||
"C_Cpp_Runner.warnings": [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wpedantic",
|
||||
"-Wshadow",
|
||||
"-Wformat=2",
|
||||
"-Wcast-align",
|
||||
"-Wconversion",
|
||||
"-Wsign-conversion",
|
||||
"-Wnull-dereference"
|
||||
],
|
||||
"C_Cpp_Runner.msvcWarnings": [
|
||||
"/W4",
|
||||
"/permissive-",
|
||||
"/w14242",
|
||||
"/w14287",
|
||||
"/w14296",
|
||||
"/w14311",
|
||||
"/w14826",
|
||||
"/w44062",
|
||||
"/w44242",
|
||||
"/w14905",
|
||||
"/w14906",
|
||||
"/w14263",
|
||||
"/w44265",
|
||||
"/w14928"
|
||||
],
|
||||
"C_Cpp_Runner.enableWarnings": true,
|
||||
"C_Cpp_Runner.warningsAsError": false,
|
||||
"C_Cpp_Runner.compilerArgs": [],
|
||||
"C_Cpp_Runner.linkerArgs": [],
|
||||
"C_Cpp_Runner.includePaths": [],
|
||||
"C_Cpp_Runner.includeSearch": [
|
||||
"*",
|
||||
"**/*"
|
||||
],
|
||||
"C_Cpp_Runner.excludeSearch": [
|
||||
"**/build",
|
||||
"**/build/**",
|
||||
"**/.*",
|
||||
"**/.*/**",
|
||||
"**/.vscode",
|
||||
"**/.vscode/**"
|
||||
],
|
||||
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||
"C_Cpp_Runner.showCompilationTime": false,
|
||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||
}
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue