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