add OpenHarmony 1.0 baseline

This commit is contained in:
wenjun
2020-09-08 10:21:39 +08:00
parent 94f5f466b4
commit 6df931fc98
736 changed files with 111817 additions and 0 deletions

82
kernel/base/BUILD.gn Executable file
View File

@@ -0,0 +1,82 @@
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
#
# 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.
static_library("base") {
sources = [
"ipc/los_mux.c",
"ipc/los_sem_debug.c",
"ipc/los_queue_debug.c",
"ipc/los_ipcdebug.c",
"ipc/los_mux_debug.c",
"ipc/los_sem.c",
"ipc/los_event.c",
"ipc/los_queue.c",
"core/los_swtmr.c",
"core/los_task.c",
"core/los_timeslice.c",
"core/los_sortlink.c",
"core/los_bitmap.c",
"core/los_process.c",
"core/los_sys.c",
"core/los_tick.c",
"mem/bestfit/los_memory.c",
"mem/bestfit/los_multipledlinkhead.c",
"mem/membox/los_membox.c",
"mem/common/los_memstat.c",
"om/los_err.c",
"misc/task_shellcmd.c",
"misc/los_stackinfo.c",
"misc/sysinfo_shellcmd.c",
"misc/los_misc.c",
"misc/swtmr_shellcmd.c",
"misc/mempt_shellcmd.c",
"misc/vm_shellcmd.c",
"mp/los_stat.c",
"mp/los_lockdep.c",
"mp/los_mp.c",
"mp/los_percpu.c",
"sched/sched_sq/los_priqueue.c",
"sched/sched_sq/los_sched.c",
"vm/filemap.c",
"vm/pmm.c",
"vm/vm.c",
"vm/vmm.c",
]
include_dirs = [
"include",
"../extended/include",
"../extended/vdso/include",
"../extended/dynload/include",
"../include",
"mem",
]
}

54
kernel/base/Makefile Executable file
View File

@@ -0,0 +1,54 @@
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
#
# 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 $(LITEOSTOPDIR)/config.mk
MODULE_NAME := $(notdir $(shell pwd))
LOCAL_SRCS := $(wildcard ipc/*.c) $(wildcard core/*.c) $(wildcard mem/membox/*.c) $(wildcard mem/common/*.c) \
$(wildcard om/*.c)\
$(wildcard misc/*.c)\
$(wildcard mem/bestfit/*.c) \
$(wildcard mp/*.c) \
$(wildcard sched/sched_sq/*.c) \
$(wildcard vm/*.c)
ifeq ($(LOSCFG_MEM_RECORDINFO), y)
LOCAL_SRCS += $(wildcard mem/common/memrecord/*.c)
endif
LOCAL_INCLUDE := \
-I $(LITEOSTOPDIR)/kernel/base/include \
-I $(LITEOSTOPDIR)/kernel/extended/include \
-I $(LITEOSTOPDIR)/kernel/base/mem \
-I $(LITEOSTOPDIR)/kernel/base/vm
LOCAL_FLAGS := $(LITEOS_CFLAGS_INTERWORK) $(LOCAL_INCLUDE) $(LITEOS_GCOV_OPTS)
include $(MODULE)

148
kernel/base/core/los_bitmap.c Executable file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_bitmap.h"
#include "los_printf.h"
#include "los_toolchain.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_BITMAP_MASK 0x1FU
#define OS_BITMAP_WORD_MASK ~0UL
/* find first zero bit starting from LSB */
STATIC INLINE UINT16 Ffz(UINTPTR x)
{
return __builtin_ffsl(~x) - 1;
}
VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap |= 1U << (pos & OS_BITMAP_MASK);
}
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap &= ~(1U << (pos & OS_BITMAP_MASK));
}
UINT16 LOS_HighBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return (OS_BITMAP_MASK - CLZ(bitmap));
}
UINT16 LOS_LowBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return CTZ(bitmap);
}
VOID LOS_BitmapSetNBits(UINTPTR *bitmap, UINT32 start, UINT32 numsSet)
{
UINTPTR *p = bitmap + BITMAP_WORD(start);
const UINT32 size = start + numsSet;
UINT16 bitsToSet = BITMAP_BITS_PER_WORD - (start % BITMAP_BITS_PER_WORD);
UINTPTR maskToSet = BITMAP_FIRST_WORD_MASK(start);
while (numsSet > bitsToSet) {
*p |= bitsToSet;
numsSet -= bitsToSet;
bitsToSet = BITMAP_BITS_PER_WORD;
maskToSet = OS_BITMAP_WORD_MASK;
p++;
}
if (numsSet) {
maskToSet &= BITMAP_LAST_WORD_MASK(size);
*p |= maskToSet;
}
}
VOID LOS_BitmapClrNBits(UINTPTR *bitmap, UINT32 start, UINT32 numsClear)
{
UINTPTR *p = bitmap + BITMAP_WORD(start);
const UINT32 size = start + numsClear;
UINT16 bitsToClear = BITMAP_BITS_PER_WORD - (start % BITMAP_BITS_PER_WORD);
UINTPTR maskToClear = BITMAP_FIRST_WORD_MASK(start);
while (numsClear >= bitsToClear) {
*p &= ~maskToClear;
numsClear -= bitsToClear;
bitsToClear = BITMAP_BITS_PER_WORD;
maskToClear = OS_BITMAP_WORD_MASK;
p++;
}
if (numsClear) {
maskToClear &= BITMAP_LAST_WORD_MASK(size);
*p &= ~maskToClear;
}
}
INT32 LOS_BitmapFfz(UINTPTR *bitmap, UINT32 numBits)
{
INT32 bit, i;
for (i = 0; i < BITMAP_NUM_WORDS(numBits); i++) {
if (bitmap[i] == OS_BITMAP_WORD_MASK) {
continue;
}
bit = i * BITMAP_BITS_PER_WORD + Ffz(bitmap[i]);
if (bit < numBits) {
return bit;
}
return -1;
}
return -1;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

2004
kernel/base/core/los_process.c Executable file

File diff suppressed because it is too large Load Diff

244
kernel/base/core/los_sortlink.c Executable file
View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_sortlink_pri.h"
#include "los_memory.h"
#include "los_exc.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
LITE_OS_SEC_TEXT_INIT UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
{
UINT32 size;
LOS_DL_LIST *listObject = NULL;
UINT32 index;
size = sizeof(LOS_DL_LIST) << OS_TSK_SORTLINK_LOGLEN;
listObject = (LOS_DL_LIST *)LOS_MemAlloc(m_aucSysMem0, size); /* system resident resource */
if (listObject == NULL) {
return LOS_NOK;
}
(VOID)memset_s(listObject, size, 0, size);
sortLinkHeader->sortLink = listObject;
sortLinkHeader->cursor = 0;
for (index = 0; index < OS_TSK_SORTLINK_LEN; index++, listObject++) {
LOS_ListInit(listObject);
}
return LOS_OK;
}
LITE_OS_SEC_TEXT VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
SortLinkList *listSorted = NULL;
LOS_DL_LIST *listObject = NULL;
UINT32 sortIndex;
UINT32 rollNum;
UINT32 timeout;
/*
* huge rollnum could cause carry to invalid high bit
* and eventually affect the calculation of sort index.
*/
if (sortList->idxRollNum > OS_TSK_MAX_ROLLNUM) {
SET_SORTLIST_VALUE(sortList, OS_TSK_MAX_ROLLNUM);
}
timeout = sortList->idxRollNum;
sortIndex = timeout & OS_TSK_SORTLINK_MASK;
rollNum = (timeout >> OS_TSK_SORTLINK_LOGLEN) + 1;
if (sortIndex == 0) {
rollNum--;
}
EVALUATE_L(sortList->idxRollNum, rollNum);
sortIndex = sortIndex + sortLinkHeader->cursor;
sortIndex = sortIndex & OS_TSK_SORTLINK_MASK;
EVALUATE_H(sortList->idxRollNum, sortIndex);
listObject = sortLinkHeader->sortLink + sortIndex;
if (listObject->pstNext == listObject) {
LOS_ListTailInsert(listObject, &sortList->sortLinkNode);
} else {
listSorted = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
do {
if (ROLLNUM(listSorted->idxRollNum) <= ROLLNUM(sortList->idxRollNum)) {
ROLLNUM_SUB(sortList->idxRollNum, listSorted->idxRollNum);
} else {
ROLLNUM_SUB(listSorted->idxRollNum, sortList->idxRollNum);
break;
}
listSorted = LOS_DL_LIST_ENTRY(listSorted->sortLinkNode.pstNext, SortLinkList, sortLinkNode);
} while (&listSorted->sortLinkNode != listObject);
LOS_ListTailInsert(&listSorted->sortLinkNode, &sortList->sortLinkNode);
}
}
LITE_OS_SEC_TEXT STATIC VOID OsCheckSortLink(const LOS_DL_LIST *listHead, const LOS_DL_LIST *listNode)
{
LOS_DL_LIST *tmp = listNode->pstPrev;
/* recursive check until double link round to itself */
while (tmp != listNode) {
if (tmp == listHead) {
goto FOUND;
}
tmp = tmp->pstPrev;
}
/* delete invalid sortlink node */
PRINT_ERR("the node is not on this sortlink!\n");
OsBackTrace();
FOUND:
return;
}
LITE_OS_SEC_TEXT VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_DL_LIST *listObject = NULL;
SortLinkList *nextSortList = NULL;
UINT32 sortIndex;
sortIndex = SORT_INDEX(sortList->idxRollNum);
listObject = sortLinkHeader->sortLink + sortIndex;
/* check if pstSortList node is on the right sortlink */
OsCheckSortLink(listObject, &sortList->sortLinkNode);
if (listObject != sortList->sortLinkNode.pstNext) {
nextSortList = LOS_DL_LIST_ENTRY(sortList->sortLinkNode.pstNext, SortLinkList, sortLinkNode);
ROLLNUM_ADD(nextSortList->idxRollNum, sortList->idxRollNum);
}
LOS_ListDelete(&sortList->sortLinkNode);
}
LITE_OS_SEC_TEXT STATIC UINT32 OsCalcExpierTime(UINT32 rollNum, UINT32 sortIndex, UINT16 curSortIndex)
{
UINT32 expireTime;
if (sortIndex > curSortIndex) {
sortIndex = sortIndex - curSortIndex;
} else {
sortIndex = OS_TSK_SORTLINK_LEN - curSortIndex + sortIndex;
}
expireTime = ((rollNum - 1) << OS_TSK_SORTLINK_LOGLEN) + sortIndex;
return expireTime;
}
LITE_OS_SEC_TEXT UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader)
{
UINT16 cursor;
UINT32 minSortIndex = OS_INVALID_VALUE;
UINT32 minRollNum = OS_TSK_LOW_BITS_MASK;
UINT32 expireTime = OS_INVALID_VALUE;
LOS_DL_LIST *listObject = NULL;
SortLinkList *listSorted = NULL;
UINT32 i;
cursor = (sortLinkHeader->cursor + 1) & OS_TSK_SORTLINK_MASK;
for (i = 0; i < OS_TSK_SORTLINK_LEN; i++) {
listObject = sortLinkHeader->sortLink + ((cursor + i) & OS_TSK_SORTLINK_MASK);
if (!LOS_ListEmpty(listObject)) {
listSorted = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
if (minRollNum > ROLLNUM(listSorted->idxRollNum)) {
minRollNum = ROLLNUM(listSorted->idxRollNum);
minSortIndex = (cursor + i) & OS_TSK_SORTLINK_MASK;
}
}
}
if (minRollNum != OS_TSK_LOW_BITS_MASK) {
expireTime = OsCalcExpierTime(minRollNum, minSortIndex, sortLinkHeader->cursor);
}
return expireTime;
}
LITE_OS_SEC_TEXT VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttribute *sortLinkHeader)
{
SortLinkList *sortList = NULL;
LOS_DL_LIST *listObject = NULL;
UINT32 i;
UINT32 sortIndex;
UINT32 rollNum;
if (sleepTicks == 0) {
return;
}
sortIndex = sleepTicks & OS_TSK_SORTLINK_MASK;
rollNum = (sleepTicks >> OS_TSK_SORTLINK_LOGLEN) + 1;
if (sortIndex == 0) {
rollNum--;
sortIndex = OS_TSK_SORTLINK_LEN;
}
for (i = 0; i < OS_TSK_SORTLINK_LEN; i++) {
listObject = sortLinkHeader->sortLink + ((sortLinkHeader->cursor + i) & OS_TSK_SORTLINK_MASK);
if (listObject->pstNext != listObject) {
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
ROLLNUM_SUB(sortList->idxRollNum, rollNum - 1);
if ((i > 0) && (i < sortIndex)) {
ROLLNUM_DEC(sortList->idxRollNum);
}
}
}
sortLinkHeader->cursor = (sortLinkHeader->cursor + sleepTicks - 1) % OS_TSK_SORTLINK_LEN;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttribute *sortLinkHeader,
const SortLinkList *targetSortList)
{
SortLinkList *listSorted = NULL;
LOS_DL_LIST *listObject = NULL;
UINT32 sortIndex = SORT_INDEX(targetSortList->idxRollNum);
UINT32 rollNum = ROLLNUM(targetSortList->idxRollNum);
listObject = sortLinkHeader->sortLink + sortIndex;
listSorted = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
while (listSorted != targetSortList) {
rollNum += ROLLNUM(listSorted->idxRollNum);
listSorted = LOS_DL_LIST_ENTRY((listSorted->sortLinkNode).pstNext, SortLinkList, sortLinkNode);
}
return OsCalcExpierTime(rollNum, sortIndex, sortLinkHeader->cursor);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

543
kernel/base/core/los_swtmr.c Executable file
View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_swtmr_pri.h"
#include "los_sortlink_pri.h"
#include "los_queue_pri.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#if (LOSCFG_BASE_CORE_SWTMR_LIMIT <= 0)
#error "swtmr maxnum cannot be zero"
#endif /* LOSCFG_BASE_CORE_SWTMR_LIMIT <= 0 */
LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrCBArray = NULL; /* First address in Timer memory space */
LITE_OS_SEC_BSS UINT8 *g_swtmrHandlerPool = NULL; /* Pool of Swtmr Handler */
LITE_OS_SEC_BSS LOS_DL_LIST g_swtmrFreeList; /* Free list of Software Timer */
/* spinlock for swtmr module, only available on SMP mode */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_swtmrSpin);
#define SWTMR_LOCK(state) LOS_SpinLockSave(&g_swtmrSpin, &(state))
#define SWTMR_UNLOCK(state) LOS_SpinUnlockRestore(&g_swtmrSpin, (state))
LITE_OS_SEC_TEXT VOID OsSwtmrTask(VOID)
{
SwtmrHandlerItemPtr swtmrHandlePtr = NULL;
SwtmrHandlerItem swtmrHandle;
UINT32 ret, swtmrHandlerQueue;
swtmrHandlerQueue = OsPercpuGet()->swtmrHandlerQueue;
for (;;) {
ret = LOS_QueueRead(swtmrHandlerQueue, &swtmrHandlePtr, sizeof(CHAR *), LOS_WAIT_FOREVER);
if ((ret == LOS_OK) && (swtmrHandlePtr != NULL)) {
swtmrHandle.handler = swtmrHandlePtr->handler;
swtmrHandle.arg = swtmrHandlePtr->arg;
(VOID)LOS_MemboxFree(g_swtmrHandlerPool, swtmrHandlePtr);
if (swtmrHandle.handler != NULL) {
swtmrHandle.handler(swtmrHandle.arg);
}
}
}
}
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID)
{
UINT32 ret, swtmrTaskID;
TSK_INIT_PARAM_S swtmrTask;
UINT32 cpuid = ArchCurrCpuid();
(VOID)memset_s(&swtmrTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
swtmrTask.pfnTaskEntry = (TSK_ENTRY_FUNC)OsSwtmrTask;
swtmrTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
swtmrTask.pcName = "Swt_Task";
swtmrTask.usTaskPrio = 0;
swtmrTask.uwResved = LOS_TASK_STATUS_DETACHED;
#if (LOSCFG_KERNEL_SMP == YES)
swtmrTask.usCpuAffiMask = CPUID_TO_AFFI_MASK(cpuid);
#endif
ret = LOS_TaskCreate(&swtmrTaskID, &swtmrTask);
if (ret == LOS_OK) {
g_percpu[cpuid].swtmrTaskID = swtmrTaskID;
OS_TCB_FROM_TID(swtmrTaskID)->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
}
return ret;
}
LITE_OS_SEC_TEXT_INIT VOID OsSwtmrRecycle(UINT32 processID)
{
for (UINT16 index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++) {
if (g_swtmrCBArray[index].uwOwnerPid == processID) {
LOS_SwtmrDelete(index);
}
}
}
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID)
{
UINT32 size;
UINT16 index;
UINT32 ret;
SWTMR_CTRL_S *swtmr = NULL;
UINT32 swtmrHandlePoolSize;
UINT32 cpuid = ArchCurrCpuid();
if (cpuid == 0) {
size = sizeof(SWTMR_CTRL_S) * LOSCFG_BASE_CORE_SWTMR_LIMIT;
swtmr = (SWTMR_CTRL_S *)LOS_MemAlloc(m_aucSysMem0, size); /* system resident resource */
if (swtmr == NULL) {
return LOS_ERRNO_SWTMR_NO_MEMORY;
}
(VOID)memset_s(swtmr, size, 0, size);
g_swtmrCBArray = swtmr;
LOS_ListInit(&g_swtmrFreeList);
for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
swtmr->usTimerID = index;
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);
}
swtmrHandlePoolSize = LOS_MEMBOX_SIZE(sizeof(SwtmrHandlerItem), OS_SWTMR_HANDLE_QUEUE_SIZE);
g_swtmrHandlerPool = (UINT8 *)LOS_MemAlloc(m_aucSysMem1, swtmrHandlePoolSize); /* system resident resource */
if (g_swtmrHandlerPool == NULL) {
return LOS_ERRNO_SWTMR_NO_MEMORY;
}
ret = LOS_MemboxInit(g_swtmrHandlerPool, swtmrHandlePoolSize, sizeof(SwtmrHandlerItem));
if (ret != LOS_OK) {
return LOS_ERRNO_SWTMR_HANDLER_POOL_NO_MEM;
}
}
ret = LOS_QueueCreate(NULL, OS_SWTMR_HANDLE_QUEUE_SIZE, &g_percpu[cpuid].swtmrHandlerQueue, 0, sizeof(CHAR *));
if (ret != LOS_OK) {
return LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED;
}
ret = OsSwtmrTaskCreate();
if (ret != LOS_OK) {
return LOS_ERRNO_SWTMR_TASK_CREATE_FAILED;
}
ret = OsSortLinkInit(&g_percpu[cpuid].swtmrSortLink);
if (ret != LOS_OK) {
return LOS_ERRNO_SWTMR_SORTLINK_CREATE_FAILED;
}
return LOS_OK;
}
/*
* Description: Start Software Timer
* Input : swtmr --- Need to start software timer
*/
LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
{
if ((swtmr->ucOverrun == 0) && ((swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ||
(swtmr->ucMode == LOS_SWTMR_MODE_OPP) ||
(swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE))) {
SET_SORTLIST_VALUE(&(swtmr->stSortList), swtmr->uwExpiry);
} else {
SET_SORTLIST_VALUE(&(swtmr->stSortList), swtmr->uwInterval);
}
OsAdd2SortLink(&OsPercpuGet()->swtmrSortLink, &swtmr->stSortList);
swtmr->ucState = OS_SWTMR_STATUS_TICKING;
#if (LOSCFG_KERNEL_SMP == YES)
swtmr->uwCpuid = ArchCurrCpuid();
#endif
return;
}
/*
* Description: Delete Software Timer
* Input : swtmr --- Need to delete software timer, When using, Ensure that it can't be NULL.
*/
STATIC INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
{
/* insert to free list */
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);
swtmr->ucState = OS_SWTMR_STATUS_UNUSED;
swtmr->uwOwnerPid = 0;
}
/*
* Description: Tick interrupt interface module of software timer
* Return : LOS_OK on success or error code on failure
*/
LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)
{
SortLinkList *sortList = NULL;
SWTMR_CTRL_S *swtmr = NULL;
SwtmrHandlerItemPtr swtmrHandler = NULL;
LOS_DL_LIST *listObject = NULL;
SortLinkAttribute* swtmrSortLink = &OsPercpuGet()->swtmrSortLink;
swtmrSortLink->cursor = (swtmrSortLink->cursor + 1) & OS_TSK_SORTLINK_MASK;
listObject = swtmrSortLink->sortLink + swtmrSortLink->cursor;
/*
* it needs to be carefully coped with, since the swtmr is in specific sortlink
* while other cores still has the chance to process it, like stop the timer.
*/
LOS_SpinLock(&g_swtmrSpin);
if (LOS_ListEmpty(listObject)) {
LOS_SpinUnlock(&g_swtmrSpin);
return;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
ROLLNUM_DEC(sortList->idxRollNum);
while (ROLLNUM(sortList->idxRollNum) == 0) {
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
LOS_ListDelete(&sortList->sortLinkNode);
swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
swtmrHandler = (SwtmrHandlerItemPtr)LOS_MemboxAlloc(g_swtmrHandlerPool);
if (swtmrHandler != NULL) {
swtmrHandler->handler = swtmr->pfnHandler;
swtmrHandler->arg = swtmr->uwArg;
if (LOS_QueueWrite(OsPercpuGet()->swtmrHandlerQueue, swtmrHandler, sizeof(CHAR *), LOS_NO_WAIT)) {
(VOID)LOS_MemboxFree(g_swtmrHandlerPool, swtmrHandler);
}
}
if (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) {
OsSwtmrDelete(swtmr);
if (swtmr->usTimerID < (OS_SWTMR_MAX_TIMERID - LOSCFG_BASE_CORE_SWTMR_LIMIT)) {
swtmr->usTimerID += LOSCFG_BASE_CORE_SWTMR_LIMIT;
} else {
swtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT;
}
} else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) {
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
} else {
swtmr->ucOverrun++;
OsSwtmrStart(swtmr);
}
if (LOS_ListEmpty(listObject)) {
break;
}
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
}
LOS_SpinUnlock(&g_swtmrSpin);
}
/*
* Description: Get next timeout
* Return : Count of the Timer list
*/
LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID)
{
return OsSortLinkGetNextExpireTime(&OsPercpuGet()->swtmrSortLink);
}
/*
* Description: Stop of Software Timer interface
* Input : swtmr --- the software timer contrl handler
*/
LITE_OS_SEC_TEXT STATIC VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
{
SortLinkAttribute *sortLinkHeader = NULL;
#if (LOSCFG_KERNEL_SMP == YES)
/*
* the timer is running on the specific processor,
* we need delete the timer from that processor's sortlink.
*/
sortLinkHeader = &g_percpu[swtmr->uwCpuid].swtmrSortLink;
#else
sortLinkHeader = &g_percpu[0].swtmrSortLink;
#endif
OsDeleteSortLink(sortLinkHeader, &swtmr->stSortList);
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
swtmr->ucOverrun = 0;
}
/*
* Description: Get next software timer expiretime
* Input : swtmr --- the software timer contrl handler
*/
LITE_OS_SEC_TEXT STATIC UINT32 OsSwtmrTimeGet(const SWTMR_CTRL_S *swtmr)
{
SortLinkAttribute *sortLinkHeader = NULL;
#if (LOSCFG_KERNEL_SMP == YES)
/*
* the timer is running on the specific processor,
* we need search the timer from that processor's sortlink.
*/
sortLinkHeader = &g_percpu[swtmr->uwCpuid].swtmrSortLink;
#else
sortLinkHeader = &g_percpu[0].swtmrSortLink;
#endif
return OsSortLinkGetTargetExpireTime(sortLinkHeader, &swtmr->stSortList);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
UINT8 mode,
SWTMR_PROC_FUNC handler,
UINT16 *swtmrID,
UINTPTR arg)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
SortLinkList *sortList = NULL;
if (interval == 0) {
return LOS_ERRNO_SWTMR_INTERVAL_NOT_SUITED;
}
if ((mode != LOS_SWTMR_MODE_ONCE) && (mode != LOS_SWTMR_MODE_PERIOD) &&
(mode != LOS_SWTMR_MODE_NO_SELFDELETE)) {
return LOS_ERRNO_SWTMR_MODE_INVALID;
}
if (handler == NULL) {
return LOS_ERRNO_SWTMR_PTR_NULL;
}
if (swtmrID == NULL) {
return LOS_ERRNO_SWTMR_RET_PTR_NULL;
}
SWTMR_LOCK(intSave);
if (LOS_ListEmpty(&g_swtmrFreeList)) {
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_MAXSIZE;
}
sortList = LOS_DL_LIST_ENTRY(g_swtmrFreeList.pstNext, SortLinkList, sortLinkNode);
swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_swtmrFreeList));
SWTMR_UNLOCK(intSave);
swtmr->uwOwnerPid = OsCurrProcessGet()->processID;
swtmr->pfnHandler = handler;
swtmr->ucMode = mode;
swtmr->ucOverrun = 0;
swtmr->uwInterval = interval;
swtmr->uwExpiry = interval;
swtmr->uwArg = arg;
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
SET_SORTLIST_VALUE(&(swtmr->stSortList), 0);
*swtmrID = swtmr->usTimerID;
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
SWTMR_LOCK(intSave);
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
swtmr = g_swtmrCBArray + swtmrCBID;
if (swtmr->usTimerID != swtmrID) {
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
/*
* If the status of swtmr is timing, it should stop the swtmr first,
* then start the swtmr again.
*/
case OS_SWTMR_STATUS_TICKING:
OsSwtmrStop(swtmr);
/* fall-through */
case OS_SWTMR_STATUS_CREATED:
OsSwtmrStart(swtmr);
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
SWTMR_LOCK(intSave);
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
swtmr = g_swtmrCBArray + swtmrCBID;
if (swtmr->usTimerID != swtmrID) {
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
case OS_SWTMR_STATUS_CREATED:
ret = LOS_ERRNO_SWTMR_NOT_STARTED;
break;
case OS_SWTMR_STATUS_TICKING:
OsSwtmrStop(swtmr);
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT16 swtmrID, UINT32 *tick)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
if (tick == NULL) {
return LOS_ERRNO_SWTMR_TICK_PTR_NULL;
}
SWTMR_LOCK(intSave);
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
swtmr = g_swtmrCBArray + swtmrCBID;
if (swtmr->usTimerID != swtmrID) {
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
case OS_SWTMR_STATUS_CREATED:
ret = LOS_ERRNO_SWTMR_NOT_STARTED;
break;
case OS_SWTMR_STATUS_TICKING:
*tick = OsSwtmrTimeGet(swtmr);
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrDelete(UINT16 swtmrID)
{
SWTMR_CTRL_S *swtmr = NULL;
UINT32 intSave;
UINT32 ret = LOS_OK;
UINT16 swtmrCBID;
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return LOS_ERRNO_SWTMR_ID_INVALID;
}
SWTMR_LOCK(intSave);
swtmrCBID = swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
swtmr = g_swtmrCBArray + swtmrCBID;
if (swtmr->usTimerID != swtmrID) {
SWTMR_UNLOCK(intSave);
return LOS_ERRNO_SWTMR_ID_INVALID;
}
switch (swtmr->ucState) {
case OS_SWTMR_STATUS_UNUSED:
ret = LOS_ERRNO_SWTMR_NOT_CREATED;
break;
case OS_SWTMR_STATUS_TICKING:
OsSwtmrStop(swtmr);
/* fall-through */
case OS_SWTMR_STATUS_CREATED:
OsSwtmrDelete(swtmr);
break;
default:
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
break;
}
SWTMR_UNLOCK(intSave);
return ret;
}
#endif /* (LOSCFG_BASE_CORE_SWTMR == YES) */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif

82
kernel/base/core/los_sys.c Executable file
View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_sys_pri.h"
#include "los_tick_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_MAX_VALUE 0xFFFFFFFF
LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID)
{
UINT32 intSave;
UINT64 tick;
/*
* use core0's tick as system's timeline,
* the tick needs to be atomic.
*/
TICK_LOCK(intSave);
tick = g_tickCount[0];
TICK_UNLOCK(intSave);
return tick;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID)
{
return g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec)
{
if (millisec == OS_MAX_VALUE) {
return OS_MAX_VALUE;
}
return ((UINT64)millisec * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_MS_PER_SECOND;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 tick)
{
return ((UINT64)tick * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

2015
kernel/base/core/los_task.c Executable file

File diff suppressed because it is too large Load Diff

93
kernel/base/core/los_tick.c Executable file
View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_tick_pri.h"
#include "los_swtmr_pri.h"
#include "los_task_pri.h"
#include "los_timeslice_pri.h"
#ifdef LOSCFG_KERNEL_TICKLESS
#include "los_tickless_pri.h"
#endif
#ifdef LOSCFG_KERNEL_VDSO
#include "los_vdso.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS volatile UINT64 g_tickCount[LOSCFG_KERNEL_CORE_NUM] = {0};
LITE_OS_SEC_DATA_INIT UINT32 g_sysClock;
LITE_OS_SEC_DATA_INIT UINT32 g_tickPerSecond;
LITE_OS_SEC_BSS DOUBLE g_cycle2NsScale;
/* spinlock for task module */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_tickSpin);
/*
* Description : Tick interruption handler
*/
LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
{
UINT32 intSave;
TICK_LOCK(intSave);
g_tickCount[ArchCurrCpuid()]++;
TICK_UNLOCK(intSave);
#ifdef LOSCFG_KERNEL_VDSO
OsUpdateVdsoTimeval();
#endif
#ifdef LOSCFG_KERNEL_TICKLESS
OsTickIrqFlagSet(OsTicklessFlagGet());
#endif
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == YES)
HalClockIrqClear(); /* diff from every platform */
#endif
OsTimesliceCheck();
OsTaskScan(); /* task timeout scan */
#if (LOSCFG_BASE_CORE_SWTMR == YES)
OsSwtmrScan();
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_timeslice_pri.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_TEXT VOID OsTimesliceCheck(VOID)
{
LosTaskCB *runTask = NULL;
LosProcessCB *runProcess = OsCurrProcessGet();
if (runProcess->policy != LOS_SCHED_RR) {
goto SCHED_TASK;
}
if (runProcess->timeSlice != 0) {
runProcess->timeSlice--;
if (runProcess->timeSlice == 0) {
LOS_Schedule();
}
}
SCHED_TASK:
runTask = OsCurrTaskGet();
if (runTask->policy != LOS_SCHED_RR) {
return;
}
if (runTask->timeSlice != 0) {
runTask->timeSlice--;
if (runTask->timeSlice == 0) {
LOS_Schedule();
}
}
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_BASE_PRI_H
#define _LOS_BASE_PRI_H
#include "los_base.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_GOTO_ERREND() do { \
goto LOS_ERREND; \
} while (0)
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_BASE_PRI_H */

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_BINARYTREE_PRI_H
#define _LOS_BINARYTREE_PRI_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct tagBinNode {
struct tagBinNode *left;
struct tagBinNode *right;
UINT32 nodeID;
CHAR keyValue[0];
} BinNode;
typedef struct {
BinNode leaf;
UINTPTR linkReg1;
UINTPTR linkReg2;
UINTPTR linkReg3;
} LinkRegNode;
#define LR_COUNT 4096
extern LinkRegNode g_linkRegNode[LR_COUNT];
extern UINT32 g_linkRegNodeIndex;
extern LinkRegNode *g_linkRegRoot;
typedef struct {
BinNode leaf;
UINTPTR addr;
} AddrNode;
#define ADDR_COUNT 40960
extern AddrNode g_addrNode[ADDR_COUNT];
extern UINT32 g_addrNodeIndex;
extern AddrNode *g_addrRoot;
typedef struct {
BinNode leaf;
UINT32 reqSize;
} ReqSizeNode;
#define REQ_SIZE_COUNT 4096
extern ReqSizeNode g_reqSizeNode[REQ_SIZE_COUNT];
extern UINT32 g_reqSizeNodeIndex;
extern ReqSizeNode *g_reqSizeRoot;
typedef struct {
BinNode leaf;
UINT32 taskID;
} TaskIDNode;
#define TASK_ID_COUNT 1024
extern UINT32 OsBinTreeInsert(const VOID *node, UINT32 nodeLen, BinNode **leaf,
BinNode *(*GetMyBinNode)(UINT32 *nodeID),
INT32 (*CompareNode)(const VOID *node1, const VOID *node2));
extern INT32 OsCompareLRNode(const VOID *node1, const VOID *node2);
extern BinNode *OsGetLRBinNode(UINT32 *nodeID);
extern INT32 OsCompareAddrNode(const VOID *node1, const VOID *node2);
extern BinNode *OsGetAddrBinNode(UINT32 *nodeID);
extern INT32 OsCompareReqSizeNode(const VOID *node1, const VOID *node2);
extern BinNode *OsGetReqSizeBinNode(UINT32 *nodeID);
extern INT32 OsCompareTaskIDNode(const VOID *node1, const VOID *node2);
extern BinNode *OsGetTaskIDBinNode(UINT32 *nodeID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_BINARYTREE_PRI_H */

127
kernel/base/include/los_err_pri.h Executable file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_ERR_PRI_H
#define _LOS_ERR_PRI_H
#include "los_err.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_err
* Define the error magic word.
*/
#define OS_ERR_MAGIC_WORD 0xa1b2c3f8
/**
* @ingroup los_err
* @brief Error handling macro capable of returning error codes.
*
* @par Description:
* This API is used to call the error handling function by using an error code and return the same error code.
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param errNo [IN] Error code.
*
* @retval errNo
* @par Dependency:
* <ul><li>los_err_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
#define OS_RETURN_ERROR(errNo) do { \
(VOID)LOS_ErrHandle("os_unspecific_file", OS_ERR_MAGIC_WORD, errNo, 0, NULL); \
return errNo; \
} while (0)
/**
* @ingroup los_err
* @brief Error handling macro capable of returning error codes.
*
* @par Description:
* This API is used to call the error handling function by using an error code and the line number of
* the erroneous line, and return the same error code.
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param errLine [IN] Line number of the erroneous line.
* @param errNo [IN] Error code.
*
* @retval errNo
* @par Dependency:
* <ul><li>los_err_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
#define OS_RETURN_ERROR_P2(errLine, errNo) do { \
(VOID)LOS_ErrHandle("os_unspecific_file", errLine, errNo, 0, NULL); \
return errNo; \
} while (0)
/**
* @ingroup los_err
* @brief Macro for jumping to error handler.
*
* @par Description:
* This API is used to call the error handling function by using an error code.
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param errorNo [IN] Error code.
*
* @retval None.
* @par Dependency:
* <ul><li>los_err_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
#define OS_GOTO_ERR_HANDLER(errorNo) do { \
errNo = errorNo; \
errLine = OS_ERR_MAGIC_WORD; \
goto ERR_HANDLER; \
} while (0)
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_ERR_PRI_H */

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_EVENT_PRI_H
#define _LOS_EVENT_PRI_H
#include "los_event.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_COMPAT_POSIX
typedef struct {
volatile INT32 *realValue;
INT32 value;
UINT32 clearEvent;
} EventCond;
extern UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB,
UINT32 eventMask, UINT32 mode, UINT32 timeout);
#endif
extern VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag);
extern UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout);
extern UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_EVENT_PRI_H */

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_FUTEX_PRI_H
#define _LOS_FUTEX_PRI_H
#include "los_list.h"
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_REQUEUE 3
#define FUTEX_WAKE_OP 5
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#define FUTEX_PRIVATE 128
#define FUTEX_MASK 0x3U
typedef struct {
UINTPTR key;
UINT32 index;
UINT32 pid;
LOS_DL_LIST pendList;
LOS_DL_LIST queueList;
LOS_DL_LIST futexList;
} FutexNode;
extern UINT32 OsFutexInit(VOID);
extern VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags);
extern INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber);
extern INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime);
extern INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber,
INT32 count, const UINT32 *newUserVaddr);
#endif

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/*
* @defgroup los_heap Heap
* @ingroup kernel
*/
#ifndef _LOS_HEAP_PRI_H
#define _LOS_HEAP_PRI_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define ALIGNE(sz) (((sz) + HEAP_ALIGN - 1) & (~(HEAP_ALIGN - 1)))
#define OS_MEM_ALIGN(value, align) (((UINT32)(UINTPTR)(value) + (UINT32)((align) - 1)) & \
(~(UINT32)((align) - 1)))
#define OS_MEM_ALIGN_FLAG 0x80000000
#define OS_MEM_SET_ALIGN_FLAG(align) ((align) = ((align) | OS_MEM_ALIGN_FLAG))
#define OS_MEM_GET_ALIGN_FLAG(align) ((align) & OS_MEM_ALIGN_FLAG)
#define OS_MEM_GET_ALIGN_GAPSIZE(align) ((align) & (~OS_MEM_ALIGN_FLAG))
typedef struct tagLosHeapStatus {
UINT32 totalUsedSize;
UINT32 totalFreeSize;
UINT32 maxFreeNodeSize;
UINT32 usedNodeNum;
UINT32 freeNodeNum;
} LosHeapStatus;
struct LosHeapNode {
struct LosHeapNode* prev;
UINT32 size : 30;
UINT32 used : 1;
UINT32 align : 1;
UINT8 data[0];
};
struct LosHeapManager {
struct LosHeapNode *head;
struct LosHeapNode *tail;
UINT32 size;
#if (LOSCFG_MEM_MUL_POOL == YES)
VOID *nextPool;
#endif
};
/**
* @ingroup los_heap
* @brief Look up the next memory node according to one memory node in the memory block list.
*
* @par Description:
* This API is used to look up the next memory node according to one memory node in the memory block list.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param heapMan [IN] Type #LosHeapManager * Pointer to the manager,to distinguish heap.
* @param node [IN] Type #LosHeapNode * Size of memory in bytes to allocate.
*
* @retval LosHeapNode * Pointer to next memory node.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern struct LosHeapNode* OsHeapPrvGetNext(struct LosHeapManager *heapMan, struct LosHeapNode* node);
/**
* @ingroup los_heap
* @brief Obtain the heap information.
*
* @par Description:
* This API is used to obtain the heap information.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * A pointer pointed to the heap memory pool.
*
* @retval None.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern VOID OsAlarmHeapInfo(VOID *pool);
/**
* @ingroup los_heap
* @brief Obtain the heap status.
*
* @par Description:
* This API is used to obtain the heap status.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * A pointer pointed to the heap memory pool.
* @param status [OUT] Type #LosHeapStatus * Heap status.
*
* @retval UINT32 Get status result.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status);
/**
* @ingroup los_heap
* @brief Get the max free block size.
*
* @par Description:
* This API is used to Get the max free block size.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * A pointer pointed to the heap memory pool.
*
* @retval UINT32 Max free block size.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern UINT32 OsHeapGetMaxFreeBlkSize(VOID *pool);
/**
* @ingroup OsHeapInit
* @brief Initialize the heap memory pool.
*
* @par Description:
* This API is used to initialize the heap memory and get the begin address and
* size of heap memory,then initialize LosHeapManager .
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * A pointer pointed to the heap memory pool.
* @param size [IN] Type #UINT32 Size of memory in bytes to initialized.
*
* @retval BOOL Get status return.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern BOOL OsHeapInit(VOID *pool, UINT32 size);
/**
* @ingroup OsHeapAlloc
* @brief Alloc memory block from the heap.
*
* @par Description:
* This API is used to alloc memory block from the heap memory pool.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * Pointer to the manager,to distinguish heap
* @param size [IN] Type #UINT32 Size of memory in bytes to alloc.
*
* @retval VOID * Get the address of the memory we alloced or NULL.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern VOID* OsHeapAlloc(VOID *pool, UINT32 size);
/**
* @ingroup OsHeapAllocAlign
* @brief Alloc memory block from the heap with align.
*
* @par Description:
* This API is used to alloc memory block from the heap memory pool with align.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * Pointer to the manager,to distinguish heap
* @param size [IN] Type #UINT32 Size of memory in bytes to alloc.
* @param boundary [IN] Type #UINT32 Boundary the heap needs align.
*
* @retval VOID * Get the address of the memory we alloced or NULL.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary);
/**
* @ingroup OsHeapFree
* @brief Free memory block from heap memory pool.
*
* @par Description:
* This API is used to To free the memory block from heap memory pool.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param pool [IN] Type #VOID * Pointer to the manager,to distinguish heap
* @param ptr [IN] Type #VOID * Pinter of heap memory we want to free.
*
* @retval BOOL Get result return.
*
* @par Dependency:
* <ul><li>los_heap_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern BOOL OsHeapFree(VOID *pool, VOID* ptr);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_HEAP_PRI_H */

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_IPCDEBUG_PRI_H
#define _LOS_IPCDEBUG_PRI_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
CHAR *buf; /**< Control block array total buffer */
size_t ipcDebugCBSize; /**< Single control block size */
size_t ipcDebugCBCnt; /**< Number of control blocks */
UINT32 sortElemOff; /**< The offset of the member to be compared in the control block */
} IpcSortParam;
/* Compare the size of the last access time */
typedef BOOL (*OsCompareFunc)(const IpcSortParam *sortParam, UINT32 left, UINT32 right);
/* Get the address of the comparison member variable */
#define SORT_ELEM_ADDR(sortParam, index) \
((sortParam)->buf + ((index) * (sortParam)->ipcDebugCBSize) + (sortParam)->sortElemOff)
/* Sort this index array. */
extern VOID OsArraySortByTime(UINT32 *sortArray, UINT32 start, UINT32 end, const IpcSortParam *sortParam,
OsCompareFunc compareFunc);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_IPCDEBUG_PRI_H */

View File

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

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_MEMORY_PRI_H
#define _LOS_MEMORY_PRI_H
#include "los_memory.h"
#include "los_spinlock.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern UINT32 OsMemSystemInit(UINTPTR memStart);
extern STATUS_T OsKHeapInit(size_t size);
#ifdef LOSCFG_EXC_INTERACTION
extern UINT32 OsMemExcInteractionInit(UINTPTR memStart);
#endif
extern VOID OsDumpMemByte(size_t length, UINTPTR addr);
#ifdef LOSCFG_MEM_LEAKCHECK
extern VOID OsMemUsedNodeShow(VOID *pool);
#endif
extern VOID OsMemResetEndNode(VOID *pool, UINTPTR preAddr);
extern UINT32 OsMemLargeNodeFree(const VOID *ptr);
extern BOOL OsMemIsHeapNode(const VOID *ptr);
extern UINT32 OsShellCmdMemCheck(INT32 argc, const CHAR *argv[]);
/* spinlock for mem module, only available on SMP mode */
extern SPIN_LOCK_S g_memSpin;
#define MEM_LOCK(state) LOS_SpinLockSave(&g_memSpin, &(state))
#define MEM_UNLOCK(state) LOS_SpinUnlockRestore(&g_memSpin, (state))
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MEMORY_PRI_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_MEMRECORD_PRI_H
#define _LOS_MEMRECORD_PRI_H
#include "los_memory.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define RECORD_LEN 4000
typedef struct {
UINT32 addrID;
UINT32 taskID;
UINT32 reqSizeID;
UINT32 allocatedSizeID;
UINT32 actType;
UINT64 sysTick;
UINT32 linkRegID;
} MemRecordInfo;
#define MEM_RECORDSHOW_TIMEOUT 6000
extern VOID OsMemRecordShowSet(UINT32 value);
extern VOID OsMemRecordMalloc(const VOID *ptr, UINT32 size);
extern VOID OsMemRecordFree(const VOID *ptr, UINT32 size);
extern VOID OsMemRecordShowTask(VOID);
extern VOID OsDecTo64F(UINT32 num, CHAR *base64, INT32 base64Len);
#ifndef LOSCFG_MEM_RECORDINFO
INLINE VOID OsMemRecordFree(const VOID *ptr, UINT32 size)
{
return;
}
#endif
#ifndef LOSCFG_MEM_RECORDINFO
INLINE VOID OsMemRecordMalloc(const VOID *ptr, UINT32 size)
{
return;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MEMRECORD_PRI_H */

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_MEMSTAT_PRI_H
#define _LOS_MEMSTAT_PRI_H
#include "los_typedef.h"
#include "los_memory.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
UINT32 memUsed;
} TskMemUsedInfo;
extern VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID);
extern VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID);
extern UINT32 OsTaskMemUsage(UINT32 taskID);
extern VOID OsTaskMemClear(UINT32 taskID);
#define OS_MEM_ENABLE_MEM_STATISTICS
#ifdef LOS_MEM_SLAB
typedef struct {
UINT32 slabUsed;
} TskSlabUsedInfo;
extern VOID OsTaskSlabUsedInc(UINT32 usedSize, UINT32 taskID);
extern VOID OsTaskSlabUsedDec(UINT32 usedSize, UINT32 taskID);
extern UINT32 OsTaskSlabUsage(UINT32 taskID);
#endif
#ifdef OS_MEM_ENABLE_MEM_STATISTICS
#define OS_MEM_ADD_USED(usedSize, taskID) OsTaskMemUsedInc(usedSize, taskID)
#define OS_MEM_REDUCE_USED(usedSize, taskID) OsTaskMemUsedDec(usedSize, taskID)
#define OS_MEM_CLEAR(taskID) OsTaskMemClear(taskID)
#ifdef LOS_MEM_SLAB
#define OS_SLAB_ADD_USED(usedSize, taskID) OsTaskSlabUsedInc(usedSize, taskID)
#define OS_SLAB_REDUCE_USED(usedSize, taskID) OsTaskSlabUsedDec(usedSize, taskID)
#endif
#else
#define OS_MEM_ADD_USED(usedSize, taskID)
#define OS_MEM_REDUCE_USED(usedSize, taskID)
#define OS_MEM_CLEAR(taskID)
#ifdef LOS_MEM_SLAB
#define OS_SLAB_ADD_USED(usedSize, taskID)
#define OS_SLAB_REDUCE_USED(usedSize, taskID)
#endif
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MEMSTAT_PRI_H */

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_MULTIPLE_DLINK_HEAD_PRI_H
#define _LOS_MULTIPLE_DLINK_HEAD_PRI_H
#include "los_base.h"
#include "los_list.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_MAX_MULTI_DLNK_LOG2 30
#define OS_MIN_MULTI_DLNK_LOG2 4
#define OS_MULTI_DLNK_NUM ((OS_MAX_MULTI_DLNK_LOG2 - OS_MIN_MULTI_DLNK_LOG2) + 1)
#define OS_DLNK_HEAD_SIZE OS_MULTI_DLNK_HEAD_SIZE
#define OS_MULTI_DLNK_HEAD_SIZE sizeof(LosMultipleDlinkHead)
typedef struct {
LOS_DL_LIST listHead[OS_MULTI_DLNK_NUM];
} LosMultipleDlinkHead;
STATIC INLINE LOS_DL_LIST *OsDLnkNextMultiHead(VOID *headAddr, LOS_DL_LIST *listNodeHead)
{
LosMultipleDlinkHead *head = (LosMultipleDlinkHead *)headAddr;
return (&head->listHead[OS_MULTI_DLNK_NUM - 1] == listNodeHead) ? NULL : (listNodeHead + 1);
}
extern VOID OsDLnkInitMultiHead(VOID *headAddr);
extern LOS_DL_LIST *OsDLnkMultiHead(VOID *headAddr, UINT32 size);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MULTIPLE_DLINK_HEAD_PRI_H */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_MUX_PRI_H
#define _LOS_MUX_PRI_H
#include "los_mux.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_MUX_MAGIC 0xEBCFDEA0
extern VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner);
extern UINT32 OsMuxLockUnsafe(LosMux *mutex, UINT32 timeout);
extern UINT32 OsMuxTrylockUnsafe(LosMux *mutex, UINT32 timeout);
extern UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MUX_PRI_H */

70
kernel/base/include/los_oom.h Executable file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_OOM_H
#define _LOS_OOM_H
#include "los_typedef.h"
#define OOM_TASK_PRIORITY 9
#define OOM_TASK_STACK_SIZE 0x1000
#define OOM_CHECK_MIN 10 /* 0.1s */
#define OOM_DEFAULT_CHECK_INTERVAL 100 /* 1s */
#define OOM_CHECK_MAX 1000 /* 10s */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD 0x80000 /* 512KByte */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN 0 /* 0, means always no memory */
#define OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX 0x100000 /* 1MByte */
#define OOM_DEFAULT_RECLAIM_MEM_THRESHOLD 0x500000 /* 5MByte */
typedef UINT32 (*OomFn)(UINTPTR param);
typedef struct {
UINT32 lowMemThreshold; /* byte */
UINT32 reclaimMemThreshold; /* byte */
UINT32 checkInterval; /* microsecond */
OomFn processVictimCB; /* process victim process cb function */
OomFn scoreCB; /* out of memory, the process score function */
UINT16 swtmrID;
BOOL enabled; /* oom is enabled or not */
} OomCB;
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomEnable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomDisable(VOID);
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold);
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval);
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID);
#endif

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_PERCPU_PRI_H
#define _LOS_PERCPU_PRI_H
#include "los_base.h"
#include "los_hw_cpu.h"
#include "los_sortlink_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#if (LOSCFG_KERNEL_SMP == YES)
typedef enum {
CPU_RUNNING = 0, /* cpu is running */
CPU_HALT, /* cpu in the halt */
CPU_EXC /* cpu in the exc */
} ExcFlag;
#endif
typedef struct {
SortLinkAttribute taskSortLink; /* task sort link */
SortLinkAttribute swtmrSortLink; /* swtmr sort link */
UINT32 idleTaskID; /* idle task id */
UINT32 taskLockCnt; /* task lock flag */
UINT32 swtmrHandlerQueue; /* software timer timeout queue id */
UINT32 swtmrTaskID; /* software timer task id */
UINT32 schedFlag; /* pending scheduler flag */
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 excFlag; /* cpu halt or exc flag */
#endif
} Percpu;
/* the kernel per-cpu structure */
extern Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM];
STATIC INLINE Percpu *OsPercpuGet(VOID)
{
return &g_percpu[ArchCurrCpuid()];
}
STATIC INLINE Percpu *OsPercpuGetByID(UINT32 cpuid)
{
return &g_percpu[cpuid];
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_PERCPU_PRI_H */

56
kernel/base/include/los_pmm.h Executable file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_pmm physical memory management
* @ingroup kernel
*/
#ifndef __LOS_PMM_H__
#define __LOS_PMM_H__
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
BOOL OsIsPaddrValid(paddr_t pa);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_PMM_H__ */

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_PRINTF_PRI_H
#define _LOS_PRINTF_PRI_H
#include "los_printf.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern VOID UartVprintf(const CHAR *fmt, va_list ap);
extern VOID PrintExcInfo(const CHAR *fmt, ...);
extern const CHAR *OsLogLvGet(INT32 level);
extern VOID LkDprintf(const CHAR *fmt, va_list ap);
#ifdef LOSCFG_SHELL_DMESG
extern VOID DmesgPrintf(const CHAR *fmt, va_list ap);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_PRINTF_PRI_H */

View File

@@ -0,0 +1,245 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_PRIQUEUE_PRI_H
#define _LOS_PRIQUEUE_PRI_H
#include "los_config.h"
#include "los_list.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern LOS_DL_LIST *g_priQueueList;
extern UINT32 g_priQueueBitmap;
#define OS_PRIORITY_QUEUE_NUM 32
/**
* @ingroup los_priqueue
* @brief Initialize the priority queue.
*
* @par Description:
* This API is used to initialize the priority queue.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param none.
*
* @retval #LOS_NOK Insufficient memory for priority queue initialization.
* @retval #LOS_OK The priority queue successfully initialized.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see none.
*/
extern UINT32 OsPriQueueInit(VOID);
/**
* @ingroup los_priqueue
* @brief Obtain the item with highest priority.
*
* @par Description:
* This API is used to obtain the item with highest priority in the priority queue.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param bitMap [IN] bit map of priority queue.
*
* @retval NULL The priority queue is empty.
* @retval item node The node of the item with highest priority.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see none.
*/
extern LOS_DL_LIST *OsPriQueueTop(LOS_DL_LIST *priQueueList, UINT32 *bitMap);
/**
* @ingroup los_priqueue
* @brief Insert a item to the head of priority queue.
*
* @par Description:
* This API is used to insert a item to the head of priority queue according to the priority of this item.
* @attention
* <ul>
* <li>Param priqueueItem must point to valid memory.</li>
* <li>Param priority rang is [0, OS_PRIORITY_QUEUE_NUM),included 0 and not included OS_PRIORITY_QUEUE_NUM.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param bitMap [IN] bit map of priority queue.
* @param priqueueItem [IN] The node of item to be inserted.
* @param priority [IN] Priority of the item be inserted.
*
* @retval none.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsPriQueueDequeue.
*/
extern VOID OsPriQueueEnqueueHead(
LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority);
/**
* @ingroup los_priqueue
* @brief Insert a item to the priority queue.
*
* @par Description:
* This API is used to insert a item to the priority queue according to the priority of this item.
* @attention
* <ul>
* <li>Param priqueueItem must point to valid memory.</li>
* <li>Param priority rang is [0, OS_PRIORITY_QUEUE_NUM),included 0 and not included OS_PRIORITY_QUEUE_NUM.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param bitMap [IN] bit map of priority queue.
* @param priqueueItem [IN] The node of item to be inserted.
* @param priority [IN] Priority of the item be inserted.
*
* @retval none.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsPriQueueDequeue.
*/
extern VOID OsPriQueueEnqueue(
LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority);
/**
* @ingroup los_priqueue
* @brief Delete a item from the priority queue.
*
* @par Description:
* This API is used to delete a item from the priority queue.
* @attention
* <ul>
* <li>Param priqueueItem must point to valid memory.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param bitMap [IN] bit map of priority queue.
* @param priqueueItem [IN] The node of item to be deleted.
*
* @retval none.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsPriQueueEnqueue.
*/
extern VOID OsPriQueueDequeue(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem);
/**
* @ingroup los_priqueue
* @brief Delete a item from the priority queue.
*
* @par Description:
* This API is used to delete a item from the process priority queue.
* @attention
* <ul>
* <li>Param priqueueItem must point to valid memory.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param bitMap [IN] bit map of priority queue.
* @param priqueueItem [IN] The node of item to be deleted.
*
* @retval none.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsPriQueueProcessDequeue.
*/
extern VOID OsPriQueueProcessDequeue(LOS_DL_LIST *priqueueItem);
/**
* @ingroup los_priqueue
* @brief Obtain the number of items with the specified priority.
*
* @par Description:
* This API is used to obtain the number of items with the specified priority.
* @attention
* <ul>
* <li>Param priority rang is [0, OS_PRIORITY_QUEUE_NUM),included 0 and not included OS_PRIORITY_QUEUE_NUM.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param priority [IN] Obtain the number of items with the specified priority.
*
* @retval The number of items The number of items with the specified priority.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see none.
*/
extern UINT32 OsPriQueueSize(LOS_DL_LIST *priQueueList, UINT32 priority);
/**
* @ingroup los_priqueue
* @brief Obtain the item with highest priority.
*
* @par Description:
* This API is used to obtain the item with highest priority in the priority queue.
* @attention
* <ul>
* <li>None.</li>
* </ul>
* @param none.
*
* @retval NULL The priority queue is empty.
* @retval item node The node of the item with highest priority.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see none.
*/
extern LOS_DL_LIST *OsTaskPriQueueTop(VOID);
/**
* @ingroup los_priqueue
* @brief Obtain the number of items with the specified priority.
*
* @par Description:
* This API is used to obtain the number of items with the specified process priority.
* @attention
* <ul>
* <li>Param priority rang is [0, OS_PRIORITY_QUEUE_NUM),included 0 and not included OS_PRIORITY_QUEUE_NUM.</li>
* </ul>
* @param priQueueList [IN] The list of priority queue.
* @param priority [IN] Obtain the number of items with the specified priority.
*
* @retval The number of items The number of items with the specified priority.
* @par Dependency:
* <ul><li>los_priqueue_pri.h: the header file that contains the API declaration.</li></ul>
* @see none.
*/
extern UINT32 OsPriQueueProcessSize(LOS_DL_LIST *priQueueList, UINT32 priority);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_PRIQUEUE_PRI_H */

View File

@@ -0,0 +1,498 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_PROCESS_PRI_H
#define _LOS_PROCESS_PRI_H
#include "los_sortlink_pri.h"
#include "los_priqueue_pri.h"
#include "los_task_pri.h"
#include "los_sem_pri.h"
#include "los_process.h"
#include "los_vm_map.h"
#if (LOSCFG_KERNEL_LITEIPC == YES)
#include "hm_liteipc.h"
#endif
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_type.h"
#endif
#ifdef LOSCFG_SECURITY_VID
#include "vid_type.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_PCB_NAME_LEN OS_TCB_NAME_LEN
#ifdef LOSCFG_SECURITY_CAPABILITY
#define OS_GROUPS_NUMBER_MAX 256
typedef struct {
UINT32 userID;
UINT32 effUserID;
UINT32 gid;
UINT32 effGid;
UINT32 groupNumber;
UINT32 groups[1];
} User;
#endif
typedef struct {
UINT32 groupID; /**< Process group ID is the PID of the process that created the group */
LOS_DL_LIST processList; /**< List of processes under this process group */
LOS_DL_LIST exitProcessList; /**< List of closed processes (zombie processes) under this group */
LOS_DL_LIST groupList; /**< Process group list */
} ProcessGroup;
typedef struct ProcessCB {
CHAR processName[OS_PCB_NAME_LEN]; /**< Process name */
UINT32 processID; /**< process ID = leader thread ID */
UINT16 processStatus; /**< [15:4] process Status; [3:0] The number of threads currently
running in the process */
UINT16 priority; /**< process priority */
UINT16 policy; /**< process policy */
UINT16 timeSlice; /**< Remaining time slice */
UINT16 consoleID; /**< The console id of task belongs */
UINT16 processMode; /**< Kernel Mode:0; User Mode:1; */
UINT32 parentProcessID; /**< Parent process ID */
UINT32 exitCode; /**< process exit status */
LOS_DL_LIST pendList; /**< Block list to which the process belongs */
LOS_DL_LIST childrenList; /**< my children process list */
LOS_DL_LIST exitChildList; /**< my exit children process list */
LOS_DL_LIST siblingList; /**< linkage in my parent's children list */
ProcessGroup *group; /**< Process group to which a process belongs */
LOS_DL_LIST subordinateGroupList; /**< linkage in my group list */
UINT32 threadGroupID; /**< Which thread group , is the main thread ID of the process */
UINT32 threadScheduleMap; /**< The scheduling bitmap table for the thread group of the
process */
LOS_DL_LIST threadSiblingList; /**< List of threads under this process */
LOS_DL_LIST threadPriQueueList[OS_PRIORITY_QUEUE_NUM]; /**< The process's thread group schedules the
priority hash table */
volatile UINT32 threadNumber; /**< Number of threads alive under this process */
UINT32 threadCount; /**< Total number of threads created under this process */
LOS_DL_LIST waitList; /**< The process holds the waitLits to support wait/waitpid */
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 timerCpu; /**< CPU core number of this task is delayed or pended */
#endif
UINTPTR sigHandler; /**< signal handler */
sigset_t sigShare; /**< signal share bit */
#if (LOSCFG_KERNEL_LITEIPC == YES)
ProcIpcInfo ipcInfo; /**< memory pool for lite ipc */
#endif
LosVmSpace *vmSpace; /**< VMM space for processes */
#ifdef LOSCFG_FS_VFS
struct files_struct *files; /**< Files held by the process */
#endif
timer_t timerID; /**< iTimer */
#ifdef LOSCFG_SECURITY_CAPABILITY
User *user;
UINT32 capability;
#endif
#ifdef LOSCFG_SECURITY_VID
TimerIdMap timerIdMap;
#endif
#ifdef LOSCFG_DRIVERS_TZDRIVER
struct file *execFile; /**< Exec bin of the process */
#endif
mode_t umask;
} LosProcessCB;
#define CLONE_VM 0x00000100
#define CLONE_FS 0x00000200
#define CLONE_FILES 0x00000400
#define CLONE_SIGHAND 0x00000800
#define CLONE_PTRACE 0x00002000
#define CLONE_VFORK 0x00004000
#define CLONE_PARENT 0x00008000
#define CLONE_THREAD 0x00010000
#define OS_PCB_FROM_PID(processID) (((LosProcessCB *)g_processCBArray) + (processID))
#define OS_PCB_FROM_SIBLIST(ptr) LOS_DL_LIST_ENTRY((ptr), LosProcessCB, siblingList)
#define OS_PCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY((ptr), LosProcessCB, pendList)
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is created but does not participate in scheduling.
*/
#define OS_PROCESS_STATUS_INIT 0x0010U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is ready.
*/
#define OS_PROCESS_STATUS_READY 0x0020U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is running.
*/
#define OS_PROCESS_STATUS_RUNNING 0x0040U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is pend
*/
#define OS_PROCESS_STATUS_PEND 0x0080U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is run out but the resources occupied by the process are not recovered.
*/
#define OS_PROCESS_STATUS_ZOMBIES 0x100U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The number of task currently running under the process, it only works with multiple cores.
*/
#define OS_PROCESS_RUNTASK_COUNT_MASK 0x000FU
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process status mask.
*/
#define OS_PROCESS_STATUS_MASK 0xFFF0U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process status equal this is process control block unused,
* coexisting with OS_PROCESS_STATUS_ZOMBIES means that the control block is not recovered.
*/
#define OS_PROCESS_FLAG_UNUSED 0x0200U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process has been call exit, it only works with multiple cores.
*/
#define OS_PROCESS_FLAG_EXIT 0x0400U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is the leader of the process group.
*/
#define OS_PROCESS_FLAG_GROUP_LEADER 0x0800U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process has performed the exec operation.
*/
#define OS_PROCESS_FLAG_ALREADY_EXEC 0x1000U
/**
* @ingroup los_process
* Flag that indicates the process or process control block status.
*
* The process is dying or already dying.
*/
#define OS_PROCESS_STATUS_INACTIVE (OS_PROCESS_FLAG_EXIT | OS_PROCESS_STATUS_ZOMBIES)
/**
* @ingroup los_process
* Used to check if the process control block is unused.
*/
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
{
return ((processCB->processStatus & OS_PROCESS_FLAG_UNUSED) != 0);
}
/**
* @ingroup los_process
* Used to check if the process is inactive.
*/
STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)
{
return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_INACTIVE)) != 0);
}
/**
* @ingroup los_process
* Used to check if the process is dead.
*/
STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)
{
return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_ZOMBIES)) != 0);
}
/**
* @ingroup los_process
* Hold the time slice process
*/
#define OS_PROCESS_SCHED_RR_INTERVAL LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
/**
* @ingroup los_process
* The highest priority of a kernel mode process.
*/
#define OS_PROCESS_PRIORITY_HIGHEST 0
/**
* @ingroup los_process
* The lowest priority of a kernel mode process
*/
#define OS_PROCESS_PRIORITY_LOWEST 31
/**
* @ingroup los_process
* The highest priority of a user mode process.
*/
#define OS_USER_PROCESS_PRIORITY_HIGHEST 10
/**
* @ingroup los_process
* The lowest priority of a user mode process
*/
#define OS_USER_PROCESS_PRIORITY_LOWEST OS_PROCESS_PRIORITY_LOWEST
/**
* @ingroup los_process
* User state root process default priority
*/
#define OS_PROCESS_USERINIT_PRIORITY 28
#define OS_GET_PROCESS_STATUS(status) ((UINT16)((UINT16)(status) & OS_PROCESS_STATUS_MASK))
#define OS_PROCESS_GET_RUNTASK_COUNT(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_RUNTASK_COUNT_MASK))
#define OS_PROCESS_RUNTASK_COUNT_ADD(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_STATUS_MASK) | \
((OS_PROCESS_GET_RUNTASK_COUNT(status) + 1) & OS_PROCESS_RUNTASK_COUNT_MASK))
#define OS_PROCESS_RUNTASK_COUNT_DEC(status) ((UINT16)(((UINT16)(status)) & OS_PROCESS_STATUS_MASK) | \
((OS_PROCESS_GET_RUNTASK_COUNT(status) - 1) & OS_PROCESS_RUNTASK_COUNT_MASK))
#define OS_TASK_DEFAULT_STACK_SIZE 0x2000
#define OS_USER_TASK_SYSCALL_SATCK_SIZE 0x3000
#define OS_USER_TASK_STACK_SIZE 0x100000
#define OS_KERNEL_MODE 0x0U
#define OS_USER_MODE 0x1U
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
{
return (processCB->processMode == OS_USER_MODE);
}
#define LOS_SCHED_NORMAL 0U
#define LOS_SCHED_FIFO 1U
#define LOS_SCHED_RR 2U
#define LOS_PRIO_PROCESS 0U
#define LOS_PRIO_PGRP 1U
#define LOS_PRIO_USER 2U
#define OS_KERNEL_PROCESS_GROUP 2U
#define OS_USER_PRIVILEGE_PROCESS_GROUP 1U
/*
* Process exit code
* 31 15 8 7 0
* | | exit code | core dump | signal |
*/
#define OS_PRO_EXIT_OK 0
STATIC INLINE VOID OsProcessExitCodeCoreDumpSet(LosProcessCB *processCB)
{
processCB->exitCode |= 0x80U;
}
STATIC INLINE VOID OsProcessExitCodeSignalSet(LosProcessCB *processCB, UINT32 signal)
{
processCB->exitCode |= signal & 0x7FU;
}
STATIC INLINE VOID OsProcessExitCodeSignalClear(LosProcessCB *processCB)
{
processCB->exitCode &= (~0x7FU);
}
STATIC INLINE BOOL OsProcessExitCodeSignalIsSet(LosProcessCB *processCB)
{
return (processCB->exitCode) & 0x7FU;
}
STATIC INLINE VOID OsProcessExitCodeSet(LosProcessCB *processCB, UINT32 code)
{
processCB->exitCode |= ((code & 0x000000FFU) << 8U) & 0x0000FF00U; /* 8: Move 8 bits to the left, exitCode */
}
extern LosProcessCB *g_processCBArray;
extern LosProcessCB *g_runProcess[LOSCFG_KERNEL_CORE_NUM];
extern UINT32 g_processMaxNum;
#define OS_PID_CHECK_INVALID(pid) (((UINT32)(pid)) >= g_processMaxNum)
STATIC INLINE BOOL OsProcessIDUserCheckInvalid(UINT32 pid)
{
return ((pid >= g_processMaxNum) || (pid == 0));
}
STATIC INLINE LosProcessCB *OsCurrProcessGet(VOID)
{
UINT32 intSave;
LosProcessCB *runProcess = NULL;
intSave = LOS_IntLock();
runProcess = g_runProcess[ArchCurrCpuid()];
LOS_IntRestore(intSave);
return runProcess;
}
STATIC INLINE VOID OsCurrProcessSet(const LosProcessCB *process)
{
g_runProcess[ArchCurrCpuid()] = (LosProcessCB *)process;
}
STATIC INLINE UINT32 OsCpuProcessIDGetUnsafe(UINT16 cpuID)
{
LosProcessCB *runProcess = g_runProcess[cpuID];
return runProcess->processID;
}
STATIC INLINE UINT32 OsCpuProcessIDGet(UINT16 cpuID)
{
UINT32 pid;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
pid = OsCpuProcessIDGetUnsafe(cpuID);
SCHEDULER_UNLOCK(intSave);
return pid;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
STATIC INLINE User *OsCurrUserGet(VOID)
{
User *user = NULL;
UINT32 intSave;
intSave = LOS_IntLock();
user = OsCurrProcessGet()->user;
LOS_IntRestore(intSave);
return user;
}
#endif
/*
* return immediately if no child has exited.
*/
#define LOS_WAIT_WNOHANG (1 << 0U)
/*
* return if a child has stopped (but not traced via ptrace(2)).
* Status for traced children which have stopped is provided even
* if this option is not specified.
*/
#define LOS_WAIT_WUNTRACED (1 << 1U)
/*
* return if a stopped child has been resumed by delivery of SIGCONT.
* (For Linux-only options, see below.)
*/
#define LOS_WAIT_WCONTINUED (1 << 3U)
/*
* Indicates that you are already in a wait state
*/
#define OS_PROCESS_WAIT (1 << 15U)
/*
* Wait for any child process to finish
*/
#define OS_PROCESS_WAIT_ANY (1 << 0U)
/*
* Wait for the child process specified by the pid to finish
*/
#define OS_PROCESS_WAIT_PRO (1 << 1U)
/*
* Waits for any child process in the specified process group to finish.
*/
#define OS_PROCESS_WAIT_GID (1 << 2U)
#define OS_PROCESS_INFO_ALL 1
#define OS_PROCESS_DEFAULT_UMASK 0022
extern UINTPTR __user_init_entry;
extern UINTPTR __user_init_bss;
extern UINTPTR __user_init_end;
extern UINTPTR __user_init_load_addr;
extern UINT32 OsKernelInitProcess(VOID);
extern VOID OsProcessCBRecyleToFree(VOID);
extern VOID OsProcessResourcesToFree(LosProcessCB *processCB);
extern VOID OsProcessExit(LosTaskCB *runTask, INT32 status);
extern UINT32 OsUserInitProcess(VOID);
extern VOID OsTaskSchedQueueDequeue(LosTaskCB *taskCB, UINT16 status);
extern VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 status);
extern INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size);
extern VOID OsWaitSignalToWakeProcess(LosProcessCB *processCB);
extern UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name,
LosVmSpace *oldAspace, UINTPTR oldFiles);
extern UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize);
extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy, BOOL policyFlag);
extern INT32 OsGetProcessPriority(INT32 which, INT32 pid);
extern VOID *OsUserStackAlloc(UINT32 processID, UINT32 *size);
extern UINT32 OsGetUserInitProcessID(VOID);
extern UINT32 OsGetIdleProcessID(VOID);
extern INT32 OsSetProcessGroupID(UINT32 pid, UINT32 gid);
extern INT32 OsSetCurrProcessGroupID(UINT32 gid);
extern UINT32 OsGetKernelInitProcessID(VOID);
extern VOID OsSetSigHandler(UINTPTR addr);
extern UINTPTR OsGetSigHandler(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_QUEUE_DEBUG_PRI_H
#define _LOS_QUEUE_DEBUG_PRI_H
#include "los_config.h"
#include "los_task.h"
#include "los_queue_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* queue debug initialization interface */
extern UINT32 OsQueueDbgInit(VOID);
STATIC INLINE UINT32 OsQueueDbgInitHook(VOID)
{
#ifdef LOSCFG_DEBUG_QUEUE
return OsQueueDbgInit();
#else
return LOS_OK;
#endif
}
/* Update the last time the queue was executed */
extern VOID OsQueueDbgTimeUpdate(UINT32 queueID);
STATIC INLINE VOID OsQueueDbgTimeUpdateHook(UINT32 queueID)
{
#ifdef LOSCFG_DEBUG_QUEUE
OsQueueDbgTimeUpdate(queueID);
#endif
}
/* Update the task entry of the queue debug info when created or deleted */
extern VOID OsQueueDbgUpdate(UINT32 queueID, TSK_ENTRY_FUNC entry);
STATIC INLINE VOID OsQueueDbgUpdateHook(UINT32 queueID, TSK_ENTRY_FUNC entry)
{
#ifdef LOSCFG_DEBUG_QUEUE
OsQueueDbgUpdate(queueID, entry);
#endif
}
/* check the leak of queue */
extern VOID OsQueueCheck(VOID);
STATIC INLINE VOID OsQueueCheckHook(VOID)
{
#ifdef LOSCFG_DEBUG_QUEUE
OsQueueCheck();
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_QUEUE_DEBUG_PRI_H */

View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_QUEUE_PRI_H
#define _LOS_QUEUE_PRI_H
#include "los_queue.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef enum {
OS_QUEUE_READ = 0,
OS_QUEUE_WRITE = 1,
OS_QUEUE_N_RW = 2
} QueueReadWrite;
typedef enum {
OS_QUEUE_HEAD = 0,
OS_QUEUE_TAIL = 1
} QueueHeadTail;
#define OS_QUEUE_OPERATE_TYPE(ReadOrWrite, HeadOrTail) (((UINT32)(HeadOrTail) << 1) | (ReadOrWrite))
#define OS_QUEUE_READ_WRITE_GET(type) ((type) & 0x01U)
#define OS_QUEUE_READ_HEAD (OS_QUEUE_READ | (OS_QUEUE_HEAD << 1))
#define OS_QUEUE_READ_TAIL (OS_QUEUE_READ | (OS_QUEUE_TAIL << 1))
#define OS_QUEUE_WRITE_HEAD (OS_QUEUE_WRITE | (OS_QUEUE_HEAD << 1))
#define OS_QUEUE_WRITE_TAIL (OS_QUEUE_WRITE | (OS_QUEUE_TAIL << 1))
#define OS_QUEUE_OPERATE_GET(type) ((type) & 0x03U)
#define OS_QUEUE_IS_READ(type) (OS_QUEUE_READ_WRITE_GET(type) == OS_QUEUE_READ)
#define OS_QUEUE_IS_WRITE(type) (OS_QUEUE_READ_WRITE_GET(type) == OS_QUEUE_WRITE)
/**
* @ingroup los_queue
* Queue information block structure
*/
typedef struct {
UINT8 *queueHandle; /**< Pointer to a queue handle */
UINT16 queueState; /**< Queue state */
UINT16 queueLen; /**< Queue length */
UINT16 queueSize; /**< Node size */
UINT32 queueID; /**< queueID */
UINT16 queueHead; /**< Node head */
UINT16 queueTail; /**< Node tail */
UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */
LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */
LOS_DL_LIST memList; /**< Pointer to the memory linked list */
} LosQueueCB;
/* queue state */
/**
* @ingroup los_queue
* Message queue state: not in use.
*/
#define OS_QUEUE_UNUSED 0
/**
* @ingroup los_queue
* Message queue state: used.
*/
#define OS_QUEUE_INUSED 1
/**
* @ingroup los_queue
* Not in use.
*/
#define OS_QUEUE_WAIT_FOR_POOL 1
/**
* @ingroup los_queue
* Normal message queue.
*/
#define OS_QUEUE_NORMAL 0
/**
* @ingroup los_queue
* Queue information control block
*/
extern LosQueueCB *g_allQueue;
/**
* @ingroup los_queue
* COUNT | INDEX split bit
*/
#define QUEUE_SPLIT_BIT 16
/**
* @ingroup los_queue
* Set the queue id
*/
#define SET_QUEUE_ID(count, queueID) (((count) << QUEUE_SPLIT_BIT) | (queueID))
/**
* @ingroup los_queue
* get the queue index
*/
#define GET_QUEUE_INDEX(queueID) ((queueID) & ((1U << QUEUE_SPLIT_BIT) - 1))
/**
* @ingroup los_queue
* get the queue count
*/
#define GET_QUEUE_COUNT(queueID) ((queueID) >> QUEUE_SPLIT_BIT)
/**
* @ingroup los_queue
* Obtain a handle of the queue that has a specified ID.
*
*/
#define GET_QUEUE_HANDLE(queueID) (((LosQueueCB *)g_allQueue) + GET_QUEUE_INDEX(queueID))
/**
* @ingroup los_queue
* Obtain the head node in a queue doubly linked list.
*/
#define GET_QUEUE_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosQueueCB, readWriteList[OS_QUEUE_WRITE])
/**
* @ingroup los_queue
* @brief Alloc a stationary memory for a mail.
*
* @par Description:
* This API is used to alloc a stationary memory for a mail according to queueID.
* @attention
* <ul>
* <li>Do not alloc memory in unblocking modes such as interrupt.</li>
* <li>This API cannot be called before the Huawei LiteOS is initialized.</li>
* <li>The argument timeout is a relative time.</li>
* </ul>
*
* @param queueID [IN] Queue ID. The value range is [1,LOSCFG_BASE_IPC_QUEUE_LIMIT].
* @param mailPool [IN] The memory poll that stores the mail.
* @param timeout [IN] Expiry time. The value range is [0,LOS_WAIT_FOREVER].
*
* @retval #NULL The memory allocation is failed.
* @retval #pMem The address of alloc memory.
* @par Dependency:
* <ul><li>los_queue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsQueueMailFree
*/
extern VOID *OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeout);
/**
* @ingroup los_queue
* @brief Free a stationary memory of a mail.
*
* @par Description:
* This API is used to free a stationary memory for a mail according to queueID.
* @attention
* <ul>
* <li>This API cannot be called before the Huawei LiteOS is initialized.</li>
* </ul>
*
* @param queueID [IN] Queue ID. The value range is [1,LOSCFG_BASE_IPC_QUEUE_LIMIT].
* @param mailPool [IN] The mail memory poll address.
* @param mailMem [IN] The mail memory block address.
*
* @retval #LOS_OK 0x00000000: The memory free successfully.
* @retval #OS_ERRNO_QUEUE_MAIL_HANDLE_INVALID 0x02000619: The handle of the queue passed-in when the memory
* for the queue is being freed is invalid.
* @retval #OS_ERRNO_QUEUE_MAIL_PTR_INVALID 0x0200061a: The pointer to the memory to be freed is null.
* @retval #OS_ERRNO_QUEUE_MAIL_FREE_ERROR 0x0200061b: The memory for the queue fails to be freed.
* @par Dependency:
* <ul><li>los_queue_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsQueueMailAlloc
*/
extern UINT32 OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem);
extern UINT32 OsQueueInit(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_QUEUE_PRI_H */

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SCHED_PRI_H
#define _LOS_SCHED_PRI_H
#include "los_percpu_pri.h"
#include "los_hwi.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern UINT32 g_taskScheduled;
/*
* Schedule flag, one bit represents one core.
* This flag is used to prevent kernel scheduling before OSStartToRun.
*/
#define OS_SCHEDULER_SET(cpuid) do { \
g_taskScheduled |= (1U << (cpuid)); \
} while (0);
#define OS_SCHEDULER_CLR(cpuid) do { \
g_taskScheduled &= ~(1U << (cpuid)); \
} while (0);
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))
typedef enum {
INT_NO_RESCH = 0, /* no needs to schedule */
INT_PEND_RESCH, /* pending schedule flag */
} SchedFlag;
/* Check if preemptable with counter flag */
STATIC INLINE BOOL OsPreemptable(VOID)
{
/*
* Unlike OsPreemptableInSched, the int may be not disabled when OsPreemptable
* is called, needs mannually disable interrupt, to prevent current task from
* being migrated to another core, and get the wrong preeptable status.
*/
UINT32 intSave = LOS_IntLock();
BOOL preemptable = (OsPercpuGet()->taskLockCnt == 0);
if (!preemptable) {
/* Set schedule flag if preemption is disabled */
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
}
LOS_IntRestore(intSave);
return preemptable;
}
STATIC INLINE BOOL OsPreemptableInSched(VOID)
{
BOOL preemptable = FALSE;
#if (LOSCFG_KERNEL_SMP == YES)
/*
* For smp systems, schedule must hold the task spinlock, and this counter
* will increase by 1 in that case.
*/
preemptable = (OsPercpuGet()->taskLockCnt == 1);
#else
preemptable = (OsPercpuGet()->taskLockCnt == 0);
#endif
if (!preemptable) {
/* Set schedule flag if preemption is disabled */
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
}
return preemptable;
}
/*
* This function simply picks the next task and switches to it.
* Current task needs to already be in the right state or the right
* queues it needs to be in.
*/
extern VOID OsSchedResched(VOID);
/*
* This function put the current task back to the ready queue and
* try to do the schedule. However, the schedule won't be definitely
* taken place while there're no other higher priority tasks or locked.
*/
extern VOID OsSchedPreempt(VOID);
/*
* Just like OsSchedPreempt, except this function will do the OS_INT_ACTIVE
* check, in case the schedule taken place in the middle of an interrupt.
*/
STATIC INLINE VOID LOS_Schedule(VOID)
{
if (OS_INT_ACTIVE) {
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
return;
}
/*
* trigger schedule in task will also do the slice check
* if neccessary, it will give up the timeslice more in time.
* otherwhise, there's no other side effects.
*/
OsSchedPreempt();
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SCHED_PRI_H */

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SEM_DEBUG_PRI_H
#define _LOS_SEM_DEBUG_PRI_H
#include "los_config.h"
#include "los_sem_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* semaphore debug initialization interface */
extern UINT32 OsSemDbgInit(VOID);
STATIC INLINE UINT32 OsSemDbgInitHook(VOID)
{
#ifdef LOSCFG_DEBUG_SEMAPHORE
return OsSemDbgInit();
#else
return LOS_OK;
#endif
}
/* Update the last time the semaphore was executed */
extern VOID OsSemDbgTimeUpdate(UINT32 semID);
STATIC INLINE VOID OsSemDbgTimeUpdateHook(UINT32 semID)
{
#ifdef LOSCFG_DEBUG_SEMAPHORE
OsSemDbgTimeUpdate(semID);
#endif
return;
}
/* Update the SEM_DEBUG_CB of the semaphore when created or deleted */
extern VOID OsSemDbgUpdate(UINT32 semID, TSK_ENTRY_FUNC creater, UINT16 count);
STATIC INLINE VOID OsSemDbgUpdateHook(UINT32 semID, TSK_ENTRY_FUNC creater, UINT16 count)
{
#ifdef LOSCFG_DEBUG_SEMAPHORE
OsSemDbgUpdate(semID, creater, count);
#endif
return;
}
/* get the full data of SEM_DFX_CB */
extern UINT32 OsSemInfoGetFullData(VOID);
STATIC INLINE VOID OsSemInfoGetFullDataHook(VOID)
{
#ifdef LOSCFG_DEBUG_SEMAPHORE
(VOID)OsSemInfoGetFullData();
#endif
return;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SEM_DEBUG_PRI_H */

120
kernel/base/include/los_sem_pri.h Executable file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SEM_PRI_H
#define _LOS_SEM_PRI_H
#include "los_sem.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_sem
* Semaphore control structure.
*/
typedef struct {
UINT8 semStat; /**< Semaphore state */
UINT16 semCount; /**< Number of available semaphores */
UINT16 maxSemCount; /**< Max number of available semaphores */
UINT32 semID; /**< Semaphore control structure ID */
LOS_DL_LIST semList; /**< Queue of tasks that are waiting on a semaphore */
} LosSemCB;
/**
* @ingroup los_sem
* The semaphore is not in use.
*
*/
#define OS_SEM_UNUSED 0
/**
* @ingroup los_sem
* The semaphore is used.
*
*/
#define OS_SEM_USED 1
/**
* @ingroup los_sem
* Obtain the head node in a semaphore doubly linked list.
*
*/
#define GET_SEM_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosSemCB, semList)
extern LosSemCB *g_allSem;
/**
* @ingroup los_sem
* COUNT | INDEX split bit
*/
#define SEM_SPLIT_BIT 16
/**
* @ingroup los_sem
* Set the semaphore id
*/
#define SET_SEM_ID(count, semID) (((count) << SEM_SPLIT_BIT) | (semID))
/**
* @ingroup los_sem
* get the semaphore index
*/
#define GET_SEM_INDEX(semID) ((semID) & ((1U << SEM_SPLIT_BIT) - 1))
/**
* @ingroup los_sem
* get the semaphore count
*/
#define GET_SEM_COUNT(semID) ((semID) >> SEM_SPLIT_BIT)
/**
* @ingroup los_sem
* Obtain a semaphore ID.
*
*/
#define GET_SEM(semID) (((LosSemCB *)g_allSem) + GET_SEM_INDEX(semID))
/**
* @ingroup los_sem
* Maximum value of task information.
*
*/
#define OS_MAX_PENDTASK_INFO 4
extern UINT32 OsSemInit(VOID);
extern UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SEM_PRI_H */

198
kernel/base/include/los_signal.h Executable file
View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SIGNAL_H
#define _LOS_SIGNAL_H
#include <stddef.h>
#include <limits.h>
#include <sys/types.h>
#include <signal.h>
#include "los_event.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define LOS_BIT_SET(val, bit) ((val) = (val) | (1ULL << (UINT32)(bit)))
#define LOS_BIT_CLR(val, bit) ((val) = (val) & ~(1ULL << (UINT32)(bit)))
#define LOS_IS_BIT_SET(val, bit) (bool)((((val) >> (UINT32)(bit)) & 1ULL))
#define OS_SYSCALL_SET_CPSR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs) - 4)) = (cpsr))
#define OS_SYSCALL_SET_SR(regs, cpsr) (*((unsigned long *)((UINTPTR)(regs))) = (cpsr))
#define OS_SYSCALL_GET_CPSR(regs) (*((unsigned long *)((UINTPTR)(regs) - 4)))
#define SIG_STOP_VISIT 1
#define OS_KERNEL_KILL_PERMISSION 0U
#define OS_USER_KILL_PERMISSION 3U
#define OS_RETURN_IF(expr, errcode) \
if ((expr)) { \
return errcode; \
}
#define OS_RETURN_IF_VOID(expr) \
if ((expr)) { \
return; \
}
#define OS_GOTO_EXIT_IF(expr, errcode) \
if (expr) { \
ret = errcode; \
goto EXIT; \
}
#define OS_GOTO_EXIT_IF_ONLY(expr) \
if (expr) { \
goto EXIT; \
}
#define OS_RETURN_VOID_IF_NULL(pPara) \
if (NULL == (pPara)) { \
return; \
}
#define OS_RETURN_IF_NULL(pPara) \
if (NULL == (pPara)) { \
return (-EINVAL); \
}
#define OS_GOTO_EXIT_IF_NULL(pPara) \
if (NULL == (pPara)) { \
ret = -EINVAL; \
goto EXIT; \
}
typedef void (*sa_sighandler_t)(int);
typedef void (*sa_siginfoaction_t)(int, siginfo_t *, void *);
#define SIGNO2SET(s) ((sigset_t)1ULL << (s))
#define NULL_SIGNAL_SET ((sigset_t)0ULL)
#define FULL_SIGNAL_SET ((sigset_t)~0ULL)
static inline int GOOD_SIGNO(unsigned int sig)
{
return (sig < _NSIG) ? 1 : 0;
}
#define MAX_SIG_ARRAY_IN_MUSL 128
typedef struct {
unsigned long sig[MAX_SIG_ARRAY_IN_MUSL / sizeof(unsigned long)];
} sigset_t_l;
typedef struct sigaction sigaction_t;
struct sigactq {
struct sigactq *flink; /* Forward link */
sigaction_t act; /* Sigaction data */
uint8_t signo; /* Signal associated with action */
};
typedef struct sigactq sigactq_t;
struct sq_entry_s {
struct sq_entry_s *flink;
};
typedef struct sq_entry_s sq_entry_t;
struct sigpendq {
struct sigpendq *flink; /* Forward link */
siginfo_t info; /* Signal information */
uint8_t type; /* (Used to manage allocations) */
};
typedef struct sigpendq sigpendq_t;
struct sq_queue_s {
sq_entry_t *head;
sq_entry_t *tail;
};
typedef struct sq_queue_s sq_queue_t;
#define TASK_IRQ_CONTEXT \
unsigned int R0; \
unsigned int R1; \
unsigned int R2; \
unsigned int R3; \
unsigned int R12; \
unsigned int USP; \
unsigned int ULR; \
unsigned int CPSR; \
unsigned int PC;
typedef struct {
TASK_IRQ_CONTEXT
} TaskIrqDataSize;
typedef struct {
TASK_IRQ_CONTEXT
unsigned int R7;
unsigned int count;
} sig_switch_context;
typedef struct {
sigset_t sigFlag;
sigset_t sigPendFlag;
sigset_t sigprocmask; /* Signals that are blocked */
sq_queue_t sigactionq;
LOS_DL_LIST waitList;
sigset_t sigwaitmask; /* Waiting for pending signals */
siginfo_t sigunbinfo; /* Signal info when task unblocked */
sig_switch_context context;
} sig_cb;
#define SIGEV_THREAD_ID 4
int sys_sigqueue(pid_t, int, const union sigval);
int sys_sigpending(sigset_t *);
int sys_rt_sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *ts, size_t sigsetsize);
int sys_sigsuspend(const sigset_t *);
int OsKillLock(pid_t pid, int sig);
int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact);
int OsSigprocMask(int how, const sigset_t_l *set, sigset_t_l *oldset);
int OsPthreadKill(UINT32 tid, int signo);
int OsSigEmptySet(sigset_t *);
int OsSigAddSet(sigset_t *, int);
int OsSigIsMember(const sigset_t *, int);
void OsSaveSignalContext(unsigned int *sp);
void OsRestorSignalContext(unsigned int *sp);
int OsKill(pid_t pid, int sig, int permission);
int OsDispatch(pid_t pid, siginfo_t *info, int permission);
int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout);
int OsPause(void);
int OsSigPending(sigset_t *set);
int OsSigSuspend(const sigset_t *set);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SIGNAL_H */

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SORTLINK_PRI_H
#define _LOS_SORTLINK_PRI_H
#include "los_typedef.h"
#include "los_list.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*
* Sortlink Rollnum Structure:
* ------------------------------------------
* | 31 | 30 | 29 |.......| 4 | 3 | 2 | 1 | 0 |
* ------------------------------------------
* |<-High Bits->|<---------Low Bits--------->|
*
* Low Bits : circles
* High Bits : sortlink index
*/
#define OS_TSK_HIGH_BITS 3U
#define OS_TSK_LOW_BITS (32U - OS_TSK_HIGH_BITS)
#define OS_TSK_SORTLINK_LOGLEN OS_TSK_HIGH_BITS
#define OS_TSK_SORTLINK_LEN (1U << OS_TSK_SORTLINK_LOGLEN)
#define OS_TSK_SORTLINK_MASK (OS_TSK_SORTLINK_LEN - 1U)
#define OS_TSK_MAX_ROLLNUM (0xFFFFFFFFU - OS_TSK_SORTLINK_LEN)
#define OS_TSK_HIGH_BITS_MASK (OS_TSK_SORTLINK_MASK << OS_TSK_LOW_BITS)
#define OS_TSK_LOW_BITS_MASK (~OS_TSK_HIGH_BITS_MASK)
#define EVALUATE_L(NUM, VALUE) NUM = (((NUM) & OS_TSK_HIGH_BITS_MASK) | (VALUE))
#define EVALUATE_H(NUM, VALUE) NUM = (((NUM) & OS_TSK_LOW_BITS_MASK) | ((VALUE) << OS_TSK_LOW_BITS))
#define ROLLNUM_SUB(NUM1, NUM2) \
NUM1 = (((NUM1) & OS_TSK_HIGH_BITS_MASK) | \
(ROLLNUM(NUM1) - ROLLNUM(NUM2)))
#define ROLLNUM_ADD(NUM1, NUM2) \
NUM1 = (((NUM1) & OS_TSK_HIGH_BITS_MASK) | \
(ROLLNUM(NUM1) + ROLLNUM(NUM2)))
#define ROLLNUM_DEC(NUM) NUM = ((NUM) - 1)
#define ROLLNUM(NUM) ((NUM) & OS_TSK_LOW_BITS_MASK)
#define SORT_INDEX(NUM) ((NUM) >> OS_TSK_LOW_BITS)
#define SET_SORTLIST_VALUE(sortList, value) (((SortLinkList *)(sortList))->idxRollNum = (value))
typedef struct {
LOS_DL_LIST sortLinkNode;
UINT32 idxRollNum;
} SortLinkList;
typedef struct {
LOS_DL_LIST *sortLink;
UINT16 cursor;
UINT16 reserved;
} SortLinkAttribute;
extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
extern VOID OsAdd2SortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList);
extern VOID OsDeleteSortLink(const SortLinkAttribute *sortLinkHeader, SortLinkList *sortList);
extern UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader);
extern UINT32 OsSortLinkGetTargetExpireTime(const SortLinkAttribute *sortLinkHeader,
const SortLinkList *targetSortList);
extern VOID OsSortLinkUpdateExpireTime(UINT32 sleepTicks, SortLinkAttribute *sortLinkHeader);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SORTLINK_PRI_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_STACK_INFO_PRI_H
#define _LOS_STACK_INFO_PRI_H
#include "los_typedef.h"
#include "arch_config.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
VOID *stackTop;
UINT32 stackSize;
CHAR *stackName;
} StackInfo;
#define OS_INVALID_WATERLINE 0xFFFFFFFF
#define OS_STACK_MAGIC_CHECK(topstack) (*(UINTPTR *)(topstack) == OS_STACK_MAGIC_WORD) /* 1:magic valid 0:unvalid */
extern VOID OsExcStackInfo(VOID);
extern VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum);
extern VOID OsStackInit(VOID *stacktop, UINT32 stacksize);
/**
* @ingroup los_task
* @brief Get stack waterline.
*
* @par Description:
* This API is used to get stack waterline size and check stack whether overflow.
*
* @attention None
*
* @param stackBottom [IN] Type #const UINTPTR * pointer to stack bottom.
* @param stackTop [IN] Type #const UINTPTR * pointer to stack top.
* @param peakUsed [OUT] Type #UINT32 * stack waterline.
*
* @retval #LOS_NOK stack overflow
* @retval #LOS_OK stack is normal, not overflow
* @par Dependency:
* <ul><li>los_stackinfo_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
extern UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_STACK_INFO_PRI_H */

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_STAT_PRI_H
#define __LOS_STAT_PRI_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
UINT64 runtime;
UINT32 contexSwitch;
} SchedPercpu;
typedef struct {
UINT64 startRuntime;
UINT64 allRuntime;
UINT32 allContextSwitch;
SchedPercpu schedPercpu[LOSCFG_KERNEL_SMP_CORE_NUM];
} SchedStat;
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_STAT_PRI_H */

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SWTMR_PRI_H
#define _LOS_SWTMR_PRI_H
#include "los_swtmr.h"
#include "los_spinlock.h"
#ifdef LOSCFG_SECURITY_VID
#include "vid_api.h"
#else
#define MAX_INVALID_TIMER_VID OS_SWTMR_MAX_TIMERID
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_swtmr_pri
* Software timer state
*/
enum SwtmrState {
OS_SWTMR_STATUS_UNUSED, /**< The software timer is not used. */
OS_SWTMR_STATUS_CREATED, /**< The software timer is created. */
OS_SWTMR_STATUS_TICKING /**< The software timer is timing. */
};
/**
* @ingroup los_swtmr_pri
* Structure of the callback function that handles software timer timeout
*/
typedef struct {
SWTMR_PROC_FUNC handler; /**< Callback function that handles software timer timeout */
UINTPTR arg; /**< Parameter passed in when the callback function
that handles software timer timeout is called */
} SwtmrHandlerItem;
/**
* @ingroup los_swtmr_pri
* Type of the pointer to the structure of the callback function that handles software timer timeout
*/
typedef SwtmrHandlerItem *SwtmrHandlerItemPtr;
extern SWTMR_CTRL_S *g_swtmrCBArray;
extern SortLinkAttribute g_swtmrSortLink; /* The software timer count list */
#define OS_SWT_FROM_SID(swtmrID) ((SWTMR_CTRL_S *)g_swtmrCBArray + ((swtmrID) % LOSCFG_BASE_CORE_SWTMR_LIMIT))
/**
* @ingroup los_swtmr_pri
* @brief Scan a software timer.
*
* @par Description:
* <ul>
* <li>This API is used to scan a software timer when a Tick interrupt occurs and determine whether
* the software timer expires.</li>
* </ul>
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param None.
*
* @retval None.
* @par Dependency:
* <ul><li>los_swtmr_pri.h: the header file that contains the API declaration.</li></ul>
* @see LOS_SwtmrStop
*/
extern VOID OsSwtmrScan(VOID);
extern UINT32 OsSwtmrInit(VOID);
extern VOID OsSwtmrTask(VOID);
extern VOID OsSwtmrRecycle(UINT32 processID);
extern SPIN_LOCK_S g_swtmrSpin;
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SWTMR_PRI_H */

104
kernel/base/include/los_sys_pri.h Executable file
View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_SYS_PRI_H
#define _LOS_SYS_PRI_H
#include "los_sys.h"
#include "los_base_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_sys
* Number of milliseconds in one second.
*/
#define OS_SYS_MS_PER_SECOND 1000
/**
* @ingroup los_sys
* Number of microseconds in one second.
*/
#define OS_SYS_US_PER_SECOND 1000000
/**
* @ingroup los_sys
* Number of nanoseconds in one second.
*/
#define OS_SYS_NS_PER_SECOND 1000000000
/**
* @ingroup los_sys
* Number of microseconds in one milliseconds.
*/
#define OS_SYS_US_PER_MS 1000
/**
* @ingroup los_sys
* Number of nanoseconds in one milliseconds.
*/
#define OS_SYS_NS_PER_MS 1000000
/**
* @ingroup los_sys
* Number of nanoseconds in one microsecond.
*/
#define OS_SYS_NS_PER_US 1000
/**
* @ingroup los_sys
* The maximum length of name.
*/
#define OS_SYS_APPVER_NAME_MAX 64
/**
* @ingroup los_sys
* The magic word.
*/
#define OS_SYS_MAGIC_WORD 0xAAAAAAAA
/**
* @ingroup los_sys
* The initialization value of stack space.
*/
#define OS_SYS_EMPTY_STACK 0xCACACACA
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SYS_PRI_H */

View File

@@ -0,0 +1,587 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_TASK_PRI_H
#define _LOS_TASK_PRI_H
#include "los_task.h"
#include "los_sched_pri.h"
#include "los_sortlink_pri.h"
#include "los_spinlock.h"
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
#include "los_stat_pri.h"
#endif
#include "los_stackinfo_pri.h"
#include "los_futex_pri.h"
#include "los_signal.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_task
* Define task siginal types.
*
* Task siginal types.
*/
#define SIGNAL_NONE 0U
#define SIGNAL_KILL (1U << 0)
#define SIGNAL_SUSPEND (1U << 1)
#define SIGNAL_AFFI (1U << 2)
/* scheduler lock */
extern SPIN_LOCK_S g_taskSpin;
#define SCHEDULER_LOCK(state) LOS_SpinLockSave(&g_taskSpin, &(state))
#define SCHEDULER_UNLOCK(state) LOS_SpinUnlockRestore(&g_taskSpin, state)
/* default and non-running task's ownership id */
#define OS_TASK_INVALID_CPUID 0xFFFF
/**
* @ingroup los_task
* Null task ID
*
*/
#define OS_TASK_ERRORID 0xFFFFFFFF
/**
* @ingroup los_task
* Define a usable task priority.
*
* Highest task priority.
*/
#define OS_TASK_PRIORITY_HIGHEST 0
/**
* @ingroup los_task
* Define a usable task priority.
*
* Lowest task priority.
*/
#define OS_TASK_PRIORITY_LOWEST 31
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is init.
*/
#define OS_TASK_STATUS_INIT 0x0001U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is ready.
*/
#define OS_TASK_STATUS_READY 0x0002U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is running.
*/
#define OS_TASK_STATUS_RUNNING 0x0004U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is suspended.
*/
#define OS_TASK_STATUS_SUSPEND 0x0008U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is blocked.
*/
#define OS_TASK_STATUS_PEND 0x0010U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is delayed.
*/
#define OS_TASK_STATUS_DELAY 0x0020U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The time for waiting for an event to occur expires.
*/
#define OS_TASK_STATUS_TIMEOUT 0x0040U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is pend for a period of time.
*/
#define OS_TASK_STATUS_PEND_TIME 0x0080U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is exit.
*/
#define OS_TASK_STATUS_EXIT 0x0100U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task control block is unused.
*/
#define OS_TASK_STATUS_UNUSED 0x0200U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is joinable.
*/
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U
/**
* @ingroup los_task
* Flag that indicates the task or task control block status.
*
* The task is status detached.
*/
#define OS_TASK_FLAG_DETACHED 0x0800U
/**
* @ingroup los_task
* Flag that indicates the task property.
*
* The task is idle task, Belong to idle process.
*/
#define OS_TASK_FLAG_IDLEFLAG 0x1000U
/**
* @ingroup los_task
* Flag that indicates the task property.
*
* The task is system-level task, like idle, swtmr and etc.
*/
#define OS_TASK_FLAG_SYSTEM_TASK 0x2000U
/**
* @ingroup los_task
* Flag that indicates the task property.
*
* Specifies the process creation task.
*/
#define OS_TASK_FLAG_SPECIFIES_PROCESS 0x4000U
/**
* @ingroup los_task
* Boundary on which the stack size is aligned.
*
*/
#define OS_TASK_STACK_SIZE_ALIGN 16U
/**
* @ingroup los_task
* Boundary on which the stack address is aligned.
*
*/
#define OS_TASK_STACK_ADDR_ALIGN 8U
/**
* @ingroup los_task
* Number of usable task priorities.
*/
#define OS_TSK_PRINUM (OS_TASK_PRIORITY_LOWEST - OS_TASK_PRIORITY_HIGHEST + 1)
/**
* @ingroup los_task
* @brief Check whether a task ID is valid.
*
* @par Description:
* This API is used to check whether a task ID, excluding the idle task ID, is valid.
* @attention None.
*
* @param taskID [IN] Task ID.
*
* @retval 0 or 1. One indicates that the task ID is invalid, whereas zero indicates that the task ID is valid.
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
#define OS_TSK_GET_INDEX(taskID) (taskID)
/**
* @ingroup los_task
* @brief Obtain the pointer to a task control block.
*
* @par Description:
* This API is used to obtain the pointer to a task control block using a corresponding parameter.
* @attention None.
*
* @param ptr [IN] Parameter used for obtaining the task control block.
*
* @retval Pointer to the task control block.
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
#define OS_TCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosTaskCB, pendList)
/**
* @ingroup los_task
* @brief Obtain the pointer to a task control block.
*
* @par Description:
* This API is used to obtain the pointer to a task control block that has a specified task ID.
* @attention None.
*
* @param TaskID [IN] Task ID.
*
* @retval Pointer to the task control block.
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
#define OS_TCB_FROM_TID(taskID) (((LosTaskCB *)g_taskCBArray) + (taskID))
#ifndef LOSCFG_STACK_POINT_ALIGN_SIZE
#define LOSCFG_STACK_POINT_ALIGN_SIZE (sizeof(UINTPTR) * 2)
#endif
#define OS_TASK_RESOURCE_STATCI_SIZE 0x1000
#define OS_TASK_RESOURCE_FREE_PRIORITY 5
#define OS_RESOURCE_EVENT_MASK 0xFF
#define OS_RESOURCE_EVENT_OOM 0x02
#define OS_RESOURCE_EVENT_FREE 0x04
#define OS_TCB_NAME_LEN 32
typedef struct {
VOID *stackPointer; /**< Task stack pointer */
UINT16 taskStatus; /**< Task status */
UINT16 priority; /**< Task priority */
UINT16 policy;
UINT16 timeSlice; /**< Remaining time slice */
UINT32 stackSize; /**< Task stack size */
UINTPTR topOfStack; /**< Task stack top */
UINT32 taskID; /**< Task ID */
TSK_ENTRY_FUNC taskEntry; /**< Task entrance function */
VOID *joinRetval; /**< pthread adaption */
VOID *taskSem; /**< Task-held semaphore */
VOID *taskMux; /**< Task-held mutex */
VOID *taskEvent; /**< Task-held event */
UINTPTR args[4]; /**< Parameter, of which the maximum number is 4 */
CHAR taskName[OS_TCB_NAME_LEN]; /**< Task name */
LOS_DL_LIST pendList; /**< Task pend node */
LOS_DL_LIST threadList; /**< thread list */
SortLinkList sortList; /**< Task sortlink node */
UINT32 eventMask; /**< Event mask */
UINT32 eventMode; /**< Event mode */
UINT32 priBitMap; /**< BitMap for recording the change of task priority,
the priority can not be greater than 31 */
INT32 errorNo; /**< Error Num */
UINT32 signal; /**< Task signal */
sig_cb sig;
#if (LOSCFG_KERNEL_SMP == YES)
UINT16 currCpu; /**< CPU core number of this task is running on */
UINT16 lastCpu; /**< CPU core number of this task is running on last time */
UINT16 cpuAffiMask; /**< CPU affinity mask, support up to 16 cores */
UINT32 timerCpu; /**< CPU core number of this task is delayed or pended */
#if (LOSCFG_KERNEL_SMP_TASK_SYNC == YES)
UINT32 syncSignal; /**< Synchronization for signal handling */
#endif
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
LockDep lockDep;
#endif
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
SchedStat schedStat; /**< Schedule statistics */
#endif
#endif
UINTPTR userArea;
UINTPTR userMapBase;
UINT32 userMapSize; /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE */
UINT32 processID; /**< Which belong process */
FutexNode futex;
LOS_DL_LIST joinList; /**< join list */
LOS_DL_LIST lockList; /**< Hold the lock list */
UINT32 waitID; /**< Wait for the PID or GID of the child process */
UINT16 waitFlag; /**< The type of child process that is waiting, belonging to a group or parent,
a specific child process, or any child process */
#if (LOSCFG_KERNEL_LITEIPC == YES)
UINT32 ipcStatus;
LOS_DL_LIST msgListHead;
BOOL accessMap[LOSCFG_BASE_CORE_TSK_LIMIT];
#endif
} LosTaskCB;
typedef struct {
LosTaskCB *runTask;
LosTaskCB *newTask;
} LosTask;
struct ProcessSignalInfo {
siginfo_t *sigInfo; /**< Signal to be dispatched */
LosTaskCB *defaultTcb; /**< Default TCB */
LosTaskCB *unblockedTcb; /**< The signal unblock on this TCB*/
LosTaskCB *awakenedTcb; /**< This TCB was awakened */
LosTaskCB *receivedTcb; /**< This TCB received the signal */
};
typedef int (*ForEachTaskCB)(LosTaskCB *tcb, void *arg);
/**
* @ingroup los_task
* Maximum number of tasks.
*
*/
extern UINT32 g_taskMaxNum;
/**
* @ingroup los_task
* Starting address of a task.
*
*/
extern LosTaskCB *g_taskCBArray;
/**
* @ingroup los_task
* Time slice structure.
*/
typedef struct {
LosTaskCB *task; /**< Current running task */
UINT16 time; /**< Expiration time point */
UINT16 timeout; /**< Expiration duration */
} OsTaskRobin;
STATIC INLINE LosTaskCB *OsCurrTaskGet(VOID)
{
return (LosTaskCB *)ArchCurrTaskGet();
}
STATIC INLINE VOID OsCurrTaskSet(LosTaskCB *task)
{
ArchCurrTaskSet(task);
}
STATIC INLINE VOID OsCurrUserTaskSet(UINTPTR thread)
{
ArchCurrUserTaskSet(thread);
}
STATIC INLINE LosTaskCB *OsGetTaskCB(UINT32 taskID)
{
return OS_TCB_FROM_TID(taskID);
}
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
return TRUE;
}
return FALSE;
}
STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
return TRUE;
}
return FALSE;
}
STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & (OS_TASK_STATUS_UNUSED | OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT)) {
return TRUE;
}
return FALSE;
}
#define OS_TID_CHECK_INVALID(taskID) ((UINT32)(taskID) >= g_taskMaxNum)
/* get task info */
#define OS_ALL_TASK_MASK 0xFFFFFFFF
#define OS_PROCESS_PRI_QUEUE_SIZE(processCB) OsPriQueueProcessSize(g_priQueueList, (processCB)->priority)
#define OS_TASK_PRI_QUEUE_ENQUEUE(processCB, taskCB) \
OsPriQueueEnqueue((processCB)->threadPriQueueList, &((processCB)->threadScheduleMap), \
&((taskCB)->pendList), (taskCB)->priority)
#define OS_TASK_PRI_QUEUE_ENQUEUE_HEAD(processCB, taskCB) \
OsPriQueueEnqueueHead((processCB)->threadPriQueueList, &((processCB)->threadScheduleMap), \
&((taskCB)->pendList), (taskCB)->priority)
#define OS_TASK_PRI_QUEUE_DEQUEUE(processCB, taskCB) \
OsPriQueueDequeue((processCB)->threadPriQueueList, &((processCB)->threadScheduleMap), &((taskCB)->pendList))
#define OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, status) OsTaskSchedQueueEnqueue(taskCB, status)
#define OS_TASK_SCHED_QUEUE_DEQUEUE(taskCB, status) OsTaskSchedQueueDequeue(taskCB, status)
#define OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB) \
OsPriQueueEnqueue(g_priQueueList, &g_priQueueBitmap, &((processCB)->pendList), (processCB)->priority)
#define OS_PROCESS_PRI_QUEUE_ENQUEUE_HEAD(processCB) \
OsPriQueueEnqueueHead(g_priQueueList, &g_priQueueBitmap, &((processCB)->pendList), (processCB)->priority)
#define OS_PROCESS_PRI_QUEUE_DEQUEUE(processCB) OsPriQueueProcessDequeue(&((processCB)->pendList))
#define OS_TASK_PRI_QUEUE_SIZE(processCB, taskCB) OsPriQueueSize((processCB)->threadPriQueueList, (taskCB)->priority)
#define OS_TASK_GET_NEW(processCB) LOS_DL_LIST_ENTRY(OsPriQueueTop((processCB)->threadPriQueueList, \
&((processCB)->threadScheduleMap)), \
LosTaskCB, pendList)
#define OS_PROCESS_GET_NEW() \
LOS_DL_LIST_ENTRY(OsPriQueueTop(g_priQueueList, &g_priQueueBitmap), LosProcessCB, pendList)
/**
* @ingroup los_task
* @brief Modify the priority of task.
*
* @par Description:
* This API is used to modify the priority of task.
*
* @attention
* <ul>
* <li>The taskCB should be a correct pointer to task control block structure.</li>
* <li>the priority should be in [0, OS_TASK_PRIORITY_LOWEST].</li>
* </ul>
*
* @param taskCB [IN] Type #LosTaskCB * pointer to task control block structure.
* @param priority [IN] Type #UINT16 the priority of task.
*
* @retval None.
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
extern VOID OsTaskPriModify(LosTaskCB *taskCB, UINT16 priority);
/**
* @ingroup los_task
* @brief pend running task to pendlist
*
* @par Description:
* This API is used to pend task to pendlist and add to sorted delay list.
*
* @attention
* <ul>
* <li>The list should be a vaild pointer to pendlist.</li>
* </ul>
*
* @param list [IN] Type #LOS_DL_LIST * pointer to list which running task will be pended.
* @param timeout [IN] Type #UINT32 Expiry time. The value range is [0,LOS_WAIT_FOREVER].
* @param needSched [IN] Type #bool need sched
*
* @retval LOS_OK wait success
* @retval LOS_NOK pend out
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsTaskWake
*/
extern UINT32 OsTaskWait(LOS_DL_LIST *list, UINT32 timeout, BOOL needSched);
/**
* @ingroup los_task
* @brief delete task from pendlist.
*
* @par Description:
* This API is used to delete task from pendlist and also add to the priqueue.
*
* @attention
* <ul>
* <li>The resumedTask should be the task which will be add to priqueue.</li>
* </ul>
*
* @param resumedTask [IN] Type #LosTaskCB * pointer to the task which will be add to priqueue.
*
* @retval None.
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see OsTaskWait
*/
extern VOID OsTaskWake(LosTaskCB *resumedTask);
extern UINT32 OsTaskSetDeatchUnsafe(LosTaskCB *taskCB);
extern VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB);
extern UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB);
extern VOID OsTaskSchedule(LosTaskCB *, LosTaskCB *);
extern VOID OsStartToRun(LosTaskCB *);
extern VOID OsTaskScan(VOID);
extern VOID OsIdleTask(VOID);
extern UINT32 OsIdleTaskCreate(VOID);
extern UINT32 OsTaskInit(VOID);
extern UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv);
extern UINT32 OsShellCmdTskInfoGet(UINT32 taskID, VOID *seqfile, UINT16 flag);
extern VOID* OsGetMainTask(VOID);
extern VOID OsSetMainTask(VOID);
extern LosTaskCB* OsGetTopTask(VOID);
extern UINT32 OsGetIdleTaskId(VOID);
extern VOID OsTaskEntry(UINT32 taskID);
extern SortLinkAttribute *OsTaskSortLinkGet(VOID);
extern UINT32 OsTaskSwitchCheck(LosTaskCB *oldTask, LosTaskCB *newTask);
extern UINT32 OsTaskProcSignal(VOID);
extern VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask);
extern UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave);
extern VOID OsTaskResourcesToFree(LosTaskCB *taskCB);
extern VOID OsRunTaskToDelete(LosTaskCB *taskCB);
extern UINT32 OsTaskSyncWait(const LosTaskCB *taskCB);
extern INT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam);
extern INT32 OsTaskSchedulerSetUnsafe(LosTaskCB *taskCB, UINT16 policy, UINT16 priority,
BOOL policyFlag, UINT32 intSave);
extern INT32 OsSetCurrTaskName(const CHAR *name);
extern VOID OsTaskCBRecyleToFree(VOID);
extern VOID OsTaskExitGroup(UINT32 status);
extern VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status);
extern VOID OsExecDestroyTaskGroup(VOID);
extern VOID OsProcessSuspendAllTask(VOID);
extern UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB);
extern VOID OsWriteResourceEvent(UINT32 events);
extern UINT32 OsCreateResourceFreeTask(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_TASK_PRI_H */

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_TICK_PRI_H
#define _LOS_TICK_PRI_H
#include "los_base.h"
#include "los_tick.h"
#include "los_spinlock.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* spinlock for tick */
extern SPIN_LOCK_S g_tickSpin;
#define TICK_LOCK(state) LOS_SpinLockSave(&g_tickSpin, &(state))
#define TICK_UNLOCK(state) LOS_SpinUnlockRestore(&g_tickSpin, (state))
/**
* @ingroup los_tick
* Count of Ticks
*/
extern volatile UINT64 g_tickCount[];
/**
* @ingroup los_tick
* Cycle to nanosecond scale
*/
extern DOUBLE g_cycle2NsScale;
/**
* @ingroup los_tick
* @brief Handle the system tick timeout.
*
* @par Description:
* This API is called when the system tick timeout and triggers the interrupt.
*
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param none.
*
* @retval None.
* @par Dependency:
* <ul><li>los_tick.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern VOID OsTickHandler(VOID);
/**
* @ingroup los_tick
* Convert from the cycle count to nanosecond.
*/
#define CYCLE_TO_NS(cycles) ((cycles) * g_cycle2NsScale)
/**
* Current system timer register is 32 bit, therefore TIMER_MAXLOAD define just in order to avoid ambiguity.
*/
#define TIMER_MAXLOAD 0xffffffff
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_TICK_PRI_H */

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_timeslice Timeslice
* @ingroup kernel
*/
#ifndef _LOS_TIMESLICE_PRI_H
#define _LOS_TIMESLICE_PRI_H
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* @ingroup los_timeslice
* @brief Check time slices.
*
* @par Description:
* <ul>
* <li>This API is used to check time slices. If the number of Ticks equals to the time for task switch,
* tasks are switched. Otherwise, the Tick counting continues.</li>
* </ul>
* @attention
* <ul>
* <li>None.</li>
* </ul>
*
* @param None.
*
* @retval None.
* @par Dependency:
* <ul><li>los_timeslice_pri.h: the header file that contains the API declaration.</li></ul>
* @see None.
*/
extern VOID OsTimesliceCheck(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_TIMESLICE_PRI_H */

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_TYPEDEF_PRI_H
#define _LOS_TYPEDEF_PRI_H
#include "los_typedef.h"
#endif /* _LOS_TYPEDEF_PRI_H */

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/* flags for initial mapping struct */
#define MMU_INITIAL_MAPPING_TEMPORARY (0x1)
#define MMU_INITIAL_MAPPING_FLAG_UNCACHED (0x2)
#define MMU_INITIAL_MAPPING_FLAG_DEVICE (0x4)
#define MMU_INITIAL_MAPPING_FLAG_DYNAMIC (0x8)
#ifndef ASSEMBLY
#ifndef __LOS_VM_BOOT_H__
#define __LOS_VM_BOOT_H__
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_KHEAP_BLOCK_SIZE (512 * 1024UL)
typedef struct ArchMmuInitMapping {
PADDR_T phys;
VADDR_T virt;
size_t size;
unsigned int flags;
const char *name;
} LosArchMmuInitMapping;
extern UINTPTR g_vmBootMemBase;
extern BOOL g_kHeapInited;
UINT32 OsVmAddrCheck(size_t tempAddr, size_t length);
VOID *OsVmBootMemAlloc(size_t len);
UINT32 OsSysMemInit(VOID);
VOID OsInitMappingStartUp(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_BOOT_H__ */
#endif /* ASSEMBLY */

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_map vm common definition
* @ingroup kernel
*/
#ifndef __LOS_VM_COMMON_H__
#define __LOS_VM_COMMON_H__
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* user address space, defaults to below kernel space with a 16MB guard gap on either side */
#ifndef USER_ASPACE_BASE
#define USER_ASPACE_BASE ((vaddr_t)0x01000000UL)
#endif
#ifndef USER_ASPACE_SIZE
#define USER_ASPACE_SIZE ((vaddr_t)KERNEL_ASPACE_BASE - USER_ASPACE_BASE - 0x01000000UL)
#endif
#define USER_ASPACE_TOP_MAX ((vaddr_t)(USER_ASPACE_BASE + USER_ASPACE_SIZE))
#define USER_HEAP_BASE ((vaddr_t)(USER_ASPACE_TOP_MAX >> 2))
#define USER_MAP_BASE ((vaddr_t)(USER_ASPACE_TOP_MAX >> 1))
#define USER_MAP_SIZE ((vaddr_t)(USER_ASPACE_SIZE >> 3))
#ifndef PAGE_SIZE
#define PAGE_SIZE (0x1000U)
#endif
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define PAGE_SHIFT (12)
#define KB (1024UL)
#define MB (1024UL * 1024UL)
#define GB (1024UL * 1024UL * 1024UL)
#define ROUNDUP(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#define ROUNDDOWN(a, b) ((a) & ~((b) - 1))
#define ROUNDOFFSET(a, b) ((a) & ((b) - 1))
#define MIN2(a, b) (((a) < (b)) ? (a) : (b))
#define IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1)))
#define IS_PAGE_ALIGNED(x) IS_ALIGNED(x, PAGE_SIZE)
#define IS_SECTION_ALIGNED(x) IS_ALIGNED(x, SECTION_SIZE)
#define LOS_ERRNO_VM_NO_ERROR (0)
#define LOS_ERRNO_VM_GENERIC (-1)
#define LOS_ERRNO_VM_NOT_FOUND (-2)
#define LOS_ERRNO_VM_NOT_READY (-3)
#define LOS_ERRNO_VM_NO_MSG (-4)
#define LOS_ERRNO_VM_NO_MEMORY (-5)
#define LOS_ERRNO_VM_ALREADY_STARTED (-6)
#define LOS_ERRNO_VM_NOT_VALID (-7)
#define LOS_ERRNO_VM_INVALID_ARGS (-8)
#define LOS_ERRNO_VM_NOT_ENOUGH_BUFFER (-9)
#define LOS_ERRNO_VM_NOT_SUSPENDED (-10)
#define LOS_ERRNO_VM_OBJECT_DESTROYED (-11)
#define LOS_ERRNO_VM_NOT_BLOCKED (-12)
#define LOS_ERRNO_VM_TIMED_OUT (-13)
#define LOS_ERRNO_VM_ALREADY_EXISTS (-14)
#define LOS_ERRNO_VM_CHANNEL_CLOSED (-15)
#define LOS_ERRNO_VM_OFFLINE (-16)
#define LOS_ERRNO_VM_NOT_ALLOWED (-17)
#define LOS_ERRNO_VM_BAD_PATH (-18)
#define LOS_ERRNO_VM_ALREADY_MOUNTED (-19)
#define LOS_ERRNO_VM_IO (-20)
#define LOS_ERRNO_VM_NOT_DIR (-21)
#define LOS_ERRNO_VM_NOT_FILE (-22)
#define LOS_ERRNO_VM_RECURSE_TOO_DEEP (-23)
#define LOS_ERRNO_VM_NOT_SUPPORTED (-24)
#define LOS_ERRNO_VM_TOO_BIG (-25)
#define LOS_ERRNO_VM_CANCELLED (-26)
#define LOS_ERRNO_VM_NOT_IMPLEMENTED (-27)
#define LOS_ERRNO_VM_CHECKSUM_FAIL (-28)
#define LOS_ERRNO_VM_CRC_FAIL (-29)
#define LOS_ERRNO_VM_CMD_UNKNOWN (-30)
#define LOS_ERRNO_VM_BAD_STATE (-31)
#define LOS_ERRNO_VM_BAD_LEN (-32)
#define LOS_ERRNO_VM_BUSY (-33)
#define LOS_ERRNO_VM_THREAD_DETACHED (-34)
#define LOS_ERRNO_VM_I2C_NACK (-35)
#define LOS_ERRNO_VM_ALREADY_EXPIRED (-36)
#define LOS_ERRNO_VM_OUT_OF_RANGE (-37)
#define LOS_ERRNO_VM_NOT_CONFIGURED (-38)
#define LOS_ERRNO_VM_NOT_MOUNTED (-39)
#define LOS_ERRNO_VM_FAULT (-40)
#define LOS_ERRNO_VM_NO_RESOURCES (-41)
#define LOS_ERRNO_VM_BAD_HANDLE (-42)
#define LOS_ERRNO_VM_ACCESS_DENIED (-43)
#define LOS_ERRNO_VM_PARTIAL_WRITE (-44)
#define LOS_ERRNO_VM_LOCK (-45)
#define LOS_ERRNO_VM_MAP_FAILED (-46)
#define VM_ERR(args...) do { \
PRINT_ERR("%s %d ", __FUNCTION__, __LINE__); \
if (PRINT_LEVEL == LOS_DEBUG_LEVEL) { \
PRINTK(args); \
} \
PRINTK("\n"); \
} while (0)
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_COMMON_H__ */

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_dump virtual memory dump operation
* @ingroup kernel
*/
#ifndef __LOS_VM_DUMP_H__
#define __LOS_VM_DUMP_H__
#include "los_vm_map.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**
* These macros is used for process memory usage statistics.
* Include virtual memory, shared memory and physical memory.
*/
#define PROCESS_VM_INDEX_MAX 3
#define PROCESS_MEMINFO_LEN (sizeof(UINT32) * PROCESS_VM_INDEX_MAX)
#define PROCESS_VM_INDEX 0
#define PROCESS_SM_INDEX 1
#define PROCESS_PM_INDEX 2
const CHAR *OsGetRegionNameOrFilePath(LosVmMapRegion *region);
INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region);
UINT32 OsShellCmdProcessVmUsage(LosVmSpace *space);
VOID OsShellCmdProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm);
VOID OsUProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm);
VOID OsKProcessPmUsage(LosVmSpace *kAspace, UINT32 *actualPm);
VOID OsDumpAspace(LosVmSpace *space);
UINT32 OsCountRegionPages(LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages);
UINT32 OsCountAspacePages(LosVmSpace *space);
VOID OsDumpAllAspace(VOID);
VOID OsVmPhysDump(VOID);
VOID OsVmPhysUsedInfoGet(UINT32 *usedCount, UINT32 *totalCount);
INT32 OsRegionOverlapCheck(LosVmSpace *space, LosVmMapRegion *region);
VOID OsDumpPte(VADDR_T vaddr);
LosProcessCB *OsGetPIDByAspace(LosVmSpace *space);
CHAR *OsArchFlagsToStr(const UINT32 archFlags);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_DUMP_H__ */

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_fault vm fault definition
* @ingroup kernel
*/
#ifndef __LOS_VM_FAULT_H__
#define __LOS_VM_FAULT_H__
#include "los_typedef.h"
#include "los_exc.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct {
VADDR_T excAddr;
VADDR_T fixAddr;
} LosExcTable;
#define VM_MAP_PF_FLAG_WRITE (1U << 0)
#define VM_MAP_PF_FLAG_USER (1U << 1)
#define VM_MAP_PF_FLAG_INSTRUCTION (1U << 2)
#define VM_MAP_PF_FLAG_NOT_PRESENT (1U << 3)
STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_FAULT_H__ */

View File

@@ -0,0 +1,214 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_filemap vm filemap definition
* @ingroup kernel
*/
#ifndef __LOS_VM_FILEMAP_H__
#define __LOS_VM_FILEMAP_H__
#include "fs/file.h"
#include "los_vm_map.h"
#include "los_vm_page.h"
#include "los_vm_common.h"
#include "los_vm_phys.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct FilePage {
LOS_DL_LIST node;
LOS_DL_LIST lru;
LOS_DL_LIST i_mmap; /* list of mappings */
UINT32 n_maps; /* num of mapping */
struct VmPhysSeg *physSeg; /* physical memory that file page belongs to */
struct VmPage *vmPage;
struct page_mapping *mapping;
VM_OFFSET_T pgoff;
UINT32 flags;
UINT16 dirtyOff;
UINT16 dirtyEnd;
} LosFilePage;
typedef struct MapInfo {
LOS_DL_LIST node;
VADDR_T vaddr;
LosFilePage *page;
LosArchMmu *archMmu;
} LosMapInfo;
enum OsPageFlags {
FILE_PAGE_FREE,
FILE_PAGE_LOCKED,
FILE_PAGE_REFERENCED,
FILE_PAGE_DIRTY,
FILE_PAGE_LRU,
FILE_PAGE_ACTIVE,
FILE_PAGE_SHARED,
};
#define PGOFF_MAX 2000
#define MAX_SHRINK_PAGECACHE_TRY 2
#define VM_FILEMAP_MAX_SCAN (SYS_MEM_SIZE_DEFAULT >> PAGE_SHIFT)
#define VM_FILEMAP_MIN_SCAN 32
STATIC INLINE VOID OsSetPageLocked(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_LOCKED);
}
STATIC INLINE VOID OsCleanPageLocked(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_LOCKED);
}
STATIC INLINE VOID OsSetPageDirty(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_DIRTY);
}
STATIC INLINE VOID OsCleanPageDirty(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_DIRTY);
}
STATIC INLINE VOID OsSetPageActive(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_ACTIVE);
}
STATIC INLINE VOID OsCleanPageActive(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_ACTIVE);
}
STATIC INLINE VOID OsSetPageLRU(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_LRU);
}
STATIC INLINE VOID OsSetPageFree(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_FREE);
}
STATIC INLINE VOID OsCleanPageFree(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_FREE);
}
STATIC INLINE VOID OsSetPageReferenced(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_REFERENCED);
}
STATIC INLINE VOID OsCleanPageReferenced(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_REFERENCED);
}
STATIC INLINE BOOL OsIsPageActive(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_ACTIVE);
}
STATIC INLINE BOOL OsIsPageLocked(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_LOCKED);
}
STATIC INLINE BOOL OsIsPageReferenced(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_REFERENCED);
}
STATIC INLINE BOOL OsIsPageDirty(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_DIRTY);
}
STATIC INLINE BOOL OsIsPageMapped(LosFilePage *page)
{
return (page->n_maps != 0);
}
/* The follow three functions is used to SHM module */
STATIC INLINE VOID OsSetPageShared(LosVmPage *page)
{
LOS_BitmapSet(&page->flags, FILE_PAGE_SHARED);
}
STATIC INLINE VOID OsCleanPageShared(LosVmPage *page)
{
LOS_BitmapClr(&page->flags, FILE_PAGE_SHARED);
}
STATIC INLINE BOOL OsIsPageShared(LosVmPage *page)
{
return BIT_GET(page->flags, FILE_PAGE_SHARED);
}
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region);
LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff);
LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff);
LosMapInfo *OsGetMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr);
VOID OsAddMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr);
VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *pgFault, BOOL cleanDirty);
VOID OsFileCacheFlush(struct page_mapping *mapping);
VOID OsFileCacheRemove(struct page_mapping *mapping);
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info);
VOID OsUnmapAllLocked(LosFilePage *page);
VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType);
VOID OsLruCacheDel(LosFilePage *fpage);
LosFilePage *OsDumpDirtyPage(LosFilePage *oldPage);
VOID OsDoFlushDirtyPage(LosFilePage *fpage);
VOID OsDeletePageCacheLru(LosFilePage *page);
STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region);
VOID OsPageRefDecNoLock(LosFilePage *page);
VOID OsPageRefIncLocked(LosFilePage *page);
int OsTryShrinkMemory(size_t nPage);
VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, int off, int len);
typedef struct ProcessCB LosProcessCB;
VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_FILEMAP_H__ */

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_VM_IOMAP_H__
#define __LOS_VM_IOMAP_H__
#include "los_typedef.h"
#include "los_vm_zone.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
enum DmaMemType {
DMA_CACHE,
DMA_NOCACHE
};
#define IS_PERIPH_ADDR(addr) ((addr >= PERIPH_PMM_BASE) && (addr <= PERIPH_PMM_BASE + PERIPH_PMM_SIZE))
#define IS_MEMORY_ADDR(addr) ((addr >= DDR_MEM_ADDR) && (addr <= DDR_MEM_ADDR + DDR_MEM_SIZE))
/* thread safety */
VOID *LOS_DmaMemAlloc(DMA_ADDR_T *dmaAddr, size_t size, size_t align, enum DmaMemType type);
VOID LOS_DmaMemFree(VOID *vaddr);
DMA_ADDR_T LOS_DmaVaddrToPaddr(VOID *vaddr);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_IOMAP_H__ */

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_map vm lock operation
* @ingroup kernel
*/
#ifndef __LOS_VM_LOCK_H__
#define __LOS_VM_LOCK_H__
#include "los_mux.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATIC INLINE STATUS_T LOS_MuxAcquire(LosMux *m)
{
return LOS_MuxLock(m, LOS_WAIT_FOREVER);
}
STATIC INLINE STATUS_T LOS_MuxRelease(LosMux *m)
{
return LOS_MuxUnlock(m);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_LOCK_H__ */

314
kernel/base/include/los_vm_map.h Executable file
View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_map vm mapping management
* @ingroup kernel
*/
#ifndef __LOS_VM_MAP_H__
#define __LOS_VM_MAP_H__
#include "los_typedef.h"
#include "los_arch_mmu.h"
#include "los_rbtree.h"
#include "los_vm_syscall.h"
#include "los_vm_zone.h"
#include "los_vm_common.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct VmMapRange {
VADDR_T base; /**< vm region base addr */
UINT32 size; /**< vm region size */
} LosVmMapRange;
struct VmMapRegion;
typedef struct VmMapRegion LosVmMapRegion;
struct VmFileOps;
typedef struct VmFileOps LosVmFileOps;
struct VmSpace;
typedef struct VmSpace LosVmSpace;
typedef struct VmFault {
UINT32 flags; /* FAULT_FLAG_xxx flags */
unsigned long pgoff; /* Logical page offset based on region */
VADDR_T vaddr; /* Faulting virtual address */
VADDR_T *pageKVaddr; /* KVaddr of pagefault's vm page's paddr */
} LosVmPgFault;
struct VmFileOps {
void (*open)(struct VmMapRegion *region);
void (*close)(struct VmMapRegion *region);
int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault);
void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset);
};
struct VmMapRegion {
LosRbNode rbNode; /**< region red-black tree node */
LosVmSpace *space;
LOS_DL_LIST node; /**< region dl list */
LosVmMapRange range; /**< region address range */
VM_OFFSET_T pgOff; /**< region page offset to file */
UINT32 regionFlags; /**< region flags: cow, user_wired */
UINT32 shmid; /**< shmid about shared region */
UINT8 protectFlags; /**< vm region protect flags: PROT_READ, PROT_WRITE, */
UINT8 forkFlags; /**< vm space fork flags: COPY, ZERO, */
UINT8 regionType; /**< vm region type: ANON, FILE, DEV */
union {
struct VmRegionFile {
unsigned int fileMagic;
struct file *file;
const LosVmFileOps *vmFOps;
} rf;
struct VmRegionAnon {
LOS_DL_LIST node; /**< region LosVmPage list */
} ra;
struct VmRegionDev {
LOS_DL_LIST node; /**< region LosVmPage list */
const LosVmFileOps *vmFOps;
} rd;
} unTypeData;
};
typedef struct VmSpace {
LOS_DL_LIST node; /**< vm space dl list */
LOS_DL_LIST regions; /**< region dl list */
LosRbTree regionRbTree; /**< region red-black tree root */
LosMux regionMux; /**< region list mutex lock */
VADDR_T base; /**< vm space base addr */
UINT32 size; /**< vm space size */
VADDR_T heapBase; /**< vm space heap base address */
VADDR_T heapNow; /**< vm space heap base now */
LosVmMapRegion *heap; /**< heap region */
VADDR_T mapBase; /**< vm space mapping area base */
UINT32 mapSize; /**< vm space mapping area size */
LosArchMmu archMmu; /**< vm mapping physical memory */
#ifdef LOSCFG_DRIVERS_TZDRIVER
VADDR_T codeStart; /**< user process code area start */
VADDR_T codeEnd; /**< user process code area end */
#endif
} LosVmSpace;
#define VM_MAP_REGION_TYPE_NONE (0x0)
#define VM_MAP_REGION_TYPE_ANON (0x1)
#define VM_MAP_REGION_TYPE_FILE (0x2)
#define VM_MAP_REGION_TYPE_DEV (0x4)
#define VM_MAP_REGION_TYPE_MASK (0x7)
/* the high 8 bits(24~31) should reserved, shm will use it */
#define VM_MAP_REGION_FLAG_CACHED (0<<0)
#define VM_MAP_REGION_FLAG_UNCACHED (1<<0)
#define VM_MAP_REGION_FLAG_UNCACHED_DEVICE (2<<0) /* only exists on some arches, otherwise UNCACHED */
#define VM_MAP_REGION_FLAG_WRITE_COMBINING (3<<0) /* only exists on some arches, otherwise UNCACHED */
#define VM_MAP_REGION_FLAG_CACHE_MASK (3<<0)
#define VM_MAP_REGION_FLAG_PERM_USER (1<<2)
#define VM_MAP_REGION_FLAG_PERM_READ (1<<3)
#define VM_MAP_REGION_FLAG_PERM_WRITE (1<<4)
#define VM_MAP_REGION_FLAG_PERM_EXECUTE (1<<5)
#define VM_MAP_REGION_FLAG_PROT_MASK (0xF<<2)
#define VM_MAP_REGION_FLAG_NS (1<<6) /* NON-SECURE */
#define VM_MAP_REGION_FLAG_SHARED (1<<7)
#define VM_MAP_REGION_FLAG_PRIVATE (1<<8)
#define VM_MAP_REGION_FLAG_FLAG_MASK (3<<7)
#define VM_MAP_REGION_FLAG_STACK (1<<9)
#define VM_MAP_REGION_FLAG_HEAP (1<<10)
#define VM_MAP_REGION_FLAG_DATA (1<<11)
#define VM_MAP_REGION_FLAG_TEXT (1<<12)
#define VM_MAP_REGION_FLAG_BSS (1<<13)
#define VM_MAP_REGION_FLAG_VDSO (1<<14)
#define VM_MAP_REGION_FLAG_MMAP (1<<15)
#define VM_MAP_REGION_FLAG_SHM (1<<16)
#define VM_MAP_REGION_FLAG_INVALID (1<<17) /* indicates that flags are not specified */
STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
{
UINT32 regionFlags = 0;
regionFlags |= VM_MAP_REGION_FLAG_PERM_USER;
regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0;
regionFlags |= (prot & PROT_WRITE) ? VM_MAP_REGION_FLAG_PERM_WRITE : 0;
regionFlags |= (prot & PROT_EXEC) ? VM_MAP_REGION_FLAG_PERM_EXECUTE : 0;
regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;
regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0;
return regionFlags;
}
STATIC INLINE BOOL LOS_IsKernelAddress(VADDR_T vaddr)
{
return ((vaddr >= (VADDR_T)KERNEL_ASPACE_BASE) &&
(vaddr <= ((VADDR_T)KERNEL_ASPACE_BASE + ((VADDR_T)KERNEL_ASPACE_SIZE - 1))));
}
STATIC INLINE BOOL LOS_IsKernelAddressRange(VADDR_T vaddr, size_t len)
{
return (vaddr + len > vaddr) && LOS_IsKernelAddress(vaddr) && (LOS_IsKernelAddress(vaddr + len - 1));
}
STATIC INLINE VADDR_T LOS_RegionEndAddr(LosVmMapRegion *region)
{
return (region->range.base + region->range.size - 1);
}
STATIC INLINE size_t LOS_RegionSize(VADDR_T start, VADDR_T end)
{
return (end - start + 1);
}
STATIC INLINE BOOL LOS_IsRegionTypeFile(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_FILE;
}
STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region)
{
return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
(VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
}
STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region)
{
return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
}
STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_FILE;
}
STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_DEV;
}
STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_DEV;
}
STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region)
{
return region->regionType == VM_MAP_REGION_TYPE_ANON;
}
STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region)
{
region->regionType = VM_MAP_REGION_TYPE_ANON;
}
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
{
return ((vaddr >= USER_ASPACE_BASE) &&
(vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
}
STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
{
return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
}
STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr)
{
return ((vaddr >= VMALLOC_START) &&
(vaddr <= (VMALLOC_START + (VMALLOC_SIZE - 1))));
}
STATIC INLINE BOOL OsIsVmRegionEmpty(LosVmSpace *vmSpace)
{
if (vmSpace->regionRbTree.ulNodes == 0) {
return TRUE;
}
return FALSE;
}
LosVmSpace *LOS_GetKVmSpace(VOID);
LOS_DL_LIST *LOS_GetVmSpaceList(VOID);
LosVmSpace *LOS_GetVmallocSpace(VOID);
VOID OsInitMappingStartUp(VOID);
VOID OsKSpaceInit(VOID);
BOOL LOS_IsRangeInSpace(const LosVmSpace *space, VADDR_T vaddr, size_t size);
STATUS_T LOS_VmSpaceReserve(LosVmSpace *space, size_t size, VADDR_T vaddr);
LosVmSpace *LOS_GetKVmSpace(VOID);
INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
VADDR_T OsAllocRange(LosVmSpace *vmSpace, size_t len);
VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len);
LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset);
BOOL OsInsertRegion(LosRbTree *regionRbTree, LosVmMapRegion *region);
LosVmSpace *LOS_SpaceGet(VADDR_T vaddr);
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region);
LosVmMapRegion *LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
LosVmMapRegion *LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr);
PADDR_T LOS_PaddrQuery(VOID *vaddr);
LosVmMapRegion *LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff);
STATUS_T OsRegionsRemove(LosVmSpace *space, VADDR_T vaddr, size_t size);
STATUS_T OsVmRegionAdjust(LosVmSpace *space, VADDR_T vaddr, size_t size);
LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size);
STATUS_T OsIsRegionCanExpand(LosVmSpace *space, LosVmMapRegion *region, size_t size);
STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region);
STATUS_T LOS_VmSpaceFree(LosVmSpace *space);
STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, size_t len, UINT32 flags);
BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb);
STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace);
STATUS_T LOS_UserSpaceVmAlloc(LosVmSpace *space, size_t size, VOID **ptr, UINT8 align_log2, UINT32 regionFlags);
LosMux *OsGVmSpaceMuxGet(VOID);
STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size);
/**
* thread safety
* it is used to malloc continuous virtual memory, no sure for continuous physical memory.
*/
VOID *LOS_VMalloc(size_t size);
VOID LOS_VFree(const VOID *addr);
/**
* thread safety
* these is used to malloc or free kernel memory.
* when the size is large and close to multiples of pages,
* will alloc pmm pages, otherwise alloc bestfit memory.
*/
VOID *LOS_KernelMalloc(UINT32 size);
VOID *LOS_KernelMallocAlign(UINT32 size, UINT32 boundary);
VOID *LOS_KernelRealloc(VOID *ptr, UINT32 size);
VOID LOS_KernelFree(VOID *ptr);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_MAP_H__ */

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_VM_PAGE_H__
#define __LOS_VM_PAGE_H__
#include "los_typedef.h"
#include "los_bitmap.h"
#include "los_list.h"
#include "los_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct VmPage {
LOS_DL_LIST node; /**< vm object dl list */
UINT32 index; /**< vm page index to vm object */
PADDR_T physAddr; /**< vm page physical addr */
Atomic refCounts; /**< vm page ref count */
UINT32 flags; /**< vm page flags */
UINT8 order; /**< vm page in which order list */
UINT8 segID; /**< the segment id of vm page */
UINT16 nPages; /**< the vm page is used for kernel heap */
} LosVmPage;
extern LosVmPage *g_vmPageArray;
extern size_t g_vmPageArraySize;
LosVmPage *LOS_VmPageGet(PADDR_T paddr);
VOID OsVmPageStartup(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_PAGE_H__ */

120
kernel/base/include/los_vm_phys.h Executable file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_VM_PHYS_H__
#define __LOS_VM_PHYS_H__
#include "los_typedef.h"
#include "los_list.h"
#include "los_spinlock.h"
#include "los_vm_page.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define VM_LIST_ORDER_MAX 9
#define VM_PHYS_SEG_MAX 32
#ifndef min
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#define VM_PAGE_TO_PHYS(page) (page->physAddr)
#define VM_ORDER_TO_PAGES(order) (1 << (order))
#define VM_ORDER_TO_PHYS(order) (1 << (PAGE_SHIFT + (order)))
#define VM_PHYS_TO_ORDER(phys) (min(LOS_LowBitGet((phys) >> PAGE_SHIFT), VM_LIST_ORDER_MAX - 1))
struct VmFreeList {
LOS_DL_LIST node;
UINT32 listCnt;
};
enum OsLruList {
VM_LRU_INACTIVE_ANON = 0,
VM_LRU_ACTIVE_ANON,
VM_LRU_INACTIVE_FILE,
VM_LRU_ACTIVE_FILE,
VM_LRU_UNEVICTABLE,
VM_NR_LRU_LISTS
};
typedef struct VmPhysSeg {
PADDR_T start; /* The start of physical memory area */
size_t size; /* The size of physical memory area */
LosVmPage *pageBase; /* The first page address of this area */
SPIN_LOCK_S freeListLock; /* The buddy list spinlock */
struct VmFreeList freeList[VM_LIST_ORDER_MAX]; /* The free pages in the buddy list */
SPIN_LOCK_S lruLock;
size_t lruSize[VM_NR_LRU_LISTS];
LOS_DL_LIST lruList[VM_NR_LRU_LISTS];
} LosVmPhysSeg;
struct VmPhysArea {
PADDR_T start;
size_t size;
};
extern struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX];
extern INT32 g_vmPhysSegNum;
UINT32 OsVmPagesToOrder(size_t nPages);
struct VmPhysSeg *OsVmPhysSegGet(LosVmPage *page);
LosVmPhysSeg *OsGVmPhysSegGet(VOID);
VOID *OsVmPageToVaddr(LosVmPage *page);
VOID OsVmPhysSegAdd(VOID);
VOID OsVmPhysInit(VOID);
VOID OsVmPhysAreaSizeAdjust(size_t size);
UINT32 OsVmPhysPageNumGet(VOID);
LosVmPage *OsVmVaddrToPage(VOID *ptr);
VOID OsPhysSharePageCopy(PADDR_T oldPaddr, PADDR_T *newPaddr, LosVmPage *newPage);
VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages);
LosVmPage *OsVmPhysToPage(paddr_t pa, UINT8 segID);
LosVmPage *LOS_PhysPageAlloc(VOID);
VOID LOS_PhysPageFree(LosVmPage *page);
size_t LOS_PhysPagesAlloc(size_t nPages, LOS_DL_LIST *list);
size_t LOS_PhysPagesFree(LOS_DL_LIST *list);
VOID *LOS_PhysPagesAllocContiguous(size_t nPages);
VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages);
VADDR_T *LOS_PaddrToKVaddr(PADDR_T paddr);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_PHYS_H__ */

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOS_SHM_PRI_H__
#define __LOS_SHM_PRI_H__
#include "los_typedef.h"
#include "los_vm_map.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
VOID OsShmFork(LosVmSpace *space, LosVmMapRegion *oldRegion, LosVmMapRegion *newRegion);
VOID OsShmRegionFree(LosVmSpace *space, LosVmMapRegion *region);
BOOL OsIsShmRegion(LosVmMapRegion *region);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_SHM_PRI_H__ */

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_syscall vm syscall definition
* @ingroup kernel
*/
#ifndef __LOS_VM_SYSCALL_H__
#define __LOS_VM_SYSCALL_H__
#include "sys/shm.h"
#include "sys/mman.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATIC INLINE BOOL LOS_IsNamedMapping(unsigned long flags)
{
return ((flags & MAP_ANONYMOUS) == 0);
}
STATIC INLINE BOOL LOS_IsAnonymousMapping(unsigned long flags)
{
return ((flags & MAP_ANONYMOUS) == MAP_ANONYMOUS);
}
VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags, int fd, unsigned long pgoff);
STATUS_T LOS_UnMMap(VADDR_T addr, size_t size);
VOID *LOS_DoBrk(VOID *addr);
int LOS_DoMprotect(VADDR_T vaddr, size_t len, unsigned long prot);
VADDR_T LOS_DoMremap(VADDR_T oldAddress, size_t oldSize, size_t newSize, int flags, VADDR_T newAddr);
VOID LOS_DumpMemRegion(VADDR_T vaddr);
INT32 ShmInit(VOID);
INT32 ShmDeinit(VOID);
INT32 ShmGet(key_t key, size_t size, INT32 shmflg);
VOID *ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg);
INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf);
INT32 ShmDt(const VOID *shmaddr);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __LOS_VM_SYSCALL_H__ */

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __VM_ZONE_H__
#define __VM_ZONE_H__
#include "board.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define DEFINE_(X) X##U
#define DEFINE(X) DEFINE_(X)
#define KERNEL_VMM_BASE DEFINE(KERNEL_VADDR_BASE)
#define KERNEL_VMM_SIZE DEFINE(KERNEL_VADDR_SIZE)
#define KERNEL_ASPACE_BASE KERNEL_VMM_BASE
#define KERNEL_ASPACE_SIZE KERNEL_VMM_SIZE
/* Uncached vmm aspace */
#define UNCACHED_VMM_BASE (KERNEL_VMM_BASE + KERNEL_VMM_SIZE)
#define UNCACHED_VMM_SIZE DDR_MEM_SIZE
#define VMALLOC_START (UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)
#define VMALLOC_SIZE 0x08000000
#define PERIPH_DEVICE_BASE (VMALLOC_START + VMALLOC_SIZE)
#define PERIPH_DEVICE_SIZE PERIPH_PMM_SIZE
#define PERIPH_CACHED_BASE (PERIPH_DEVICE_BASE + PERIPH_DEVICE_SIZE)
#define PERIPH_CACHED_SIZE PERIPH_PMM_SIZE
#define PERIPH_UNCACHED_BASE (PERIPH_CACHED_BASE + PERIPH_CACHED_SIZE)
#define PERIPH_UNCACHED_SIZE PERIPH_PMM_SIZE
#define IO_DEVICE_ADDR(paddr) (paddr - PERIPH_PMM_BASE + PERIPH_DEVICE_BASE)
#define IO_CACHED_ADDR(paddr) (paddr - PERIPH_PMM_BASE + PERIPH_CACHED_BASE)
#define IO_UNCACHED_ADDR(paddr) (paddr - PERIPH_PMM_BASE + PERIPH_UNCACHED_BASE)
#define MEM_CACHED_ADDR(paddr) (paddr - DDR_MEM_ADDR + KERNEL_VMM_BASE)
#define MEM_UNCACHED_ADDR(paddr) (paddr - DDR_MEM_ADDR + UNCACHED_VMM_BASE)
#define VMM_TO_UNCACHED_ADDR(vaddr) (vaddr - KERNEL_VMM_BASE + UNCACHED_VMM_BASE)
#define UNCACHED_TO_VMM_ADDR(vaddr) (vaddr - UNCACHED_VMM_BASE + KERNEL_VMM_BASE)
#define VMM_TO_DMA_ADDR(vaddr) (vaddr - KERNEL_VMM_BASE + SYS_MEM_BASE)
#define DMA_TO_VMM_ADDR(vaddr) (vaddr - SYS_MEM_BASE + KERNEL_VMM_BASE)
#if (PERIPH_UNCACHED_BASE >= (0xFFFFFFFFU - PERIPH_UNCACHED_SIZE))
#error "Kernel virtual memory space has overflowed!"
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif

349
kernel/base/ipc/los_event.c Executable file
View File

@@ -0,0 +1,349 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_event_pri.h"
#include "los_task_pri.h"
#include "los_spinlock.h"
#include "los_mp.h"
#include "los_percpu_pri.h"
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#include "los_exc.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
{
UINT32 intSave;
if (eventCB == NULL) {
return LOS_ERRNO_EVENT_PTR_NULL;
}
intSave = LOS_IntLock();
eventCB->uwEventID = 0;
LOS_ListInit(&eventCB->stEventList);
LOS_IntRestore(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode)
{
if (ptr == NULL) {
return LOS_ERRNO_EVENT_PTR_NULL;
}
if (eventMask == 0) {
return LOS_ERRNO_EVENT_EVENTMASK_INVALID;
}
if (eventMask & LOS_ERRTYPE_ERROR) {
return LOS_ERRNO_EVENT_SETBIT_INVALID;
}
if (((mode & LOS_WAITMODE_OR) && (mode & LOS_WAITMODE_AND)) ||
(mode & ~(LOS_WAITMODE_OR | LOS_WAITMODE_AND | LOS_WAITMODE_CLR)) ||
!(mode & (LOS_WAITMODE_OR | LOS_WAITMODE_AND))) {
return LOS_ERRNO_EVENT_FLAGS_INVALID;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
{
UINT32 ret = 0;
LOS_ASSERT(OsIntLocked());
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
if (mode & LOS_WAITMODE_OR) {
if ((*eventID & eventMask) != 0) {
ret = *eventID & eventMask;
}
} else {
if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {
ret = *eventID & eventMask;
}
}
if (ret && (mode & LOS_WAITMODE_CLR)) {
*eventID = *eventID & ~ret;
}
return ret;
}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
{
UINT32 ret;
LosTaskCB *runTask = NULL;
ret = OsEventParamCheck(eventCB, eventMask, mode);
if (ret != LOS_OK) {
return ret;
}
if (OS_INT_ACTIVE) {
return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;
}
runTask = OsCurrTaskGet();
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
OsBackTrace();
return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
UINT32 timeout, BOOL once)
{
UINT32 ret = 0;
LosTaskCB *runTask = OsCurrTaskGet();
if (once == FALSE) {
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
}
if (ret == 0) {
if (timeout == 0) {
return ret;
}
if (!OsPreemptableInSched()) {
return LOS_ERRNO_EVENT_READ_IN_LOCK;
}
runTask->eventMask = eventMask;
runTask->eventMode = mode;
runTask->taskEvent = eventCB;
ret = OsTaskWait(&eventCB->stEventList, timeout, TRUE);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
runTask->taskEvent = NULL;
return LOS_ERRNO_EVENT_READ_TIMEOUT;
}
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
}
return ret;
}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout,
BOOL once)
{
UINT32 ret;
UINT32 intSave;
ret = OsEventReadCheck(eventCB, eventMask, mode);
if (ret != LOS_OK) {
return ret;
}
SCHEDULER_LOCK(intSave);
ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
{
UINT8 exitFlag = 0;
if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) ||
((resumedTask->eventMode & LOS_WAITMODE_AND) &&
((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {
exitFlag = 1;
resumedTask->taskEvent = NULL;
OsTaskWake(resumedTask);
}
return exitFlag;
}
LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
{
LosTaskCB *resumedTask = NULL;
LosTaskCB *nextTask = NULL;
BOOL schedFlag = FALSE;
eventCB->uwEventID |= events;
if (!LOS_ListEmpty(&eventCB->stEventList)) {
for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);
&resumedTask->pendList != &eventCB->stEventList;) {
nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);
if (OsEventResume(resumedTask, eventCB, events)) {
schedFlag = TRUE;
}
if (once == TRUE) {
break;
}
resumedTask = nextTask;
}
}
if ((exitFlag != NULL) && (schedFlag == TRUE)) {
*exitFlag = 1;
}
}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once)
{
UINT32 intSave;
UINT8 exitFlag = 0;
if (eventCB == NULL) {
return LOS_ERRNO_EVENT_PTR_NULL;
}
if (events & LOS_ERRTYPE_ERROR) {
return LOS_ERRNO_EVENT_SETBIT_INVALID;
}
SCHEDULER_LOCK(intSave);
OsEventWriteUnsafe(eventCB, events, once, &exitFlag);
SCHEDULER_UNLOCK(intSave);
if (exitFlag == 1) {
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
{
UINT32 ret;
UINT32 intSave;
ret = OsEventParamCheck((VOID *)eventID, eventMask, mode);
if (ret != LOS_OK) {
return ret;
}
SCHEDULER_LOCK(intSave);
ret = OsEventPoll(eventID, eventMask, mode);
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
{
return OsEventRead(eventCB, eventMask, mode, timeout, FALSE);
}
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
{
return OsEventWrite(eventCB, events, FALSE);
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
UINT32 timeout)
{
return OsEventRead(eventCB, eventMask, mode, timeout, TRUE);
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events)
{
return OsEventWrite(eventCB, events, TRUE);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
{
UINT32 intSave;
if (eventCB == NULL) {
return LOS_ERRNO_EVENT_PTR_NULL;
}
SCHEDULER_LOCK(intSave);
if (!LOS_ListEmpty(&eventCB->stEventList)) {
SCHEDULER_UNLOCK(intSave);
return LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY;
}
eventCB->uwEventID = 0;
LOS_ListDelInit(&eventCB->stEventList);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events)
{
UINT32 intSave;
if (eventCB == NULL) {
return LOS_ERRNO_EVENT_PTR_NULL;
}
SCHEDULER_LOCK(intSave);
eventCB->uwEventID &= events;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#ifdef LOSCFG_COMPAT_POSIX
LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB,
UINT32 eventMask, UINT32 mode, UINT32 timeout)
{
UINT32 ret;
UINT32 intSave;
ret = OsEventReadCheck(eventCB, eventMask, mode);
if (ret != LOS_OK) {
return ret;
}
SCHEDULER_LOCK(intSave);
if (*cond->realValue != cond->value) {
eventCB->uwEventID &= cond->clearEvent;
goto OUT;
}
ret = OsEventReadImp(eventCB, eventMask, mode, timeout, FALSE);
OUT:
SCHEDULER_UNLOCK(intSave);
return ret;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

944
kernel/base/ipc/los_futex.c Executable file
View File

@@ -0,0 +1,944 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_futex_pri.h"
#include "los_process_pri.h"
#include "los_sys_pri.h"
#include "los_sched_pri.h"
#include "los_mp.h"
#include "los_exc.h"
#include "los_mux_pri.h"
#include "user_copy.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList)
#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList)
#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE
#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE)
typedef struct {
LosMux listLock;
LOS_DL_LIST lockList;
} FutexHash;
#define FUTEX_INDEX_MAX 128
FutexHash g_futexHash[FUTEX_INDEX_MAX];
STATIC INT32 OsFutexLock(LosMux *lock)
{
UINT32 ret = LOS_MuxLock(lock, LOS_WAIT_FOREVER);
if (ret != LOS_OK) {
PRINT_ERR("Futex lock failed! ERROR: 0x%x!\n", ret);
return LOS_EINVAL;
}
return LOS_OK;
}
STATIC INT32 OsFutexUnlock(LosMux *lock)
{
UINT32 ret = LOS_MuxUnlock(lock);
if (ret != LOS_OK) {
PRINT_ERR("Futex unlock failed! ERROR: 0x%x!\n", ret);
return LOS_EINVAL;
}
return LOS_OK;
}
UINT32 OsFutexInit(VOID)
{
INT32 count;
UINT32 ret;
for (count = 0; count < FUTEX_INDEX_MAX; count++) {
LOS_ListInit(&g_futexHash[count].lockList);
ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);
if (ret) {
return ret;
}
}
return LOS_OK;
}
#ifdef LOS_FUTEX_DEBUG
STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
{
FutexNode *tempNode = NULL;
FutexNode *lastNode = NULL;
LosTaskCB *taskCB = NULL;
LOS_DL_LIST *queueList = NULL;
tempNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
PRINTK("key : 0x%x : ->", tempNode->key);
for (queueList = &tempNode->queueList; ;) {
lastNode = OS_FUTEX_FROM_QUEUELIST(queueList);
if (!LOS_ListEmpty(&(lastNode->pendList))) {
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(lastNode->pendList)));
PRINTK(" %d(%d) ->", taskCB->taskID, taskCB->priority);
} else {
taskCB = LOS_DL_LIST_ENTRY(lastNode, LosTaskCB, futex);
PRINTK(" %d(%d) ->", taskCB->taskID, -1);
}
queueList = queueList->pstNext;
if (queueList == &tempNode->queueList) {
break;
}
}
PRINTK("\n");
}
VOID OsFutexHashShow(VOID)
{
LOS_DL_LIST *futexList = NULL;
INT32 count;
/* The maximum number of barrels of a hash table */
INT32 hashNodeMax = FUTEX_INDEX_MAX;
PRINTK("################los_futex_pri.hash ######################\n");
for (count = 0; count < hashNodeMax; count++) {
futexList = &(g_futexHash[count].lockList);
if (LOS_ListEmpty(futexList)) {
continue;
}
PRINTK("hash -> index : %d\n", count);
for (futexList = futexList->pstNext;
futexList != &(g_futexHash[count].lockList);
futexList = futexList->pstNext) {
OsFutexShowTaskNodeAttr(futexList);
}
}
}
#endif
STATIC UINT32 OsFutexGetTick(UINT32 absTime)
{
UINT32 interval;
/* the values not less than per Millisecond */
if (absTime < OS_SYS_MS_PER_SECOND) {
interval = OS_SYS_MS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
} else {
interval = absTime / OS_SYS_MS_PER_SECOND;
}
interval = LOS_MS2Tick(interval);
if (interval == 0) {
interval = 1;
}
return interval;
}
STATIC INLINE VOID OsFutexSetKey(UINTPTR futexKey, FutexNode *node)
{
node->key = futexKey;
node->index = futexKey / OS_FUTEX_KEY_BASE;
node->pid = LOS_GetCurrProcessID();
}
STATIC INLINE VOID OsFutexDeinitFutexNode(FutexNode *node)
{
node->index = OS_INVALID_VALUE;
node->pid = 0;
LOS_ListDelete(&node->queueList);
}
STATIC INLINE VOID OsFutexReplaceQueueListHeadNode(FutexNode *oldHeadNode, FutexNode *newHeadNode)
{
LOS_DL_LIST *futexList = oldHeadNode->futexList.pstPrev;
LOS_ListDelete(&oldHeadNode->futexList);
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);
}
STATIC INLINE VOID OsFutexDeleteKeyFromFutexList(FutexNode *node)
{
LOS_ListDelete(&node->futexList);
}
STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
{
FutexNode *nextNode = NULL;
if (node->index >= FUTEX_INDEX_MAX) {
return;
}
if (LOS_ListEmpty(&node->queueList)) {
OsFutexDeleteKeyFromFutexList(node);
if (queueFlags != NULL) {
*queueFlags = TRUE;
}
goto EXIT;
}
/* FutexList is not NULL, but the header node of queueList */
if (node->futexList.pstNext != NULL) {
if (isDeleteHead == TRUE) {
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList));
OsFutexReplaceQueueListHeadNode(node, nextNode);
if (headNode != NULL) {
*headNode = nextNode;
}
} else {
return;
}
}
EXIT:
OsFutexDeinitFutexNode(node);
return;
}
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
{
FutexHash *hashNode = NULL;
UINT32 index = node->key / OS_FUTEX_KEY_BASE;
if (index >= FUTEX_INDEX_MAX) {
return;
}
hashNode = &g_futexHash[index];
if (OsMuxLockUnsafe(&hashNode->listLock, LOS_WAIT_FOREVER)) {
return;
}
if (node->index != index) {
goto EXIT;
}
OsFutexDeleteKeyNodeFromHash(node, isDeleteHead, headNode, queueFlags);
EXIT:
if (OsMuxUnlockUnsafe(OsCurrTaskGet(), &hashNode->listLock, NULL)) {
return;
}
return;
}
STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead)
{
FutexNode *tempNode = (FutexNode *)node;
FutexNode *nextNode = NULL;
BOOL queueFlag = FALSE;
while (LOS_ListEmpty(&(tempNode->pendList))) { /* already weak */
if (!LOS_ListEmpty(&(tempNode->queueList))) { /* It's not a head node */
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&(tempNode->queueList)));
}
OsFutexDeleteKeyNodeFromHash(tempNode, isDeleteHead, headNode, &queueFlag);
if (queueFlag) {
return NULL;
}
tempNode = nextNode;
}
return tempNode;
}
STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
{
FutexNode *headNode = NULL;
FutexNode *tailNode = NULL;
LOS_DL_LIST *futexList = NULL;
FutexHash *hashNode = &g_futexHash[node->index];
if (LOS_ListEmpty(&hashNode->lockList)) {
LOS_ListHeadInsert(&(hashNode->lockList), &(node->futexList));
goto EXIT;
}
headNode = OS_FUTEX_FROM_FUTEXLIST(LOS_DL_LIST_FIRST(&(hashNode->lockList)));
/* The small key is at the front of the queue */
if (node->key < headNode->key) {
LOS_ListHeadInsert(&(hashNode->lockList), &(node->futexList));
goto EXIT;
}
tailNode = OS_FUTEX_FROM_FUTEXLIST(LOS_DL_LIST_LAST(&(hashNode->lockList)));
if (node->key > tailNode->key) {
LOS_ListTailInsert(&(hashNode->lockList), &(node->futexList));
goto EXIT;
}
for (futexList = hashNode->lockList.pstNext;
futexList != &(hashNode->lockList);
futexList = futexList->pstNext) {
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
if (node->key > headNode->key) {
continue;
} else if (node->key < headNode->key) {
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
break;
}
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
break;
}
EXIT:
return;
}
STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
{
LOS_DL_LIST *listHead = queueList;
LOS_DL_LIST *listTail = queueList->pstPrev;
FutexNode *tempNode = NULL;
LosTaskCB *taskTail = NULL;
for (; listHead != listTail; listTail = listTail->pstPrev) {
tempNode = OS_FUTEX_FROM_QUEUELIST(listTail);
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
if (runTask->priority >= taskTail->priority) {
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
} else if (runTask->priority < taskTail->priority) {
if (listTail->pstPrev == listHead) {
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
}
}
}
return LOS_NOK;
}
STATIC INT32 OsFutexInsertFindFromFrontToBack(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
{
LOS_DL_LIST *listHead = queueList;
LOS_DL_LIST *listTail = queueList->pstPrev;
FutexNode *tempNode = NULL;
LosTaskCB *taskHead = NULL;
for (; listHead != listTail; listHead = listHead->pstNext) {
tempNode = OS_FUTEX_FROM_QUEUELIST(listHead);
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
/* High priority comes before low priority,
* in the case of the same priority, after the current node
*/
if (runTask->priority >= taskHead->priority) {
if (listHead->pstNext == listTail) {
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
}
continue;
} else if (runTask->priority < taskHead->priority) {
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
return LOS_OK;
}
}
return LOS_NOK;
}
STATIC INT32 OsFutexRecycleAndFindHeadNode(FutexNode *headNode, FutexNode *node, FutexNode **firstNode)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
*firstNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(headNode, NULL, TRUE);
SCHEDULER_UNLOCK(intSave);
/* The head node is removed and there was originally only one node under the key */
if (*firstNode == NULL) {
OsFutexInsertNewFutexKeyToHash(node);
LOS_ListInit(&(node->queueList));
return LOS_OK;
}
return LOS_OK;
}
STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node, const LosTaskCB *run)
{
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));
LOS_DL_LIST *queueList = &((*firstNode)->queueList);
FutexNode *tailNode = NULL;
LosTaskCB *taskTail = NULL;
if (run->priority < taskHead->priority) {
/* The one with the highest priority is inserted at the top of the queue */
LOS_ListTailInsert(queueList, &(node->queueList));
OsFutexReplaceQueueListHeadNode(*firstNode, node);
*firstNode = node;
return LOS_OK;
}
if (LOS_ListEmpty(queueList) && (run->priority >= taskHead->priority)) {
/* Insert the next position in the queue with equal priority */
LOS_ListHeadInsert(queueList, &(node->queueList));
return LOS_OK;
}
tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));
if ((run->priority >= taskTail->priority) ||
((run->priority - taskHead->priority) > (taskTail->priority - run->priority))) {
return OsFutexInsertFindFormBackToFront(queueList, run, node);
}
return OsFutexInsertFindFromFrontToBack(queueList, run, node);
}
STATIC FutexNode *OsFindFutexNode(const FutexNode *node)
{
FutexHash *hashNode = &g_futexHash[node->index];
LOS_DL_LIST *futexList = &(hashNode->lockList);
FutexNode *headNode = NULL;
for (futexList = futexList->pstNext;
futexList != &(hashNode->lockList);
futexList = futexList->pstNext) {
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
if ((headNode->key == node->key) && (headNode->pid == node->pid)) {
return headNode;
}
}
return NULL;
}
STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
{
FutexNode *headNode = NULL;
FutexNode *firstNode = NULL;
UINT32 intSave;
INT32 ret;
headNode = OsFindFutexNode(node);
if (headNode == NULL) {
OsFutexInsertNewFutexKeyToHash(node);
LOS_ListInit(&(node->queueList));
return LOS_OK;
}
ret = OsFutexRecycleAndFindHeadNode(headNode, node, &firstNode);
if (ret != LOS_OK) {
return ret;
} else if (firstNode == NULL) {
return ret;
}
SCHEDULER_LOCK(intSave);
ret = OsFutexInsertTasktoPendList(&firstNode, node, OsCurrTaskGet());
SCHEDULER_UNLOCK(intSave);
return ret;
}
STATIC INT32 OsFutexWaitParmaCheck(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
{
UINTPTR futexKey = (UINTPTR)userVaddr;
UINT32 lockVal;
INT32 ret;
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
if (flags) {
PRINT_ERR("Futex wait parma check failed! error flags: 0x%x\n", flags);
return LOS_EINVAL;
}
if ((futexKey % sizeof(INT32)) || (futexKey < OS_FUTEX_KEY_BASE) || (futexKey >= OS_FUTEX_KEY_MAX)) {
PRINT_ERR("Futex wait parma check failed! error futex key: 0x%x\n", futexKey);
return LOS_EINVAL;
}
if (!absTime) {
PRINT_ERR("Futex wait parma check failed! error absTime: %u\n", absTime);
return LOS_EINVAL;
}
ret = LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32));
if (ret) {
PRINT_ERR("Futex wait parma check failed! copy from user failed!\n");
return LOS_EINVAL;
}
if (lockVal != val) {
return LOS_EBADF;
}
return LOS_OK;
}
STATIC INT32 OsFutexDeleteTimeoutTaskNode(FutexHash *hashNode, FutexNode *node)
{
UINT32 intSave;
if (OsFutexLock(&hashNode->listLock)) {
return LOS_EINVAL;
}
if (node->index < FUTEX_INDEX_MAX) {
SCHEDULER_LOCK(intSave);
(VOID)OsFutexDeleteAlreadyWakeTaskAndGetNext(node, NULL, TRUE);
SCHEDULER_UNLOCK(intSave);
}
#ifdef LOS_FUTEX_DEBUG
OsFutexHashShow();
#endif
if (OsFutexUnlock(&hashNode->listLock)) {
return LOS_EINVAL;
}
return LOS_ETIMEDOUT;
}
STATIC INT32 OsFutexInserTaskToHash(LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey)
{
INT32 ret;
*taskCB = OsCurrTaskGet();
*node = &((*taskCB)->futex);
OsFutexSetKey(futexKey, *node);
ret = OsFindAndInsertToHash(*node);
if (ret) {
return LOS_NOK;
}
LOS_ListInit(&((*node)->pendList));
return LOS_OK;
}
STATIC INT32 OsFutexWaitTask(const UINT32 timeOut, const UINT32 *userVaddr)
{
INT32 futexRet;
UINT32 intSave;
LosTaskCB *taskCB = NULL;
FutexNode *node = NULL;
UINTPTR futexKey = (UINTPTR)userVaddr;
UINT32 index = futexKey / OS_FUTEX_KEY_BASE;
FutexHash *hashNode = &g_futexHash[index];
if (OsFutexLock(&hashNode->listLock)) {
return LOS_EINVAL;
}
if (OsFutexInserTaskToHash(&taskCB, &node, futexKey)) {
goto EXIT_ERR;
}
SCHEDULER_LOCK(intSave);
OsTaskWait(&(node->pendList), timeOut, FALSE);
OsPercpuGet()->taskLockCnt++;
LOS_SpinUnlock(&g_taskSpin);
#ifdef LOS_FUTEX_DEBUG
OsFutexHashShow();
#endif
futexRet = OsFutexUnlock(&hashNode->listLock);
if (futexRet) {
OsPercpuGet()->taskLockCnt--;
LOS_IntRestore(intSave);
goto EXIT_UNLOCK_ERR;
}
LOS_SpinLock(&g_taskSpin);
OsPercpuGet()->taskLockCnt--;
/*
* it will immediately do the scheduling, so there's no need to release the
* task spinlock. when this task's been rescheduled, it will be holding the spinlock.
*/
OsSchedResched();
if (taskCB->taskStatus & OS_TASK_STATUS_TIMEOUT) {
taskCB->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
SCHEDULER_UNLOCK(intSave);
return OsFutexDeleteTimeoutTaskNode(hashNode, node);
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
EXIT_ERR:
futexRet = OsFutexUnlock(&hashNode->listLock);
EXIT_UNLOCK_ERR:
if (futexRet) {
return futexRet;
}
return LOS_NOK;
}
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
{
INT32 ret;
UINT32 timeOut = LOS_WAIT_FOREVER;
ret = OsFutexWaitParmaCheck(userVaddr, flags, val, absTime);
if (ret) {
return ret;
}
if (absTime != LOS_WAIT_FOREVER) {
timeOut = OsFutexGetTick(absTime);
}
return OsFutexWaitTask(timeOut, userVaddr);
}
/* Check to see if the task to be awakened has timed out
* if time out, to weak next pend task.
*/
STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNumber,
FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny)
{
INT32 count;
LosTaskCB *taskCB = NULL;
FutexNode *node = headNode;
for (count = 0; count < wakeNumber; count++) {
/* Ensure the integrity of the head */
*nextNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(node, NULL, FALSE);
if (*nextNode == NULL) {
/* The last node in queuelist is invalid or the entire list is invalid */
return;
}
node = *nextNode;
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(node->pendList)));
OsTaskWake(taskCB);
*wakeAny = TRUE;
*nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&(node->queueList)));
if (node != headNode) {
OsFutexDeinitFutexNode(node);
}
if (LOS_ListEmpty(&headNode->queueList)) {
/* Wakes up the entire linked list node */
*nextNode = NULL;
return;
}
node = *nextNode;
}
return;
}
STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny)
{
UINT32 intSave;
FutexNode *node = NULL;
FutexNode *headNode = NULL;
UINT32 index = futexKey / OS_FUTEX_KEY_BASE;
FutexHash *hashNode = &g_futexHash[index];
FutexNode tempNode = {
.key = futexKey,
.index = index,
.pid = LOS_GetCurrProcessID(),
};
node = OsFindFutexNode(&tempNode);
if (node == NULL) {
return LOS_EBADF;
}
headNode = node;
SCHEDULER_LOCK(intSave);
OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny);
if ((*newHeadNode) != NULL) {
OsFutexReplaceQueueListHeadNode(headNode, *newHeadNode);
OsFutexDeinitFutexNode(headNode);
} else if (headNode->index < FUTEX_INDEX_MAX) {
OsFutexDeleteKeyFromFutexList(headNode);
OsFutexDeinitFutexNode(headNode);
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
{
INT32 ret, futexRet;
UINTPTR futexKey = (UINTPTR)userVaddr;
FutexHash *hashNode = NULL;
INT32 index = futexKey / OS_FUTEX_KEY_BASE;
FutexNode *headNode = NULL;
BOOL wakeAny = FALSE;
if (!(flags & FUTEX_WAKE)) {
PRINT_ERR("Futex wake param check failed! error flags: 0x%x\n", flags);
return LOS_EINVAL;
}
if ((futexKey % sizeof(INT32)) || (futexKey < OS_FUTEX_KEY_BASE) || (futexKey >= OS_FUTEX_KEY_MAX)) {
PRINT_ERR("Futex wake param check failed! error futex key: 0x%x\n", futexKey);
return LOS_EINVAL;
}
hashNode = &g_futexHash[index];
if (OsFutexLock(&hashNode->listLock)) {
return LOS_EINVAL;
}
ret = OsFutexWakeTask(futexKey, wakeNumber, &headNode, &wakeAny);
if (ret) {
goto EXIT_ERR;
}
#ifdef LOS_FUTEX_DEBUG
OsFutexHashShow();
#endif
futexRet = OsFutexUnlock(&hashNode->listLock);
if (futexRet) {
goto EXIT_UNLOCK_ERR;
}
if (wakeAny == TRUE) {
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
return LOS_OK;
EXIT_ERR:
futexRet = OsFutexUnlock(&hashNode->listLock);
EXIT_UNLOCK_ERR:
if (futexRet) {
return futexRet;
}
return ret;
}
STATIC INT32 OsFutexRequeueInsertNewKey(UINTPTR newFutexKey, INT32 newIndex, FutexNode *oldHeadNode)
{
INT32 ret;
UINT32 intSave;
LosTaskCB *task = NULL;
FutexNode *nextNode = NULL;
FutexNode newTempNode = {
.key = newFutexKey,
.index = newIndex,
.pid = LOS_GetCurrProcessID(),
};
LOS_DL_LIST *queueList = &oldHeadNode->queueList;
FutexNode *newHeadNode = OsFindFutexNode(&newTempNode);
if (newHeadNode == NULL) {
OsFutexInsertNewFutexKeyToHash(oldHeadNode);
return LOS_OK;
}
do {
nextNode = OS_FUTEX_FROM_QUEUELIST(queueList);
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&nextNode->pendList)) {
queueList = queueList->pstNext;
OsFutexDeinitFutexNode(nextNode);
SCHEDULER_UNLOCK(intSave);
if (queueList->pstNext != NULL) {
continue;
} else {
return LOS_OK;
}
}
task = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(nextNode->pendList)));
queueList = queueList->pstNext;
LOS_ListDelete(&nextNode->queueList);
ret = OsFutexInsertTasktoPendList(&newHeadNode, nextNode, task);
SCHEDULER_UNLOCK(intSave);
if (ret != LOS_OK) {
PRINT_ERR("Futex requeue insert new key failed!\n");
}
} while (queueList->pstNext != NULL);
return LOS_OK;
}
STATIC VOID OsFutexRequeueSplitTwoLists(FutexHash *oldHashNode, FutexNode *oldHeadNode, UINTPTR futexKey, INT32 count)
{
LOS_DL_LIST *queueList = &oldHeadNode->queueList;
FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));
INT32 newIndex = futexKey / OS_FUTEX_KEY_BASE;
FutexNode *nextNode = NULL;
FutexNode *newHeadNode = NULL;
LOS_DL_LIST *futexList = NULL;
BOOL IsAll = FALSE;
INT32 i;
for (i = 0; i < count; i++) {
nextNode = OS_FUTEX_FROM_QUEUELIST(queueList);
nextNode->key = futexKey;
nextNode->index = newIndex;
if (queueList->pstNext == &oldHeadNode->queueList) {
IsAll = TRUE;
break;
}
queueList = queueList->pstNext;
}
futexList = oldHeadNode->futexList.pstPrev;
LOS_ListDelete(&oldHeadNode->futexList);
if (IsAll == TRUE) {
return;
}
newHeadNode = OS_FUTEX_FROM_QUEUELIST(queueList);
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);
oldHeadNode->queueList.pstPrev = &nextNode->queueList;
nextNode->queueList.pstNext = &oldHeadNode->queueList;
newHeadNode->queueList.pstPrev = &tailNode->queueList;
tailNode->queueList.pstNext = &newHeadNode->queueList;
return;
}
STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, INT32 wakeNumber,
UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny)
{
INT32 ret;
FutexNode *oldHeadNode = NULL;
INT32 oldIndex = oldFutexKey / OS_FUTEX_KEY_BASE;
FutexHash *oldHashNode = &g_futexHash[oldIndex];
FutexNode oldTempNode = {
.key = oldFutexKey,
.index = oldIndex,
.pid = LOS_GetCurrProcessID(),
};
if (wakeNumber > 0) {
ret = OsFutexWakeTask(oldFutexKey, wakeNumber, &oldHeadNode, wakeAny);
if ((ret != LOS_OK) || (oldHeadNode == NULL)) {
return NULL;
}
}
if (requeueCount <= 0) {
return NULL;
}
if (oldHeadNode == NULL) {
oldHeadNode = OsFindFutexNode(&oldTempNode);
if (oldHeadNode == NULL) {
return NULL;
}
}
OsFutexRequeueSplitTwoLists(oldHashNode, oldHeadNode, newFutexKey, requeueCount);
return oldHeadNode;
}
STATIC INT32 OsFutexRequeueParamCheck(UINTPTR oldFutexKey, UINTPTR newFutexKey)
{
if (oldFutexKey == newFutexKey) {
return LOS_EINVAL;
}
if ((oldFutexKey % sizeof(INT32)) || (oldFutexKey < OS_FUTEX_KEY_BASE) || (oldFutexKey >= OS_FUTEX_KEY_MAX)) {
PRINT_ERR("Futex requeue param check failed! error old futex key: 0x%x\n", oldFutexKey);
return LOS_EINVAL;
}
if ((newFutexKey % sizeof(INT32)) || (newFutexKey < OS_FUTEX_KEY_BASE) || (newFutexKey >= OS_FUTEX_KEY_MAX)) {
PRINT_ERR("Futex requeue param check failed! error new futex key: 0x%x\n", newFutexKey);
return LOS_EINVAL;
}
return LOS_OK;
}
INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr)
{
INT32 ret;
UINTPTR oldFutexKey = (UINTPTR)userVaddr;
UINTPTR newFutexKey = (UINTPTR)newUserVaddr;
INT32 oldIndex = oldFutexKey / OS_FUTEX_KEY_BASE;
INT32 newIndex = newFutexKey / OS_FUTEX_KEY_BASE;
FutexHash *oldHashNode = NULL;
FutexHash *newHashNode = NULL;
FutexNode *oldHeadNode = NULL;
BOOL wakeAny = FALSE;
if (OsFutexRequeueParamCheck(oldFutexKey, newFutexKey)) {
return LOS_EINVAL;
}
oldHashNode = &g_futexHash[oldIndex];
if (OsFutexLock(&oldHashNode->listLock)) {
return LOS_EINVAL;
}
oldHeadNode = OsFutexRequeueRemoveOldKeyAndGetHead(oldFutexKey, wakeNumber, newFutexKey, count, &wakeAny);
if (oldHeadNode == NULL) {
(VOID)OsFutexUnlock(&oldHashNode->listLock);
if (wakeAny == TRUE) {
ret = LOS_OK;
goto EXIT;
}
return LOS_EBADF;
}
newHashNode = &g_futexHash[newIndex];
if (oldIndex != newIndex) {
if (OsFutexUnlock(&oldHashNode->listLock)) {
return LOS_EINVAL;
}
if (OsFutexLock(&newHashNode->listLock)) {
return LOS_EINVAL;
}
}
ret = OsFutexRequeueInsertNewKey(newFutexKey, newIndex, oldHeadNode);
if (OsFutexUnlock(&newHashNode->listLock)) {
return LOS_EINVAL;
}
EXIT:
if (wakeAny == TRUE) {
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
return ret;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

90
kernel/base/ipc/los_ipcdebug.c Executable file
View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_ipcdebug_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_DEBUG_QUEUE)
VOID OsArraySortByTime(UINT32 *sortArray, UINT32 start, UINT32 end, const IpcSortParam *sortParam,
OsCompareFunc compareFunc)
{
UINT32 left = start;
UINT32 right = end;
UINT32 idx = start;
UINT32 pivot = sortArray[start];
while (left < right) {
while ((left < right) && (sortArray[right] < sortParam->ipcDebugCBCnt) && (pivot < sortParam->ipcDebugCBCnt) &&
compareFunc(sortParam, sortArray[right], pivot)) {
right--;
}
if (left < right) {
sortArray[left] = sortArray[right];
idx = right;
left++;
}
while ((left < right) && (sortArray[left] < sortParam->ipcDebugCBCnt) && (pivot < sortParam->ipcDebugCBCnt) &&
compareFunc(sortParam, pivot, sortArray[left])) {
left++;
}
if (left < right) {
sortArray[right] = sortArray[left];
idx = left;
right--;
}
}
sortArray[idx] = pivot;
if (start < idx) {
OsArraySortByTime(sortArray, start, idx - 1, sortParam, compareFunc);
}
if (idx < end) {
OsArraySortByTime(sortArray, idx + 1, end, sortParam, compareFunc);
}
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

612
kernel/base/ipc/los_mux.c Executable file
View File

@@ -0,0 +1,612 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_pri.h"
#include "los_bitmap.h"
#include "los_spinlock.h"
#include "los_mp.h"
#include "los_task_pri.h"
#include "los_exc.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#if (LOSCFG_BASE_IPC_MUX == YES)
#define MUTEXATTR_TYPE_MASK 0x0FU
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrInit(LosMuxAttr *attr)
{
if (attr == NULL) {
return LOS_EINVAL;
}
attr->protocol = LOS_MUX_PRIO_INHERIT;
attr->prioceiling = OS_TASK_PRIORITY_LOWEST;
attr->type = LOS_MUX_DEFAULT;
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy(LosMuxAttr *attr)
{
if (attr == NULL) {
return LOS_EINVAL;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType(const LosMuxAttr *attr, INT32 *outType)
{
INT32 type;
if ((attr == NULL) || (outType == NULL)) {
return LOS_EINVAL;
}
type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK);
if ((type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
return LOS_EINVAL;
}
*outType = type;
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType(LosMuxAttr *attr, INT32 type)
{
if ((attr == NULL) || (type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
return LOS_EINVAL;
}
attr->type = (UINT8)((attr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol(const LosMuxAttr *attr, INT32 *protocol)
{
if ((attr != NULL) && (protocol != NULL)) {
*protocol = attr->protocol;
} else {
return LOS_EINVAL;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol(LosMuxAttr *attr, INT32 protocol)
{
if (attr == NULL) {
return LOS_EINVAL;
}
switch (protocol) {
case LOS_MUX_PRIO_NONE:
case LOS_MUX_PRIO_INHERIT:
case LOS_MUX_PRIO_PROTECT:
attr->protocol = (UINT8)protocol;
return LOS_OK;
default:
return LOS_EINVAL;
}
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling(const LosMuxAttr *attr, INT32 *prioceiling)
{
if (attr == NULL) {
return LOS_EINVAL;
}
if (prioceiling != NULL) {
*prioceiling = attr->prioceiling;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioceiling)
{
if ((attr == NULL) ||
(prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
(prioceiling > OS_TASK_PRIORITY_LOWEST)) {
return LOS_EINVAL;
}
attr->prioceiling = (UINT8)prioceiling;
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling(LosMux *mutex, INT32 prioceiling, INT32 *oldPrioceiling)
{
INT32 ret;
INT32 retLock;
if ((mutex == NULL) ||
(prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
(prioceiling > OS_TASK_PRIORITY_LOWEST)) {
return LOS_EINVAL;
}
retLock = LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
if (retLock != LOS_OK) {
return retLock;
}
if (oldPrioceiling != NULL) {
*oldPrioceiling = mutex->attr.prioceiling;
}
ret = LOS_MuxAttrSetPrioceiling(&mutex->attr, prioceiling);
retLock = LOS_MuxUnlock(mutex);
if ((ret == LOS_OK) && (retLock != LOS_OK)) {
return retLock;
}
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling(const LosMux *mutex, INT32 *prioceiling)
{
if ((mutex != NULL) && (prioceiling != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
*prioceiling = mutex->attr.prioceiling;
return LOS_OK;
}
return LOS_EINVAL;
}
LITE_OS_SEC_TEXT BOOL LOS_MuxIsValid(const LosMux *mutex)
{
if ((mutex != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
return TRUE;
}
return FALSE;
}
STATIC UINT32 OsCheckMutexAttr(const LosMuxAttr *attr)
{
if (((INT8)(attr->type) < LOS_MUX_NORMAL) || (attr->type > LOS_MUX_ERRORCHECK)) {
return LOS_NOK;
}
if (((INT8)(attr->prioceiling) < OS_TASK_PRIORITY_HIGHEST) || (attr->prioceiling > OS_TASK_PRIORITY_LOWEST)) {
return LOS_NOK;
}
if (((INT8)(attr->protocol) < LOS_MUX_PRIO_NONE) || (attr->protocol > LOS_MUX_PRIO_PROTECT)) {
return LOS_NOK;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
{
UINT32 intSave;
if (mutex == NULL) {
return LOS_EINVAL;
}
if (attr == NULL) {
(VOID)LOS_MuxAttrInit(&mutex->attr);
} else {
(VOID)memcpy_s(&mutex->attr, sizeof(LosMuxAttr), attr, sizeof(LosMuxAttr));
}
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
return LOS_EINVAL;
}
SCHEDULER_LOCK(intSave);
mutex->muxCount = 0;
mutex->owner = NULL;
LOS_ListInit(&mutex->muxList);
mutex->magic = OS_MUX_MAGIC;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
{
UINT32 intSave;
if (mutex == NULL) {
return LOS_EINVAL;
}
SCHEDULER_LOCK(intSave);
if (mutex->magic != OS_MUX_MAGIC) {
SCHEDULER_UNLOCK(intSave);
return LOS_EBADF;
}
if (mutex->muxCount != 0) {
SCHEDULER_UNLOCK(intSave);
return LOS_EBUSY;
}
(VOID)memset_s(mutex, sizeof(LosMux), 0, sizeof(LosMux));
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask, LosTaskCB *owner)
{
if ((owner->priority > runTask->priority) && (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT)) {
LOS_BitmapSet(&(owner->priBitMap), owner->priority);
OsTaskPriModify(owner, runTask->priority);
}
}
VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner)
{
UINT16 bitMapPri;
if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
return;
}
if (owner->priority >= taskCB->priority) {
bitMapPri = LOS_LowBitGet(owner->priBitMap);
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&(owner->priBitMap), bitMapPri);
OsTaskPriModify(owner, bitMapPri);
}
} else {
if (LOS_HighBitGet(owner->priBitMap) != taskCB->priority) {
LOS_BitmapClr(&(owner->priBitMap), taskCB->priority);
}
}
}
STATIC LOS_DL_LIST *OsMuxPendFindPosSub(const LosTaskCB *runTask, const LosMux *mutex)
{
LosTaskCB *pendedTask = NULL;
LOS_DL_LIST *node = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, &(mutex->muxList), LosTaskCB, pendList) {
if (pendedTask->priority < runTask->priority) {
continue;
} else if (pendedTask->priority > runTask->priority) {
node = &pendedTask->pendList;
break;
} else {
node = pendedTask->pendList.pstNext;
break;
}
}
return node;
}
STATIC LOS_DL_LIST *OsMuxPendFindPos(const LosTaskCB *runTask, LosMux *mutex)
{
LosTaskCB *pendedTask1 = NULL;
LosTaskCB *pendedTask2 = NULL;
LOS_DL_LIST *node = NULL;
if (LOS_ListEmpty(&mutex->muxList)) {
node = &mutex->muxList;
} else {
pendedTask1 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&mutex->muxList));
pendedTask2 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_LAST(&mutex->muxList));
if ((pendedTask1 != NULL) && (pendedTask1->priority > runTask->priority)) {
node = mutex->muxList.pstNext;
} else if ((pendedTask2 != NULL) && (pendedTask2->priority <= runTask->priority)) {
node = &mutex->muxList;
} else {
node = OsMuxPendFindPosSub(runTask, mutex);
}
}
return node;
}
STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
{
UINT32 ret;
LOS_DL_LIST *node = NULL;
LosTaskCB *owner = NULL;
if ((mutex->muxList.pstPrev == NULL) || (mutex->muxList.pstNext == NULL)) {
/* This is for mutex macro initialization. */
mutex->muxCount = 0;
mutex->owner = NULL;
LOS_ListInit(&mutex->muxList);
}
if (mutex->muxCount == 0) {
mutex->muxCount++;
mutex->owner = (VOID *)runTask;
LOS_ListTailInsert(&runTask->lockList, &mutex->holdList);
if ((runTask->priority > mutex->attr.prioceiling) && (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT)) {
LOS_BitmapSet(&runTask->priBitMap, runTask->priority);
OsTaskPriModify(runTask, mutex->attr.prioceiling);
}
return LOS_OK;
}
if (((LosTaskCB *)mutex->owner == runTask) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
mutex->muxCount++;
return LOS_OK;
}
if (!timeout) {
return LOS_EINVAL;
}
if (!OsPreemptableInSched()) {
return LOS_EDEADLK;
}
OsMuxBitmapSet(mutex, runTask, (LosTaskCB *)mutex->owner);
owner = (LosTaskCB *)mutex->owner;
runTask->taskMux = (VOID *)mutex;
node = OsMuxPendFindPos(runTask, mutex);
ret = OsTaskWait(node, timeout, TRUE);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
runTask->taskMux = NULL;
ret = LOS_ETIMEDOUT;
}
if (timeout != LOS_WAIT_FOREVER) {
OsMuxBitmapRestore(mutex, runTask, owner);
}
return ret;
}
UINT32 OsMuxLockUnsafe(LosMux *mutex, UINT32 timeout)
{
LosTaskCB *runTask = OsCurrTaskGet();
if (mutex->magic != OS_MUX_MAGIC) {
return LOS_EBADF;
}
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
return LOS_EINVAL;
}
if ((mutex->attr.type == LOS_MUX_ERRORCHECK) && (mutex->muxCount != 0) && (mutex->owner == (VOID *)runTask)) {
return LOS_EDEADLK;
}
return OsMuxPendOp(runTask, mutex, timeout);
}
UINT32 OsMuxTrylockUnsafe(LosMux *mutex, UINT32 timeout)
{
LosTaskCB *runTask = OsCurrTaskGet();
if (mutex->magic != OS_MUX_MAGIC) {
return LOS_EBADF;
}
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
return LOS_EINVAL;
}
if ((mutex->owner != NULL) && ((LosTaskCB *)mutex->owner != runTask)) {
return LOS_EBUSY;
}
if ((mutex->attr.type != LOS_MUX_RECURSIVE) && (mutex->muxCount != 0)) {
return LOS_EBUSY;
}
return OsMuxPendOp(runTask, mutex, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
{
LosTaskCB *runTask = NULL;
UINT32 intSave;
UINT32 ret;
if (mutex == NULL) {
return LOS_EINVAL;
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
runTask = (LosTaskCB *)OsCurrTaskGet();
/* DO NOT Call blocking API in system tasks */
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
OsBackTrace();
}
SCHEDULER_LOCK(intSave);
ret = OsMuxLockUnsafe(mutex, timeout);
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxTrylock(LosMux *mutex)
{
LosTaskCB *runTask = NULL;
UINT32 intSave;
UINT32 ret;
if (mutex == NULL) {
return LOS_EINVAL;
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
runTask = (LosTaskCB *)OsCurrTaskGet();
/* DO NOT Call blocking API in system tasks */
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
OsBackTrace();
}
SCHEDULER_LOCK(intSave);
ret = OsMuxTrylockUnsafe(mutex, 0);
SCHEDULER_UNLOCK(intSave);
return ret;
}
STATIC VOID OsMuxPostOpSub(LosTaskCB *taskCB, LosMux *mutex)
{
LosTaskCB *pendedTask = NULL;
UINT16 bitMapPri;
if (!LOS_ListEmpty(&mutex->muxList)) {
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, (&mutex->muxList), LosTaskCB, pendList) {
if (bitMapPri != pendedTask->priority) {
LOS_BitmapClr(&taskCB->priBitMap, pendedTask->priority);
}
}
}
bitMapPri = LOS_LowBitGet(taskCB->priBitMap);
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);
OsTaskPriModify((LosTaskCB *)mutex->owner, bitMapPri);
}
STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
LosTaskCB *resumedTask = NULL;
if (LOS_ListEmpty(&mutex->muxList)) {
LOS_ListDelete(&mutex->holdList);
mutex->owner = NULL;
return LOS_OK;
}
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));
if (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT) {
if (resumedTask->priority > taskCB->priority) {
if (LOS_HighBitGet(taskCB->priBitMap) != resumedTask->priority) {
LOS_BitmapClr(&taskCB->priBitMap, resumedTask->priority);
}
} else if (taskCB->priBitMap != 0) {
OsMuxPostOpSub(taskCB, mutex);
}
}
mutex->muxCount = 1;
mutex->owner = (VOID *)resumedTask;
resumedTask->taskMux = NULL;
LOS_ListDelete(&mutex->holdList);
LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);
OsTaskWake(resumedTask);
if (needSched != NULL) {
*needSched = TRUE;
}
return LOS_OK;
}
UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
UINT16 bitMapPri;
if (mutex->magic != OS_MUX_MAGIC) {
return LOS_EBADF;
}
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
return LOS_EINVAL;
}
if (mutex->muxCount == 0) {
return LOS_EPERM;
}
if ((LosTaskCB *)mutex->owner != taskCB) {
return LOS_EPERM;
}
if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
return LOS_OK;
}
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);
OsTaskPriModify(taskCB, bitMapPri);
}
}
/* Whether a task block the mutex lock. */
return OsMuxPostOp(taskCB, mutex, needSched);
}
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
{
LosTaskCB *runTask = NULL;
BOOL needSched = FALSE;
UINT32 intSave;
UINT32 ret;
if (mutex == NULL) {
return LOS_EINVAL;
}
if (OS_INT_ACTIVE) {
return LOS_EINTR;
}
runTask = (LosTaskCB *)OsCurrTaskGet();
/* DO NOT Call blocking API in system tasks */
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
OsBackTrace();
}
SCHEDULER_LOCK(intSave);
ret = OsMuxUnlockUnsafe(runTask, mutex, &needSched);
SCHEDULER_UNLOCK(intSave);
if (needSched == TRUE) {
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
return ret;
}
#endif /* (LOSCFG_BASE_IPC_MUX == YES) */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

504
kernel/base/ipc/los_queue.c Executable file
View File

@@ -0,0 +1,504 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_pri.h"
#include "los_queue_debug_pri.h"
#include "los_task_pri.h"
#include "los_spinlock.h"
#include "los_mp.h"
#include "los_percpu_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#if (LOSCFG_BASE_IPC_QUEUE == YES)
#if (LOSCFG_BASE_IPC_QUEUE_LIMIT <= 0)
#error "queue maxnum cannot be zero"
#endif /* LOSCFG_BASE_IPC_QUEUE_LIMIT <= 0 */
LITE_OS_SEC_BSS LosQueueCB *g_allQueue = NULL;
LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_freeQueueList;
/*
* Description : queue initial
* Return : LOS_OK on success or error code on failure
*/
LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID)
{
LosQueueCB *queueNode = NULL;
UINT32 index;
UINT32 size;
size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB);
/* system resident memory, don't free */
g_allQueue = (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_allQueue == NULL) {
return LOS_ERRNO_QUEUE_NO_MEMORY;
}
(VOID)memset_s(g_allQueue, size, 0, size);
LOS_ListInit(&g_freeQueueList);
for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
queueNode = ((LosQueueCB *)g_allQueue) + index;
queueNode->queueID = index;
LOS_ListTailInsert(&g_freeQueueList, &queueNode->readWriteList[OS_QUEUE_WRITE]);
}
if (OsQueueDbgInitHook() != LOS_OK) {
return LOS_ERRNO_QUEUE_NO_MEMORY;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName, UINT16 len, UINT32 *queueID,
UINT32 flags, UINT16 maxMsgSize)
{
LosQueueCB *queueCB = NULL;
UINT32 intSave;
LOS_DL_LIST *unusedQueue = NULL;
UINT8 *queue = NULL;
UINT16 msgSize;
(VOID)queueName;
(VOID)flags;
if (queueID == NULL) {
return LOS_ERRNO_QUEUE_CREAT_PTR_NULL;
}
if (maxMsgSize > (OS_NULL_SHORT - sizeof(UINT32))) {
return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;
}
if ((len == 0) || (maxMsgSize == 0)) {
return LOS_ERRNO_QUEUE_PARA_ISZERO;
}
msgSize = maxMsgSize + sizeof(UINT32);
/*
* Memory allocation is time-consuming, to shorten the time of disable interrupt,
* move the memory allocation to here.
*/
queue = (UINT8 *)LOS_MemAlloc(m_aucSysMem1, (UINT32)len * msgSize);
if (queue == NULL) {
return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
}
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&g_freeQueueList)) {
SCHEDULER_UNLOCK(intSave);
OsQueueCheckHook();
(VOID)LOS_MemFree(m_aucSysMem1, queue);
return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
}
unusedQueue = LOS_DL_LIST_FIRST(&g_freeQueueList);
LOS_ListDelete(unusedQueue);
queueCB = GET_QUEUE_LIST(unusedQueue);
queueCB->queueLen = len;
queueCB->queueSize = msgSize;
queueCB->queueHandle = queue;
queueCB->queueState = OS_QUEUE_INUSED;
queueCB->readWriteableCnt[OS_QUEUE_READ] = 0;
queueCB->readWriteableCnt[OS_QUEUE_WRITE] = len;
queueCB->queueHead = 0;
queueCB->queueTail = 0;
LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_READ]);
LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_WRITE]);
LOS_ListInit(&queueCB->memList);
OsQueueDbgUpdateHook(queueCB->queueID, OsCurrTaskGet()->taskEntry);
SCHEDULER_UNLOCK(intSave);
*queueID = queueCB->queueID;
return LOS_OK;
}
STATIC LITE_OS_SEC_TEXT UINT32 OsQueueReadParameterCheck(UINT32 queueID, const VOID *bufferAddr,
const UINT32 *bufferSize, UINT32 timeout)
{
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
return LOS_ERRNO_QUEUE_INVALID;
}
if ((bufferAddr == NULL) || (bufferSize == NULL)) {
return LOS_ERRNO_QUEUE_READ_PTR_NULL;
}
if ((*bufferSize == 0) || (*bufferSize > (OS_NULL_SHORT - sizeof(UINT32)))) {
return LOS_ERRNO_QUEUE_READSIZE_IS_INVALID;
}
OsQueueDbgTimeUpdateHook(queueID);
if (timeout != LOS_NO_WAIT) {
if (OS_INT_ACTIVE) {
return LOS_ERRNO_QUEUE_READ_IN_INTERRUPT;
}
}
return LOS_OK;
}
STATIC LITE_OS_SEC_TEXT UINT32 OsQueueWriteParameterCheck(UINT32 queueID, const VOID *bufferAddr,
const UINT32 *bufferSize, UINT32 timeout)
{
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
return LOS_ERRNO_QUEUE_INVALID;
}
if (bufferAddr == NULL) {
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
}
if (*bufferSize == 0) {
return LOS_ERRNO_QUEUE_WRITESIZE_ISZERO;
}
OsQueueDbgTimeUpdateHook(queueID);
if (timeout != LOS_NO_WAIT) {
if (OS_INT_ACTIVE) {
return LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT;
}
}
return LOS_OK;
}
STATIC VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize)
{
UINT8 *queueNode = NULL;
UINT32 msgDataSize;
UINT16 queuePosion;
/* get the queue position */
switch (OS_QUEUE_OPERATE_GET(operateType)) {
case OS_QUEUE_READ_HEAD:
queuePosion = queueCB->queueHead;
((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
break;
case OS_QUEUE_WRITE_HEAD:
(queueCB->queueHead == 0) ? (queueCB->queueHead = queueCB->queueLen - 1) : (--queueCB->queueHead);
queuePosion = queueCB->queueHead;
break;
case OS_QUEUE_WRITE_TAIL:
queuePosion = queueCB->queueTail;
((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
break;
default: /* read tail, reserved. */
PRINT_ERR("invalid queue operate type!\n");
return;
}
queueNode = &(queueCB->queueHandle[(queuePosion * (queueCB->queueSize))]);
if (OS_QUEUE_IS_READ(operateType)) {
if (memcpy_s(&msgDataSize, sizeof(UINT32), queueNode + queueCB->queueSize - sizeof(UINT32),
sizeof(UINT32)) != EOK) {
PRINT_ERR("get msgdatasize failed\n");
return;
}
if (memcpy_s(bufferAddr, *bufferSize, queueNode, msgDataSize) != EOK) {
PRINT_ERR("copy message to buffer failed\n");
return;
}
*bufferSize = msgDataSize;
} else {
if (memcpy_s(queueNode, queueCB->queueSize, bufferAddr, *bufferSize) != EOK) {
PRINT_ERR("store message failed\n");
return;
}
if (memcpy_s(queueNode + queueCB->queueSize - sizeof(UINT32), sizeof(UINT32), bufferSize,
sizeof(UINT32)) != EOK) {
PRINT_ERR("store message size failed\n");
return;
}
}
}
STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueID,
UINT32 operateType, const UINT32 *bufferSize)
{
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
return LOS_ERRNO_QUEUE_NOT_CREATE;
}
if (OS_QUEUE_IS_READ(operateType) && (*bufferSize < (queueCB->queueSize - sizeof(UINT32)))) {
return LOS_ERRNO_QUEUE_READ_SIZE_TOO_SMALL;
} else if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {
return LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;
}
return LOS_OK;
}
UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout)
{
LosQueueCB *queueCB = NULL;
LosTaskCB *resumedTask = NULL;
UINT32 ret;
UINT32 readWrite = OS_QUEUE_READ_WRITE_GET(operateType);
UINT32 intSave;
SCHEDULER_LOCK(intSave);
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
ret = OsQueueOperateParamCheck(queueCB, queueID, operateType, bufferSize);
if (ret != LOS_OK) {
goto QUEUE_END;
}
if (queueCB->readWriteableCnt[readWrite] == 0) {
if (timeout == LOS_NO_WAIT) {
ret = OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;
goto QUEUE_END;
}
if (!OsPreemptableInSched()) {
ret = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
goto QUEUE_END;
}
ret = OsTaskWait(&queueCB->readWriteList[readWrite], timeout, TRUE);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
ret = LOS_ERRNO_QUEUE_TIMEOUT;
goto QUEUE_END;
}
} else {
queueCB->readWriteableCnt[readWrite]--;
}
OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);
if (!LOS_ListEmpty(&queueCB->readWriteList[!readWrite])) {
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[!readWrite]));
OsTaskWake(resumedTask);
SCHEDULER_UNLOCK(intSave);
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
return LOS_OK;
} else {
queueCB->readWriteableCnt[!readWrite]++;
}
QUEUE_END:
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID,
VOID *bufferAddr,
UINT32 *bufferSize,
UINT32 timeout)
{
UINT32 ret;
UINT32 operateType;
ret = OsQueueReadParameterCheck(queueID, bufferAddr, bufferSize, timeout);
if (ret != LOS_OK) {
return ret;
}
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD);
return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueID,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout)
{
UINT32 ret;
UINT32 operateType;
ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeout);
if (ret != LOS_OK) {
return ret;
}
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_HEAD);
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueID,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout)
{
UINT32 ret;
UINT32 operateType;
ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeout);
if (ret != LOS_OK) {
return ret;
}
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL);
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout)
{
return LOS_QueueReadCopy(queueID, bufferAddr, &bufferSize, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout)
{
if (bufferAddr == NULL) {
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
}
bufferSize = sizeof(CHAR *);
return LOS_QueueWriteCopy(queueID, &bufferAddr, bufferSize, timeout);
}
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueID,
VOID *bufferAddr,
UINT32 bufferSize,
UINT32 timeout)
{
if (bufferAddr == NULL) {
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
}
bufferSize = sizeof(CHAR *);
return LOS_QueueWriteHeadCopy(queueID, &bufferAddr, bufferSize, timeout);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
{
LosQueueCB *queueCB = NULL;
UINT8 *queue = NULL;
UINT32 intSave;
UINT32 ret;
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
return LOS_ERRNO_QUEUE_NOT_FOUND;
}
SCHEDULER_LOCK(intSave);
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
ret = LOS_ERRNO_QUEUE_NOT_CREATE;
goto QUEUE_END;
}
if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_READ])) {
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_WRITE])) {
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
if (!LOS_ListEmpty(&queueCB->memList)) {
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
if ((queueCB->readWriteableCnt[OS_QUEUE_WRITE] + queueCB->readWriteableCnt[OS_QUEUE_READ]) !=
queueCB->queueLen) {
ret = LOS_ERRNO_QUEUE_IN_TSKWRITE;
goto QUEUE_END;
}
queue = queueCB->queueHandle;
queueCB->queueHandle = NULL;
queueCB->queueState = OS_QUEUE_UNUSED;
queueCB->queueID = SET_QUEUE_ID(GET_QUEUE_COUNT(queueCB->queueID) + 1, GET_QUEUE_INDEX(queueCB->queueID));
OsQueueDbgUpdateHook(queueCB->queueID, NULL);
LOS_ListTailInsert(&g_freeQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
SCHEDULER_UNLOCK(intSave);
ret = LOS_MemFree(m_aucSysMem1, (VOID *)queue);
return ret;
QUEUE_END:
SCHEDULER_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)
{
UINT32 intSave;
UINT32 ret = LOS_OK;
LosQueueCB *queueCB = NULL;
LosTaskCB *tskCB = NULL;
if (queueInfo == NULL) {
return LOS_ERRNO_QUEUE_PTR_NULL;
}
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
return LOS_ERRNO_QUEUE_INVALID;
}
(VOID)memset_s((VOID *)queueInfo, sizeof(QUEUE_INFO_S), 0, sizeof(QUEUE_INFO_S));
SCHEDULER_LOCK(intSave);
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
ret = LOS_ERRNO_QUEUE_NOT_CREATE;
goto QUEUE_END;
}
queueInfo->uwQueueID = queueID;
queueInfo->usQueueLen = queueCB->queueLen;
queueInfo->usQueueSize = queueCB->queueSize;
queueInfo->usQueueHead = queueCB->queueHead;
queueInfo->usQueueTail = queueCB->queueTail;
queueInfo->usReadableCnt = queueCB->readWriteableCnt[OS_QUEUE_READ];
queueInfo->usWritableCnt = queueCB->readWriteableCnt[OS_QUEUE_WRITE];
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_READ], LosTaskCB, pendList) {
queueInfo->uwWaitReadTask |= 1ULL << tskCB->taskID;
}
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_WRITE], LosTaskCB, pendList) {
queueInfo->uwWaitWriteTask |= 1ULL << tskCB->taskID;
}
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->memList, LosTaskCB, pendList) {
queueInfo->uwWaitMemTask |= 1ULL << tskCB->taskID;
}
QUEUE_END:
SCHEDULER_UNLOCK(intSave);
return ret;
}
#endif /* (LOSCFG_BASE_IPC_QUEUE == YES) */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

208
kernel/base/ipc/los_queue_debug.c Executable file
View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_hw_pri.h"
#include "los_ipcdebug_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 creater; /* The task entry who created this queue */
UINT64 lastAccessTime; /* The last access time */
} QueueDebugCB;
STATIC QueueDebugCB *g_queueDebugArray = NULL;
STATIC BOOL QueueCompareValue(const IpcSortParam *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->creater = 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 creater:0x%p, Latest operation time: 0x%llx\n",
node->creater, node->lastAccessTime);
}
STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count)
{
LosQueueCB queueNode = {0};
QueueDebugCB queueDebugNode = {0};
UINT32 index, intSave;
IpcSortParam queueSortParam;
queueSortParam.buf = (CHAR *)g_queueDebugArray;
queueSortParam.ipcDebugCBSize = sizeof(QueueDebugCB);
queueSortParam.ipcDebugCBCnt = LOSCFG_BASE_IPC_SEM_LIMIT;
queueSortParam.sortElemOff = OFFSET_OF_FIELD(QueueDebugCB, lastAccessTime);
if (count > 0) {
SCHEDULER_LOCK(intSave);
OsArraySortByTime(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 == OS_QUEUE_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 == OS_QUEUE_UNUSED) ||
((queueNode.queueState == OS_QUEUE_INUSED) && (queueDebugNode.creater == NULL))) {
continue;
}
if ((queueNode.queueState == OS_QUEUE_INUSED) &&
(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_CMD_DEBUG
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 */

298
kernel/base/ipc/los_sem.c Executable file
View File

@@ -0,0 +1,298 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_pri.h"
#include "los_sem_debug_pri.h"
#include "los_err_pri.h"
#include "los_task_pri.h"
#include "los_exc.h"
#include "los_spinlock.h"
#include "los_mp.h"
#include "los_percpu_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#if (LOSCFG_BASE_IPC_SEM == YES)
#if (LOSCFG_BASE_IPC_SEM_LIMIT <= 0)
#error "sem maxnum cannot be zero"
#endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList;
LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;
/*
* Description : Initialize the semaphore doubly linked list
* Return : LOS_OK on success, or error code on failure
*/
LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)
{
LosSemCB *semNode = NULL;
UINT32 index;
LOS_ListInit(&g_unusedSemList);
/* system resident memory, don't free */
g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));
if (g_allSem == NULL) {
return LOS_ERRNO_SEM_NO_MEMORY;
}
for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) {
semNode = ((LosSemCB *)g_allSem) + index;
semNode->semID = SET_SEM_ID(0, index);
semNode->semStat = OS_SEM_UNUSED;
LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);
}
if (OsSemDbgInitHook() != LOS_OK) {
return LOS_ERRNO_SEM_NO_MEMORY;
}
return LOS_OK;
}
/*
* Description : Create a semaphore,
* Input : count --- semaphore count,
* maxCount --- Max number of available semaphores,
* semHandle --- Index of semaphore,
* Return : LOS_OK on success ,or error code on failure
*/
LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle)
{
UINT32 intSave;
LosSemCB *semCreated = NULL;
LOS_DL_LIST *unusedSem = NULL;
UINT32 errNo;
UINT32 errLine;
if (semHandle == NULL) {
return LOS_ERRNO_SEM_PTR_NULL;
}
if (count > maxCount) {
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW);
}
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&g_unusedSemList)) {
SCHEDULER_UNLOCK(intSave);
OsSemInfoGetFullDataHook();
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY);
}
unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList);
LOS_ListDelete(unusedSem);
semCreated = GET_SEM_LIST(unusedSem);
semCreated->semCount = count;
semCreated->semStat = OS_SEM_USED;
semCreated->maxSemCount = maxCount;
LOS_ListInit(&semCreated->semList);
*semHandle = semCreated->semID;
OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
ERR_HANDLER:
OS_RETURN_ERROR_P2(errLine, errNo);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle)
{
return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle)
{
return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
{
UINT32 intSave;
LosSemCB *semDeleted = NULL;
UINT32 errNo;
UINT32 errLine;
if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
}
semDeleted = GET_SEM(semHandle);
SCHEDULER_LOCK(intSave);
if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {
SCHEDULER_UNLOCK(intSave);
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
}
if (!LOS_ListEmpty(&semDeleted->semList)) {
SCHEDULER_UNLOCK(intSave);
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);
}
LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);
semDeleted->semStat = OS_SEM_UNUSED;
semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));
OsSemDbgUpdateHook(semDeleted->semID, NULL, 0);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
ERR_HANDLER:
OS_RETURN_ERROR_P2(errLine, errNo);
}
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
{
UINT32 intSave;
LosSemCB *semPended = GET_SEM(semHandle);
UINT32 retErr = LOS_OK;
LosTaskCB *runTask = NULL;
if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
}
if (OS_INT_ACTIVE) {
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n");
OsBackTrace();
return LOS_ERRNO_SEM_PEND_INTERR;
}
runTask = OsCurrTaskGet();
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
OsBackTrace();
return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK;
}
SCHEDULER_LOCK(intSave);
if ((semPended->semStat == OS_SEM_UNUSED) || (semPended->semID != semHandle)) {
retErr = LOS_ERRNO_SEM_INVALID;
goto OUT;
}
/* Update the operate time, no matter the actual Pend success or not */
OsSemDbgTimeUpdateHook(semHandle);
if (semPended->semCount > 0) {
semPended->semCount--;
goto OUT;
} else if (!timeout) {
retErr = LOS_ERRNO_SEM_UNAVAILABLE;
goto OUT;
}
if (!OsPreemptableInSched()) {
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n");
OsBackTrace();
retErr = LOS_ERRNO_SEM_PEND_IN_LOCK;
goto OUT;
}
runTask->taskSem = (VOID *)semPended;
retErr = OsTaskWait(&semPended->semList, timeout, TRUE);
if (retErr == LOS_ERRNO_TSK_TIMEOUT) {
runTask->taskSem = NULL;
retErr = LOS_ERRNO_SEM_TIMEOUT;
}
OUT:
SCHEDULER_UNLOCK(intSave);
return retErr;
}
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
{
LosSemCB *semPosted = NULL;
LosTaskCB *resumedTask = NULL;
if (GET_SEM_INDEX(semHandle) >= LOSCFG_BASE_IPC_SEM_LIMIT) {
return LOS_ERRNO_SEM_INVALID;
}
semPosted = GET_SEM(semHandle);
if ((semPosted->semID != semHandle) || (semPosted->semStat == OS_SEM_UNUSED)) {
return LOS_ERRNO_SEM_INVALID;
}
/* Update the operate time, no matter the actual Post success or not */
OsSemDbgTimeUpdateHook(semHandle);
if (semPosted->semCount == OS_SEM_COUNT_MAX) {
return LOS_ERRNO_SEM_OVERFLOW;
}
if (!LOS_ListEmpty(&semPosted->semList)) {
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));
resumedTask->taskSem = NULL;
OsTaskWake(resumedTask);
if (needSched != NULL) {
*needSched = TRUE;
}
} else {
semPosted->semCount++;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
{
UINT32 intSave;
UINT32 ret;
BOOL needSched = FALSE;
SCHEDULER_LOCK(intSave);
ret = OsSemPostUnsafe(semHandle, &needSched);
SCHEDULER_UNLOCK(intSave);
if (needSched) {
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
return ret;
}
#endif /* (LOSCFG_BASE_IPC_SEM == YES) */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

311
kernel/base/ipc/los_sem_debug.c Executable file
View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_ipcdebug_pri.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define OS_ALL_SEM_MASK 0xffffffff
#if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_SHELL_CMD_DEBUG)
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 == OS_SEM_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");
}
#endif
#ifdef LOSCFG_DEBUG_SEMAPHORE
typedef struct {
UINT16 origSemCount; /* Number of orignal available semaphores */
UINT64 lastAccessTime; /* The last operation time */
TSK_ENTRY_FUNC creater; /* The task entry who created this sem */
} SemDebugCB;
STATIC SemDebugCB *g_semDebugArray = NULL;
STATIC BOOL SemCompareValue(const IpcSortParam *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 creater, UINT16 count)
{
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semID)];
semDebug->creater = creater;
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};
IpcSortParam semSortParam;
semSortParam.buf = (CHAR *)g_semDebugArray;
semSortParam.ipcDebugCBSize = sizeof(SemDebugCB);
semSortParam.ipcDebugCBCnt = LOSCFG_BASE_IPC_SEM_LIMIT;
semSortParam.sortElemOff = OFFSET_OF_FIELD(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);
OsArraySortByTime(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 != OS_SEM_USED) || (semDebug.creater == NULL)) {
continue;
}
PRINTK(" 0x%-07x0x%-07u0x%-14u%-22p0x%llx\n", semNode.semID, semDebug.origSemCount,
semNode.semCount, semDebug.creater, 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 == OS_SEM_USED) && (semDebug->creater != 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 != OS_SEM_USED) || (semDebug->creater == 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;
}
#endif /* LOSCFG_DEBUG_SEMAPHORE */
#ifdef LOSCFG_SHELL_CMD_DEBUG
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 == OS_SEM_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 {
if (GET_SEM_INDEX(semID) >= LOSCFG_BASE_IPC_SEM_LIMIT) {
PRINTK("\nInvalid semphore id!\n");
return LOS_OK;
}
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 != OS_SEM_USED)) {
PRINTK("\nThe semphore 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 semphore!\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) {
#ifdef LOSCFG_DEBUG_SEMAPHORE
PRINTK("\nUsage: sem [fulldata|ID]\n");
#else
PRINTK("\nUsage: sem [ID]\n");
#endif
return OS_ERROR;
}
if (argc == 0) {
semID = OS_ALL_SEM_MASK;
} else {
#ifdef LOSCFG_DEBUG_SEMAPHORE
if (strcmp(argv[0], "fulldata") == 0) {
ret = OsSemInfoGetFullData();
return ret;
}
#endif
semID = strtoul(argv[0], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0)) {
PRINTK("\nsem ID can't access %s.\n", argv[0]);
return 0;
}
}
ret = OsSemInfoOutput(semID);
return ret;
}
SHELLCMD_ENTRY(sem_shellcmd, CMD_TYPE_EX, "sem", 1, (CmdCallBackFunc)OsShellCmdSemInfoGet);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

691
kernel/base/ipc/los_signal.c Executable file
View File

@@ -0,0 +1,691 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_signal.h"
#include "pthread.h"
#include "los_process_pri.h"
#include "los_hw_pri.h"
#include "user_copy.h"
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_api.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int raise(int sig)
{
(VOID)sig;
PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
errno = ENOSYS;
return -1;
}
#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
#define UINT64_BIT_SIZE 64
int OsSigIsMember(const sigset_t *set, int signo)
{
int ret = LOS_NOK;
/* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
signo -= 1;
/* Verify the signal */
if (GOOD_SIGNO(signo)) {
/* Check if the signal is in the set */
ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);
}
return ret;
}
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
{
bool masked = FALSE;
sig_cb *sigcb = &stcb->sig;
OS_RETURN_IF_NULL(sigcb);
/* If signo is 0, not send signal, just check process or pthread exist */
if (info->si_signo == 0) {
return 0;
}
masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);
if (masked) {
/* If signal is in wait list and mask list, need unblock it */
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) {
OsTaskWake(stcb);
OsSigEmptySet(&sigcb->sigwaitmask);
} else {
OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);
}
} else {
/* unmasked signal actions */
OsSigAddSet(&sigcb->sigFlag, info->si_signo);
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) {
OsTaskWake(stcb);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
(void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t));
return 0;
}
void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
{
sigset_t unmaskset;
rtcb->sig.sigprocmask = set;
unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);
if (unmaskset != NULL_SIGNAL_SET) {
/* pendlist do */
rtcb->sig.sigFlag |= unmaskset;
rtcb->sig.sigPendFlag ^= unmaskset;
}
}
int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset)
{
LosTaskCB *spcb = NULL;
sigset_t oldSigprocmask;
int ret = LOS_OK;
unsigned int intSave;
sigset_t set;
int retVal;
if (setl != NULL) {
retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t));
if (retVal != 0) {
return -EFAULT;
}
}
SCHEDULER_LOCK(intSave);
spcb = OsCurrTaskGet();
/* If requested, copy the old mask to user. */
oldSigprocmask = spcb->sig.sigprocmask;
/* If requested, modify the current signal mask. */
if (setl != NULL) {
/* Okay, determine what we are supposed to do */
switch (how) {
/* Set the union of the current set and the signal
* set pointed to by set as the new sigprocmask.
*/
case SIG_BLOCK:
spcb->sig.sigprocmask |= set;
break;
/* Set the intersection of the current set and the
* signal set pointed to by set as the new sigprocmask.
*/
case SIG_UNBLOCK:
spcb->sig.sigprocmask &= ~(set);
break;
/* Set the signal set pointed to by set as the new sigprocmask. */
case SIG_SETMASK:
spcb->sig.sigprocmask = set;
break;
default:
ret = -EINVAL;
break;
}
/* If pending mask not in sigmask, need set sigflag. */
OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);
}
SCHEDULER_UNLOCK(intSave);
if (oldset != NULL) {
retVal = LOS_ArchCopyToUser(&(oldset->sig[0]), &oldSigprocmask, sizeof(sigset_t));
if (retVal != 0) {
return -EFAULT;
}
}
return ret;
}
int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
{
int ret;
/* Visit the main thread last (if present) */
LosTaskCB *taskCB = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {
ret = handler(taskCB, arg);
OS_RETURN_IF(ret != 0, ret);
}
return LOS_OK;
}
static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
{
struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
int ret;
int isMember;
if (tcb == NULL) {
return 0;
}
/* If the default tcb is not setted, then set this one as default. */
if (!info->defaultTcb) {
info->defaultTcb = tcb;
}
isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);
if (isMember && (!info->awakenedTcb)) {
/* This means the task is waiting for this signal. Stop looking for it and use this tcb.
* The requirement is: if more than one task in this task group is waiting for the signal,
* then only one indeterminate task in the group will receive the signal.
*/
ret = OsTcbDispatch(tcb, info->sigInfo);
OS_RETURN_IF(ret < 0, ret);
/* set this tcb as awakenedTcb */
info->awakenedTcb = tcb;
OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
}
/* Is this signal unblocked on this thread? */
isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);
if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {
/* if unblockedTcb of this signal is not setted, then set it. */
if (!info->unblockedTcb) {
info->unblockedTcb = tcb;
}
ret = OsTcbDispatch(tcb, info->sigInfo);
OS_RETURN_IF(ret < 0, ret);
/* set this tcb as receivedTcb */
info->receivedTcb = tcb;
OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
}
return 0; /* Keep searching */
}
static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
{
struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
if ((tcb != NULL) && (info != NULL) && (info->sigInfo != NULL)) {
sig_cb *sigcb = &tcb->sig;
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->sigInfo->si_signo)) {
OsTaskWake(tcb);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
return 0;
}
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
{
LosTaskCB *tcb = NULL;
if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {
if (info->unblockedTcb) {
tcb = info->unblockedTcb;
} else if (info->defaultTcb) {
tcb = info->defaultTcb;
} else {
return;
}
/* Deliver the signal to the selected task */
(void)OsTcbDispatch(tcb, sigInfo);
}
}
int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
{
int ret;
struct ProcessSignalInfo info = {
.sigInfo = sigInfo,
.defaultTcb = NULL,
.unblockedTcb = NULL,
.awakenedTcb = NULL,
.receivedTcb = NULL
};
/* visit all taskcb and dispatch signal */
if ((info.sigInfo != NULL) && (info.sigInfo->si_signo == SIGKILL)) {
(void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);
OsWaitSignalToWakeProcess(spcb);
return 0;
} else {
ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);
}
if (ret < 0) {
return ret;
}
SigProcessLoadTcb(&info, sigInfo);
return 0;
}
int OsSigEmptySet(sigset_t *set)
{
*set = NULL_SIGNAL_SET;
return 0;
}
/* Privilege process can't send to kernel and privilege process */
static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
{
UINT32 gid = spcb->group->groupID;
if (gid == OS_KERNEL_PROCESS_GROUP) {
return -EPERM;
} else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {
return -EPERM;
}
return 0;
}
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
{
LosProcessCB *spcb = OS_PCB_FROM_PID(pid);
if (OsProcessIsUnused(spcb)) {
return -ESRCH;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
LosProcessCB *current = OsCurrProcessGet();
/* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
if (OsProcessIsInactive(spcb)) {
return LOS_OK;
}
/* Kernel process always has kill permission and user process should check permission */
if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {
if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
return -EPERM;
}
}
#endif
if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
return -EPERM;
}
return OsSigProcessSend(spcb, info);
}
int OsKill(pid_t pid, int sig, int permission)
{
siginfo_t info;
int ret;
/* Make sure that the para is valid */
if (!GOOD_SIGNO(sig) || pid < 0) {
return -EINVAL;
}
if (OsProcessIDUserCheckInvalid(pid)) {
return -ESRCH;
}
/* Create the siginfo structure */
info.si_signo = sig;
info.si_code = SI_USER;
info.si_value.sival_ptr = NULL;
/* Send the signal */
ret = OsDispatch(pid, &info, permission);
return ret;
}
int OsKillLock(pid_t pid, int sig)
{
int ret;
unsigned int intSave;
SCHEDULER_LOCK(intSave);
ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);
SCHEDULER_UNLOCK(intSave);
return ret;
}
int OsPthreadKill(UINT32 tid, int signo)
{
LosTaskCB *stcb = NULL;
siginfo_t info;
int ret;
UINT32 intSave;
/* Make sure that the signal is valid */
OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
if (OS_TID_CHECK_INVALID(tid)) {
return -ESRCH;
}
/* Create the siginfo structure */
info.si_signo = signo;
info.si_code = SI_USER;
info.si_value.sival_ptr = NULL;
/* Keep things stationary through the following */
SCHEDULER_LOCK(intSave);
/* Get the TCB associated with the thread */
stcb = OsGetTaskCB(tid);
OS_GOTO_EXIT_IF(stcb == NULL, -ESRCH);
ret = OsUserTaskOperatePermissionsCheck(stcb);
OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
/* Dispatch the signal to thread, bypassing normal task group thread
* dispatch rules. */
ret = OsTcbDispatch(stcb, &info);
EXIT:
SCHEDULER_UNLOCK(intSave);
return ret;
}
int OsSigAddSet(sigset_t *set, int signo)
{
/* Verify the signal */
if (!GOOD_SIGNO(signo)) {
return -EINVAL;
} else {
/* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
signo -= 1;
/* Add the signal to the set */
*set |= SIGNO2SET((unsigned int)signo);
return LOS_OK;
}
}
int OsSigPending(sigset_t *set)
{
LosTaskCB *tcb = NULL;
unsigned int intSave;
if (set == NULL) {
return -EFAULT;
}
SCHEDULER_LOCK(intSave);
tcb = OsCurrTaskGet();
*set = tcb->sig.sigPendFlag;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
STATIC int FindFirstSetedBit(UINT64 n)
{
int count;
if (n == 0) {
return -1;
}
for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
return (count < UINT64_BIT_SIZE) ? count : (-1);
}
int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
{
LosTaskCB *task = NULL;
sig_cb *sigcb = NULL;
int ret;
task = OsCurrTaskGet();
sigcb = &task->sig;
if (sigcb->waitList.pstNext == NULL) {
LOS_ListInit(&sigcb->waitList);
}
/* If pendingflag & set > 0, shound clear pending flag */
sigset_t clear = sigcb->sigPendFlag & *set;
if (clear) {
sigcb->sigPendFlag ^= clear;
ret = FindFirstSetedBit((UINT64)clear) + 1;
} else {
OsSigAddSet(set, SIGKILL);
OsSigAddSet(set, SIGSTOP);
sigcb->sigwaitmask |= *set;
ret = OsTaskWait(&sigcb->waitList, timeout, TRUE);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
ret = -EAGAIN;
}
sigcb->sigwaitmask = NULL_SIGNAL_SET;
}
if (info != NULL) {
(void) memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
}
return ret;
}
int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
{
int ret;
unsigned int intSave;
SCHEDULER_LOCK(intSave);
ret = OsSigTimedWaitNoLock(set, info, timeout);
SCHEDULER_UNLOCK(intSave);
return ret;
}
int OsPause(void)
{
LosTaskCB *spcb = NULL;
sigset_t oldSigprocmask;
spcb = OsCurrTaskGet();
oldSigprocmask = spcb->sig.sigprocmask;
return OsSigSuspend(&oldSigprocmask);
}
int OsSigSuspend(const sigset_t *set)
{
unsigned int intSave;
LosTaskCB *rtcb = NULL;
unsigned int sigTempProcMask;
sigset_t setSuspend;
int ret;
if (set == NULL) {
return -EINVAL;
}
SCHEDULER_LOCK(intSave);
rtcb = OsCurrTaskGet();
sigTempProcMask = rtcb->sig.sigprocmask;
/* Wait signal calc */
setSuspend = FULL_SIGNAL_SET & (~(*set));
/* If pending mask not in sigmask, need set sigflag */
OsSigMaskSwitch(rtcb, *set);
ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
if (ret < 0) {
PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
}
/* Restore old sigprocmask */
OsSigMaskSwitch(rtcb, sigTempProcMask);
SCHEDULER_UNLOCK(intSave);
return -EINTR;
}
int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
{
UINTPTR addr;
sigaction_t action;
if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
return -EINVAL;
}
if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
return -EFAULT;
}
if (sig == SIGSYS) {
addr = OsGetSigHandler();
if (addr == 0) {
OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);
return LOS_OK;
}
return -EINVAL;
}
return LOS_OK;
}
void OsSaveSignalContext(unsigned int *sp)
{
UINTPTR sigHandler;
UINT32 intSave;
LosTaskCB *task = NULL;
LosProcessCB *process = NULL;
sig_cb *sigcb = NULL;
unsigned long cpsr;
OS_RETURN_IF_VOID(sp == NULL);
cpsr = OS_SYSCALL_GET_CPSR(sp);
OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));
SCHEDULER_LOCK(intSave);
task = OsCurrTaskGet();
process = OsCurrProcessGet();
sigcb = &task->sig;
if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
sigHandler = OsGetSigHandler();
if (sigHandler == 0) {
sigcb->sigFlag = 0;
process->sigShare = 0;
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
return;
}
/* One pthread do the share signal */
sigcb->sigFlag |= process->sigShare;
unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1;
OsProcessExitCodeSignalSet(process, signo);
sigcb->context.CPSR = cpsr;
sigcb->context.PC = sp[REG_PC];
sigcb->context.USP = sp[REG_SP];
sigcb->context.ULR = sp[REG_LR];
sigcb->context.R0 = sp[REG_R0];
sigcb->context.R1 = sp[REG_R1];
sigcb->context.R2 = sp[REG_R2];
sigcb->context.R3 = sp[REG_R3];
sigcb->context.R7 = sp[REG_R7];
sigcb->context.R12 = sp[REG_R12];
sp[REG_PC] = sigHandler;
sp[REG_R0] = signo;
sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
/* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
sigcb->sigFlag ^= 1ULL << (signo - 1);
sigcb->context.count++;
}
SCHEDULER_UNLOCK(intSave);
}
void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7)
{
UINTPTR sigHandler;
LosTaskCB *task = NULL;
LosProcessCB *process = NULL;
sig_cb *sigcb = NULL;
unsigned long cpsr;
UINT32 intSave;
TaskIrqContext *context = (TaskIrqContext *)(sp);
OS_RETURN_IF_VOID(sp == NULL);
cpsr = context->CPSR;
OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));
SCHEDULER_LOCK(intSave);
task = OsCurrTaskGet();
process = OsCurrProcessGet();
sigcb = &task->sig;
if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
sigHandler = OsGetSigHandler();
if (sigHandler == 0) {
sigcb->sigFlag = 0;
process->sigShare = 0;
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("The current process pid =%d starts fail!\n", task->processID);
return;
}
sigcb->sigFlag |= process->sigShare;
unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1;
OsProcessExitCodeSignalSet(process, signo);
(VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize));
sigcb->context.R7 = r7;
context->PC = sigHandler;
context->R0 = signo;
context->R1 = (UINT32)(UINTPTR)sigcb->sigunbinfo.si_value.sival_ptr;
/* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
sigcb->sigFlag ^= 1ULL << (signo - 1);
sigcb->context.count++;
}
SCHEDULER_UNLOCK(intSave);
}
void OsRestorSignalContext(unsigned int *sp)
{
LosTaskCB *task = NULL; /* Do not adjust this statement */
LosProcessCB *process = NULL;
sig_cb *sigcb = NULL;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
task = OsCurrTaskGet();
sigcb = &task->sig;
if (sigcb->context.count != 1) {
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("sig error count : %d\n", sigcb->context.count);
return;
}
process = OsCurrProcessGet();
sp[REG_PC] = sigcb->context.PC;
OS_SYSCALL_SET_CPSR(sp, sigcb->context.CPSR);
sp[REG_SP] = sigcb->context.USP;
sp[REG_LR] = sigcb->context.ULR;
sp[REG_R0] = sigcb->context.R0;
sp[REG_R1] = sigcb->context.R1;
sp[REG_R2] = sigcb->context.R2;
sp[REG_R3] = sigcb->context.R3;
sp[REG_R7] = sigcb->context.R7;
sp[REG_R12] = sigcb->context.R12;
sigcb->context.count--;
process->sigShare = 0;
OsProcessExitCodeSignalClear(process);
SCHEDULER_UNLOCK(intSave);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_multipledlinkhead_pri.h"
#include "los_bitmap.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATIC INLINE UINT32 OsLog2(UINT32 size)
{
return (size > 0) ? (UINT32)LOS_HighBitGet(size) : 0;
}
LITE_OS_SEC_TEXT_INIT VOID OsDLnkInitMultiHead(VOID *headAddr)
{
LosMultipleDlinkHead *dlinkHead = (LosMultipleDlinkHead *)headAddr;
LOS_DL_LIST *listNodeHead = dlinkHead->listHead;
UINT32 index;
for (index = 0; index < OS_MULTI_DLNK_NUM; ++index, ++listNodeHead) {
LOS_ListInit(listNodeHead);
}
}
LITE_OS_SEC_TEXT_MINOR LOS_DL_LIST *OsDLnkMultiHead(VOID *headAddr, UINT32 size)
{
LosMultipleDlinkHead *dlinkHead = (LosMultipleDlinkHead *)headAddr;
UINT32 index = OsLog2(size);
if (index > OS_MAX_MULTI_DLNK_LOG2) {
return NULL;
} else if (index <= OS_MIN_MULTI_DLNK_LOG2) {
index = OS_MIN_MULTI_DLNK_LOG2;
}
return dlinkHead->listHead + (index - OS_MIN_MULTI_DLNK_LOG2);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,424 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "string.h"
#include "securec.h"
#include "los_hwi.h"
#include "los_typedef.h"
#include "los_heap_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
static UINT32 g_memAllocCount = 0;
static UINT32 g_memFreeCount = 0;
#if (LOSCFG_HEAP_MEMORY_PEAK_STATISTICS == YES)
static UINT32 g_memCurHeapUsed = 0;
static UINT32 g_memMaxHeapUsed = 0;
#endif
#define HEAP_CAST(t, exp) ((t)(exp))
#define HEAP_ALIGN 4
#define HEAP_TAIL_NODE_SIZE_THRESHOLD 1024
/*
* Description : look up the next memory node according to one memory node in the memory block list.
* Input : struct LosHeapManager *heapMan --- Pointer to the manager,to distinguish heap
* struct LosHeapNode *node --- Size of memory in bytes to allocate
* Return : Pointer to next memory node
*/
struct LosHeapNode* OsHeapPrvGetNext(struct LosHeapManager *heapMan, struct LosHeapNode *node)
{
return (heapMan->tail == node) ? NULL : (struct LosHeapNode *)(UINTPTR)(node->data + node->size);
}
/*
* Description : To initialize the heap memory and get the begin address and size of heap memory,
* then initialize LosHeapManager.
* Input : VOID *pool --- begin address of the heap memory pool
* UITN32 size --- size of the heap memory pool
* Return : 1:success 0:error
*/
BOOL OsHeapInit(VOID *pool, UINT32 size)
{
struct LosHeapNode *node = NULL;
struct LosHeapManager *heapMan = HEAP_CAST(struct LosHeapManager *, pool);
if ((heapMan == NULL) || (size <= (sizeof(struct LosHeapNode) + sizeof(struct LosHeapManager)))) {
return FALSE;
}
// Ignore the return code when matching CSEC rule 6.6(2).
(VOID)memset_s(pool, size, 0, size);
heapMan->size = size;
node = heapMan->head = (struct LosHeapNode *)((UINT8*)pool + sizeof(struct LosHeapManager));
heapMan->tail = node;
node->used = 0;
node->prev = NULL;
node->size = size - sizeof(struct LosHeapNode) - sizeof(struct LosHeapManager);
return TRUE;
}
/*
* Description : update used size
* Input : size --- alloc memory size
* ret --- memory chunk
*/
VOID OsHeapUpdateUsedSize(UINT32 size, VOID *ret)
{
#if (LOSCFG_HEAP_MEMORY_PEAK_STATISTICS == YES)
g_memCurHeapUsed += (size + sizeof(struct LosHeapNode));
if (g_memCurHeapUsed > g_memMaxHeapUsed) {
g_memMaxHeapUsed = g_memCurHeapUsed;
}
#endif
if (ret != NULL) {
g_memAllocCount++;
}
}
/*
* Description : To alloc memory block from the heap memory poll
* Input : VOID *pool --- Pointer to the manager,to distinguish heap
* UINT32 size --- size of the heap memory pool
* Return : NULL:error, other value:the address of the memory we alloced
*/
VOID* OsHeapAlloc(VOID *pool, UINT32 size)
{
struct LosHeapNode *node = NULL;
struct LosHeapNode *next = NULL;
struct LosHeapNode *best = NULL;
VOID *ret = NULL;
UINT32 alignSize = ALIGNE(size);
struct LosHeapManager *heapMan = HEAP_CAST(struct LosHeapManager *, pool);
if (heapMan == NULL) {
return NULL;
}
node = heapMan->tail;
while (node != NULL) {
if ((node->used == 0) && (node->size >= alignSize) &&
((best == NULL) || (best->size > node->size))) {
best = node;
if (best->size == alignSize) {
goto SIZE_MATCH;
}
}
node = node->prev;
}
/* alloc failed */
if (best == NULL) {
PRINT_ERR("there's not enough whole to alloc %x Bytes!\n", alignSize);
goto OUT;
}
if ((best->size - alignSize) > sizeof(struct LosHeapNode)) {
/* hole divide into 2 */
node = (struct LosHeapNode*)(UINTPTR)(best->data + alignSize);
node->used = 0;
node->size = best->size - alignSize - sizeof(struct LosHeapNode);
node->prev = best;
if (best != heapMan->tail) {
next = OsHeapPrvGetNext(heapMan, node);
if (next != NULL) {
next->prev = node;
}
} else {
heapMan->tail = node;
}
best->size = alignSize;
}
SIZE_MATCH:
best->align = 0;
best->used = 1;
ret = best->data;
OsHeapUpdateUsedSize(alignSize, ret);
OUT:
return ret;
}
/*
* Description : To alloc memory block from the heap memory poll with
* Input : VOID *pool --- Pointer to the manager,to distinguish heap
* UINT32 size --- size of the heap memory pool
* UINT32 boundary --- boundary the heap needs align
* Return : NULL:error, other value:the address of the memory we alloced
*/
VOID* OsHeapAllocAlign(VOID *pool, UINT32 size, UINT32 boundary)
{
UINT32 useSize;
UINT32 gapSize;
VOID *ret = NULL;
VOID *alignedPtr = NULL;
if ((pool == NULL) || (size == 0) || (boundary < sizeof(VOID *)) || !IS_ALIGNED(boundary, boundary)) {
return NULL;
}
/* worst case is that the node happen to be 4 bytes ahead of the boundary */
useSize = (size + boundary) - sizeof(VOID*);
if (useSize < size) {
return NULL;
}
ret = OsHeapAlloc(pool, useSize);
if (ret != NULL) {
alignedPtr = (VOID *)(UINTPTR)OS_MEM_ALIGN(ret, boundary);
if (ret == alignedPtr) {
goto OUT;
}
gapSize = (UINTPTR)alignedPtr - (UINTPTR)ret;
OS_MEM_SET_ALIGN_FLAG(gapSize);
*((UINT32 *)((UINTPTR)alignedPtr - (sizeof(UINTPTR) / sizeof(UINT8)))) = gapSize;
ret = alignedPtr;
}
OUT:
return ret;
}
STATIC VOID OsDoHeapFree(struct LosHeapManager *heapMan, struct LosHeapNode *curNode)
{
struct LosHeapNode *node = curNode;
struct LosHeapNode *next = NULL;
/* set to unused status */
node->used = 0;
#if (LOSCFG_HEAP_MEMORY_PEAK_STATISTICS == YES)
if (g_memCurHeapUsed >= (node->size + sizeof(struct LosHeapNode))) {
g_memCurHeapUsed -= (node->size + sizeof(struct LosHeapNode));
}
#endif
/* unused region before and after combination */
while (node->prev && !node->prev->used) {
node = node->prev;
}
next = OsHeapPrvGetNext(heapMan, node);
while (next != NULL) {
if (next->used) {
next->prev = node;
break;
}
node->size += sizeof(struct LosHeapNode) + next->size;
if (heapMan->tail == next) {
heapMan->tail = node;
}
next = OsHeapPrvGetNext(heapMan, node);
}
}
/*
* Description : To free the memory block from heap memory poll
* Input : VOID* pool --- Pointer to the manager,to distinguish heap
* VOID* ptr --- the pointer of heap memory we want to free
* Return : 1:success 0:error
*/
BOOL OsHeapFree(VOID *pool, VOID *ptr)
{
struct LosHeapNode *node = NULL;
UINT32 gapSize;
BOOL ret = TRUE;
struct LosHeapManager *heapMan = HEAP_CAST(struct LosHeapManager *, pool);
if ((heapMan == NULL) || (ptr == NULL)) {
return LOS_NOK;
}
/* find the real ptr through gap size */
gapSize = *((UINT32 *)((UINTPTR)ptr - (sizeof(UINTPTR) / sizeof(UINT8))));
if (OS_MEM_GET_ALIGN_FLAG(gapSize)) {
gapSize = OS_MEM_GET_ALIGN_GAPSIZE(gapSize);
ptr = (VOID *)((UINTPTR)ptr - gapSize);
}
if (((UINTPTR)ptr < (UINTPTR)heapMan->head) ||
((UINTPTR)ptr > ((UINTPTR)heapMan->tail + sizeof(struct LosHeapNode)))) {
PRINT_ERR("0x%x out of range!\n", (UINTPTR)ptr);
return FALSE;
}
node = ((struct LosHeapNode *)ptr) - 1;
/* check if the address is a node of the heap memory list */
if ((node->used == 0) || (!((UINTPTR)node == (UINTPTR)heapMan->head) &&
(((UINTPTR)node->prev < (UINTPTR)heapMan->head) ||
((UINTPTR)node->prev > ((UINTPTR)heapMan->tail + sizeof(struct LosHeapNode))) ||
((UINTPTR)OsHeapPrvGetNext(heapMan, node->prev) != (UINTPTR)node)))) {
ret = FALSE;
goto OUT;
}
OsDoHeapFree(heapMan, node);
OUT:
if (ret == TRUE) {
g_memFreeCount++;
}
return ret;
}
/*
* Description : print heap information
* Input : pool --- Pointer to the manager, to distinguish heap
*/
VOID OsAlarmHeapInfo(VOID *pool)
{
struct LosHeapManager *heapMan = HEAP_CAST(struct LosHeapManager *, pool);
LosHeapStatus status = {0};
(VOID)heapMan;
if (OsHeapStatisticsGet(pool, &status) == LOS_NOK) {
return;
}
PRINT_INFO("pool addr pool size used size free size max free alloc Count free Count\n");
PRINT_INFO("0x%-8x 0x%-8x 0x%-8x 0x%-8x 0x%-8x 0x%-8x 0x%-8x\n",
pool, heapMan->size, status.totalUsedSize, status.totalFreeSize, status.maxFreeNodeSize,
status.usedNodeNum, status.freeNodeNum);
}
/*
* Description : collect heap statistics
* Input : pool --- Pointer to the manager, to distinguish heap
* Output : status --- heap statistics
* Return : LOS_OK on success or error code on failure
*/
UINT32 OsHeapStatisticsGet(VOID *pool, LosHeapStatus *status)
{
UINT32 heapUsed = 0;
UINT32 maxFreeNodeSize = 0;
UINT32 freeNodeNum = 0;
UINT32 usedNodeNum = 0;
struct LosHeapNode *node = NULL;
struct LosHeapManager *ramHeap = HEAP_CAST(struct LosHeapManager *, pool);
if (ramHeap == NULL) {
return LOS_NOK;
}
if (status == NULL) {
return LOS_NOK;
}
/* heap mannager header use heap space */
heapUsed += sizeof(struct LosHeapManager);
node = ramHeap->tail;
while (node != NULL) {
if (node->used) {
heapUsed += (node->size + sizeof(struct LosHeapNode));
usedNodeNum++;
} else {
if (node->size > maxFreeNodeSize) {
maxFreeNodeSize = node->size;
}
freeNodeNum++;
}
node = node->prev;
}
if (ramHeap->size < heapUsed) {
return LOS_NOK;
}
status->totalUsedSize = heapUsed;
status->maxFreeNodeSize = maxFreeNodeSize;
status->totalFreeSize = ramHeap->size - status->totalUsedSize;
status->usedNodeNum = usedNodeNum;
status->freeNodeNum = freeNodeNum;
return LOS_OK;
}
#if (LOSCFG_HEAP_MEMORY_PEAK_STATISTICS == YES)
UINT32 LOS_HeapGetHeapMemoryPeak(VOID)
{
return g_memMaxHeapUsed;
}
#endif
/*
* Description : get max free block size
* Input : pool --- Pointer to the manager, to distinguish heap
* Return : max free block size
*/
UINT32 OsHeapGetMaxFreeBlkSize(VOID *pool)
{
UINT32 size = 0;
UINT32 temp;
struct LosHeapNode *node = NULL;
struct LosHeapManager *ramHeap = HEAP_CAST(struct LosHeapManager *, pool);
if (ramHeap == NULL) {
return LOS_NOK;
}
node = ramHeap->tail;
while (node != NULL) {
if (!(node->used)) {
temp = node->size;
if (temp > size) {
size = temp;
}
}
node = node->prev;
}
return size;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_memstat_pri.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS_MINOR STATIC TskMemUsedInfo g_tskMemUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT];
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
if (OS_INT_ACTIVE) {
return;
}
g_tskMemUsedInfo[taskID].memUsed += usedSize;
}
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
if (OS_INT_ACTIVE) {
return;
}
if (g_tskMemUsedInfo[taskID].memUsed < usedSize) {
PRINT_WARN("mem used of current task '%s':0x%x, decrease size:0x%x\n",
OsCurrTaskGet()->taskName, g_tskMemUsedInfo[taskID].memUsed, usedSize);
return;
}
g_tskMemUsedInfo[taskID].memUsed -= usedSize;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskMemUsage(UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return LOS_NOK;
}
return g_tskMemUsedInfo[taskID].memUsed;
}
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemClear(UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
if (g_tskMemUsedInfo[taskID].memUsed != 0) {
PRINT_WARN("mem used of task '%s' is:0x%x, not zero when task being deleted\n",
OsCurrTaskGet()->taskName, g_tskMemUsedInfo[taskID].memUsed);
}
g_tskMemUsedInfo[taskID].memUsed = 0;
}
#ifdef LOS_MEM_SLAB
LITE_OS_SEC_BSS_MINOR STATIC TskSlabUsedInfo g_tskSlabUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT];
LITE_OS_SEC_TEXT_MINOR VOID OsTaskSlabUsedInc(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
g_tskSlabUsedInfo[taskID].slabUsed += usedSize;
}
LITE_OS_SEC_TEXT_MINOR VOID OsTaskSlabUsedDec(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return;
}
g_tskSlabUsedInfo[taskID].slabUsed -= usedSize;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskSlabUsage(UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
return LOS_NOK;
}
return g_tskSlabUsedInfo[taskID].slabUsed;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
#ifdef LOSCFG_MEM_RECORDINFO
#include "los_binarytree_pri.h"
#include "los_typedef.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
UINT32 OsBinTreeInsert(const VOID *node, UINT32 nodeLen, BinNode **leaf,
BinNode *(*GetMyBinNode)(UINT32 *nodeID),
INT32 (*CompareNode)(const VOID *node1, const VOID *node2))
{
UINT32 nodeID;
INT32 result;
BinNode **currentNode = leaf;
if (leaf == NULL) {
return OS_INVALID;
}
do {
if (*currentNode != NULL) {
result = CompareNode(node, (const VOID *)(*currentNode));
if (result == 0) {
return (*currentNode)->nodeID;
} else if (result < 0) {
currentNode = (BinNode **)(&((*currentNode)->left));
} else {
currentNode = (BinNode **)(&((*currentNode)->right));
}
} else {
(*currentNode) = GetMyBinNode(&nodeID);
if (*currentNode == NULL) {
return OS_INVALID;
}
(VOID)memcpy_s((*currentNode)->keyValue, (nodeLen - sizeof(BinNode)),
((BinNode *)node)->keyValue, (nodeLen - sizeof(BinNode)));
(*currentNode)->nodeID = nodeID;
/* initialize the children to NULL */
(*currentNode)->left = NULL;
(*currentNode)->right = NULL;
return (*currentNode)->nodeID;
}
} while (1);
}
/* LRNODE */
LinkRegNode g_linkRegNode[LR_COUNT];
UINT32 g_linkRegNodeIndex = 0;
LinkRegNode *g_linkRegRoot = NULL;
INT32 OsCompareLRNode(const VOID *node1, const VOID *node2)
{
LinkRegNode *linkRegNode1 = (LinkRegNode *)node1;
LinkRegNode *linkRegNode2 = (LinkRegNode *)node2;
if (linkRegNode1->linkReg1 < linkRegNode2->linkReg1) {
return -1;
} else if ((linkRegNode1->linkReg1 == linkRegNode2->linkReg1) &&
(linkRegNode1->linkReg2 < linkRegNode2->linkReg2)) {
return -1;
} else if ((linkRegNode1->linkReg1 == linkRegNode2->linkReg1) &&
(linkRegNode1->linkReg2 == linkRegNode2->linkReg2) &&
(linkRegNode1->linkReg3 < linkRegNode2->linkReg3)) {
return -1;
} else if ((linkRegNode1->linkReg1 == linkRegNode2->linkReg1) &&
(linkRegNode1->linkReg2 == linkRegNode2->linkReg2) &&
(linkRegNode1->linkReg3 == linkRegNode2->linkReg3)) {
return 0;
} else {
return 1;
}
}
BinNode *OsGetLRBinNode(UINT32 *nodeID)
{
if (g_linkRegNodeIndex < LR_COUNT) {
*nodeID = g_linkRegNodeIndex;
return (BinNode *)(&g_linkRegNode[g_linkRegNodeIndex++]);
} else {
*nodeID = (UINT32)-1;
return NULL;
}
}
/* ADDRNODE */
AddrNode g_addrNode[ADDR_COUNT];
UINT32 g_addrNodeIndex = 0;
AddrNode *g_addrRoot = NULL;
INT32 OsCompareAddrNode(const VOID *node1, const VOID *node2)
{
AddrNode *addrNode1 = (AddrNode *)node1;
AddrNode *addrNode2 = (AddrNode *)node2;
if (addrNode1->addr < addrNode2->addr) {
return -1;
} else if (addrNode1->addr == addrNode2->addr) {
return 0;
} else {
return 1;
}
}
BinNode *OsGetAddrBinNode(UINT32 *nodeID)
{
if (g_addrNodeIndex < ADDR_COUNT) {
*nodeID = g_addrNodeIndex;
return (BinNode *)(&g_addrNode[g_addrNodeIndex++]);
} else {
*nodeID = (UINT32)-1;
return NULL;
}
}
/* REQSIZENODE */
ReqSizeNode g_reqSizeNode[REQ_SIZE_COUNT];
UINT32 g_reqSizeNodeIndex = 0;
ReqSizeNode *g_reqSizeRoot = NULL;
INT32 OsCompareReqSizeNode(const VOID *node1, const VOID *node2)
{
ReqSizeNode *reqSizeNode1 = (ReqSizeNode *)node1;
ReqSizeNode *reqSizeNode2 = (ReqSizeNode *)node2;
if (reqSizeNode1->reqSize < reqSizeNode2->reqSize) {
return -1;
} else if (reqSizeNode1->reqSize == reqSizeNode2->reqSize) {
return 0;
} else {
return 1;
}
}
BinNode *OsGetReqSizeBinNode(UINT32 *nodeID)
{
if (g_reqSizeNodeIndex < REQ_SIZE_COUNT) {
*nodeID = g_reqSizeNodeIndex;
return (BinNode *)(&g_reqSizeNode[g_reqSizeNodeIndex++]);
} else {
*nodeID = (UINT32)-1;
return NULL;
}
}
/* TASKIDNODE */
STATIC TaskIDNode g_taskIDNode[TASK_ID_COUNT];
STATIC UINT32 g_taskIDNodeIndex = 0;
STATIC TaskIDNode *g_taskIDRoot = NULL;
INT32 OsCompareTaskIDNode(const VOID *node1, const VOID *node2)
{
TaskIDNode *taskIDNode1 = (TaskIDNode *)node1;
TaskIDNode *taskIDNode2 = (TaskIDNode *)node2;
if (taskIDNode1->taskID < taskIDNode2->taskID) {
return -1;
} else if (taskIDNode1->taskID == taskIDNode2->taskID) {
return 0;
} else {
return 1;
}
}
BinNode *OsGetTaskIDBinNode(UINT32 *nodeID)
{
if (g_taskIDNodeIndex < TASK_ID_COUNT) {
*nodeID = g_taskIDNodeIndex;
return (BinNode *)(&g_taskIDNode[g_taskIDNodeIndex++]);
} else {
*nodeID = (UINT32)-1;
return NULL;
}
}
#define BINARYTREE_TASKID_COUNT 11
#define BINARYTREE_REQSIZE_COUNT 4
STATIC const UINT32 g_binaryTreeTaskID[BINARYTREE_TASKID_COUNT] = { 33, 10, 20, 9, 42, 34, 45, 47, 46, 50, 49 };
STATIC const UINT32 g_binaryTreeReqSize[BINARYTREE_REQSIZE_COUNT] = { 616, 136, 1708, 1580 };
VOID OsBinaryTreeInit(VOID)
{
INT32 index;
LinkRegNode linkRegNode;
AddrNode node;
TaskIDNode taskNode;
ReqSizeNode reqNode;
UINT32 ret;
/* equal to the middle address of __text_start and __text_end */
linkRegNode.linkReg1 = (UINTPTR)(((&__text_end - &__text_start) / 2) + &__text_start);
linkRegNode.linkReg2 = linkRegNode.linkReg1;
linkRegNode.linkReg3 = linkRegNode.linkReg1;
ret = OsBinTreeInsert(&linkRegNode, sizeof(LinkRegNode), (BinNode **)&g_linkRegRoot,
OsGetLRBinNode, OsCompareLRNode);
if (ret == OS_INVALID) {
PRINT_ERR("binary tree init failed\n");
}
/* equal to the middle address of __bss_end and OS_SYS_FUNC_ADDR_END */
node.addr = ((OS_SYS_FUNC_ADDR_END - (UINTPTR)(&__bss_end)) >> 1) + (UINTPTR)(&__bss_end);
ret = OsBinTreeInsert(&node, sizeof(AddrNode), (BinNode **)&g_addrRoot,
OsGetAddrBinNode, OsCompareAddrNode);
if (ret == OS_INVALID) {
PRINT_ERR("binary tree init failed\n");
}
for (index = 0; index < BINARYTREE_TASKID_COUNT; index++) {
taskNode.taskID = g_binaryTreeTaskID[index];
ret = OsBinTreeInsert(&taskNode, sizeof(TaskIDNode), (BinNode **)&g_taskIDRoot,
OsGetTaskIDBinNode, OsCompareTaskIDNode);
if (ret == OS_INVALID) {
PRINT_ERR("binary tree init failed\n");
}
}
for (index = 0; index < BINARYTREE_REQSIZE_COUNT; index++) {
reqNode.reqSize = g_binaryTreeReqSize[index];
ret = OsBinTreeInsert(&reqNode, sizeof(ReqSizeNode), (BinNode **)&g_reqSizeRoot,
OsGetReqSizeBinNode, OsCompareReqSizeNode);
if (ret == OS_INVALID) {
PRINT_ERR("binary tree init failed\n");
}
}
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_typedef.h"
#include "los_printf.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* array used for 64 binary conversion, include 64 characters */
const CHAR g_base64Array[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '~', '!'
};
#define LOGARITHM 6 /* the logarithm of 64 to base 2 */
#define BASE64_MARK ((1U << LOGARITHM) - 1)
VOID OsDecTo64F(UINT32 num, CHAR *base64, INT32 base64Len)
{
INT32 len = base64Len - 1;
UINT32 tempNum = num;
if (base64 == NULL) {
PRINT_ERR("%s:%d input null buf\n", __FUNCTION__, __LINE__);
return;
}
if (base64Len <= 0) {
PRINT_ERR("%s:%d input illegal Len\n", __FUNCTION__, __LINE__);
return;
}
while (num) {
if (len < 0) {
PRINT_ERR("Len[%d] is too short, input num: %u\n", base64Len, tempNum);
break;
}
base64[len--] = g_base64Array[num & BASE64_MARK];
num >>= LOGARITHM;
}
for (; len >= 0; len--) {
base64[len] = '0';
}
base64[base64Len] = '\0';
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,356 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_memrecord_pri.h"
#include "stdio.h"
#include "los_binarytree_pri.h"
#include "los_event.h"
#include "los_exc.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
enum MemActType {
OS_MEM_VALIDFREE,
OS_MEM_INVALIDFREE,
OS_MEM_ALLOC
};
STATIC MemRecordInfo g_memRecord1[RECORD_LEN] = {0};
STATIC MemRecordInfo g_memRecord2[RECORD_LEN] = {0};
STATIC MemRecordInfo *g_saveMemRecord = g_memRecord1;
STATIC MemRecordInfo *g_printMemRecord = NULL;
STATIC MemRecordInfo *g_curPtr = NULL;
STATIC volatile UINT32 g_memRecordIndex = 0;
STATIC volatile UINT32 g_memLastEndIndex = 0;
STATIC EVENT_CB_S g_memShowEvent;
UINT32 g_memRecordShowEnable = 1;
STATIC UINT32 g_lastAddrNodeIndex = 0;
STATIC UINT32 g_lastReqSizeNodeIndex = 0;
STATIC UINT32 g_lastlinkRegNodeIndex = 0;
#define INDEX_LENGTH 2
#define ADDR_ID_LENGTH 3
#define REQSIZE_ID_LENGTH 2
#define ACTTYPE_LENGTH 4
#define TASK_ID_LENGTH 2
#define SYS_TICK_LENGTH 6
#define LINK_REG_ID_LENGTH 2
#define INFO_STR_LENGTH 20
#define PRINT_STR_LENGTH 32
#define NODE_VALUE_LENGTH 7
#define READ_EVENT_MASK 0xFFF
#define WRITE_EVENT 0x112
STATIC VOID OsMemRecordCompressInfo(VOID)
{
UINT32 count;
CHAR infoStr[INFO_STR_LENGTH];
UINT32 currentIndex = g_addrNodeIndex;
for (count = g_lastAddrNodeIndex; count < currentIndex; count++) {
OsDecTo64F(g_addrNode[count].leaf.nodeID, infoStr, ADDR_ID_LENGTH);
printf("~^%s%x^~\n", infoStr, g_addrNode[count].addr);
}
g_lastAddrNodeIndex = currentIndex;
currentIndex = g_reqSizeNodeIndex;
for (count = g_lastReqSizeNodeIndex; count < currentIndex; count++) {
OsDecTo64F(g_reqSizeNode[count].leaf.nodeID, infoStr, REQSIZE_ID_LENGTH);
printf("*^%s%u^*\n", infoStr, g_reqSizeNode[count].reqSize);
}
g_lastReqSizeNodeIndex = currentIndex;
currentIndex = g_linkRegNodeIndex;
for (count = g_lastlinkRegNodeIndex; count < currentIndex; count++) {
OsDecTo64F(g_linkRegNode[count].leaf.nodeID, infoStr, LINK_REG_ID_LENGTH);
printf("$^%s%x%x%x^$\n", infoStr, g_linkRegNode[count].linkReg1, g_linkRegNode[count].linkReg2,
g_linkRegNode[count].linkReg3);
}
g_lastlinkRegNodeIndex = currentIndex;
}
STATIC VOID PrintPtrAssign(CHAR *printStr, UINT32 strLen, UINT32 startIndex, UINT32 index)
{
CHAR nodeValue[NODE_VALUE_LENGTH];
UINT32 tmpIndex = 0;
/* 3 bytes for ending "!~" and '\0'. */
if (strLen < (INDEX_LENGTH + ADDR_ID_LENGTH + REQSIZE_ID_LENGTH + ACTTYPE_LENGTH +
TASK_ID_LENGTH + SYS_TICK_LENGTH + LINK_REG_ID_LENGTH + index + 3)) {
PRINT_ERR("printStr is not big enough\n");
return;
}
OsDecTo64F(startIndex, nodeValue, INDEX_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].addrID, nodeValue, ADDR_ID_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].reqSizeID, nodeValue, REQSIZE_ID_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].actType, nodeValue, ACTTYPE_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].taskID, nodeValue, TASK_ID_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].sysTick, nodeValue, SYS_TICK_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
tmpIndex = 0;
OsDecTo64F(g_curPtr[startIndex].linkRegID, nodeValue, LINK_REG_ID_LENGTH);
printStr[index++] = nodeValue[tmpIndex++];
printStr[index++] = nodeValue[tmpIndex];
printStr[index++] = '!';
printStr[index++] = '~';
printStr[index++] = '\0';
printf("%s\n", printStr);
}
STATIC VOID OsMemRecordShow(VOID)
{
UINT32 index = 0;
UINT32 startIndex = g_memLastEndIndex;
UINT32 endIndex;
MemRecordInfo *printMemRecord = g_printMemRecord;
CHAR printStr[PRINT_STR_LENGTH];
if (g_curPtr == NULL) {
g_curPtr = g_printMemRecord;
}
OsMemRecordCompressInfo();
if (g_curPtr != NULL) {
printStr[index++] = '~';
printStr[index++] = '!';
if (g_curPtr == printMemRecord) {
while (startIndex < RECORD_LEN) {
PrintPtrAssign(printStr, PRINT_STR_LENGTH, startIndex, index);
startIndex++;
}
g_memLastEndIndex = 0;
}
}
startIndex = g_memLastEndIndex;
endIndex = g_memRecordIndex;
if ((g_curPtr == g_saveMemRecord) && (g_printMemRecord != NULL) && (startIndex >= endIndex)) {
printf("Rec:error:the printf speed is low,Rnd\n");
startIndex = 0;
}
g_curPtr = g_saveMemRecord;
index = 0;
printStr[index++] = '~';
printStr[index++] = '!';
while (startIndex < endIndex) {
PrintPtrAssign(printStr, PRINT_STR_LENGTH, startIndex, index);
startIndex++;
}
g_memLastEndIndex = endIndex;
}
STATIC VOID OsMemRecordExchange(VOID)
{
if (g_saveMemRecord == g_memRecord1) {
g_saveMemRecord = g_memRecord2;
g_printMemRecord = g_memRecord1;
} else {
g_saveMemRecord = g_memRecord1;
g_printMemRecord = g_memRecord2;
}
g_memRecordIndex = 0;
(VOID)LOS_EventWrite(&g_memShowEvent, WRITE_EVENT);
}
#define LINK_REG1_INDEX 1
#define LINK_REG2_INDEX 2
#define LINK_REG3_INDEX 3
#define LINK_REG_NUM 3
STATIC INLINE VOID OsMemRecordLR(LinkRegNode *linkRegNode)
{
UINTPTR framePtr, framePtrTmp;
UINT32 index = 0;
linkRegNode->linkReg1 = 0;
linkRegNode->linkReg2 = 0;
linkRegNode->linkReg3 = 0;
framePtr = Get_Fp();
while ((framePtr > OS_SYS_FUNC_ADDR_START) &&
(framePtr < OS_SYS_FUNC_ADDR_END) &&
((framePtr % sizeof(CHAR *)) == 0)) {
framePtrTmp = framePtr;
if (index == LINK_REG1_INDEX) {
linkRegNode->linkReg1 = *((UINTPTR *)(framePtrTmp));
} else if (index == LINK_REG2_INDEX) {
linkRegNode->linkReg2 = *((UINTPTR *)(framePtrTmp));
} else if (index == LINK_REG3_INDEX) {
linkRegNode->linkReg3 = *((UINTPTR *)(framePtrTmp));
}
framePtr = *((UINTPTR *)(framePtrTmp - sizeof(UINTPTR *)));
index++;
if (index == (LINK_REG_NUM + 1)) {
break;
}
}
}
STATIC VOID OsMemRecordTaskID(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
if (runTask != NULL) {
g_saveMemRecord[g_memRecordIndex].taskID = LOS_CurTaskIDGet();
} else {
g_saveMemRecord[g_memRecordIndex].taskID = 0;
}
}
STATIC INLINE VOID OsMemRecord(const VOID *ptr, UINT32 size)
{
UINT64 tickCount = LOS_TickCountGet();
UINT32 nodeID;
LinkRegNode linkRegNode;
AddrNode node;
ReqSizeNode reqNode;
OsMemRecordLR(&linkRegNode);
nodeID = OsBinTreeInsert(&linkRegNode, sizeof(linkRegNode), (BinNode **)&g_linkRegRoot, OsGetLRBinNode,
OsCompareLRNode);
if (nodeID == OS_INVALID) {
PRINT_WARN("LIST g_linkRegRoot insert linkRegNode failed!\n");
}
g_saveMemRecord[g_memRecordIndex].linkRegID = nodeID;
node.addr = (UINTPTR)ptr;
nodeID = OsBinTreeInsert(&node, sizeof(AddrNode), (BinNode **)&g_addrRoot, OsGetAddrBinNode,
OsCompareAddrNode);
if (nodeID == OS_INVALID) {
PRINT_WARN("LIST g_addrRoot insert addrNode failed!\n");
}
g_saveMemRecord[g_memRecordIndex].addrID = nodeID;
g_saveMemRecord[g_memRecordIndex].sysTick = tickCount;
OsMemRecordTaskID();
reqNode.reqSize = size;
nodeID = OsBinTreeInsert(&reqNode, sizeof(ReqSizeNode), (BinNode **)&g_reqSizeRoot, OsGetReqSizeBinNode,
OsCompareReqSizeNode);
if (nodeID == OS_INVALID) {
PRINT_WARN("LIST g_reqSizeRoot insert reqSizeNode failed!\n");
}
g_saveMemRecord[g_memRecordIndex].reqSizeID = nodeID;
g_memRecordIndex++;
if (g_memRecordIndex == RECORD_LEN) {
OsMemRecordExchange();
}
}
#ifdef LOSCFG_MEM_RECORDINFO
VOID OsMemRecordMalloc(const VOID *ptr, UINT32 size)
{
if (g_memRecordShowEnable == 0) {
return;
}
OsMemRecord(ptr, size);
g_saveMemRecord[g_memRecordIndex].actType = OS_MEM_ALLOC;
}
#endif
#ifdef LOSCFG_MEM_RECORDINFO
VOID OsMemRecordFree(const VOID *ptr, UINT32 size)
{
UINT32 actType;
if (g_memRecordShowEnable == 0) {
return;
}
actType = (size == 0) ? OS_MEM_INVALIDFREE : OS_MEM_VALIDFREE;
OsMemRecord(ptr, size);
g_saveMemRecord[g_memRecordIndex].actType = actType;
}
#endif
VOID OsMemRecordShowTask(VOID)
{
(VOID)LOS_EventInit(&g_memShowEvent);
while (1) {
(VOID)LOS_EventRead(&g_memShowEvent, READ_EVENT_MASK,
LOS_WAITMODE_OR | LOS_WAITMODE_CLR, MEM_RECORDSHOW_TIMEOUT);
if (g_memRecordShowEnable) {
OsMemRecordShow();
}
}
}
VOID OsMemRecordShowSet(UINT32 value)
{
g_memRecordShowEnable = value;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,237 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_membox.h"
#include "los_hwi.h"
#include "los_spinlock.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_AARCH64
#define OS_MEMBOX_MAGIC 0xa55a5aa5a55a5aa5
#else
#define OS_MEMBOX_MAGIC 0xa55a5aa5
#endif
#define OS_MEMBOX_SET_MAGIC(addr) \
((LOS_MEMBOX_NODE *)(addr))->pstNext = (LOS_MEMBOX_NODE *)OS_MEMBOX_MAGIC
#define OS_MEMBOX_CHECK_MAGIC(addr) \
((((LOS_MEMBOX_NODE *)(addr))->pstNext == (LOS_MEMBOX_NODE *)OS_MEMBOX_MAGIC) ? LOS_OK : LOS_NOK)
#define OS_MEMBOX_USER_ADDR(addr) \
((VOID *)((UINT8 *)(addr) + OS_MEMBOX_NODE_HEAD_SIZE))
#define OS_MEMBOX_NODE_ADDR(addr) \
((LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) - OS_MEMBOX_NODE_HEAD_SIZE))
/* spinlock for mem module, only available on SMP mode */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_memboxSpin);
#define MEMBOX_LOCK(state) LOS_SpinLockSave(&g_memboxSpin, &(state))
#define MEMBOX_UNLOCK(state) LOS_SpinUnlockRestore(&g_memboxSpin, (state))
STATIC INLINE UINT32 OsCheckBoxMem(const LOS_MEMBOX_INFO *boxInfo, const VOID *node)
{
UINT32 offset;
if (boxInfo->uwBlkSize == 0) {
return LOS_NOK;
}
offset = (UINT32)((UINTPTR)node - (UINTPTR)(boxInfo + 1));
if ((offset % boxInfo->uwBlkSize) != 0) {
return LOS_NOK;
}
if ((offset / boxInfo->uwBlkSize) >= boxInfo->uwBlkNum) {
return LOS_NOK;
}
return OS_MEMBOX_CHECK_MAGIC(node);
}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize)
{
LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
LOS_MEMBOX_NODE *node = NULL;
UINT32 index;
UINT32 intSave;
if (pool == NULL) {
return LOS_NOK;
}
if (blkSize == 0) {
return LOS_NOK;
}
if (poolSize < sizeof(LOS_MEMBOX_INFO)) {
return LOS_NOK;
}
MEMBOX_LOCK(intSave);
boxInfo->uwBlkSize = LOS_MEMBOX_ALLIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE);
if (boxInfo->uwBlkSize == 0) {
MEMBOX_UNLOCK(intSave);
return LOS_NOK;
}
boxInfo->uwBlkNum = (poolSize - sizeof(LOS_MEMBOX_INFO)) / boxInfo->uwBlkSize;
boxInfo->uwBlkCnt = 0;
if (boxInfo->uwBlkNum == 0) {
MEMBOX_UNLOCK(intSave);
return LOS_NOK;
}
node = (LOS_MEMBOX_NODE *)(boxInfo + 1);
boxInfo->stFreeList.pstNext = node;
for (index = 0; index < boxInfo->uwBlkNum - 1; ++index) {
node->pstNext = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize);
node = node->pstNext;
}
node->pstNext = NULL;
MEMBOX_UNLOCK(intSave);
return LOS_OK;
}
LITE_OS_SEC_TEXT VOID *LOS_MemboxAlloc(VOID *pool)
{
LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
LOS_MEMBOX_NODE *node = NULL;
LOS_MEMBOX_NODE *nodeTmp = NULL;
UINT32 intSave;
if (pool == NULL) {
return NULL;
}
MEMBOX_LOCK(intSave);
node = &(boxInfo->stFreeList);
if (node->pstNext != NULL) {
nodeTmp = node->pstNext;
node->pstNext = nodeTmp->pstNext;
OS_MEMBOX_SET_MAGIC(nodeTmp);
boxInfo->uwBlkCnt++;
}
MEMBOX_UNLOCK(intSave);
return (nodeTmp == NULL) ? NULL : OS_MEMBOX_USER_ADDR(nodeTmp);
}
LITE_OS_SEC_TEXT UINT32 LOS_MemboxFree(VOID *pool, VOID *box)
{
LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
UINT32 ret = LOS_NOK;
UINT32 intSave;
if ((pool == NULL) || (box == NULL)) {
return LOS_NOK;
}
MEMBOX_LOCK(intSave);
do {
LOS_MEMBOX_NODE *node = OS_MEMBOX_NODE_ADDR(box);
if (OsCheckBoxMem(boxInfo, node) != LOS_OK) {
break;
}
node->pstNext = boxInfo->stFreeList.pstNext;
boxInfo->stFreeList.pstNext = node;
boxInfo->uwBlkCnt--;
ret = LOS_OK;
} while (0);
MEMBOX_UNLOCK(intSave);
return ret;
}
LITE_OS_SEC_TEXT_MINOR VOID LOS_MemboxClr(VOID *pool, VOID *box)
{
LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
if ((pool == NULL) || (box == NULL)) {
return;
}
(VOID)memset_s(box, (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE), 0,
(boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE));
}
LITE_OS_SEC_TEXT_MINOR VOID LOS_ShowBox(VOID *pool)
{
UINT32 index;
UINT32 intSave;
LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
LOS_MEMBOX_NODE *node = NULL;
if (pool == NULL) {
return;
}
MEMBOX_LOCK(intSave);
PRINT_INFO("membox(%p,0x%x,0x%x):\r\n", pool, boxInfo->uwBlkSize, boxInfo->uwBlkNum);
PRINT_INFO("free node list:\r\n");
for (node = boxInfo->stFreeList.pstNext, index = 0; node != NULL;
node = node->pstNext, ++index) {
PRINT_INFO("(%u,%p)\r\n", index, node);
}
PRINT_INFO("all node list:\r\n");
node = (LOS_MEMBOX_NODE *)(boxInfo + 1);
for (index = 0; index < boxInfo->uwBlkNum; ++index, node = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize)) {
PRINT_INFO("(%u,%p,%p)\r\n", index, node, node->pstNext);
}
MEMBOX_UNLOCK(intSave);
}
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemboxStatisticsGet(const VOID *boxMem, UINT32 *maxBlk,
UINT32 *blkCnt, UINT32 *blkSize)
{
if ((boxMem == NULL) || (maxBlk == NULL) || (blkCnt == NULL) || (blkSize == NULL)) {
return LOS_NOK;
}
*maxBlk = ((OS_MEMBOX_S *)boxMem)->uwBlkNum;
*blkCnt = ((OS_MEMBOX_S *)boxMem)->uwBlkCnt;
*blkSize = ((OS_MEMBOX_S *)boxMem)->uwBlkSize;
return LOS_OK;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "stdio.h"
#include "stdlib.h"
#include "los_signal.h"
#include "los_printf.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
#include "log.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
LITE_OS_SEC_TEXT_MINOR VOID OsPrintKillUsage(VOID)
{
PRINTK("\nkill: usage: kill [sigspec] [pid]\n");
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdKill(INT32 argc, const CHAR **argv)
{
#define ARG_NUM 2
INT32 sigNo = 0;
INT32 pidNo = 0;
INT32 ret;
CHAR *endPtr = NULL;
if (argc == ARG_NUM) {
sigNo = strtoul(argv[0], &endPtr, 0);
if (*endPtr != 0) {
PRINTK("\nsigNo can't access %s.\n", argv[0]);
goto ERROR;
}
endPtr = NULL;
pidNo = strtoul(argv[1], &endPtr, 0);
if (*endPtr != 0) {
PRINTK("\npidNo can't access %s.\n", argv[1]);
goto ERROR;
}
ret = OsKill(pidNo, abs(sigNo), OS_USER_KILL_PERMISSION);
HILOG_INFO(LOG_CORE, "Send signal(%d) to pidNo = %d!\n", abs(sigNo), pidNo);
if (ret == -1) {
HILOG_ERROR(LOG_CORE, "Kill fail ret = %d! Operation not permitted\n", ret);
goto ERROR;
}
if (ret < 0) {
PRINTK("\n Kill fail ret = %d! process not exist or sigNo is invalid\n", ret);
goto ERROR;
}
} else {
PRINTK("\nPara number errno!\n");
goto ERROR;
}
return 0;
ERROR:
OsPrintKillUsage();
return 0;
}
#ifdef LOSCFG_SHELL
SHELLCMD_ENTRY(kill_shellcmd, CMD_TYPE_EX, "kill", 2, (CmdCallBackFunc)OsShellCmdKill);
#endif

69
kernel/base/misc/los_misc.c Executable file
View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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
#endif /* __cplusplus */
LITE_OS_SEC_TEXT UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary)
{
if ((addr + boundary - 1) > addr) {
return (addr + boundary - 1) & ~((UINTPTR)(boundary - 1));
} else {
return addr & ~((UINTPTR)(boundary - 1));
}
}
LITE_OS_SEC_TEXT_MINOR VOID LOS_Msleep(UINT32 msecs)
{
UINT32 interval;
if (msecs == 0) {
interval = 0;
} else {
interval = LOS_MS2Tick(msecs);
if (interval == 0) {
interval = 1;
}
}
(VOID)LOS_TaskDelay(interval);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

125
kernel/base/misc/los_stackinfo.c Executable file
View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_stackinfo_pri.h"
#include "los_printf_pri.h"
#include "los_config.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
const StackInfo *g_stackInfo = NULL;
UINT32 g_stackNum;
UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed)
{
UINT32 size;
const UINTPTR *tmp = NULL;
if (*stackTop == OS_STACK_MAGIC_WORD) {
tmp = stackTop + 1;
while ((tmp < stackBottom) && (*tmp == OS_STACK_INIT)) {
tmp++;
}
size = (UINT32)((UINTPTR)stackBottom - (UINTPTR)tmp);
*peakUsed = (size == 0) ? size : (size + sizeof(CHAR *));
return LOS_OK;
} else {
*peakUsed = OS_INVALID_WATERLINE;
return LOS_NOK;
}
}
VOID OsExcStackCheck(VOID)
{
UINT32 index;
UINT32 cpuid;
UINTPTR *stackTop = NULL;
if (g_stackInfo == NULL) {
return;
}
for (index = 0; index < g_stackNum; index++) {
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
stackTop = (UINTPTR *)((UINTPTR)g_stackInfo[index].stackTop + cpuid * g_stackInfo[index].stackSize);
if (*stackTop != OS_STACK_MAGIC_WORD) {
PRINT_ERR("cpu:%u %s overflow , magic word changed to 0x%x\n",
LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, g_stackInfo[index].stackName, *stackTop);
}
}
}
}
VOID OsExcStackInfo(VOID)
{
UINT32 index;
UINT32 cpuid;
UINT32 size;
UINTPTR *stackTop = NULL;
UINTPTR *stack = NULL;
if (g_stackInfo == NULL) {
return;
}
PrintExcInfo("\n stack name cpu id stack addr total size used size\n"
" ---------- ------ --------- -------- --------\n");
for (index = 0; index < g_stackNum; index++) {
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
stackTop = (UINTPTR *)((UINTPTR)g_stackInfo[index].stackTop + cpuid * g_stackInfo[index].stackSize);
stack = (UINTPTR *)((UINTPTR)stackTop + g_stackInfo[index].stackSize);
(VOID)OsStackWaterLineGet(stack, stackTop, &size);
PrintExcInfo("%11s %-5d %-10p 0x%-8x 0x%-4x\n", g_stackInfo[index].stackName,
LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackTop, g_stackInfo[index].stackSize, size);
}
}
OsExcStackCheck();
}
VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum)
{
g_stackInfo = stackInfo;
g_stackNum = stackNum;
}
VOID OsStackInit(VOID *stacktop, UINT32 stacksize)
{
/* initialize the task stack, write magic num to stack top */
(VOID)memset_s(stacktop, stacksize, (INT32)OS_STACK_INIT, stacksize);
*((UINTPTR *)stacktop) = OS_STACK_MAGIC_WORD;
}
#ifdef LOSCFG_SHELL_CMD_DEBUG
SHELLCMD_ENTRY(stack_shellcmd, CMD_TYPE_EX, "stack", 1, (CmdCallBackFunc)OsExcStackInfo);
#endif

342
kernel/base/misc/mempt_shellcmd.c Executable file
View File

@@ -0,0 +1,342 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "stdlib.h"
#include "los_memory_pri.h"
#ifdef LOSCFG_MEM_RECORDINFO
#include "los_memrecord_pri.h"
#endif
#ifdef LOSCFG_SHELL_EXCINFO
#include "los_excinfo_pri.h"
#endif
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
#include "los_vm_common.h"
#include "los_vm_boot.h"
#include "los_vm_map.h"
#include "los_vm_dump.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define MEM_SIZE_1K 0x400
#define MEM_SIZE_1M 0x100000
#define MEMPT_ARG_NUM_2 2
#define MEM_SIZE_TO_KB(size) (((size) + (MEM_SIZE_1K >> 1)) / MEM_SIZE_1K)
#define MEM_SIZE_TO_MB(size) (((size) + (MEM_SIZE_1M >> 1)) / MEM_SIZE_1M)
VOID OsDumpMemByte(size_t length, UINTPTR addr)
{
size_t dataLen;
UINTPTR *alignAddr = NULL;
UINT32 count = 0;
dataLen = ALIGN(length, sizeof(UINTPTR));
alignAddr = (UINTPTR *)TRUNCATE(addr, sizeof(UINTPTR));
if ((dataLen == 0) || (alignAddr == NULL)) {
return;
}
while (dataLen) {
if (IS_ALIGNED(count, sizeof(CHAR *))) {
PRINTK("\n 0x%lx :", alignAddr);
#ifdef LOSCFG_SHELL_EXCINFO
WriteExcInfoToBuf("\n 0x%lx :", alignAddr);
#endif
}
#ifdef __LP64__
PRINTK("%0+16lx ", *alignAddr);
#else
PRINTK("%0+8lx ", *alignAddr);
#endif
#ifdef LOSCFG_SHELL_EXCINFO
#ifdef __LP64__
WriteExcInfoToBuf("0x%0+16x ", *alignAddr);
#else
WriteExcInfoToBuf("0x%0+8x ", *alignAddr);
#endif
#endif
alignAddr++;
dataLen -= sizeof(CHAR *);
count++;
}
PRINTK("\n");
#ifdef LOSCFG_SHELL_EXCINFO
WriteExcInfoToBuf("\n");
#endif
return;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemCheck(INT32 argc, const CHAR *argv[])
{
if (argc > 0) {
PRINTK("\nUsage: memcheck\n");
return OS_ERROR;
}
if (LOS_MemIntegrityCheck(m_aucSysMem1) == LOS_OK) {
PRINTK("system memcheck over, all passed!\n");
#ifdef LOSCFG_SHELL_EXCINFO
WriteExcInfoToBuf("system memcheck over, all passed!\n");
#endif
}
#ifdef LOSCFG_EXC_INTERACTION
if (LOS_MemIntegrityCheck(m_aucSysMem0) == LOS_OK) {
PRINTK("exc interaction memcheck over, all passed!\n");
#ifdef LOSCFG_SHELL_EXCINFO
WriteExcInfoToBuf("exc interaction memcheck over, all passed!\n");
#endif
}
#endif
return 0;
}
#ifdef LOSCFG_SHELL
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemRead(INT32 argc, const CHAR *argv[])
{
size_t tempAddr;
size_t length;
CHAR *ptrlen = NULL;
CHAR *ptrAddr = NULL;
if ((argc == 0) || (argc > 2)) { /* argc is num of parameters */
PRINTK("\nUsage: readreg [ADDRESS] [LENGTH]\n");
return OS_ERROR;
}
if (argc == 1) {
length = 0;
} else {
length = strtoul(argv[1], &ptrlen, 0);
if ((ptrlen == NULL) || (*ptrlen != 0)) {
PRINTK("readreg invalid length %s\n", argv[1]);
return OS_ERROR;
}
}
tempAddr = strtoul(argv[0], &ptrAddr, 0);
if ((ptrAddr == NULL) || (*ptrAddr != 0)) {
PRINTK("readreg invalid address %s\n", argv[0]);
return OS_ERROR;
}
if (OsVmAddrCheck(tempAddr, length) == LOS_OK) {
goto DONE;
}
PRINTK("readreg invalid address %s\n", argv[0]);
return OS_ERROR;
DONE:
OsDumpMemByte(length, tempAddr);
return 0;
}
LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdSectionInfo(INT32 argc, const CHAR *argv[])
{
size_t textLen = &__text_end - &__text_start;
size_t dataLen = &__ram_data_end - &__ram_data_start;
size_t rodataLen = &__rodata_end - &__rodata_start;
size_t bssLen = &__bss_end - &__bss_start;
PRINTK("\r\n text data rodata bss\n");
if ((argc == 1) && (strcmp(argv[0], "-k") == 0)) {
PRINTK("Mem: %-9lu %-10lu %-10lu %-10lu\n", MEM_SIZE_TO_KB(textLen), MEM_SIZE_TO_KB(dataLen),
MEM_SIZE_TO_KB(rodataLen), MEM_SIZE_TO_KB(bssLen));
} else if ((argc == 1) && (strcmp(argv[0], "-m") == 0)) {
PRINTK("Mem: %-9lu %-10lu %-10lu %-10lu\n", MEM_SIZE_TO_MB(textLen), MEM_SIZE_TO_MB(dataLen),
MEM_SIZE_TO_MB(rodataLen), MEM_SIZE_TO_MB(bssLen));
} else {
PRINTK("Mem: %-9lu %-10lu %-10lu %-10lu\n", textLen, dataLen, rodataLen, bssLen);
}
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OsShellCmdFreeInfo(INT32 argc, const CHAR *argv[])
{
#ifdef LOSCFG_EXC_INTERACTION
UINT32 memUsed0 = LOS_MemTotalUsedGet(m_aucSysMem0);
UINT32 totalMem0 = LOS_MemPoolSizeGet(m_aucSysMem0);
UINT32 freeMem0 = totalMem0 - memUsed0;
#endif
UINT32 memUsed = LOS_MemTotalUsedGet(m_aucSysMem1);
UINT32 totalMem = LOS_MemPoolSizeGet(m_aucSysMem1);
UINT32 freeMem = totalMem - memUsed;
UINT32 usedCount, totalCount;
UINT32 memUsedHeap = memUsed;
OsVmPhysUsedInfoGet(&usedCount, &totalCount);
totalMem = SYS_MEM_SIZE_DEFAULT;
memUsed = SYS_MEM_SIZE_DEFAULT - (totalCount << PAGE_SHIFT);
memUsed += (usedCount << PAGE_SHIFT) - freeMem;
freeMem = totalMem - memUsed;
if ((argc == 0) ||
((argc == 1) && (strcmp(argv[0], "-k") == 0)) ||
((argc == 1) && (strcmp(argv[0], "-m") == 0))) {
#ifdef LOSCFG_EXC_INTERACTION
PRINTK("\r\n***** Mem:system mem Mem1:exception interaction mem *****\n");
#endif
PRINTK("\r\n total used free heap\n");
}
if ((argc == 1) && (strcmp(argv[0], "-k") == 0)) {
PRINTK("Mem: %-9u %-10u %-10u %-10u\n", MEM_SIZE_TO_KB(totalMem), MEM_SIZE_TO_KB(memUsed),
MEM_SIZE_TO_KB(freeMem), MEM_SIZE_TO_KB(memUsedHeap));
#ifdef LOSCFG_EXC_INTERACTION
PRINTK("Mem1: %-9u %-10u %-10u\n", MEM_SIZE_TO_KB(totalMem), MEM_SIZE_TO_KB(memUsed),
MEM_SIZE_TO_KB(freeMem));
#endif
} else if ((argc == 1) && (strcmp(argv[0], "-m") == 0)) {
PRINTK("Mem: %-9u %-10u %-10u %-10u\n", MEM_SIZE_TO_MB(totalMem), MEM_SIZE_TO_MB(memUsed),
MEM_SIZE_TO_MB(freeMem), MEM_SIZE_TO_MB(memUsedHeap));
#ifdef LOSCFG_EXC_INTERACTION
PRINTK("Mem1: %-9u %-10u %-10u\n", MEM_SIZE_TO_MB(totalMem), MEM_SIZE_TO_MB(memUsed),
MEM_SIZE_TO_MB(freeMem));
#endif
} else if (argc == 0) {
PRINTK("Mem: %-9u %-10u %-10u %-10u\n", totalMem, memUsed, freeMem, memUsedHeap);
#ifdef LOSCFG_EXC_INTERACTION
PRINTK("Mem1: %-9u %-10u %-10u\n", totalMem0, memUsed0, freeMem0);
#endif
} else {
PRINTK("\nUsage: free or free [-k/-m]\n");
return OS_ERROR;
}
return 0;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdFree(INT32 argc, const CHAR *argv[])
{
if (argc > 1) {
PRINTK("\nUsage: free or free [-k/-m]\n");
return OS_ERROR;
}
if (OsShellCmdFreeInfo(argc, argv) != 0) {
return OS_ERROR;
}
OsShellCmdSectionInfo(argc, argv);
return 0;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdUname(INT32 argc, const CHAR *argv[])
{
if (argc == 0) {
PRINTK("%s\n", KERNEL_NAME);
return 0;
}
if (argc == 1) {
if (strcmp(argv[0], "-a") == 0) {
PRINTK("%s %d.%d.%d.%d %s %s\n", KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE,\
__DATE__, __TIME__);
return 0;
} else if (strcmp(argv[0], "-s") == 0) {
PRINTK("%s\n", KERNEL_NAME);
return 0;
} else if (strcmp(argv[0], "-t") == 0) {
PRINTK("build date : %s %s\n", __DATE__, __TIME__);
return 0;
} else if (strcmp(argv[0], "-v") == 0) {
PRINTK("%d.%d.%d.%d\n", KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE);
return 0;
} else if (strcmp(argv[0], "--help") == 0) {
PRINTK("-a, print all information\n"
"-s, print the kernel name\n"
"-t, print the build date\n"
"-v, print the kernel version\n");
return 0;
}
}
PRINTK("uname: invalid option %s\n"
"Try 'uname --help' for more information.\n",
argv[0]);
return OS_ERROR;
}
#ifdef LOSCFG_MEM_LEAKCHECK
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemUsed(INT32 argc, const CHAR *argv[])
{
if (argc > 0) {
PRINTK("\nUsage: memused\n");
return OS_ERROR;
}
OsMemUsedNodeShow(m_aucSysMem1);
#ifdef LOSCFG_EXC_INTERACTION
PRINTK("\n exc interaction memory\n");
OsMemUsedNodeShow(m_aucSysMem0);
#endif
return 0;
}
#endif
#ifdef LOSCFG_MEM_RECORDINFO
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemRecordEnable(INT32 argc, const CHAR *argv[])
{
OsMemRecordShowSet(1);
return 0;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdMemRecordDisable(INT32 argc, const CHAR *argv[])
{
OsMemRecordShowSet(0);
return 0;
}
SHELLCMD_ENTRY(memshowenable_shellcmd, CMD_TYPE_EX, "memshowenable", 0,
(CmdCallBackFunc)OsShellCmdMemRecordEnable);
SHELLCMD_ENTRY(memshowdisable_shellcmd, CMD_TYPE_EX, "memshowdisable", 0,
(CmdCallBackFunc)OsShellCmdMemRecordDisable);
#endif
#ifdef LOSCFG_MEM_LEAKCHECK
SHELLCMD_ENTRY(memused_shellcmd, CMD_TYPE_EX, "memused", 0, (CmdCallBackFunc)OsShellCmdMemUsed);
#endif
#ifdef LOSCFG_SHELL_CMD_DEBUG
SHELLCMD_ENTRY(memcheck_shellcmd, CMD_TYPE_EX, "memcheck", 0, (CmdCallBackFunc)OsShellCmdMemCheck);
SHELLCMD_ENTRY(readreg_shellcmd, CMD_TYPE_EX, "readreg", MEMPT_ARG_NUM_2, (CmdCallBackFunc)OsShellCmdMemRead);
#endif
SHELLCMD_ENTRY(free_shellcmd, CMD_TYPE_EX, "free", XARGS, (CmdCallBackFunc)OsShellCmdFree);
SHELLCMD_ENTRY(uname_shellcmd, CMD_TYPE_EX, "uname", XARGS, (CmdCallBackFunc)OsShellCmdUname);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

147
kernel/base/misc/swtmr_shellcmd.c Executable file
View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_config.h"
#ifdef LOSCFG_SHELL_CMD_DEBUG
#include "stdlib.h"
#include "los_swtmr_pri.h"
#include "shcmd.h"
#include "shell.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define SWTMR_STRLEN 12
LITE_OS_SEC_DATA_MINOR STATIC CHAR g_shellSwtmrMode[][SWTMR_STRLEN] = {
"Once",
"Period",
"NSD",
"OPP",
};
LITE_OS_SEC_DATA_MINOR STATIC CHAR g_shellSwtmrStatus[][SWTMR_STRLEN] = {
"UnUsed",
"Created",
"Ticking",
};
STATIC VOID OsPrintSwtmrMsg(const SWTMR_CTRL_S *swtmr)
{
PRINTK("0x%08x "
"%-7s "
"%-6s "
"%-6u "
"%-6u "
"0x%08x "
"%p\n",
swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT,
g_shellSwtmrStatus[swtmr->ucState],
g_shellSwtmrMode[swtmr->ucMode],
swtmr->uwInterval,
swtmr->uwCount,
swtmr->uwArg,
swtmr->pfnHandler);
}
STATIC INLINE VOID OsPrintSwtmrMsgHead(VOID)
{
PRINTK("\r\nSwTmrID State Mode Interval Count Arg handlerAddr\n");
PRINTK("---------- ------- ------- --------- ------- ---------- --------\n");
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSwtmrInfoGet(INT32 argc, const UINT8 **argv)
{
#define OS_ALL_SWTMR_MASK 0xffffffff
SWTMR_CTRL_S *swtmr = g_swtmrCBArray;
SWTMR_CTRL_S *swtmr1 = g_swtmrCBArray;
UINT16 index;
size_t timerID;
UINT16 num = 0;
CHAR *endPtr = NULL;
if (argc > 1) {
PRINTK("\nUsage: swtmr [ID]\n");
return OS_ERROR;
}
if (argc == 0) {
timerID = OS_ALL_SWTMR_MASK;
} else {
timerID = strtoul((CHAR *)argv[0], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0) || (timerID > LOSCFG_BASE_CORE_SWTMR_LIMIT)) {
PRINTK("\nswtmr ID can't access %s.\n", argv[0]);
return OS_ERROR;
}
}
for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr1++) {
if (swtmr1->ucState == 0) {
num = num + 1;
}
}
if (num == LOSCFG_BASE_CORE_SWTMR_LIMIT) {
PRINTK("\r\nThere is no swtmr was created!\n");
return OS_ERROR;
}
if (timerID == OS_ALL_SWTMR_MASK) {
for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
if (swtmr->ucState != 0) {
OsPrintSwtmrMsgHead();
OsPrintSwtmrMsg(swtmr);
}
}
} else {
for (index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
if ((timerID == (size_t)(swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT)) && (swtmr->ucState != 0)) {
OsPrintSwtmrMsgHead();
OsPrintSwtmrMsg(swtmr);
return LOS_OK;
}
}
PRINTK("\r\nThe SwTimerID is not exist.\n");
}
return LOS_OK;
}
SHELLCMD_ENTRY(swtmr_shellcmd, CMD_TYPE_EX, "swtmr", 1, (CmdCallBackFunc)OsShellCmdSwtmrInfoGet);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* LOSCFG_SHELL */

View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_config.h"
#include "los_swtmr.h"
#include "los_sem_pri.h"
#include "los_queue_pri.h"
#include "los_swtmr_pri.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define SYSINFO_ENABLED(x) (((x) == YES) ? "YES" : "NO")
UINT32 OsShellCmdTaskCntGet(VOID)
{
UINT32 loop;
UINT32 taskCnt = 0;
UINT32 intSave;
LosTaskCB *taskCB = NULL;
intSave = LOS_IntLock();
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (LosTaskCB *)g_taskCBArray + loop;
if (OsTaskIsUnused(taskCB)) {
continue;
}
taskCnt++;
}
LOS_IntRestore(intSave);
return taskCnt;
}
UINT32 OsShellCmdSemCntGet(VOID)
{
UINT32 loop;
UINT32 semCnt = 0;
UINT32 intSave;
LosSemCB *semNode = NULL;
intSave = LOS_IntLock();
for (loop = 0; loop < LOSCFG_BASE_IPC_SEM_LIMIT; loop++) {
semNode = GET_SEM(loop);
if (semNode->semStat == OS_SEM_USED) {
semCnt++;
}
}
LOS_IntRestore(intSave);
return semCnt;
}
UINT32 OsShellCmdQueueCntGet(VOID)
{
UINT32 loop;
UINT32 queueCnt = 0;
UINT32 intSave;
LosQueueCB *queueCB = NULL;
intSave = LOS_IntLock();
queueCB = g_allQueue;
for (loop = 0; loop < LOSCFG_BASE_IPC_QUEUE_LIMIT; loop++, queueCB++) {
if (queueCB->queueState == OS_QUEUE_INUSED) {
queueCnt++;
}
}
LOS_IntRestore(intSave);
return queueCnt;
}
UINT32 OsShellCmdSwtmrCntGet(VOID)
{
UINT32 loop;
UINT32 swtmrCnt = 0;
UINT32 intSave;
SWTMR_CTRL_S *swtmrCB = NULL;
intSave = LOS_IntLock();
swtmrCB = g_swtmrCBArray;
for (loop = 0; loop < LOSCFG_BASE_CORE_SWTMR_LIMIT; loop++, swtmrCB++) {
if (swtmrCB->ucState != OS_SWTMR_STATUS_UNUSED) {
swtmrCnt++;
}
}
LOS_IntRestore(intSave);
return swtmrCnt;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdSystemInfoGet(VOID)
{
UINT8 isTaskEnable = YES;
UINT8 isSemEnable = LOSCFG_BASE_IPC_SEM;
UINT8 isQueueEnable = LOSCFG_BASE_IPC_QUEUE;
UINT8 isSwtmrEnable = LOSCFG_BASE_CORE_SWTMR;
PRINTK("\n Module Used Total Enabled\n");
PRINTK("--------------------------------------------\n");
PRINTK(" Task %-10u%-10d%s\n",
OsShellCmdTaskCntGet(),
LOSCFG_BASE_CORE_TSK_LIMIT,
SYSINFO_ENABLED(isTaskEnable));
PRINTK(" Sem %-10u%-10d%s\n",
OsShellCmdSemCntGet(),
LOSCFG_BASE_IPC_SEM_LIMIT,
SYSINFO_ENABLED(isSemEnable));
PRINTK(" Queue %-10u%-10d%s\n",
OsShellCmdQueueCntGet(),
LOSCFG_BASE_IPC_QUEUE_LIMIT,
SYSINFO_ENABLED(isQueueEnable));
PRINTK(" SwTmr %-10u%-10d%s\n",
OsShellCmdSwtmrCntGet(),
LOSCFG_BASE_CORE_SWTMR_LIMIT,
SYSINFO_ENABLED(isSwtmrEnable));
}
INT32 OsShellCmdSystemInfo(INT32 argc, const CHAR **argv)
{
if (argc == 0) {
OsShellCmdSystemInfoGet();
return 0;
}
PRINTK("systeminfo: invalid option %s\n"
"Systeminfo has NO ARGS.\n",
argv[0]);
return -1;
}
#ifdef LOSCFG_SHELL
SHELLCMD_ENTRY(systeminfo_shellcmd, CMD_TYPE_EX, "systeminfo", 1, (CmdCallBackFunc)OsShellCmdSystemInfo);
#endif /* LOSCFG_SHELL */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

501
kernel/base/misc/task_shellcmd.c Executable file
View File

@@ -0,0 +1,501 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "stdlib.h"
#include "los_config.h"
#include "los_exc.h"
#include "los_memstat_pri.h"
#include "los_sem_pri.h"
#include "los_seq_buf.h"
#include "los_task_pri.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#ifdef LOSCFG_SHELL_EXCINFO
#include "los_excinfo_pri.h"
#endif
#include "los_process_pri.h"
#include "los_vm_dump.h"
#ifdef LOSCFG_FS_VFS
#include "fs/fs.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define OS_PROCESS_MEM_INFO 0x2U
#define OS_PROCESS_INFO_LEN (g_processMaxNum * (sizeof(LosProcessCB)))
#define OS_PROCESS_GROUP_INFO_LEN (g_processMaxNum * sizeof(UINT32))
#define OS_PROCESS_UID_INFO_LEN (g_processMaxNum * sizeof(UINT32))
#define OS_PROCESS_MEM_ALL_INFO_LEN (g_processMaxNum * PROCESS_MEMINFO_LEN)
#ifdef LOSCFG_KERNEL_CPUP
#define OS_PROCESS_CPUP_INFO_LEN (g_processMaxNum * sizeof(CPUP_INFO_S))
#define OS_PROCESS_CPUP_ALLINFO_LEN (OS_PROCESS_CPUP_INFO_LEN * 3)
#else
#define OS_PROCESS_CPUP_ALLINFO_LEN 0
#endif
#define OS_PROCESS_ALL_INFO_LEN (g_processMaxNum * (sizeof(LosProcessCB) + sizeof(UINT32)) + \
OS_PROCESS_CPUP_ALLINFO_LEN + OS_PROCESS_UID_INFO_LEN)
#ifdef LOSCFG_KERNEL_CPUP
LITE_OS_SEC_BSS STATIC CPUP_INFO_S *g_processCpupAll = NULL;
LITE_OS_SEC_BSS STATIC CPUP_INFO_S *g_processCpup10s = NULL;
LITE_OS_SEC_BSS STATIC CPUP_INFO_S *g_processCpup1s = NULL;
#endif
STATIC UINT32 *g_taskWaterLine = NULL;
#define OS_INVALID_SEM_ID 0xFFFFFFFF
#define OS_TASK_WATER_LINE_SIZE (g_taskMaxNum * sizeof(UINT32))
#define OS_TASK_INFO_LEN (g_taskMaxNum * sizeof(LosTaskCB))
#define OS_TASK_ALL_INFO_LEN (g_taskMaxNum * (sizeof(LosTaskCB) + sizeof(UINT32)))
#ifdef LOSCFG_FS_VFS
#define PROCESS_INFO_SHOW(seqBuf, arg...) do { \
if (seqBuf != NULL) { \
(void)LosBufPrintf((struct SeqBuf *)seqBuf, ##arg); \
} else { \
PRINTK(arg); \
} \
} while (0)
#else
#define PROCESS_INFO_SHOW(seqBuf, arg...) PRINTK(arg)
#endif
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdProcessMode(UINT16 mode)
{
if (mode == OS_KERNEL_MODE) {
return (UINT8 *)"kernel";
} else if (mode == OS_USER_MODE) {
return (UINT8 *)"user";
}
return (UINT8 *)"ERROR";
}
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdSchedPolicy(UINT16 policy)
{
if (policy == LOS_SCHED_RR) {
return (UINT8 *)"RR";
} else if (policy == LOS_SCHED_FIFO) {
return (UINT8 *)"FIFO";
}
return (UINT8 *)"ERROR";
}
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellProcessStatus(UINT16 status)
{
status = status & OS_PROCESS_STATUS_MASK;
if (status & OS_PROCESS_STATUS_ZOMBIES) {
return (UINT8 *)"Zombies";
} else if (status & OS_PROCESS_STATUS_INIT) {
return (UINT8 *)"Init";
} else if (status & OS_PROCESS_STATUS_RUNNING) {
return (UINT8 *)"Running";
} else if (status & OS_PROCESS_STATUS_READY) {
return (UINT8 *)"Ready";
} else {
if (status & OS_PROCESS_STATUS_PEND) {
return (UINT8 *)"Pend";
}
}
return (UINT8 *)"Invalid";
}
STATIC VOID OsShellCmdProcessTitle(VOID *seqBuf, UINT16 flag)
{
PROCESS_INFO_SHOW(seqBuf, "\r\n PID PPID PGID UID Status ");
if (flag & OS_PROCESS_MEM_INFO) {
PROCESS_INFO_SHOW(seqBuf, "VirtualMem ShareMem PhysicalMem ");
}
#ifdef LOSCFG_KERNEL_CPUP
if (flag & OS_PROCESS_INFO_ALL) {
PROCESS_INFO_SHOW(seqBuf, "CPUUSE CPUUSE10s CPUUSE1s ");
} else {
PROCESS_INFO_SHOW(seqBuf, "CPUUSE10s ");
}
#endif /* LOSCFG_KERNEL_CPUP */
if (flag & OS_PROCESS_INFO_ALL) {
PROCESS_INFO_SHOW(seqBuf, "Policy Priority MTID TaskTotal Mode ");
}
PROCESS_INFO_SHOW(seqBuf, " PName\n");
}
STATIC VOID OsShellCmdProcessInfoShow(const LosProcessCB *processCB, const INT32 *group,
const UINT32 *memArray, VOID *seqBuf, UINT16 flag)
{
const UINT32 *procMemUsage = NULL;
const INT32 *user = (const INT32 *)((UINTPTR)group + OS_PROCESS_GROUP_INFO_LEN);
UINT32 pid = processCB->processID;
PROCESS_INFO_SHOW(seqBuf, "%5u%6d%5d%10d%8s", pid, (INT32)processCB->parentProcessID, group[pid], user[pid],
OsShellProcessStatus(processCB->processStatus));
if (flag & OS_PROCESS_MEM_INFO) {
procMemUsage = &memArray[pid * PROCESS_VM_INDEX_MAX];
PROCESS_INFO_SHOW(seqBuf, "%#11x%#9x%#12x", procMemUsage[PROCESS_VM_INDEX], procMemUsage[PROCESS_SM_INDEX],
procMemUsage[PROCESS_PM_INDEX]);
}
#ifdef LOSCFG_KERNEL_CPUP
if (flag & OS_PROCESS_INFO_ALL) {
PROCESS_INFO_SHOW(seqBuf, "%5u.%1u%8u.%1u%7u.%-1u ",
g_processCpupAll[pid].uwUsage / LOS_CPUP_PRECISION_MULT,
g_processCpupAll[pid].uwUsage % LOS_CPUP_PRECISION_MULT,
g_processCpup10s[pid].uwUsage / LOS_CPUP_PRECISION_MULT,
g_processCpup10s[pid].uwUsage % LOS_CPUP_PRECISION_MULT,
g_processCpup1s[pid].uwUsage / LOS_CPUP_PRECISION_MULT,
g_processCpup1s[pid].uwUsage % LOS_CPUP_PRECISION_MULT);
} else {
PROCESS_INFO_SHOW(seqBuf, "%8u.%1u ",
g_processCpup10s[pid].uwUsage / LOS_CPUP_PRECISION_MULT,
g_processCpup10s[pid].uwUsage % LOS_CPUP_PRECISION_MULT);
}
#endif /* LOSCFG_KERNEL_CPUP */
if (flag & OS_PROCESS_INFO_ALL) {
PROCESS_INFO_SHOW(seqBuf, "%6s%9u%5d%10u%7s ",
OsShellCmdSchedPolicy(processCB->policy), processCB->priority,
(INT32)processCB->threadGroupID, processCB->threadNumber,
OsShellCmdProcessMode(processCB->processMode));
}
PROCESS_INFO_SHOW(seqBuf, " %-32s\n", processCB->processName);
}
STATIC VOID OsShellCmdAllProcessInfoShow(const LosProcessCB *pcbArray, const INT32 *group,
const UINT32 *memArray, VOID *seqBuf, UINT16 flag)
{
const LosProcessCB *processCB = NULL;
UINT32 pid;
for (pid = 1; pid < g_processMaxNum; ++pid) {
processCB = pcbArray + pid;
if (OsProcessIsUnused(processCB)) {
continue;
}
OsShellCmdProcessInfoShow(processCB, group, memArray, seqBuf, flag);
}
}
STATIC VOID OsProcessMemUsageGet(UINT32 *memArray)
{
UINT32 pid;
LosProcessCB *processCB = NULL;
UINT32 *proMemUsage = NULL;
for (pid = 0; pid < g_processMaxNum; ++pid) {
processCB = g_processCBArray + pid;
if (OsProcessIsUnused(processCB)) {
continue;
}
proMemUsage = &memArray[pid * PROCESS_VM_INDEX_MAX];
/* Process memory usage statistics, idle task defaults to 0 */
if (pid == OsGetIdleProcessID()) {
proMemUsage[PROCESS_VM_INDEX] = 0;
proMemUsage[PROCESS_SM_INDEX] = 0;
proMemUsage[PROCESS_PM_INDEX] = 0;
} else {
proMemUsage[PROCESS_VM_INDEX] = OsShellCmdProcessVmUsage(processCB->vmSpace);
OsShellCmdProcessPmUsage(processCB->vmSpace, &proMemUsage[PROCESS_SM_INDEX],
&proMemUsage[PROCESS_PM_INDEX]);
}
}
}
STATIC UINT32 OsProcessInfoGet(LosProcessCB **pcbArray, INT32 **group, UINT32 **memArray, UINT16 flag)
{
UINT32 len = OS_PROCESS_ALL_INFO_LEN;
LosProcessCB *processCB = NULL;
INT32 *user = NULL;
(VOID)memcpy_s(*pcbArray, OS_PROCESS_INFO_LEN, g_processCBArray, OS_PROCESS_INFO_LEN);
*group = (INT32 *)((UINTPTR)*pcbArray + OS_PROCESS_INFO_LEN);
user = (INT32 *)((UINTPTR)*group + OS_PROCESS_GROUP_INFO_LEN);
for (UINT32 pid = 0; pid < g_processMaxNum; ++pid) {
processCB = *pcbArray + pid;
if (OsProcessIsUnused(processCB)) {
continue;
}
if (processCB->group != NULL) {
(*group)[processCB->processID] = processCB->group->groupID;
} else {
(*group)[processCB->processID] = -1;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
if (processCB->user != NULL) {
user[processCB->processID] = processCB->user->userID;
} else {
user[processCB->processID] = -1;
}
#else
user[processCB->processID] = 0;
#endif
}
#ifdef LOSCFG_KERNEL_CPUP
g_processCpupAll = (CPUP_INFO_S *)((UINTPTR)user + OS_PROCESS_UID_INFO_LEN);
g_processCpup10s = (CPUP_INFO_S *)((UINTPTR)g_processCpupAll + OS_PROCESS_CPUP_INFO_LEN);
g_processCpup1s = (CPUP_INFO_S *)((UINTPTR)g_processCpup10s + OS_PROCESS_CPUP_INFO_LEN);
(VOID)OsAllCpuUsageUnsafe(LOSCFG_BASE_CORE_PROCESS_LIMIT, g_processCpupAll, CPUP_ALL_TIME, 1);
(VOID)OsAllCpuUsageUnsafe(LOSCFG_BASE_CORE_PROCESS_LIMIT, g_processCpup10s, CPUP_LAST_TEN_SECONDS, 1);
(VOID)OsAllCpuUsageUnsafe(LOSCFG_BASE_CORE_PROCESS_LIMIT, g_processCpup1s, CPUP_LAST_ONE_SECONDS, 1);
#endif
if (flag & OS_PROCESS_MEM_INFO) {
*memArray = (UINT32 *)((UINTPTR)*pcbArray + OS_PROCESS_ALL_INFO_LEN);
OsProcessMemUsageGet(*memArray);
len += OS_PROCESS_MEM_ALL_INFO_LEN;
}
return len;
}
STATIC VOID OsShellCmdProcessInfoData(const LosProcessCB *pcbArray, const INT32 *group,
const UINT32 *memArray, VOID *seqBuf, UINT16 flag)
{
OsShellCmdProcessTitle(seqBuf, flag);
OsShellCmdAllProcessInfoShow(pcbArray, group, memArray, seqBuf, flag);
}
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdConvertTskStatus(UINT16 taskStatus)
{
if (taskStatus & OS_TASK_STATUS_INIT) {
return (UINT8 *)"Init";
} else if (taskStatus & OS_TASK_STATUS_RUNNING) {
return (UINT8 *)"Running";
} else if (taskStatus & OS_TASK_STATUS_READY) {
return (UINT8 *)"Ready";
} else {
if (taskStatus & OS_TASK_STATUS_DELAY) {
return (UINT8 *)"Delay";
} else if (taskStatus & OS_TASK_STATUS_PEND_TIME) {
if (taskStatus & OS_TASK_STATUS_SUSPEND) {
return (UINT8 *)"SuspendTime";
} else if (taskStatus & OS_TASK_STATUS_PEND) {
return (UINT8 *)"PendTime";
}
} else if (taskStatus & OS_TASK_STATUS_PEND) {
return (UINT8 *)"Pend";
} else if (taskStatus & OS_TASK_STATUS_SUSPEND) {
return (UINT8 *)"Suspend";
} else if (taskStatus & OS_TASK_STATUS_EXIT) {
return (UINT8 *)"Exit";
}
}
return (UINT8 *)"Invalid";
}
STATIC VOID OsShellCmdTaskWaterLineGet(const LosTaskCB *allTaskArray)
{
const LosTaskCB *taskCB = NULL;
UINT32 loop;
for (loop = 0; loop < g_taskMaxNum; ++loop) {
taskCB = allTaskArray + loop;
if (OsTaskIsUnused(taskCB)) {
continue;
}
(VOID)OsStackWaterLineGet((const UINTPTR *)((UINTPTR)taskCB->topOfStack + taskCB->stackSize),
(const UINTPTR *)taskCB->topOfStack, &g_taskWaterLine[taskCB->taskID]);
}
}
STATIC VOID OsShellCmdTskInfoTitle(VOID *seqBuf, UINT16 flag)
{
PROCESS_INFO_SHOW(seqBuf, "\r\n TID PID ");
#if (LOSCFG_KERNEL_SMP == YES)
PROCESS_INFO_SHOW(seqBuf, "Affi CPU ");
#endif
PROCESS_INFO_SHOW(seqBuf, " Status StackSize WaterLine ");
if (flag & OS_PROCESS_INFO_ALL) {
#ifdef LOSCFG_SHELL_CMD_DEBUG
PROCESS_INFO_SHOW(seqBuf, " StackPoint TopOfStack EventMask SemID ");
#endif
PROCESS_INFO_SHOW(seqBuf, "Policy Priority ");
}
PROCESS_INFO_SHOW(seqBuf, " MEMUSE TaskName\n");
}
#ifdef LOSCFG_SHELL_CMD_DEBUG
STATIC INLINE UINT32 OsGetSemID(const LosTaskCB *taskCB)
{
UINT32 semID = OS_INVALID_SEM_ID;
if (taskCB->taskSem != NULL) {
semID = ((LosSemCB *)taskCB->taskSem)->semID;
}
return semID;
}
#endif
STATIC INLINE VOID OsShellTskInfoData(const LosTaskCB *taskCB, VOID *seqBuf, UINT16 flag)
{
PROCESS_INFO_SHOW(seqBuf, " %4u%5u", taskCB->taskID, taskCB->processID);
#if (LOSCFG_KERNEL_SMP == YES)
PROCESS_INFO_SHOW(seqBuf, "%#5x%4d ", taskCB->cpuAffiMask, (INT16)(taskCB->currCpu));
#endif
PROCESS_INFO_SHOW(seqBuf, "%12s%#10x%#10x", OsShellCmdConvertTskStatus(taskCB->taskStatus),
taskCB->stackSize, g_taskWaterLine[taskCB->taskID]);
if (flag & OS_PROCESS_INFO_ALL) {
#ifdef LOSCFG_SHELL_CMD_DEBUG
PROCESS_INFO_SHOW(seqBuf, "%#12x%#12x%#10x%#12x", taskCB->stackPointer, taskCB->topOfStack,
taskCB->eventMask, OsGetSemID(taskCB));
#endif
PROCESS_INFO_SHOW(seqBuf, "%7s%9u", OsShellCmdSchedPolicy(taskCB->policy), taskCB->priority);
}
PROCESS_INFO_SHOW(seqBuf, "%#10x %-32s\n", OsTaskMemUsage(taskCB->taskID), taskCB->taskName);
}
STATIC VOID OsShellCmdAllTaskInfoData(const LosTaskCB *allTaskArray, VOID *seqBuf, UINT16 flag)
{
const LosTaskCB *taskCB = NULL;
UINT32 pid;
UINT32 loop;
for (pid = 1; pid < g_processMaxNum; ++pid) {
for (loop = 0; loop < g_taskMaxNum; ++loop) {
taskCB = allTaskArray + loop;
if (OsTaskIsUnused(taskCB) || (taskCB->processID != pid)) {
continue;
}
OsShellTskInfoData(taskCB, seqBuf, flag);
}
}
}
STATIC VOID OsShellCmdTskInfoData(const LosTaskCB *allTaskArray, VOID *seqBuf, UINT16 flag)
{
OsShellCmdTskInfoTitle(seqBuf, flag);
OsShellCmdAllTaskInfoData(allTaskArray, seqBuf, flag);
}
STATIC VOID OsProcessAndTaskInfoGet(LosProcessCB **pcbArray, INT32 **group, LosTaskCB **tcbArray,
UINT32 **memArray, UINT16 flag)
{
BOOL lockFlag = FALSE;
UINT32 intSave = 0;
UINT32 processInfoLen;
if (LOS_SpinHeld(&g_taskSpin) == FALSE) {
SCHEDULER_LOCK(intSave);
lockFlag = TRUE;
}
processInfoLen = OsProcessInfoGet(pcbArray, group, memArray, flag);
*tcbArray = (LosTaskCB *)((UINTPTR)*pcbArray + processInfoLen);
(VOID)memcpy_s(*tcbArray, OS_TASK_INFO_LEN, g_taskCBArray, OS_TASK_INFO_LEN);
g_taskWaterLine = (UINT32 *)((UINTPTR)*tcbArray + OS_TASK_INFO_LEN);
OsShellCmdTaskWaterLineGet(*tcbArray);
if (lockFlag == TRUE) {
SCHEDULER_UNLOCK(intSave);
}
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskID, VOID *seqBuf, UINT16 flag)
{
UINT32 size;
LosProcessCB *pcbArray = NULL;
INT32 *group = NULL;
LosTaskCB *tcbArray = NULL;
UINT32 *memArray = NULL;
if (taskID == OS_ALL_TASK_MASK) {
if (flag & OS_PROCESS_MEM_INFO) {
size = OS_PROCESS_ALL_INFO_LEN + OS_PROCESS_MEM_ALL_INFO_LEN + OS_TASK_ALL_INFO_LEN;
} else {
size = OS_PROCESS_ALL_INFO_LEN + OS_TASK_ALL_INFO_LEN;
}
pcbArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);
if (pcbArray == NULL) {
PRINT_ERR("Memory is not enough to save task info!\n");
return LOS_NOK;
}
(VOID)memset_s(pcbArray, size, 0, size);
OsProcessAndTaskInfoGet(&pcbArray, &group, &tcbArray, &memArray, flag);
OsShellCmdProcessInfoData(pcbArray, group, memArray, seqBuf, flag);
OsShellCmdTskInfoData(tcbArray, seqBuf, flag);
(VOID)LOS_MemFree(m_aucSysMem1, pcbArray);
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv)
{
UINT32 flag = 0;
flag |= OS_PROCESS_MEM_INFO;
if (argc < 2) { /* 2:Just as number of parameters */
if (argc == 1) {
if (strcmp("-a", argv[0]) == 0) {
flag |= OS_PROCESS_INFO_ALL;
} else {
PRINTK("Unknown option: %s\n", argv[0]);
goto TASK_HELP;
}
}
return OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, flag);
}
TASK_HELP:
PRINTK("usage: task or task -a\n");
return LOS_NOK;
}
#ifdef LOSCFG_SHELL
SHELLCMD_ENTRY(task_shellcmd, CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

265
kernel/base/misc/vm_shellcmd.c Executable file
View File

@@ -0,0 +1,265 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "stdlib.h"
#include "stdio.h"
#include "ctype.h"
#include "los_printf.h"
#include "string.h"
#include "securec.h"
#ifdef LOSCFG_SHELL
#include "shcmd.h"
#include "shell.h"
#endif
#include "los_oom.h"
#include "los_vm_dump.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define ARGC_2 2
#define ARGC_1 1
#define ARGC_0 0
#define VMM_CMD "vmm"
#define OOM_CMD "oom"
#define VMM_PMM_CMD "v2p"
LITE_OS_SEC_TEXT_MINOR VOID OsDumpKernelAspace(VOID)
{
LosVmSpace *kAspace = LOS_GetKVmSpace();
if (kAspace != NULL) {
OsDumpAspace(kAspace);
} else {
VM_ERR("kernel aspace is NULL");
}
return;
}
LITE_OS_SEC_TEXT_MINOR INT32 OsPid(const CHAR *str)
{
UINT32 len = strlen(str);
if (len <= 2) { // pid range is 0~63, max pid string length is 2
for (UINT32 i = 0; i < len; i++) {
if (isdigit(str[i]) == 0) {
return -1;
}
}
return atoi(str);
}
return -1;
}
LITE_OS_SEC_TEXT_MINOR VOID OsPrintUsage(VOID)
{
PRINTK("-a, print all vm address space information\n"
"-k, print the kernel vm address space information\n"
"pid(0~63), print process[pid] vm address space information\n"
"-h | --help, print vmm command usage\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsDoDumpVm(pid_t pid)
{
LosProcessCB *processCB = NULL;
if (OsProcessIDUserCheckInvalid(pid)) {
PRINTK("\tThe process [%d] not valid\n", pid);
return;
}
processCB = OS_PCB_FROM_PID(pid);
if (!OsProcessIsUnused(processCB) && (processCB->vmSpace != NULL)) {
OsDumpAspace(processCB->vmSpace);
} else {
PRINTK("\tThe process [%d] not active\n", pid);
}
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpVm(INT32 argc, const CHAR *argv[])
{
if (argc == 0) {
OsDumpAllAspace();
} else if (argc == 1) {
pid_t pid = OsPid(argv[0]);
if (strcmp(argv[0], "-a") == 0) {
OsDumpAllAspace();
} else if (strcmp(argv[0], "-k") == 0) {
OsDumpKernelAspace();
} else if (pid >= 0) {
OsDoDumpVm(pid);
} else if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) {
OsPrintUsage();
} else {
PRINTK("%s: invalid option: %s\n", VMM_CMD, argv[0]);
OsPrintUsage();
}
} else {
OsPrintUsage();
}
return OS_ERROR;
}
LITE_OS_SEC_TEXT_MINOR VOID V2PPrintUsage(VOID)
{
PRINTK("pid vaddr(0x1000000~0x3e000000), print physical address of virtual address\n"
"-h | --help, print v2p command usage\n");
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdV2P(INT32 argc, const CHAR *argv[])
{
UINT32 vaddr;
PADDR_T paddr;
CHAR *endPtr = NULL;
if (argc == 0) {
V2PPrintUsage();
} else if (argc == 1) {
if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) {
V2PPrintUsage();
}
} else if (argc == 2) {
pid_t pid = OsPid(argv[0]);
vaddr = strtoul((CHAR *)argv[1], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0)) {
PRINTK("vaddr %s invalid. should be in range(0x1000000~0x3e000000) \n", argv[1]);
return OS_ERROR;
} else {
if (pid >= 0) {
if (pid < g_taskMaxNum) {
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
if (!OsProcessIsUnused(processCB)) {
paddr = 0;
LOS_ArchMmuQuery(&processCB->vmSpace->archMmu, (VADDR_T)vaddr, &paddr, 0);
if (paddr == 0) {
PRINTK("vaddr %#x is not in range or mapped\n", vaddr);
} else {
PRINTK("vaddr %#x is paddr %#x\n", vaddr, paddr);
}
} else {
PRINTK("\tThe process [%d] not active\n", pid);
}
} else {
PRINTK("\tThe process [%d] not valid\n", pid);
}
} else {
PRINTK("%s: invalid option: %s %s\n", VMM_PMM_CMD, argv[0], argv[1]);
}
}
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpPmm(VOID)
{
OsVmPhysDump();
return OS_ERROR;
}
LITE_OS_SEC_TEXT_MINOR VOID OomPrintUsage(VOID)
{
PRINTK("\t-i [interval], set oom check interval (ms)\n"
"\t-m [mem byte], set oom low memory threshold (Byte)\n"
"\t-r [mem byte], set page cache reclaim memory threshold (Byte)\n"
"\t-h | --help, print vmm command usage\n");
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdOom(INT32 argc, const CHAR *argv[])
{
UINT32 lowMemThreshold;
UINT32 reclaimMemThreshold;
UINT32 checkInterval;
CHAR *endPtr = NULL;
if (argc == ARGC_0) {
OomInfodump();
} else if (argc == ARGC_1) {
if (strcmp(argv[0], "-h") != 0 && strcmp(argv[0], "--help") != 0) {
PRINTK("%s: invalid option: %s\n", OOM_CMD, argv[0]);
}
OomPrintUsage();
} else if (argc == ARGC_2) {
if (strcmp(argv[0], "-m") == 0) {
lowMemThreshold = strtoul((CHAR *)argv[1], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0)) {
PRINTK("[oom] low mem threshold %s(byte) invalid.\n", argv[1]);
return OS_ERROR;
} else {
OomSetLowMemThreashold(lowMemThreshold);
}
} else if (strcmp(argv[0], "-i") == 0) {
checkInterval = strtoul((CHAR *)argv[1], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0)) {
PRINTK("[oom] check interval %s(us) invalid.\n", argv[1]);
return OS_ERROR;
} else {
OomSetCheckInterval(checkInterval);
}
} else if (strcmp(argv[0], "-r") == 0) {
reclaimMemThreshold = strtoul((CHAR *)argv[1], &endPtr, 0);
if ((endPtr == NULL) || (*endPtr != 0)) {
PRINTK("[oom] reclaim mem threshold %s(byte) invalid.\n", argv[1]);
return OS_ERROR;
} else {
OomSetReclaimMemThreashold(reclaimMemThreshold);
}
} else {
PRINTK("%s: invalid option: %s %s\n", OOM_CMD, argv[0], argv[1]);
OomPrintUsage();
}
} else {
PRINTK("%s: invalid option\n", OOM_CMD);
OomPrintUsage();
}
return OS_ERROR;
}
#ifdef LOSCFG_SHELL_CMD_DEBUG
SHELLCMD_ENTRY(oom_shellcmd, CMD_TYPE_SHOW, OOM_CMD, 2, (CmdCallBackFunc)OsShellCmdOom);
SHELLCMD_ENTRY(vm_shellcmd, CMD_TYPE_SHOW, VMM_CMD, 1, (CmdCallBackFunc)OsShellCmdDumpVm);
SHELLCMD_ENTRY(v2p_shellcmd, CMD_TYPE_SHOW, VMM_PMM_CMD, 1, (CmdCallBackFunc)OsShellCmdV2P);
#endif
#ifdef LOSCFG_SHELL
SHELLCMD_ENTRY(pmm_shellcmd, CMD_TYPE_SHOW, "pmm", 0, (CmdCallBackFunc)OsShellCmdDumpPmm);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

323
kernel/base/mp/los_lockdep.c Executable file
View File

@@ -0,0 +1,323 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_base.h"
#include "los_spinlock.h"
#include "los_task_pri.h"
#include "los_printf_pri.h"
#include "los_atomic.h"
#include "los_exc.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
#define LOCKDEP_GET_NAME(lockDep, index) (((SPIN_LOCK_S *)((lockDep)->heldLocks[(index)].lockPtr))->name)
#define LOCKDEP_GET_ADDR(lockDep, index) ((lockDep)->heldLocks[(index)].lockAddr)
STATIC Atomic g_lockdepAvailable = 1;
/* atomic insurance for lockdep check */
STATIC INLINE VOID OsLockDepRequire(UINT32 *intSave)
{
*intSave = LOS_IntLock();
while (LOS_AtomicCmpXchg32bits(&g_lockdepAvailable, 0, 1)) {
/* busy waiting */
}
}
STATIC INLINE VOID OsLockDepRelease(UINT32 intSave)
{
LOS_AtomicSet(&g_lockdepAvailable, 1);
LOS_IntRestore(intSave);
}
STATIC INLINE UINT64 OsLockDepGetCycles(VOID)
{
UINT32 high, low;
LOS_GetCpuCycle(&high, &low);
/* combine cycleHi and cycleLo into 8 bytes cycles */
return (((UINT64)high << 32) + low); // 32 bits for lower half of UINT64
}
STATIC INLINE CHAR *OsLockDepErrorStringGet(enum LockDepErrType type)
{
CHAR *errorString = NULL;
switch (type) {
case LOCKDEP_ERR_DOUBLE_LOCK:
errorString = "double lock";
break;
case LOCKDEP_ERR_DEAD_LOCK:
errorString = "dead lock";
break;
case LOCKDEP_ERR_UNLOCK_WITOUT_LOCK:
errorString = "unlock without lock";
break;
case LOCKDEP_ERR_OVERFLOW:
errorString = "lockdep overflow";
break;
default:
errorString = "unknow error code";
break;
}
return errorString;
}
WEAK VOID OsLockDepPanic(enum LockDepErrType errType)
{
/* halt here */
(VOID)errType;
(VOID)LOS_IntLock();
OsBackTrace();
while (1) {}
}
STATIC VOID OsLockDepDumpLock(const LosTaskCB *task, const SPIN_LOCK_S *lock,
const VOID *requestAddr, enum LockDepErrType errType)
{
INT32 i;
const LockDep *lockDep = &task->lockDep;
const LosTaskCB *temp = task;
PrintExcInfo("lockdep check failed\n");
PrintExcInfo("error type : %s\n", OsLockDepErrorStringGet(errType));
PrintExcInfo("request addr : 0x%x\n", requestAddr);
while (1) {
PrintExcInfo("task name : %s\n", temp->taskName);
PrintExcInfo("task id : %u\n", temp->taskID);
PrintExcInfo("cpu num : %u\n", temp->currCpu);
PrintExcInfo("start dumping lockdep infomation\n");
for (i = 0; i < lockDep->lockDepth; i++) {
if (lockDep->heldLocks[i].lockPtr == lock) {
PrintExcInfo("[%d] %s <-- addr:0x%x\n", i, LOCKDEP_GET_NAME(lockDep, i),
LOCKDEP_GET_ADDR(lockDep, i));
} else {
PrintExcInfo("[%d] %s \n", i, LOCKDEP_GET_NAME(lockDep, i));
}
}
PrintExcInfo("[%d] %s <-- now\n", i, lock->name);
if (errType == LOCKDEP_ERR_DEAD_LOCK) {
temp = lock->owner;
lock = temp->lockDep.waitLock;
lockDep = &temp->lockDep;
}
if (temp == task) {
break;
}
}
OsLockDepPanic(errType);
}
STATIC BOOL OsLockDepCheckDependancy(const LosTaskCB *current, LosTaskCB *lockOwner)
{
BOOL checkResult = TRUE;
SPIN_LOCK_S *lockTemp = NULL;
do {
if (current == lockOwner) {
checkResult = FALSE;
return checkResult;
}
if (lockOwner->lockDep.waitLock != NULL) {
lockTemp = lockOwner->lockDep.waitLock;
lockOwner = lockTemp->owner;
} else {
break;
}
} while (lockOwner != SPINLOCK_OWNER_INIT);
return checkResult;
}
VOID OsLockDepCheckIn(SPIN_LOCK_S *lock)
{
UINT32 intSave;
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
VOID *requestAddr = (VOID *)__builtin_return_address(0);
LosTaskCB *current = OsCurrTaskGet();
LockDep *lockDep = &current->lockDep;
LosTaskCB *lockOwner = NULL;
OsLockDepRequire(&intSave);
if (lockDep->lockDepth >= (INT32)MAX_LOCK_DEPTH) {
checkResult = LOCKDEP_ERR_OVERFLOW;
goto OUT;
}
lockOwner = lock->owner;
/* not owned by any tasks yet, not doing following checks */
if (lockOwner == SPINLOCK_OWNER_INIT) {
goto OUT;
}
if (current == lockOwner) {
checkResult = LOCKDEP_ERR_DOUBLE_LOCK;
goto OUT;
}
if (OsLockDepCheckDependancy(current, lockOwner) != TRUE) {
checkResult = LOCKDEP_ERR_DEAD_LOCK;
goto OUT;
}
OUT:
if (checkResult == LOCKDEP_SUCEESS) {
/*
* though the check may succeed, the waitLock still need to be set.
* because the OsLockDepCheckIn and OsLockDepRecord is not strictly muti-core
* sequential, there would be more than two tasks can pass the checking, but
* only one task can successfully obtain the lock.
*/
lockDep->waitLock = lock;
lockDep->heldLocks[lockDep->lockDepth].lockAddr = requestAddr;
lockDep->heldLocks[lockDep->lockDepth].waitTime = OsLockDepGetCycles(); /* start time */
} else {
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
}
OsLockDepRelease(intSave);
}
VOID OsLockDepRecord(SPIN_LOCK_S *lock)
{
UINT32 intSave;
UINT64 cycles;
LosTaskCB *current = OsCurrTaskGet();
LockDep *lockDep = &current->lockDep;
HeldLocks *heldlock = &lockDep->heldLocks[lockDep->lockDepth];
OsLockDepRequire(&intSave);
/*
* OsLockDepCheckIn records start time t1, after the lock is obtained, we
* get the time t2, (t2 - t1) is the time of waiting for the lock
*/
cycles = OsLockDepGetCycles();
heldlock->waitTime = cycles - heldlock->waitTime;
heldlock->holdTime = cycles;
/* record lock info */
lock->owner = current;
lock->cpuid = ArchCurrCpuid();
/* record lockdep info */
heldlock->lockPtr = lock;
lockDep->lockDepth++;
lockDep->waitLock = NULL;
OsLockDepRelease(intSave);
}
VOID OsLockDepCheckOut(SPIN_LOCK_S *lock)
{
UINT32 intSave;
INT32 depth;
enum LockDepErrType checkResult = LOCKDEP_SUCEESS;
VOID *requestAddr = (VOID *)__builtin_return_address(0);
LosTaskCB *current = OsCurrTaskGet();
LosTaskCB *owner = NULL;
LockDep *lockDep = NULL;
HeldLocks *heldlocks = NULL;
OsLockDepRequire(&intSave);
owner = lock->owner;
if (owner == SPINLOCK_OWNER_INIT) {
checkResult = LOCKDEP_ERR_UNLOCK_WITOUT_LOCK;
OsLockDepDumpLock(current, lock, requestAddr, checkResult);
goto OUT;
}
lockDep = &owner->lockDep;
heldlocks = &lockDep->heldLocks[0];
depth = lockDep->lockDepth;
/* find the lock position */
while (depth-- >= 0) {
if (heldlocks[depth].lockPtr == lock) {
break;
}
}
LOS_ASSERT(depth >= 0);
/* record lock holding time */
heldlocks[depth].holdTime = OsLockDepGetCycles() - heldlocks[depth].holdTime;
/* if unlock a older lock, needs move heldLock records */
while (depth < lockDep->lockDepth - 1) {
lockDep->heldLocks[depth] = lockDep->heldLocks[depth + 1];
depth++;
}
lockDep->lockDepth--;
lock->cpuid = (UINT32)(-1);
lock->owner = SPINLOCK_OWNER_INIT;
OUT:
OsLockDepRelease(intSave);
}
VOID OsLockdepClearSpinlocks(VOID)
{
LosTaskCB *task = OsCurrTaskGet();
LockDep *lockDep = &task->lockDep;
SPIN_LOCK_S *lock = NULL;
/*
* Unlock spinlocks that running task has held.
* lockDepth will decrease after each spinlock is unlockded.
*/
while (lockDep->lockDepth) {
lock = lockDep->heldLocks[lockDep->lockDepth - 1].lockPtr;
LOS_SpinUnlock(lock);
}
}
#endif /* LOSCFG_KERNEL_SMP_LOCKDEP */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

119
kernel/base/mp/los_mp.c Executable file
View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_mp.h"
#include "los_task_pri.h"
#include "los_percpu_pri.h"
#include "los_sched_pri.h"
#include "los_swtmr.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#if (LOSCFG_KERNEL_SMP == YES)
VOID LOS_MpSchedule(UINT32 target)
{
UINT32 cpuid = ArchCurrCpuid();
target &= ~(1U << cpuid);
HalIrqSendIpi(target, LOS_MP_IPI_SCHEDULE);
}
VOID OsMpWakeHandler(VOID)
{
/* generic wakeup ipi, do nothing */
}
VOID OsMpScheduleHandler(VOID)
{
/*
* set schedule flag to differ from wake function,
* so that the scheduler can be triggered at the end of irq.
*/
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
}
VOID OsMpHaltHandler(VOID)
{
(VOID)LOS_IntLock();
OsPercpuGet()->excFlag = CPU_HALT;
while (1) {}
}
VOID OsMpCollectTasks(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 taskID = 0;
UINT32 ret;
/* recursive checking all the available task */
for (; taskID <= g_taskMaxNum; taskID++) {
taskCB = &g_taskCBArray[taskID];
if (OsTaskIsUnused(taskCB) || OsTaskIsRunning(taskCB)) {
continue;
}
/*
* though task status is not atomic, this check may success but not accomplish
* the deletion; this deletion will be handled until the next run.
*/
if (taskCB->signal & SIGNAL_KILL) {
ret = LOS_TaskDelete(taskID);
if (ret != LOS_OK) {
PRINT_WARN("GC collect task failed err:0x%x\n", ret);
}
}
}
}
UINT32 OsMpInit(VOID)
{
UINT16 swtmrId;
(VOID)LOS_SwtmrCreate(OS_MP_GC_PERIOD, LOS_SWTMR_MODE_PERIOD,
(SWTMR_PROC_FUNC)OsMpCollectTasks, &swtmrId, 0);
(VOID)LOS_SwtmrStart(swtmrId);
return LOS_OK;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

46
kernel/base/mp/los_percpu.c Executable file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_percpu_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM];
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

333
kernel/base/mp/los_stat.c Executable file
View File

@@ -0,0 +1,333 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 */
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
#define HIGHTASKPRI 16
#define NS_PER_MS 1000000
#define DECIMAL_TO_PERCENTAGE 100
typedef struct {
UINT64 idleRuntime;
UINT64 idleStarttime;
UINT64 highTaskRuntime;
UINT64 highTaskStarttime;
UINT64 spinWaitRuntime;
UINT64 sumPriority;
UINT32 prioritySwitch;
UINT32 highTaskSwitch;
UINT32 contexSwitch;
UINT32 hwiNum;
UINT32 ipiIrqNum;
} MpStatPercpu;
STATIC BOOL g_mpStaticStartFlag = FALSE;
STATIC UINT64 g_mpStaticStartTime;
STATIC MpStatPercpu g_mpStatPercpu[LOSCFG_KERNEL_SMP_CORE_NUM] = {0};
STATIC VOID OsMpSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT32 cpuid;
UINT32 idleTaskID;
UINT64 now, runtime;
if (g_mpStaticStartFlag != TRUE) {
return;
}
cpuid = ArchCurrCpuid();
idleTaskID = OsGetIdleTaskId();
now = LOS_CurrNanosec();
g_mpStatPercpu[cpuid].contexSwitch++;
if ((runTask->taskID != idleTaskID) && (newTask->taskID == idleTaskID)) {
g_mpStatPercpu[cpuid].idleStarttime = now;
}
if ((runTask->taskID == idleTaskID) && (newTask->taskID != idleTaskID)) {
runtime = now - g_mpStatPercpu[cpuid].idleStarttime;
g_mpStatPercpu[cpuid].idleRuntime += runtime;
g_mpStatPercpu[cpuid].idleStarttime = 0;
}
if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) {
g_mpStatPercpu[cpuid].highTaskStarttime = now;
}
if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) {
runtime = now - g_mpStatPercpu[cpuid].highTaskStarttime;
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
}
if (newTask->priority < HIGHTASKPRI) {
g_mpStatPercpu[cpuid].highTaskSwitch++;
}
if (newTask->taskID != idleTaskID) {
g_mpStatPercpu[cpuid].sumPriority += newTask->priority;
g_mpStatPercpu[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;
OsMpSchedStatistics(runTask, newTask);
}
LITE_OS_SEC_TEXT_MINOR VOID OsSpinWaitStatistics(UINT64 spinWaitRuntime)
{
UINT32 cpuid = ArchCurrCpuid();
g_mpStatPercpu[cpuid].spinWaitRuntime += spinWaitRuntime;
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum)
{
UINT32 cpuid = ArchCurrCpuid();
if ((g_mpStaticStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) {
return;
}
g_mpStatPercpu[cpuid].hwiNum++;
/* 16: 0~15 is ipi interrupts */
if (intNum < 16) {
g_mpStatPercpu[cpuid].ipiIrqNum++;
}
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid;
UINT32 affinity;
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 (OsTaskIsUnused(taskCB)) {
continue;
}
affinity = (UINT32)taskCB->cpuAffiMask;
PRINTK("%-30s0x%-6x%+16lf ms %10d\n", taskCB->taskName, taskCB->taskID,
(DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS,
taskCB->schedStat.allContextSwitch);
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
if (!((1U << cpuid) & affinity)) {
continue;
}
PRINTK(" "
"CPU%d %+16lf ms %12d\n", cpuid,
(DOUBLE)(taskCB->schedStat.schedPercpu[cpuid].runtime) / NS_PER_MS,
taskCB->schedStat.schedPercpu[cpuid].contexSwitch);
}
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStart(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid = 0;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_mpStaticStartFlag) {
PRINT_WARN("mp static has started\n");
SCHEDULER_UNLOCK(intSave);
return;
}
g_mpStaticStartTime = LOS_CurrNanosec();
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#if (LOSCFG_KERNEL_SMP == YES)
cpuid = taskCB->currCpu;
#endif
if ((UINT32)(OS_TASK_INVALID_CPUID) == cpuid) {
continue;
}
if (!strcmp(taskCB->taskName, "Idle")) {
g_mpStatPercpu[cpuid].idleStarttime = g_mpStaticStartTime;
}
if (taskCB->priority < HIGHTASKPRI) {
g_mpStatPercpu[cpuid].highTaskStarttime = g_mpStaticStartTime;
g_mpStatPercpu[cpuid].highTaskSwitch++;
}
if (strcmp(taskCB->taskName, "Idle")) {
g_mpStatPercpu[cpuid].sumPriority += taskCB->priority;
g_mpStatPercpu[cpuid].prioritySwitch++;
}
}
}
g_mpStaticStartFlag = TRUE;
SCHEDULER_UNLOCK(intSave);
PRINTK("mp static start\n");
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsMpStaticShow(UINT64 mpStaticPastTime)
{
UINT32 cpuid;
PRINTK("\n");
PRINTK("Passed Time: %+16lf ms\n", (DOUBLE)mpStaticPastTime / NS_PER_MS);
PRINTK("--------------------------------\n");
PRINTK("CPU Idle(%%) schedule noTick Hwi MP Hwi MP Loss(%%) "
"avg PRI HiTSK(%%) HiTSK SCH HiTSK P(ms)\n");
PRINTK("---- --------- ---------- ---------- ---------- ---------- "
"---------- ---------- ---------- ----------\n");
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
PRINTK("CPU%d %+10lf%14d%14d%14d %+11lf %+11lf %+11lf%14d %+11lf\n", cpuid,
((DOUBLE)(g_mpStatPercpu[cpuid].idleRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
g_mpStatPercpu[cpuid].contexSwitch,
g_mpStatPercpu[cpuid].hwiNum,
g_mpStatPercpu[cpuid].ipiIrqNum,
((DOUBLE)(g_mpStatPercpu[cpuid].spinWaitRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
(g_mpStatPercpu[cpuid].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST :
((DOUBLE)(g_mpStatPercpu[cpuid].sumPriority) / (g_mpStatPercpu[cpuid].prioritySwitch)),
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
g_mpStatPercpu[cpuid].highTaskSwitch,
(g_mpStatPercpu[cpuid].highTaskSwitch == 0) ? 0 :
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / (g_mpStatPercpu[cpuid].highTaskSwitch)) / NS_PER_MS);
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStop(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuid = 0;
UINT64 mpStaticStopTime;
UINT64 mpStaticPastTime;
UINT64 runtime;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_mpStaticStartFlag != TRUE) {
PRINT_WARN("Please set mp static start\n");
SCHEDULER_UNLOCK(intSave);
return;
}
g_mpStaticStartFlag = FALSE;
mpStaticStopTime = LOS_CurrNanosec();
mpStaticPastTime = mpStaticStopTime - g_mpStaticStartTime;
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#if (LOSCFG_KERNEL_SMP == YES)
cpuid = taskCB->currCpu;
#endif
if (cpuid == (UINT32)(OS_TASK_INVALID_CPUID)) {
continue;
}
if (!strcmp(taskCB->taskName, "Idle")) {
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].idleStarttime;
g_mpStatPercpu[cpuid].idleRuntime += runtime;
g_mpStatPercpu[cpuid].idleStarttime = 0;
}
if (taskCB->priority < HIGHTASKPRI) {
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].highTaskStarttime;
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
}
}
}
SCHEDULER_UNLOCK(intSave);
OsMpStaticShow(mpStaticPastTime);
(VOID)memset_s(g_mpStatPercpu, sizeof(g_mpStatPercpu), 0, sizeof(g_mpStatPercpu));
g_mpStaticStartTime = 0;
return;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

61
kernel/base/om/los_err.c Executable file
View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_err.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS STATIC LOS_ERRORHANDLE_FUNC g_errHandleHook = NULL;
LITE_OS_SEC_TEXT_INIT UINT32 LOS_ErrHandle(CHAR *fileName, UINT32 lineNo, UINT32 errorNo,
UINT32 paraLen, VOID *para)
{
if (g_errHandleHook != NULL) {
g_errHandleHook(fileName, lineNo, errorNo, paraLen, para);
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_INIT VOID LOS_SetErrHandleHook(LOS_ERRORHANDLE_FUNC fun)
{
g_errHandleHook = fun;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

View File

@@ -0,0 +1,235 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_priqueue_pri.h"
#include "los_task_pri.h"
#include "los_memory.h"
#include "los_toolchain.h"
#include "los_spinlock.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define PRIQUEUE_PRIOR0_BIT 0x80000000U
LITE_OS_SEC_BSS LOS_DL_LIST *g_priQueueList = NULL;
LITE_OS_SEC_BSS UINT32 g_priQueueBitmap;
UINT32 OsPriQueueInit(VOID)
{
UINT32 priority;
/* system resident resource */
g_priQueueList = (LOS_DL_LIST *)LOS_MemAlloc(m_aucSysMem0, (OS_PRIORITY_QUEUE_NUM * sizeof(LOS_DL_LIST)));
if (g_priQueueList == NULL) {
return LOS_NOK;
}
for (priority = 0; priority < OS_PRIORITY_QUEUE_NUM; ++priority) {
LOS_ListInit(&g_priQueueList[priority]);
}
return LOS_OK;
}
LOS_DL_LIST *OsPriQueueTop(LOS_DL_LIST *priQueueList, UINT32 *bitMap)
{
UINT32 priority;
if (*bitMap != 0) {
priority = CLZ(*bitMap);
return LOS_DL_LIST_FIRST(&priQueueList[priority]);
}
return NULL;
}
VOID OsPriQueueEnqueueHead(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority)
{
/*
* Task control blocks are inited as zero. And when task is deleted,
* and at the same time would be deleted from priority queue or
* other lists, task pend node will restored as zero.
*/
LOS_ASSERT(priqueueItem->pstNext == NULL);
if (LOS_ListEmpty(&priQueueList[priority])) {
*bitMap |= PRIQUEUE_PRIOR0_BIT >> priority;
}
LOS_ListHeadInsert(&priQueueList[priority], priqueueItem);
}
VOID OsPriQueueEnqueue(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem, UINT32 priority)
{
/*
* Task control blocks are inited as zero. And when task is deleted,
* and at the same time would be deleted from priority queue or
* other lists, task pend node will restored as zero.
*/
LOS_ASSERT(priqueueItem->pstNext == NULL);
if (LOS_ListEmpty(&priQueueList[priority])) {
*bitMap |= PRIQUEUE_PRIOR0_BIT >> priority;
}
LOS_ListTailInsert(&priQueueList[priority], priqueueItem);
}
VOID OsPriQueueDequeue(LOS_DL_LIST *priQueueList, UINT32 *bitMap, LOS_DL_LIST *priqueueItem)
{
LosTaskCB *task = NULL;
LOS_ListDelete(priqueueItem);
task = LOS_DL_LIST_ENTRY(priqueueItem, LosTaskCB, pendList);
if (LOS_ListEmpty(&priQueueList[task->priority])) {
*bitMap &= ~(PRIQUEUE_PRIOR0_BIT >> task->priority);
}
}
VOID OsPriQueueProcessDequeue(LOS_DL_LIST *priqueueItem)
{
LosProcessCB *runProcess = NULL;
LOS_ListDelete(priqueueItem);
runProcess = LOS_DL_LIST_ENTRY(priqueueItem, LosProcessCB, pendList);
if (LOS_ListEmpty(&g_priQueueList[runProcess->priority])) {
g_priQueueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> runProcess->priority);
}
}
UINT32 OsPriQueueProcessSize(LOS_DL_LIST *priQueueList, UINT32 priority)
{
UINT32 itemCnt = 0;
LOS_DL_LIST *curNode = NULL;
LOS_ASSERT(OsIntLocked());
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
LOS_DL_LIST_FOR_EACH(curNode, &priQueueList[priority]) {
++itemCnt;
}
return itemCnt;
}
UINT32 OsPriQueueSize(LOS_DL_LIST *priQueueList, UINT32 priority)
{
UINT32 itemCnt = 0;
LOS_DL_LIST *curNode = NULL;
#if (LOSCFG_KERNEL_SMP == YES)
LosTaskCB *task = NULL;
UINT32 cpuID = ArchCurrCpuid();
#endif
LOS_ASSERT(OsIntLocked());
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
LOS_DL_LIST_FOR_EACH(curNode, &priQueueList[priority]) {
#if (LOSCFG_KERNEL_SMP == YES)
task = OS_TCB_FROM_PENDLIST(curNode);
if (!(task->cpuAffiMask & (1U << cpuID))) {
continue;
}
#endif
++itemCnt;
}
return itemCnt;
}
LOS_DL_LIST *OsTaskPriQueueTop(VOID)
{
LosProcessCB *processCB = LOS_DL_LIST_ENTRY(OsPriQueueTop(g_priQueueList, &g_priQueueBitmap),
LosProcessCB,
pendList);
return OsPriQueueTop(processCB->threadPriQueueList, &processCB->threadScheduleMap);
}
STATIC INLINE VOID OsDequeEmptySchedMap(LosProcessCB *processCB)
{
if (processCB->threadScheduleMap == 0) {
processCB->processStatus &= ~OS_PROCESS_STATUS_READY;
OsPriQueueProcessDequeue(&processCB->pendList);
}
}
LITE_OS_SEC_TEXT_MINOR LosTaskCB *OsGetTopTask(VOID)
{
UINT32 priority, processPriority;
UINT32 bitmap;
UINT32 processBitmap;
LosTaskCB *newTask = NULL;
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 cpuid = ArchCurrCpuid();
#endif
LosProcessCB *processCB = NULL;
processBitmap = g_priQueueBitmap;
while (processBitmap) {
processPriority = CLZ(processBitmap);
LOS_DL_LIST_FOR_EACH_ENTRY(processCB, &g_priQueueList[processPriority], LosProcessCB, pendList) {
bitmap = processCB->threadScheduleMap;
while (bitmap) {
priority = CLZ(bitmap);
LOS_DL_LIST_FOR_EACH_ENTRY(newTask, &processCB->threadPriQueueList[priority], LosTaskCB, pendList) {
#if (LOSCFG_KERNEL_SMP == YES)
if (newTask->cpuAffiMask & (1U << cpuid)) {
#endif
newTask->taskStatus &= ~OS_TASK_STATUS_READY;
OsPriQueueDequeue(processCB->threadPriQueueList,
&processCB->threadScheduleMap,
&newTask->pendList);
OsDequeEmptySchedMap(processCB);
goto OUT;
#if (LOSCFG_KERNEL_SMP == YES)
}
#endif
}
bitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - priority - 1));
}
}
processBitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - processPriority - 1));
}
OUT:
return newTask;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_base.h"
#include "los_task_pri.h"
#include "los_percpu_pri.h"
#include "los_hw_pri.h"
#include "los_arch_mmu.h"
#include "los_process_pri.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATIC VOID OsSchedSwitchProcess(LosProcessCB *runProcess, LosProcessCB *newProcess)
{
if (runProcess == newProcess) {
return;
}
#if (LOSCFG_KERNEL_SMP == YES)
runProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_DEC(runProcess->processStatus);
newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus);
LOS_ASSERT(!(OS_PROCESS_GET_RUNTASK_COUNT(newProcess->processStatus) > LOSCFG_KERNEL_CORE_NUM));
if (OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) == 0) {
#endif
runProcess->processStatus &= ~OS_PROCESS_STATUS_RUNNING;
if ((runProcess->threadNumber > 1) && !(runProcess->processStatus & OS_PROCESS_STATUS_READY)) {
runProcess->processStatus |= OS_PROCESS_STATUS_PEND;
}
#if (LOSCFG_KERNEL_SMP == YES)
}
#endif
LOS_ASSERT(!(newProcess->processStatus & OS_PROCESS_STATUS_PEND));
newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING;
if (OsProcessIsUserMode(newProcess)) {
LOS_ArchMmuContextSwitch(&newProcess->vmSpace->archMmu);
}
#ifdef LOSCFG_KERNEL_CPUP
OsProcessCycleEndStart(newProcess->processID, OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) + 1);
#endif /* LOSCFG_KERNEL_CPUP */
OsCurrProcessSet(newProcess);
if ((newProcess->timeSlice == 0) && (newProcess->policy == LOS_SCHED_RR)) {
newProcess->timeSlice = OS_PROCESS_SCHED_RR_INTERVAL;
}
}
VOID OsSchedResched(VOID)
{
LosTaskCB *runTask = NULL;
LosTaskCB *newTask = NULL;
LosProcessCB *runProcess = NULL;
LosProcessCB *newProcess = NULL;
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
if (!OsPreemptableInSched()) {
return;
}
runTask = OsCurrTaskGet();
newTask = OsGetTopTask();
/* always be able to get one task */
LOS_ASSERT(newTask != NULL);
if (runTask == newTask) {
return;
}
runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
runProcess = OS_PCB_FROM_PID(runTask->processID);
newProcess = OS_PCB_FROM_PID(newTask->processID);
OsSchedSwitchProcess(runProcess, newProcess);
#if (LOSCFG_KERNEL_SMP == YES)
/* mask new running task's owner processor */
runTask->currCpu = OS_TASK_INVALID_CPUID;
newTask->currCpu = ArchCurrCpuid();
#endif
(VOID)OsTaskSwitchCheck(runTask, newTask);
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
OsSchedStatistics(runTask, newTask);
#endif
if ((newTask->timeSlice == 0) && (newTask->policy == LOS_SCHED_RR)) {
newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT;
}
OsCurrTaskSet((VOID*)newTask);
if (OsProcessIsUserMode(newProcess)) {
OsCurrUserTaskSet(newTask->userArea);
}
PRINT_TRACE("cpu%d run process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x ->\n"
" new process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x!\n",
ArchCurrCpuid(),
runProcess->processName, runProcess->processID, runProcess->processStatus,
runProcess->threadScheduleMap, runTask->taskName, runTask->taskID, runTask->taskStatus,
newProcess->processName, newProcess->processID, newProcess->processStatus,
newProcess->threadScheduleMap, newTask->taskName, newTask->taskID, newTask->taskStatus);
/* do the task context switch */
OsTaskSchedule(newTask, runTask);
}
VOID OsSchedPreempt(VOID)
{
LosTaskCB *runTask = NULL;
UINT32 intSave;
if (!OsPreemptable()) {
return;
}
SCHEDULER_LOCK(intSave);
/* add run task back to ready queue */
runTask = OsCurrTaskGet();
OS_TASK_SCHED_QUEUE_ENQUEUE(runTask, 0);
/* reschedule to new thread */
OsSchedResched();
SCHEDULER_UNLOCK(intSave);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

102
kernel/base/vm/los_vm_boot.c Executable file
View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_vm_boot.h"
#include "los_config.h"
#include "los_base.h"
#include "los_vm_zone.h"
#include "los_vm_map.h"
#include "los_memory_pri.h"
#include "los_vm_page.h"
#include "los_arch_mmu.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
UINTPTR g_vmBootMemBase = (UINTPTR)&__bss_end;
BOOL g_kHeapInited = FALSE;
UINT32 OsVmAddrCheck(size_t tempAddr, size_t length)
{
if ((tempAddr >= KERNEL_VMM_BASE) && ((tempAddr + length) <= (PERIPH_UNCACHED_BASE + PERIPH_UNCACHED_SIZE))) {
return LOS_OK;
}
return LOS_NOK;
}
VOID *OsVmBootMemAlloc(size_t len)
{
UINTPTR ptr;
if (g_kHeapInited) {
VM_ERR("kernel heap has been inited, should not to use boot mem alloc!");
return NULL;
}
ptr = LOS_Align(g_vmBootMemBase, sizeof(UINTPTR));
g_vmBootMemBase = ptr + LOS_Align(len, sizeof(UINTPTR));
return (VOID *)ptr;
}
UINT32 OsSysMemInit(VOID)
{
STATUS_T ret;
OsKSpaceInit();
ret = OsKHeapInit(OS_KHEAP_BLOCK_SIZE);
if (ret != LOS_OK) {
VM_ERR("OsKHeapInit fail");
return LOS_NOK;
}
OsVmPageStartup();
OsInitMappingStartUp();
ret = ShmInit();
if (ret < 0) {
VM_ERR("ShmInit fail");
return LOS_NOK;
}
return LOS_OK;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

545
kernel/base/vm/los_vm_dump.c Executable file
View File

@@ -0,0 +1,545 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_dump virtual memory dump operation
* @ingroup kernel
*/
#include "los_vm_dump.h"
#include "los_mmu_descriptor_v6.h"
#include "fs/fs.h"
#include "los_printf.h"
#include "los_vm_page.h"
#include "los_vm_phys.h"
#include "los_process_pri.h"
#include "los_atomic.h"
#include "los_vm_lock.h"
#include "los_memory_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define FLAG_SIZE 4
#define FLAG_START 2
const CHAR *OsGetRegionNameOrFilePath(LosVmMapRegion *region)
{
struct file *filep = NULL;
if (region == NULL) {
return "";
#ifdef LOSCFG_FS_VFS
} else if (LOS_IsRegionFileValid(region)) {
filep = region->unTypeData.rf.file;
return filep->f_path;
#endif
} else if (region->regionFlags & VM_MAP_REGION_FLAG_HEAP) {
return "HEAP";
} else if (region->regionFlags & VM_MAP_REGION_FLAG_STACK) {
return "STACK";
} else if (region->regionFlags & VM_MAP_REGION_FLAG_TEXT) {
return "Text";
} else if (region->regionFlags & VM_MAP_REGION_FLAG_VDSO) {
return "VDSO";
} else if (region->regionFlags & VM_MAP_REGION_FLAG_MMAP) {
return "MMAP";
} else if (region->regionFlags & VM_MAP_REGION_FLAG_SHM) {
return "SHM";
} else {
return "";
}
return "";
}
INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region)
{
LosVmMapRegion *regionTemp = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeNext = NULL;
/* search the region list */
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
regionTemp = (LosVmMapRegion *)pstRbNode;
if (region->range.base == regionTemp->range.base && region->range.size == regionTemp->range.size) {
continue;
}
if (((region->range.base + region->range.size) > regionTemp->range.base) &&
(region->range.base < (regionTemp->range.base + regionTemp->range.size))) {
VM_ERR("overlap between regions:\n"
"flals:%#x base:%p size:%08x space:%p\n"
"flags:%#x base:%p size:%08x space:%p",
region->regionFlags, region->range.base, region->range.size, region->space,
regionTemp->regionFlags, regionTemp->range.base, regionTemp->range.size, regionTemp->space);
return -1;
}
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
return 0;
}
UINT32 OsShellCmdProcessVmUsage(LosVmSpace *space)
{
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeNext = NULL;
UINT32 used = 0;
if (space == NULL) {
return 0;
}
if (space == LOS_GetKVmSpace()) {
OsShellCmdProcessPmUsage(space, NULL, &used);
} else {
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
region = (LosVmMapRegion *)pstRbNode;
used += region->range.size;
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
}
return used;
}
VOID OsKProcessPmUsage(LosVmSpace *kSpace, UINT32 *actualPm)
{
UINT32 memUsed;
UINT32 totalMem;
UINT32 freeMem;
UINT32 usedCount = 0;
UINT32 totalCount = 0;
LosVmSpace *space = NULL;
LOS_DL_LIST *spaceList = NULL;
UINT32 UProcessUsed = 0;
UINT32 pmTmp;
if (actualPm == NULL) {
return;
}
memUsed = LOS_MemTotalUsedGet(m_aucSysMem1);
totalMem = LOS_MemPoolSizeGet(m_aucSysMem1);
freeMem = totalMem - memUsed;
OsVmPhysUsedInfoGet(&usedCount, &totalCount);
/* Kernel resident memory, include default heap memory */
memUsed = SYS_MEM_SIZE_DEFAULT - (totalCount << PAGE_SHIFT);
spaceList = LOS_GetVmSpaceList();
LOS_DL_LIST_FOR_EACH_ENTRY(space, spaceList, LosVmSpace, node) {
if (space == LOS_GetKVmSpace()) {
continue;
}
OsUProcessPmUsage(space, NULL, &pmTmp);
UProcessUsed += pmTmp;
}
/* Kernel dynamic memory, include extended heap memory */
memUsed += ((usedCount << PAGE_SHIFT) - UProcessUsed);
/* Remaining heap memory */
memUsed -= freeMem;
*actualPm = memUsed;
}
VOID OsShellCmdProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
{
if (space == NULL) {
return;
}
if ((sharePm == NULL) && (actualPm == NULL)) {
return;
}
if (space == LOS_GetKVmSpace()) {
OsKProcessPmUsage(space, actualPm);
} else {
OsUProcessPmUsage(space, sharePm, actualPm);
}
}
VOID OsUProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
{
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeNext = NULL;
LosVmPage *page = NULL;
VADDR_T vaddr;
size_t size;
PADDR_T paddr;
STATUS_T ret;
INT32 shareRef;
if (sharePm != NULL) {
*sharePm = 0;
}
if (actualPm != NULL) {
*actualPm = 0;
}
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
region = (LosVmMapRegion *)pstRbNode;
vaddr = region->range.base;
size = region->range.size;
for (; size > 0; vaddr += PAGE_SIZE, size -= PAGE_SIZE) {
ret = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
if (ret < 0) {
continue;
}
page = LOS_VmPageGet(paddr);
if (page == NULL) {
continue;
}
shareRef = LOS_AtomicRead(&page->refCounts);
if (shareRef > 1) {
if (sharePm != NULL) {
*sharePm += PAGE_SIZE;
}
if (actualPm != NULL) {
*actualPm += PAGE_SIZE / shareRef;
}
} else {
if (actualPm != NULL) {
*actualPm += PAGE_SIZE;
}
}
}
RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
}
LosProcessCB *OsGetPIDByAspace(LosVmSpace *space)
{
UINT32 pid;
UINT32 intSave;
LosProcessCB *processCB = NULL;
SCHEDULER_LOCK(intSave);
for (pid = 0; pid < g_processMaxNum; ++pid) {
processCB = g_processCBArray + pid;
if (OsProcessIsUnused(processCB)) {
continue;
}
if (processCB->vmSpace == space) {
SCHEDULER_UNLOCK(intSave);
return processCB;
}
}
SCHEDULER_UNLOCK(intSave);
return NULL;
}
UINT32 OsCountRegionPages(LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages)
{
UINT32 regionPages = 0;
PADDR_T paddr;
VADDR_T vaddr;
UINT32 ref;
STATUS_T status;
float pss = 0;
LosVmPage *page = NULL;
for (vaddr = region->range.base; vaddr < region->range.base + region->range.size; vaddr = vaddr + PAGE_SIZE) {
status = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
if (status == LOS_OK) {
regionPages++;
if (pssPages == NULL) {
continue;
}
page = LOS_VmPageGet(paddr);
if (page != NULL) {
ref = LOS_AtomicRead(&page->refCounts);
pss += ((ref > 0) ? (1.0 / ref) : 1);
} else {
pss += 1;
}
}
}
if (pssPages != NULL) {
*pssPages = (UINT32)(pss + 0.5);
}
return regionPages;
}
UINT32 OsCountAspacePages(LosVmSpace *space)
{
UINT32 spacePages = 0;
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeNext = NULL;
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
region = (LosVmMapRegion *)pstRbNode;
spacePages += OsCountRegionPages(space, region, NULL);
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
return spacePages;
}
CHAR *OsArchFlagsToStr(const UINT32 archFlags)
{
UINT32 index;
UINT32 cacheFlags = archFlags & VM_MAP_REGION_FLAG_CACHE_MASK;
UINT32 flagSize = FLAG_SIZE * BITMAP_BITS_PER_WORD * sizeof(CHAR);
CHAR *archMmuFlagsStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, flagSize);
if (archMmuFlagsStr == NULL) {
return NULL;
}
(VOID)memset_s(archMmuFlagsStr, flagSize, 0, flagSize);
switch (cacheFlags) {
case 0UL:
strcat_s(archMmuFlagsStr, flagSize, " CH\0");
break;
case 1UL:
strcat_s(archMmuFlagsStr, flagSize, " UC\0");
break;
case 2UL:
strcat_s(archMmuFlagsStr, flagSize, " UD\0");
break;
case 3UL:
strcat_s(archMmuFlagsStr, flagSize, " WC\0");
break;
default:
break;
}
static const CHAR FLAGS[BITMAP_BITS_PER_WORD][FLAG_SIZE] = {
[0 ... (__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 2)] = "???\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 1] = " US\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_READ) - 1] = " RD\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_WRITE) - 1] = " WR\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_EXECUTE) - 1] = " EX\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_NS) - 1] = " NS\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) - 1] = " IN\0",
[__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) ... (BITMAP_BITS_PER_WORD - 1)] = "???\0",
};
for (index = FLAG_START; index < BITMAP_BITS_PER_WORD; index++) {
if (FLAGS[index][0] == '?') {
continue;
}
if (archFlags & (1UL << index)) {
UINT32 status = strcat_s(archMmuFlagsStr, flagSize, FLAGS[index]);
if (status != 0) {
PRINTK("error\n");
}
}
}
return archMmuFlagsStr;
}
VOID OsDumpRegion2(LosVmSpace *space, LosVmMapRegion *region)
{
UINT32 pssPages = 0;
UINT32 regionPages;
regionPages = OsCountRegionPages(space, region, &pssPages);
CHAR *flagsStr = OsArchFlagsToStr(region->regionFlags);
if (flagsStr == NULL) {
return;
}
PRINTK("\t %#010x %-32.32s %#010x %#010x %-15.15s %4d %4d\n",
region, OsGetRegionNameOrFilePath(region), region->range.base,
region->range.size, flagsStr, regionPages, pssPages);
(VOID)LOS_MemFree(m_aucSysMem0, flagsStr);
}
VOID OsDumpAspace(LosVmSpace *space)
{
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeNext = NULL;
UINT32 spacePages;
LosProcessCB *pcb = OsGetPIDByAspace(space);
if (pcb == NULL) {
return;
}
spacePages = OsCountAspacePages(space);
PRINTK("\r\n PID aspace name base size pages \n");
PRINTK(" ---- ------ ---- ---- ----- ----\n");
PRINTK(" %-4d %#010x %-10.10s %#010x %#010x %d\n", pcb->processID, space, pcb->processName,
space->base, space->size, spacePages);
PRINTK("\r\n\t region name base size mmu_flags pages pg/ref\n");
PRINTK("\t ------ ---- ---- ---- --------- ----- -----\n");
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
region = (LosVmMapRegion *)pstRbNode;
if (region != NULL) {
OsDumpRegion2(space, region);
(VOID)OsRegionOverlapCheck(space, region);
} else {
PRINTK("region is NULL\n");
}
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
return;
}
VOID OsDumpAllAspace(VOID)
{
LosVmSpace *space = NULL;
LOS_DL_LIST *aspaceList = LOS_GetVmSpaceList();
LOS_DL_LIST_FOR_EACH_ENTRY(space, aspaceList, LosVmSpace, node) {
(VOID)LOS_MuxAcquire(&space->regionMux);
OsDumpAspace(space);
(VOID)LOS_MuxRelease(&space->regionMux);
}
return;
}
STATUS_T OsRegionOverlapCheck(LosVmSpace *space, LosVmMapRegion *region)
{
int ret;
if (space == NULL || region == NULL) {
return -1;
}
(VOID)LOS_MuxAcquire(&space->regionMux);
ret = OsRegionOverlapCheckUnlock(space, region);
(VOID)LOS_MuxRelease(&space->regionMux);
return ret;
}
VOID OsDumpPte(VADDR_T vaddr)
{
UINT32 l1Index = vaddr >> MMU_DESCRIPTOR_L1_SMALL_SHIFT;
LosVmSpace *space = LOS_SpaceGet(vaddr);
UINT32 ttEntry;
LosVmPage *page = NULL;
PTE_T *l2Table = NULL;
UINT32 l2Index;
if (space == NULL) {
return;
}
ttEntry = space->archMmu.virtTtb[l1Index];
if (ttEntry) {
l2Table = LOS_PaddrToKVaddr(MMU_DESCRIPTOR_L1_PAGE_TABLE_ADDR(ttEntry));
l2Index = (vaddr % MMU_DESCRIPTOR_L1_SMALL_SIZE) >> PAGE_SHIFT;
if (l2Table == NULL) {
goto ERR;
}
page = LOS_VmPageGet(l2Table[l2Index] & ~(PAGE_SIZE - 1));
if (page == NULL) {
goto ERR;
}
PRINTK("vaddr %p, l1Index %d, ttEntry %p, l2Table %p, l2Index %d, pfn %p count %d\n",
vaddr, l1Index, ttEntry, l2Table, l2Index, l2Table[l2Index], LOS_AtomicRead(&page->refCounts));
} else {
PRINTK("vaddr %p, l1Index %d, ttEntry %p\n", vaddr, l1Index, ttEntry);
}
return;
ERR:
PRINTK("%s, error vaddr: %#x, l2Table: %#x, l2Index: %#x\n", __FUNCTION__, vaddr, l2Table, l2Index);
}
UINT32 OsVmPhySegPagesGet(LosVmPhysSeg *seg)
{
UINT32 intSave;
UINT32 flindex;
UINT32 segFreePages = 0;
LOS_SpinLockSave(&seg->freeListLock, &intSave);
for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
segFreePages += ((1 << flindex) * seg->freeList[flindex].listCnt);
}
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
return segFreePages;
}
VOID OsVmPhysDump(VOID)
{
LosVmPhysSeg *seg = NULL;
UINT32 segFreePages;
UINT32 totalFreePages = 0;
UINT32 totalPages = 0;
UINT32 segIndex;
for (segIndex = 0; segIndex < g_vmPhysSegNum; segIndex++) {
seg = &g_vmPhysSeg[segIndex];
if (seg->size > 0) {
segFreePages = OsVmPhySegPagesGet(seg);
#ifdef LOSCFG_SHELL_CMD_DEBUG
PRINTK("\r\n phys_seg base size free_pages \n");
PRINTK(" -------- ------- ---------- --------- \n");
#endif
PRINTK(" %08p %08p 0x%08x %8u \n", seg, seg->start, seg->size, segFreePages);
totalFreePages += segFreePages;
totalPages += (seg->size >> PAGE_SHIFT);
PRINTK("active anon %d\n", seg->lruSize[VM_LRU_ACTIVE_ANON]);
PRINTK("inactive anon %d\n", seg->lruSize[VM_LRU_INACTIVE_ANON]);
PRINTK("active file %d\n", seg->lruSize[VM_LRU_ACTIVE_FILE]);
PRINTK("inactice file %d\n", seg->lruSize[VM_LRU_INACTIVE_FILE]);
}
}
PRINTK("\n\rpmm pages: total = %u, used = %u, free = %u\n",
totalPages, (totalPages - totalFreePages), totalFreePages);
}
VOID OsVmPhysUsedInfoGet(UINT32 *usedCount, UINT32 *totalCount)
{
UINT32 index;
UINT32 segFreePages;
LosVmPhysSeg *physSeg = NULL;
if (usedCount == NULL || totalCount == NULL) {
return;
}
*usedCount = 0;
*totalCount = 0;
for (index = 0; index < g_vmPhysSegNum; index++) {
physSeg = &g_vmPhysSeg[index];
if (physSeg->size > 0) {
*totalCount += physSeg->size >> PAGE_SHIFT;
segFreePages = OsVmPhySegPagesGet(physSeg);
*usedCount += (*totalCount - segFreePages);
}
}
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

468
kernel/base/vm/los_vm_fault.c Executable file
View File

@@ -0,0 +1,468 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_fault vm fault definition
* @ingroup kernel
*/
#include "los_vm_fault.h"
#include "los_vm_map.h"
#include "los_vm_dump.h"
#include "los_vm_filemap.h"
#include "los_vm_page.h"
#include "los_vm_lock.h"
#include "los_exc.h"
#include "los_oom.h"
#include "los_printf.h"
#include "los_process_pri.h"
#include "arm.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
extern char __exc_table_start[];
extern char __exc_table_end[];
STATIC STATUS_T OsVmRegionRightCheck(LosVmMapRegion *region, UINT32 flags)
{
if ((flags & VM_MAP_PF_FLAG_WRITE) == VM_MAP_PF_FLAG_WRITE) {
if ((region->regionFlags & VM_MAP_REGION_FLAG_PERM_WRITE) != VM_MAP_REGION_FLAG_PERM_WRITE) {
VM_ERR("write permission check failed operation flags %x, region flags %x", flags, region->regionFlags);
return LOS_NOK;
}
}
if ((flags & VM_MAP_PF_FLAG_INSTRUCTION) == VM_MAP_PF_FLAG_INSTRUCTION) {
if ((region->regionFlags & VM_MAP_REGION_FLAG_PERM_EXECUTE) != VM_MAP_REGION_FLAG_PERM_EXECUTE) {
VM_ERR("exec permission check failed operation flags %x, region flags %x", flags, region->regionFlags);
return LOS_NOK;
}
}
return LOS_OK;
}
STATIC VOID OsFaultTryFixup(ExcContext *frame, VADDR_T excVaddr, STATUS_T *status)
{
INT32 tableNum = (__exc_table_end - __exc_table_start) / sizeof(LosExcTable);
LosExcTable *excTable = (LosExcTable *)__exc_table_start;
#ifdef LOSCFG_DEBUG_VERSION
LosVmSpace *space = NULL;
VADDR_T vaddr;
#endif
if ((frame->regCPSR & CPSR_MODE_MASK) != CPSR_MODE_USR) {
for (int i = 0; i < tableNum; ++i, ++excTable) {
if (frame->PC == (UINTPTR)excTable->excAddr) {
frame->PC = (UINTPTR)excTable->fixAddr;
frame->R2 = (UINTPTR)excVaddr;
*status = LOS_OK;
return;
}
}
}
#ifdef LOSCFG_DEBUG_VERSION
vaddr = ROUNDDOWN(excVaddr, PAGE_SIZE);
space = LOS_SpaceGet(vaddr);
if (space != NULL) {
LOS_DumpMemRegion(vaddr);
}
#endif
}
#ifdef LOSCFG_FS_VFS
STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
{
status_t ret;
PADDR_T paddr;
LosVmPage *page = NULL;
VADDR_T vaddr = (VADDR_T)vmPgFault->vaddr;
LosVmSpace *space = region->space;
ret = LOS_ArchMmuQuery(&space->archMmu, vaddr, NULL, NULL);
if (ret == LOS_OK) {
return LOS_OK;
}
if (region->unTypeData.rf.vmFOps == NULL || region->unTypeData.rf.vmFOps->fault == NULL) {
VM_ERR("region args invalid, file path: %s", region->unTypeData.rf.file->f_path);
return LOS_ERRNO_VM_INVALID_ARGS;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
page = LOS_VmPageGet(paddr);
if (page != NULL) { /* just incase of page null */
LOS_AtomicInc(&page->refCounts);
OsCleanPageLocked(page);
}
ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, 1,
region->regionFlags & (~VM_MAP_REGION_FLAG_PERM_WRITE));
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap fial");
OsDelMapInfo(region, vmPgFault, false);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
/* numap a page when cow happend only */
STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, LosVmPgFault *vmf)
{
UINT32 intSave;
LosVmPage *oldPage = NULL;
LosMapInfo *mapInfo = NULL;
LosFilePage *fpage = NULL;
VADDR_T vaddr = (VADDR_T)vmf->vaddr;
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
if (fpage != NULL) {
oldPage = fpage->vmPage;
OsSetPageLocked(oldPage);
mapInfo = OsGetMapInfo(fpage, archMmu, vaddr);
if (mapInfo != NULL) {
OsUnmapPageLocked(fpage, mapInfo);
} else {
LOS_ArchMmuUnmap(archMmu, vaddr, 1);
}
} else {
LOS_ArchMmuUnmap(archMmu, vaddr, 1);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
return oldPage;
}
#endif
status_t OsDoCowFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
{
STATUS_T ret;
VOID *kvaddr = NULL;
PADDR_T oldPaddr = 0;
PADDR_T newPaddr;
LosVmPage *oldPage = NULL;
LosVmPage *newPage = NULL;
LosVmSpace *space = NULL;
if ((vmPgFault == NULL) || (region == NULL) ||
(region->unTypeData.rf.vmFOps == NULL) || (region->unTypeData.rf.vmFOps->fault == NULL)) {
VM_ERR("region args invalid");
return LOS_ERRNO_VM_INVALID_ARGS;
}
space = region->space;
ret = LOS_ArchMmuQuery(&space->archMmu, (VADDR_T)vmPgFault->vaddr, &oldPaddr, NULL);
if (ret == LOS_OK) {
oldPage = OsCowUnmapOrg(&space->archMmu, region, vmPgFault);
}
newPage = LOS_PhysPageAlloc();
if (newPage == NULL) {
VM_ERR("pmm_alloc_page fail");
ret = LOS_ERRNO_VM_NO_MEMORY;
goto ERR_OUT;
}
newPaddr = VM_PAGE_TO_PHYS(newPage);
kvaddr = OsVmPageToVaddr(newPage);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret != LOS_OK) {
VM_ERR("call region->vm_ops->fault fail");
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
goto ERR_OUT;
}
/**
* here we get two conditions, 1.this page hasn't mapped or mapped from pagecache,
* we can take it as a normal file cow map. 2.this page has done file cow map,
* we can take it as a anonymous cow map.
*/
if ((oldPaddr == 0) || (LOS_PaddrToKVaddr(oldPaddr) == vmPgFault->pageKVaddr)) {
(VOID)memcpy_s(kvaddr, PAGE_SIZE, vmPgFault->pageKVaddr, PAGE_SIZE);
LOS_AtomicInc(&newPage->refCounts);
OsCleanPageLocked(LOS_VmPageGet(LOS_PaddrQuery(vmPgFault->pageKVaddr)));
} else {
OsPhysSharePageCopy(oldPaddr, &newPaddr, newPage);
/* use old page free the new one */
if (newPaddr == oldPaddr) {
LOS_PhysPageFree(newPage);
newPage = NULL;
}
}
ret = LOS_ArchMmuMap(&space->archMmu, (VADDR_T)vmPgFault->vaddr, newPaddr, 1, region->regionFlags);
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap fial");
ret = LOS_ERRNO_VM_NO_MEMORY;
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
goto ERR_OUT;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
if (oldPage != NULL) {
OsCleanPageLocked(oldPage);
}
return LOS_OK;
ERR_OUT:
if (newPage != NULL) {
LOS_PhysPageFree(newPage);
}
if (oldPage != NULL) {
OsCleanPageLocked(oldPage);
}
return ret;
}
status_t OsDoSharedFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
{
STATUS_T ret;
UINT32 intSave;
PADDR_T paddr = 0;
VADDR_T vaddr = (VADDR_T)vmPgFault->vaddr;
LosVmSpace *space = region->space;
LosVmPage *page = NULL;
LosFilePage *fpage = NULL;
if ((region->unTypeData.rf.vmFOps == NULL) || (region->unTypeData.rf.vmFOps->fault == NULL)) {
VM_ERR("region args invalid");
return LOS_ERRNO_VM_INVALID_ARGS;
}
ret = LOS_ArchMmuQuery(&space->archMmu, vmPgFault->vaddr, &paddr, NULL);
if (ret == LOS_OK) {
LOS_ArchMmuUnmap(&space->archMmu, vmPgFault->vaddr, 1);
ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, 1, region->regionFlags);
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed. ret=%d", ret);
return LOS_ERRNO_VM_NO_MEMORY;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmPgFault->pgoff);
if (fpage) {
OsMarkPageDirty(fpage, region, 0, 0);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
return LOS_OK;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
page = LOS_VmPageGet(paddr);
/* just in case of page null */
if (page != NULL) {
LOS_AtomicInc(&page->refCounts);
OsCleanPageLocked(page);
}
ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, 1, region->regionFlags);
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed. ret=%d", ret);
OsDelMapInfo(region, vmPgFault, TRUE);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
return ret;
}
/**
* Page read operation is a simple case, just share the pagecache(save memory)
* and make a read permission mmapping (region->arch_mmu_flags & (~ARCH_MMU_FLAG_PERM_WRITE)).
* However for write operation, vmflag (VM_PRIVATE|VM_SHREAD) decides COW or SHARED fault.
* For COW fault, pagecache is copied to private anonyous pages and the changes on this page
* won't write through to the underlying file. For SHARED fault, pagecache is mapping with
* region->arch_mmu_flags and the changes on this page will write through to the underlying file
*/
STATIC STATUS_T OsDoFileFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault, UINT32 flags)
{
STATUS_T ret;
if (flags & VM_MAP_PF_FLAG_WRITE) {
if (region->regionFlags & VM_MAP_REGION_FLAG_SHARED) {
ret = OsDoSharedFault(region, vmPgFault);
} else {
ret = OsDoCowFault(region, vmPgFault);
}
} else {
ret = OsDoReadFault(region, vmPgFault);
}
return ret;
}
STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
{
LosVmSpace *space = LOS_SpaceGet(vaddr);
LosVmMapRegion *region = NULL;
STATUS_T status;
PADDR_T oldPaddr;
PADDR_T newPaddr;
VADDR_T excVaddr = vaddr;
LosVmPage *newPage = NULL;
LosVmPgFault vmPgFault = { 0 };
if (space == NULL) {
VM_ERR("vm space not exists, vaddr: %#x", vaddr);
status = LOS_ERRNO_VM_NOT_FOUND;
OsFaultTryFixup(frame, excVaddr, &status);
return status;
}
if (((flags & VM_MAP_PF_FLAG_USER) != 0) && (!LOS_IsUserAddress(vaddr))) {
VM_ERR("user space not allowed to access invalid address: %#x", vaddr);
return LOS_ERRNO_VM_ACCESS_DENIED;
}
(VOID)LOS_MuxAcquire(&space->regionMux);
region = LOS_RegionFind(space, vaddr);
if (region == NULL) {
VM_ERR("region not exists, vaddr: %#x", vaddr);
status = LOS_ERRNO_VM_NOT_FOUND;
goto CHECK_FAILED;
}
status = OsVmRegionRightCheck(region, flags);
if (status != LOS_OK) {
status = LOS_ERRNO_VM_ACCESS_DENIED;
goto CHECK_FAILED;
}
if (OomCheckProcess()) {
/*
* under low memory, when user process request memory allocation
* it will fail, and result is LOS_NOK and current user process
* will be deleted. memory usage detail will be printed.
*/
status = LOS_ERRNO_VM_NO_MEMORY;
goto CHECK_FAILED;
}
vaddr = ROUNDDOWN(vaddr, PAGE_SIZE);
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file->f_mapping == NULL) {
goto CHECK_FAILED;
}
vmPgFault.vaddr = vaddr;
vmPgFault.pgoff = ((vaddr - region->range.base) >> PAGE_SHIFT) + region->pgOff;
vmPgFault.flags = flags;
vmPgFault.pageKVaddr = NULL;
status = OsDoFileFault(region, &vmPgFault, flags);
if (status) {
VM_ERR("vm fault error, status=%d", status);
goto CHECK_FAILED;
}
goto DONE;
}
#endif
newPage = LOS_PhysPageAlloc();
if (newPage == NULL) {
status = LOS_ERRNO_VM_NO_MEMORY;
goto CHECK_FAILED;
}
newPaddr = VM_PAGE_TO_PHYS(newPage);
(VOID)memset_s(OsVmPageToVaddr(newPage), PAGE_SIZE, 0, PAGE_SIZE);
status = LOS_ArchMmuQuery(&space->archMmu, vaddr, &oldPaddr, NULL);
if (status >= 0) {
LOS_ArchMmuUnmap(&space->archMmu, vaddr, 1);
OsPhysSharePageCopy(oldPaddr, &newPaddr, newPage);
/* use old page free the new one */
if (newPaddr == oldPaddr) {
LOS_PhysPageFree(newPage);
newPage = NULL;
}
/* map all of the pages */
status = LOS_ArchMmuMap(&space->archMmu, vaddr, newPaddr, 1, region->regionFlags);
if (status < 0) {
VM_ERR("failed to map replacement page, status:%d", status);
status = LOS_ERRNO_VM_MAP_FAILED;
goto VMM_MAP_FAILED;
}
status = LOS_OK;
goto DONE;
} else {
/* map all of the pages */
LOS_AtomicInc(&newPage->refCounts);
status = LOS_ArchMmuMap(&space->archMmu, vaddr, newPaddr, 1, region->regionFlags);
if (status < 0) {
VM_ERR("failed to map page, status:%d", status);
status = LOS_ERRNO_VM_MAP_FAILED;
goto VMM_MAP_FAILED;
}
}
status = LOS_OK;
goto DONE;
VMM_MAP_FAILED:
if (newPage != NULL) {
LOS_PhysPageFree(newPage);
}
CHECK_FAILED:
OsFaultTryFixup(frame, excVaddr, &status);
DONE:
(VOID)LOS_MuxRelease(&space->regionMux);
return status;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

775
kernel/base/vm/los_vm_filemap.c Executable file
View File

@@ -0,0 +1,775 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_filemap vm filemap definition
* @ingroup kernel
*/
#include "los_vm_filemap.h"
#include "los_vm_page.h"
#include "los_vm_phys.h"
#include "los_vm_common.h"
#include "los_vm_fault.h"
#include "los_process_pri.h"
#include "inode/inode.h"
#include "los_vm_lock.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATIC VOID OsPageCacheAdd(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
LosFilePage *fpage = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
if (fpage->pgoff > pgoff) {
LOS_ListTailInsert(&fpage->node, &page->node);
goto done_add;
}
}
LOS_ListTailInsert(&mapping->page_list, &page->node);
OsSetPageLRU(page->vmPage);
done_add:
mapping->nrpages++;
}
VOID OsAddToPageacheLru(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
OsPageCacheAdd(page, mapping, pgoff);
OsLruCacheAdd(page, VM_LRU_ACTIVE_FILE);
}
VOID OsPageCacheDel(LosFilePage *fpage)
{
/* delete from file cache list */
LOS_ListDelete(&fpage->node);
fpage->mapping->nrpages--;
/* unmap and remove map info */
if (OsIsPageMapped(fpage)) {
OsUnmapAllLocked(fpage);
}
LOS_PhysPageFree(fpage->vmPage);
LOS_MemFree(m_aucSysMem0, fpage);
}
VOID OsAddMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
{
LosMapInfo *info = NULL;
info = (LosMapInfo *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosMapInfo));
if (info == NULL) {
VM_ERR("OsAddMapInfo alloc memory failed!");
return;
}
info->page = page;
info->archMmu = archMmu;
info->vaddr = vaddr;
LOS_ListAdd(&page->i_mmap, &info->node);
page->n_maps++;
}
LosMapInfo *OsGetMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
{
LosMapInfo *info = NULL;
LOS_DL_LIST *immap = &page->i_mmap;
LOS_DL_LIST_FOR_EACH_ENTRY(info, immap, LosMapInfo, node) {
if ((info->archMmu == archMmu) && (info->vaddr == vaddr) && (info->page == page)) {
return info;
}
}
return NULL;
}
VOID OsDeletePageCacheLru(LosFilePage *page)
{
/* delete form lru list */
OsLruCacheDel(page);
/* delete from cache lits and free pmm if need */
OsPageCacheDel(page);
}
STATIC LosFilePage *OsPagecacheGetPageAndFill(struct file *filp, VM_OFFSET_T pgOff, size_t *readSize, VADDR_T *kvaddr)
{
LosFilePage *page = NULL;
struct page_mapping *mapping = filp->f_mapping;
page = OsFindGetEntry(mapping, pgOff);
if (page != NULL) {
OsSetPageLocked(page->vmPage);
OsPageRefIncLocked(page);
*kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
*readSize = PAGE_SIZE;
} else {
page = OsPageCacheAlloc(mapping, pgOff);
if (page == NULL) {
VM_ERR("Failed to alloc a page frame");
return page;
}
OsSetPageLocked(page->vmPage);
*kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
file_seek(filp, pgOff << PAGE_SHIFT, SEEK_SET);
/* "ReadPage" func exists definitely in this procedure */
*readSize = filp->f_inode->u.i_mops->readpage(filp, (char *)(UINTPTR)*kvaddr, PAGE_SIZE);
if (*readSize == 0) {
VM_ERR("read 0 bytes");
OsCleanPageLocked(page->vmPage);
}
OsAddToPageacheLru(page, mapping, pgOff);
}
return page;
}
ssize_t OsMappingRead(struct file *filp, char *buf, size_t size)
{
INT32 ret;
vaddr_t kvaddr = 0;
UINT32 intSave;
struct stat bufStat;
size_t readSize = 0;
size_t readTotal = 0;
size_t readLeft = size;
LosFilePage *page = NULL;
VM_OFFSET_T pos = file_seek(filp, 0, SEEK_CUR);
VM_OFFSET_T pgOff = pos >> PAGE_SHIFT;
INT32 offInPage = pos % PAGE_SIZE;
struct page_mapping *mapping = filp->f_mapping;
INT32 nPages = (ROUNDUP(pos + size, PAGE_SIZE) - ROUNDDOWN(pos, PAGE_SIZE)) >> PAGE_SHIFT;
ret = stat(filp->f_path, &bufStat);
if (ret != OK) {
VM_ERR("Get file size failed. (filepath=%s)", filp->f_path);
return 0;
}
if (pos >= bufStat.st_size) {
PRINT_INFO("%s filp->f_pos >= bufStat.st_size (pos=%ld, fileSize=%ld)\n", filp->f_path, pos, bufStat.st_size);
return 0;
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
for (INT32 i = 0; (i < nPages) && readLeft; i++, pgOff++) {
page = OsPagecacheGetPageAndFill(filp, pgOff, &readSize, &kvaddr);
if ((page == NULL) || (readSize == 0)) {
break;
}
if (readSize < PAGE_SIZE) {
readLeft = readSize;
}
readSize = MIN2((PAGE_SIZE - offInPage), readLeft);
(VOID)memcpy_s((VOID *)buf, readLeft, (char *)kvaddr + offInPage, readSize);
buf += readSize;
readLeft -= readSize;
readTotal += readSize;
offInPage = 0;
OsCleanPageLocked(page->vmPage);
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
file_seek(filp, pos + readTotal, SEEK_SET);
return readTotal;
}
ssize_t OsMappingWrite(struct file *filp, const char *buf, size_t size)
{
VADDR_T kvaddr;
UINT32 intSave;
INT32 writeSize = 0;
size_t writeLeft = size;
VM_OFFSET_T pos = file_seek(filp, 0, SEEK_CUR);
VM_OFFSET_T pgOff = pos >> PAGE_SHIFT;
INT32 offInPage = pos % PAGE_SIZE;
LosFilePage *page = NULL;
struct page_mapping *mapping = filp->f_mapping;
INT32 nPages = (ROUNDUP(pos + size, PAGE_SIZE) - ROUNDDOWN(pos, PAGE_SIZE)) >> PAGE_SHIFT;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
for (INT32 i = 0; i < nPages; i++, pgOff++) {
page = OsFindGetEntry(mapping, pgOff);
if (page) {
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
OsSetPageLocked(page->vmPage);
OsPageRefIncLocked(page);
} else {
page = OsPageCacheAlloc(mapping, pgOff);
if (page == NULL) {
VM_ERR("Failed to alloc a page frame");
break;
}
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
OsAddToPageacheLru(page, mapping, pgOff);
OsSetPageLocked(page->vmPage);
}
writeSize = MIN2((PAGE_SIZE - offInPage), writeLeft);
(VOID)memcpy_s((char *)(UINTPTR)kvaddr + offInPage, writeLeft, buf, writeSize);
buf += writeSize;
writeLeft -= writeSize;
OsMarkPageDirty(page, NULL, offInPage, writeSize);
offInPage = 0;
OsCleanPageLocked(page->vmPage);
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
file_seek(filp, pos + size - writeLeft, SEEK_SET);
return (size - writeLeft);
}
STATIC VOID OsPageCacheUnmap(LosFilePage *fpage, LosArchMmu *archMmu, VADDR_T vaddr)
{
UINT32 intSave;
LosMapInfo *info = NULL;
LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);
info = OsGetMapInfo(fpage, archMmu, vaddr);
if (info == NULL) {
VM_ERR("OsPageCacheUnmap get map info fail!");
} else {
OsUnmapPageLocked(fpage, info);
}
if (!(OsIsPageMapped(fpage) && ((fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE) ||
OsIsPageDirty(fpage->vmPage)))) {
OsPageRefDecNoLock(fpage);
}
LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, intSave);
}
VOID OsVmmFileRemove(LosVmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T pgoff)
{
UINT32 intSave;
vaddr_t vaddr;
paddr_t paddr = 0;
struct file *file = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
LosFilePage *tmpPage = NULL;
LosVmPage *mapPage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL)) {
return;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
vaddr = region->range.base + ((UINT32)(pgoff - region->pgOff) << PAGE_SHIFT);
status_t status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
if (status != LOS_OK) {
return;
}
mapPage = LOS_VmPageGet(paddr);
/* is page is in cache list */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, pgoff);
/* no cache or have cache but not map(cow), free it direct */
if ((fpage == NULL) || (fpage->vmPage != mapPage)) {
LOS_PhysPageFree(mapPage);
LOS_ArchMmuUnmap(archMmu, vaddr, 1);
/* this is a page cache map! */
} else {
OsPageCacheUnmap(fpage, archMmu, vaddr);
if (OsIsPageDirty(fpage->vmPage)) {
tmpPage = OsDumpDirtyPage(fpage);
}
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
if (tmpPage) {
OsDoFlushDirtyPage(tmpPage);
}
return;
}
VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, INT32 off, INT32 len)
{
if (region != NULL) {
OsSetPageDirty(fpage->vmPage);
fpage->dirtyOff = off;
fpage->dirtyEnd = len;
} else {
OsSetPageDirty(fpage->vmPage);
if ((off + len) > fpage->dirtyEnd) {
fpage->dirtyEnd = off + len;
}
if (off < fpage->dirtyOff) {
fpage->dirtyOff = off;
}
}
}
STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct file *file)
{
UINT32 fileSize;
UINT32 dirtyBegin;
UINT32 dirtyEnd;
struct stat buf_stat;
if (stat(file->f_path, &buf_stat) != OK) {
VM_ERR("FlushDirtyPage get file size failed. (filepath=%s)", file->f_path);
return 0;
}
fileSize = buf_stat.st_size;
dirtyBegin = ((UINT32)fpage->pgoff << PAGE_SHIFT);
dirtyEnd = dirtyBegin + PAGE_SIZE;
if (dirtyBegin >= fileSize) {
return 0;
}
if (dirtyEnd >= fileSize) {
return fileSize - dirtyBegin;
}
return PAGE_SIZE;
}
STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
{
UINT32 ret;
size_t len;
char *buff = NULL;
VM_OFFSET_T oldPos;
struct file *file = fpage->mapping->host;
if ((file == NULL) || (file->f_inode == NULL)) {
VM_ERR("page cache file error");
return LOS_NOK;
}
oldPos = file_seek(file, 0, SEEK_CUR);
buff = (char *)OsVmPageToVaddr(fpage->vmPage);
file_seek(file, (((UINT32)fpage->pgoff << PAGE_SHIFT) + fpage->dirtyOff), SEEK_SET);
len = fpage->dirtyEnd - fpage->dirtyOff;
len = (len == 0) ? GetDirtySize(fpage, file) : len;
if (len == 0) {
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return LOS_OK;
}
if (file->f_inode && file->f_inode->u.i_mops->writepage) {
ret = file->f_inode->u.i_mops->writepage(file, (buff + fpage->dirtyOff), len);
} else {
ret = file_write(file, (VOID *)buff, len);
}
if (ret <= 0) {
VM_ERR("WritePage error ret %d", ret);
}
ret = (ret <= 0) ? LOS_NOK : LOS_OK;
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return ret;
}
LosFilePage *OsDumpDirtyPage(LosFilePage *oldFPage)
{
LosFilePage *newFPage = NULL;
newFPage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));
if (newFPage == NULL) {
VM_ERR("Failed to allocate for temp page!");
return NULL;
}
OsCleanPageDirty(oldFPage->vmPage);
LOS_AtomicInc(&oldFPage->vmPage->refCounts);
/* no map page cache */
if (LOS_AtomicRead(&oldFPage->vmPage->refCounts) == 1) {
LOS_AtomicInc(&oldFPage->vmPage->refCounts);
}
(VOID)memcpy_s(newFPage, sizeof(LosFilePage), oldFPage, sizeof(LosFilePage));
return newFPage;
}
VOID OsDoFlushDirtyPage(LosFilePage *fpage)
{
if (fpage == NULL) {
return;
}
(VOID)OsFlushDirtyPage(fpage);
LOS_PhysPageFree(fpage->vmPage);
LOS_MemFree(m_aucSysMem0, fpage);
}
STATIC VOID OsReleaseFpage(struct page_mapping *mapping, LosFilePage *fpage)
{
UINT32 intSave;
UINT32 lruSave;
SPIN_LOCK_S *lruLock = &fpage->physSeg->lruLock;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
LOS_SpinLockSave(lruLock, &lruSave);
OsCleanPageLocked(fpage->vmPage);
OsDeletePageCacheLru(fpage);
LOS_SpinUnlockRestore(lruLock, lruSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
{
UINT32 intSave;
LosMapInfo *info = NULL;
LosFilePage *fpage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
return;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
if (fpage == NULL) {
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
return;
}
if (cleanDirty) {
OsCleanPageDirty(fpage->vmPage);
}
info = OsGetMapInfo(fpage, &region->space->archMmu, (vaddr_t)vmf->vaddr);
if (info != NULL) {
fpage->n_maps--;
LOS_ListDelete(&info->node);
LOS_AtomicDec(&fpage->vmPage->refCounts);
LOS_MemFree(m_aucSysMem0, info);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
}
INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
{
INT32 ret;
VM_OFFSET_T oldPos;
VOID *kvaddr = NULL;
UINT32 intSave;
bool newCache = false;
struct file *file = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
VM_ERR("Input param is NULL");
return LOS_NOK;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
/* get or create a new cache node */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, vmf->pgoff);
if (fpage != NULL) {
OsPageRefIncLocked(fpage);
} else {
fpage = OsPageCacheAlloc(mapping, vmf->pgoff);
if (fpage == NULL) {
VM_ERR("Failed to alloc a page frame");
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return LOS_NOK;
}
newCache = true;
}
OsSetPageLocked(fpage->vmPage);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
kvaddr = OsVmPageToVaddr(fpage->vmPage);
/* read file to new page cache */
if (newCache) {
oldPos = file_seek(file, 0, SEEK_CUR);
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);
if (file->f_inode && file->f_inode->u.i_mops->readpage) {
ret = file->f_inode->u.i_mops->readpage(file, (char *)kvaddr, PAGE_SIZE);
} else {
ret = file_read(file, kvaddr, PAGE_SIZE);
}
file_seek(file, oldPos, SEEK_SET);
if (ret == 0) {
VM_ERR("Failed to read from file!");
OsReleaseFpage(mapping, fpage);
return LOS_NOK;
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
OsAddToPageacheLru(fpage, mapping, vmf->pgoff);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
/* cow fault case no need to save mapinfo */
if (!((vmf->flags & VM_MAP_PF_FLAG_WRITE) && !(region->regionFlags & VM_MAP_REGION_FLAG_SHARED))) {
OsAddMapInfo(fpage, &region->space->archMmu, (vaddr_t)vmf->vaddr);
fpage->flags = region->regionFlags;
}
/* share page fault, mark the page dirty */
if ((vmf->flags & VM_MAP_PF_FLAG_WRITE) && (region->regionFlags & VM_MAP_REGION_FLAG_SHARED)) {
OsMarkPageDirty(fpage, region, 0, 0);
}
vmf->pageKVaddr = kvaddr;
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return LOS_OK;
}
VOID OsFileCacheFlush(struct page_mapping *mapping)
{
UINT32 intSave;
UINT32 lruLock;
LOS_DL_LIST_HEAD(dirtyList);
LosFilePage *ftemp = NULL;
LosFilePage *fpage = NULL;
if (mapping == NULL) {
return;
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
LOS_SpinLockSave(&fpage->physSeg->lruLock, &lruLock);
if (OsIsPageDirty(fpage->vmPage)) {
ftemp = OsDumpDirtyPage(fpage);
if (ftemp != NULL) {
LOS_ListTailInsert(&dirtyList, &ftemp->node);
}
}
LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, lruLock);
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, ftemp, &dirtyList, LosFilePage, node) {
OsDoFlushDirtyPage(fpage);
}
}
VOID OsFileCacheRemove(struct page_mapping *mapping)
{
UINT32 intSave;
UINT32 lruSave;
SPIN_LOCK_S *lruLock = NULL;
LOS_DL_LIST_HEAD(dirtyList);
LosFilePage *ftemp = NULL;
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &mapping->page_list, LosFilePage, node) {
lruLock = &fpage->physSeg->lruLock;
LOS_SpinLockSave(lruLock, &lruSave);
if (OsIsPageDirty(fpage->vmPage)) {
ftemp = OsDumpDirtyPage(fpage);
if (ftemp != NULL) {
LOS_ListTailInsert(&dirtyList, &ftemp->node);
}
}
OsDeletePageCacheLru(fpage);
LOS_SpinUnlockRestore(lruLock, lruSave);
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &dirtyList, LosFilePage, node) {
OsDoFlushDirtyPage(fpage);
}
}
LosVmFileOps g_commVmOps = {
.open = NULL,
.close = NULL,
.fault = OsVmmFileFault,
.remove = OsVmmFileRemove,
};
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
{
region->unTypeData.rf.vmFOps = &g_commVmOps;
region->unTypeData.rf.file = filep;
region->unTypeData.rf.fileMagic = filep->f_magicnum;
return ENOERR;
}
STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
{
struct inode *inodePtr = NULL;
if (filep == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
inodePtr = filep->f_inode;
if (inodePtr == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
if (INODE_IS_MOUNTPT(inodePtr)) {
if (inodePtr->u.i_mops->mmap) {
LOS_SetRegionTypeFile(region);
return inodePtr->u.i_mops->mmap(filep, region);
} else {
VM_ERR("file mmap not support");
return LOS_ERRNO_VM_MAP_FAILED;
}
} else if (INODE_IS_DRIVER(inodePtr)) {
if (inodePtr->u.i_ops->mmap) {
LOS_SetRegionTypeDev(region);
return inodePtr->u.i_ops->mmap(filep, region);
} else {
VM_ERR("dev mmap not support");
return LOS_ERRNO_VM_MAP_FAILED;
}
} else {
VM_ERR("mmap file type unknown");
return LOS_ERRNO_VM_MAP_FAILED;
}
}
LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
LosFilePage *fpage = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
if (fpage->pgoff == pgoff) {
return fpage;
}
if (fpage->pgoff > pgoff) {
break;
}
}
return NULL;
}
/* need mutex & change memory to dma zone. */
LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
VOID *kvaddr = NULL;
LosVmPhysSeg *physSeg = NULL;
LosVmPage *vmPage = NULL;
LosFilePage *fpage = NULL;
vmPage = LOS_PhysPageAlloc();
if (vmPage == NULL) {
VM_ERR("alloc vm page failed");
return NULL;
}
physSeg = OsVmPhysSegGet(vmPage);
kvaddr = OsVmPageToVaddr(vmPage);
if ((physSeg == NULL) || (kvaddr == NULL)) {
LOS_PhysPageFree(vmPage);
VM_ERR("alloc vm page failed!");
return NULL;
}
fpage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));
if (fpage == NULL) {
LOS_PhysPageFree(vmPage);
VM_ERR("Failed to allocate for page!");
return NULL;
}
(VOID)memset_s((VOID *)fpage, sizeof(LosFilePage), 0, sizeof(LosFilePage));
LOS_ListInit(&fpage->i_mmap);
LOS_ListInit(&fpage->node);
LOS_ListInit(&fpage->lru);
fpage->n_maps = 0;
fpage->dirtyOff = PAGE_SIZE;
fpage->dirtyEnd = 0;
fpage->physSeg = physSeg;
fpage->vmPage = vmPage;
fpage->mapping = mapping;
fpage->pgoff = pgoff;
(VOID)memset_s(kvaddr, PAGE_SIZE, 0, PAGE_SIZE);
return fpage;
}
#ifdef LOSCFG_FS_VFS
VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB)
{
int ret;
LosVmSpace *space = NULL;
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeTmp = NULL;
if (processCB == NULL) {
processCB = OsCurrProcessGet();
}
space = processCB->vmSpace;
if (space != NULL) {
/* free the regions associated with filep */
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
region = (LosVmMapRegion *)pstRbNode;
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file != filep) {
continue;
}
ret = LOS_RegionFree(space, region);
if (ret != LOS_OK) {
VM_ERR("free region error, space %p, region %p", space, region);
}
}
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
}
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

218
kernel/base/vm/los_vm_iomap.c Executable file
View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_vm_iomap.h"
#include "los_printf.h"
#include "los_vm_zone.h"
#include "los_vm_common.h"
#include "los_vm_map.h"
#include "los_vm_lock.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
VOID *ioremap(PADDR_T paddr, unsigned long size)
{
if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) {
return (VOID *)(UINTPTR)IO_DEVICE_ADDR(paddr);
}
VM_ERR("ioremap failed invalid addr or size %p %d", paddr, size);
return (VOID *)(UINTPTR)paddr;
}
VOID iounmap(VOID *vaddr) {}
VOID *ioremap_nocache(PADDR_T paddr, unsigned long size)
{
if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) {
return (VOID *)(UINTPTR)IO_UNCACHED_ADDR(paddr);
}
if (IS_MEMORY_ADDR(paddr) && IS_MEMORY_ADDR(paddr + size)) {
return (VOID *)(UINTPTR)MEM_UNCACHED_ADDR(paddr);
}
VM_ERR("ioremap_nocache failed invalid addr or size %p %d", paddr, size);
return (VOID *)(UINTPTR)paddr;
}
VOID *ioremap_cached(PADDR_T paddr, unsigned long size)
{
if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) {
return (VOID *)(UINTPTR)IO_CACHED_ADDR(paddr);
}
if (IS_MEMORY_ADDR(paddr) && IS_MEMORY_ADDR(paddr + size)) {
return (VOID *)(UINTPTR)MEM_CACHED_ADDR(paddr);
}
VM_ERR("ioremap_cached failed invalid addr or size %p %d", paddr, size);
return (VOID *)(UINTPTR)paddr;
}
int remap_pfn_range(VADDR_T vaddr, unsigned long pfn, unsigned long size, unsigned long prot)
{
STATUS_T status = LOS_OK;
int ret;
LosVmMapRegion *region = NULL;
unsigned long vpos;
unsigned long end;
unsigned long paddr = pfn << PAGE_SHIFT;
LosVmSpace *space = LOS_SpaceGet(vaddr);
if (size == 0) {
VM_ERR("invalid map size %u", size);
return LOS_ERRNO_VM_INVALID_ARGS;
}
size = ROUNDUP(size, PAGE_SIZE);
if (!IS_PAGE_ALIGNED(vaddr) || pfn == 0) {
VM_ERR("invalid map map vaddr %x or pfn %x", vaddr, pfn);
return LOS_ERRNO_VM_INVALID_ARGS;
}
if (space == NULL) {
VM_ERR("aspace not exists");
return LOS_ERRNO_VM_NOT_FOUND;
}
(VOID)LOS_MuxAcquire(&space->regionMux);
region = LOS_RegionFind(space, vaddr);
if (region == NULL) {
VM_ERR("region not exists");
status = LOS_ERRNO_VM_NOT_FOUND;
goto OUT;
}
end = vaddr + size;
if (region->range.base + region->range.size < end) {
VM_ERR("out of range:base=%x size=%d vaddr=%x len=%u",
region->range.base, region->range.size, vaddr, size);
status = LOS_ERRNO_VM_INVALID_ARGS;
goto OUT;
}
/* check */
for (vpos = vaddr; vpos < end; vpos += PAGE_SIZE) {
status = LOS_ArchMmuQuery(&space->archMmu, (VADDR_T)vpos, NULL, NULL);
if (status == LOS_OK) {
VM_ERR("remap_pfn_range, address mapping already exist");
status = LOS_ERRNO_VM_INVALID_ARGS;
goto OUT;
}
}
/* map all */
ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, size >> PAGE_SHIFT, prot);
if (ret <= 0) {
VM_ERR("ioremap LOS_ArchMmuMap failed err = %d", ret);
goto OUT;
}
status = LOS_OK;
OUT:
(VOID)LOS_MuxRelease(&space->regionMux);
return status;
}
VOID *LOS_DmaMemAlloc(DMA_ADDR_T *dmaAddr, size_t size, size_t align, enum DmaMemType type)
{
VOID *kVaddr = NULL;
if (size == 0) {
return NULL;
}
if ((type != DMA_CACHE) && (type != DMA_NOCACHE)) {
VM_ERR("The dma type = %d is not support!", type);
return NULL;
}
kVaddr = LOS_KernelMallocAlign(size, align);
if (kVaddr == NULL) {
VM_ERR("failed, size = %u, align = %u", size, align);
return NULL;
}
if (dmaAddr != NULL) {
*dmaAddr = (DMA_ADDR_T)LOS_PaddrQuery(kVaddr);
}
if (type == DMA_NOCACHE) {
kVaddr = (VOID *)VMM_TO_UNCACHED_ADDR((UINTPTR)kVaddr);
}
return kVaddr;
}
VOID LOS_DmaMemFree(VOID *vaddr)
{
UINTPTR addr;
if (vaddr == NULL) {
return;
}
addr = (UINTPTR)vaddr;
if ((addr >= UNCACHED_VMM_BASE) && (addr < UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)) {
addr = UNCACHED_TO_VMM_ADDR(addr);
LOS_KernelFree((VOID *)addr);
} else if ((addr >= KERNEL_VMM_BASE) && (addr < KERNEL_VMM_BASE + KERNEL_VMM_SIZE)) {
LOS_KernelFree((VOID *)addr);
} else {
VM_ERR("addr %#x not in dma area!!!", vaddr);
}
return;
}
DMA_ADDR_T LOS_DmaVaddrToPaddr(VOID *vaddr)
{
status_t ret;
paddr_t pa;
LosVmSpace *space = LOS_GetKVmSpace();
ret = LOS_ArchMmuQuery(&space->archMmu, (VADDR_T)(UINTPTR)vaddr, &pa, NULL);
if (ret != LOS_OK) {
return (DMA_ADDR_T)NULL;
}
return (DMA_ADDR_T)pa;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

1209
kernel/base/vm/los_vm_map.c Executable file

File diff suppressed because it is too large Load Diff

111
kernel/base/vm/los_vm_page.c Executable file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_vm_page.h"
#include "los_vm_common.h"
#include "los_vm_phys.h"
#include "los_vm_boot.h"
#include "los_vm_filemap.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LosVmPage *g_vmPageArray = NULL;
size_t g_vmPageArraySize;
STATIC VOID OsVmPageInit(LosVmPage *page, paddr_t pa, UINT8 segID)
{
LOS_ListInit(&page->node);
page->flags = FILE_PAGE_FREE;
LOS_AtomicSet(&page->refCounts, 0);
page->physAddr = pa;
page->segID = segID;
page->order = VM_LIST_ORDER_MAX;
}
STATIC INLINE VOID OsVmPageOrderListInit(LosVmPage *page, size_t nPages)
{
OsVmPhysPagesFreeContiguous(page, nPages);
}
VOID OsVmPageStartup(VOID)
{
struct VmPhysSeg *seg = NULL;
LosVmPage *page = NULL;
paddr_t pa;
UINT32 nPage;
INT32 segID;
OsVmPhysAreaSizeAdjust(ROUNDUP((g_vmBootMemBase - KERNEL_ASPACE_BASE), PAGE_SIZE));
nPage = OsVmPhysPageNumGet();
g_vmPageArraySize = nPage * sizeof(LosVmPage);
g_vmPageArray = (LosVmPage *)OsVmBootMemAlloc(g_vmPageArraySize);
OsVmPhysAreaSizeAdjust(ROUNDUP(g_vmPageArraySize, PAGE_SIZE));
OsVmPhysSegAdd();
OsVmPhysInit();
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
nPage = seg->size >> PAGE_SHIFT;
for (page = seg->pageBase, pa = seg->start; page <= seg->pageBase + nPage;
page++, pa += PAGE_SIZE) {
OsVmPageInit(page, pa, segID);
}
OsVmPageOrderListInit(seg->pageBase, nPage);
}
}
LosVmPage *LOS_VmPageGet(PADDR_T paddr)
{
INT32 segID;
LosVmPage *page = NULL;
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
page = OsVmPhysToPage(paddr, segID);
if (page != NULL) {
break;
}
}
return page;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

585
kernel/base/vm/los_vm_phys.c Executable file
View File

@@ -0,0 +1,585 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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_vm_phys.h"
#include "los_vm_boot.h"
#include "los_vm_common.h"
#include "los_vm_map.h"
#include "los_vm_dump.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define ONE_PAGE 1
/* Physical memory area array */
STATIC struct VmPhysArea g_physArea[] = {
{
.start = SYS_MEM_BASE,
.size = SYS_MEM_SIZE_DEFAULT,
},
};
struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX];
INT32 g_vmPhysSegNum = 0;
LosVmPhysSeg *OsGVmPhysSegGet()
{
return g_vmPhysSeg;
}
STATIC VOID OsVmPhysLruInit(struct VmPhysSeg *seg)
{
INT32 i;
UINT32 intSave;
LOS_SpinInit(&seg->lruLock);
LOS_SpinLockSave(&seg->lruLock, &intSave);
for (i = 0; i < VM_NR_LRU_LISTS; i++) {
seg->lruSize[i] = 0;
LOS_ListInit(&seg->lruList[i]);
}
LOS_SpinUnlockRestore(&seg->lruLock, intSave);
}
STATIC INT32 OsVmPhysSegCreate(paddr_t start, size_t size)
{
struct VmPhysSeg *seg = NULL;
if (g_vmPhysSegNum >= VM_PHYS_SEG_MAX) {
return -1;
}
seg = &g_vmPhysSeg[g_vmPhysSegNum++];
for (; (seg > g_vmPhysSeg) && ((seg - 1)->start > (start + size)); seg--) {
*seg = *(seg - 1);
}
seg->start = start;
seg->size = size;
return 0;
}
VOID OsVmPhysSegAdd(VOID)
{
INT32 i, ret;
LOS_ASSERT(g_vmPhysSegNum <= VM_PHYS_SEG_MAX);
for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {
ret = OsVmPhysSegCreate(g_physArea[i].start, g_physArea[i].size);
if (ret != 0) {
VM_ERR("create phys seg failed");
}
}
}
VOID OsVmPhysAreaSizeAdjust(size_t size)
{
INT32 i;
for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {
g_physArea[i].start += size;
g_physArea[i].size -= size;
}
}
UINT32 OsVmPhysPageNumGet(VOID)
{
UINT32 nPages = 0;
INT32 i;
for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {
nPages += g_physArea[i].size >> PAGE_SHIFT;
}
return nPages;
}
STATIC INLINE VOID OsVmPhysFreeListInit(struct VmPhysSeg *seg)
{
int i;
UINT32 intSave;
struct VmFreeList *list = NULL;
LOS_SpinInit(&seg->freeListLock);
LOS_SpinLockSave(&seg->freeListLock, &intSave);
for (i = 0; i < VM_LIST_ORDER_MAX; i++) {
list = &seg->freeList[i];
LOS_ListInit(&list->node);
list->listCnt = 0;
}
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
VOID OsVmPhysInit(VOID)
{
struct VmPhysSeg *seg = NULL;
UINT32 nPages = 0;
int i;
for (i = 0; i < g_vmPhysSegNum; i++) {
seg = &g_vmPhysSeg[i];
seg->pageBase = &g_vmPageArray[nPages];
nPages += seg->size >> PAGE_SHIFT;
OsVmPhysFreeListInit(seg);
OsVmPhysLruInit(seg);
}
}
STATIC VOID OsVmPhysFreeListAdd(LosVmPage *page, UINT8 order)
{
struct VmPhysSeg *seg = NULL;
struct VmFreeList *list = NULL;
if (page->segID >= VM_PHYS_SEG_MAX) {
LOS_Panic("The page segment id(%d) is invalid\n", page->segID);
}
page->order = order;
seg = &g_vmPhysSeg[page->segID];
list = &seg->freeList[order];
LOS_ListTailInsert(&list->node, &page->node);
list->listCnt++;
}
STATIC VOID OsVmPhysFreeListAddUnsafe(LosVmPage *page, UINT8 order)
{
struct VmPhysSeg *seg = NULL;
struct VmFreeList *list = NULL;
if (page->segID >= VM_PHYS_SEG_MAX) {
LOS_Panic("The page segment id(%d) is invalid\n", page->segID);
}
page->order = order;
seg = &g_vmPhysSeg[page->segID];
list = &seg->freeList[order];
LOS_ListTailInsert(&list->node, &page->node);
list->listCnt++;
}
STATIC VOID OsVmPhysFreeListDelUnsafe(LosVmPage *page)
{
struct VmPhysSeg *seg = NULL;
struct VmFreeList *list = NULL;
if ((page->segID >= VM_PHYS_SEG_MAX) || (page->order >= VM_LIST_ORDER_MAX)) {
LOS_Panic("The page segment id(%u) or order(%u) is invalid\n", page->segID, page->order);
}
seg = &g_vmPhysSeg[page->segID];
list = &seg->freeList[page->order];
list->listCnt--;
LOS_ListDelete(&page->node);
page->order = VM_LIST_ORDER_MAX;
}
STATIC VOID OsVmPhysFreeListDel(LosVmPage *page)
{
struct VmPhysSeg *seg = NULL;
struct VmFreeList *list = NULL;
if ((page->segID >= VM_PHYS_SEG_MAX) || (page->order >= VM_LIST_ORDER_MAX)) {
LOS_Panic("The page segment id(%u) or order(%u) is invalid\n", page->segID, page->order);
}
seg = &g_vmPhysSeg[page->segID];
list = &seg->freeList[page->order];
list->listCnt--;
LOS_ListDelete(&page->node);
page->order = VM_LIST_ORDER_MAX;
}
STATIC VOID OsVmPhysPagesSpiltUnsafe(LosVmPage *page, UINT8 oldOrder, UINT8 newOrder)
{
UINT32 order;
LosVmPage *buddyPage = NULL;
for (order = newOrder; order > oldOrder;) {
order--;
buddyPage = &page[VM_ORDER_TO_PAGES(order)];
LOS_ASSERT(buddyPage->order == VM_LIST_ORDER_MAX);
OsVmPhysFreeListAddUnsafe(buddyPage, order);
}
}
LosVmPage *OsVmPhysToPage(paddr_t pa, UINT8 segID)
{
struct VmPhysSeg *seg = NULL;
paddr_t offset;
if (segID >= VM_PHYS_SEG_MAX) {
LOS_Panic("The page segment id(%d) is invalid\n", segID);
}
seg = &g_vmPhysSeg[segID];
if ((pa < seg->start) || (pa >= (seg->start + seg->size))) {
return NULL;
}
offset = pa - seg->start;
return (seg->pageBase + (offset >> PAGE_SHIFT));
}
VOID *OsVmPageToVaddr(LosVmPage *page)
{
VADDR_T vaddr;
vaddr = KERNEL_ASPACE_BASE + page->physAddr - SYS_MEM_BASE;
return (VOID *)(UINTPTR)vaddr;
}
LosVmPage *OsVmVaddrToPage(VOID *ptr)
{
struct VmPhysSeg *seg = NULL;
PADDR_T pa = LOS_PaddrQuery(ptr);
UINT32 segID;
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
if ((pa >= seg->start) && (pa < (seg->start + seg->size))) {
return seg->pageBase + ((pa - seg->start) >> PAGE_SHIFT);
}
}
return NULL;
}
LosVmPage *OsVmPhysPagesAlloc(struct VmPhysSeg *seg, size_t nPages)
{
struct VmFreeList *list = NULL;
LosVmPage *page = NULL;
UINT32 order;
UINT32 newOrder;
if ((seg == NULL) || (nPages == 0)) {
return NULL;
}
order = OsVmPagesToOrder(nPages);
if (order < VM_LIST_ORDER_MAX) {
for (newOrder = order; newOrder < VM_LIST_ORDER_MAX; newOrder++) {
list = &seg->freeList[newOrder];
if (LOS_ListEmpty(&list->node)) {
continue;
}
page = LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(&list->node), LosVmPage, node);
goto DONE;
}
}
return NULL;
DONE:
OsVmPhysFreeListDelUnsafe(page);
OsVmPhysPagesSpiltUnsafe(page, order, newOrder);
return page;
}
VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order)
{
paddr_t pa;
LosVmPage *buddyPage = NULL;
if ((page == NULL) || (order >= VM_LIST_ORDER_MAX)) {
return;
}
if (order < VM_LIST_ORDER_MAX - 1) {
pa = VM_PAGE_TO_PHYS(page);
do {
pa ^= VM_ORDER_TO_PHYS(order);
buddyPage = OsVmPhysToPage(pa, page->segID);
if ((buddyPage == NULL) || (buddyPage->order != order)) {
break;
}
OsVmPhysFreeListDel(buddyPage);
order++;
pa &= ~(VM_ORDER_TO_PHYS(order) - 1);
page = OsVmPhysToPage(pa, page->segID);
} while (order < VM_LIST_ORDER_MAX - 1);
}
OsVmPhysFreeListAdd(page, order);
}
VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages)
{
paddr_t pa;
UINT32 order;
size_t count;
size_t n;
while (TRUE) {
pa = VM_PAGE_TO_PHYS(page);
order = VM_PHYS_TO_ORDER(pa);
n = VM_ORDER_TO_PAGES(order);
if (n > nPages) {
break;
}
OsVmPhysPagesFree(page, order);
nPages -= n;
page += n;
}
for (count = 0; count < nPages; count += n) {
order = LOS_HighBitGet(nPages);
n = VM_ORDER_TO_PAGES(order);
OsVmPhysPagesFree(page, order);
page += n;
}
}
STATIC LosVmPage *OsVmPhysPagesGet(size_t nPages)
{
UINT32 intSave;
struct VmPhysSeg *seg = NULL;
LosVmPage *page = NULL;
UINT32 segID;
if (nPages == 0) {
return NULL;
}
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave);
page = OsVmPhysPagesAlloc(seg, nPages);
if (page != NULL) {
/* the first page of continuous physical addresses holds refCounts */
LOS_AtomicSet(&page->refCounts, 0);
page->nPages = nPages;
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
return page;
}
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
return NULL;
}
VOID *LOS_PhysPagesAllocContiguous(size_t nPages)
{
LosVmPage *page = NULL;
if (nPages == 0) {
return NULL;
}
page = OsVmPhysPagesGet(nPages);
if (page == NULL) {
return NULL;
}
return OsVmPageToVaddr(page);
}
VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages)
{
UINT32 intSave;
struct VmPhysSeg *seg = NULL;
LosVmPage *page = NULL;
if (ptr == NULL) {
return;
}
page = OsVmVaddrToPage(ptr);
if (page == NULL) {
VM_ERR("vm page of ptr(%#x) is null", ptr);
return;
}
page->nPages = 0;
seg = &g_vmPhysSeg[page->segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave);
OsVmPhysPagesFreeContiguous(page, nPages);
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
VADDR_T *LOS_PaddrToKVaddr(PADDR_T paddr)
{
struct VmPhysSeg *seg = NULL;
UINT32 segID;
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
if ((paddr >= seg->start) && (paddr < (seg->start + seg->size))) {
return (VADDR_T *)(UINTPTR)(paddr - SYS_MEM_BASE + KERNEL_ASPACE_BASE);
}
}
return (VADDR_T *)(UINTPTR)(paddr - SYS_MEM_BASE + KERNEL_ASPACE_BASE);
}
VOID LOS_PhysPageFree(LosVmPage *page)
{
UINT32 intSave;
struct VmPhysSeg *seg = NULL;
if (page == NULL) {
return;
}
if (LOS_AtomicDecRet(&page->refCounts) <= 0) {
seg = &g_vmPhysSeg[page->segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave);
OsVmPhysPagesFreeContiguous(page, ONE_PAGE);
LOS_AtomicSet(&page->refCounts, 0);
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
}
LosVmPage *LOS_PhysPageAlloc(VOID)
{
return OsVmPhysPagesGet(ONE_PAGE);
}
size_t LOS_PhysPagesAlloc(size_t nPages, LOS_DL_LIST *list)
{
LosVmPage *page = NULL;
size_t count = 0;
if ((list == NULL) || (nPages == 0)) {
return 0;
}
while (nPages--) {
page = OsVmPhysPagesGet(ONE_PAGE);
if (page == NULL) {
break;
}
LOS_ListTailInsert(list, &page->node);
count++;
}
return count;
}
VOID OsPhysSharePageCopy(PADDR_T oldPaddr, PADDR_T *newPaddr, LosVmPage *newPage)
{
UINT32 intSave;
LosVmPage *oldPage = NULL;
VOID *newMem = NULL;
VOID *oldMem = NULL;
LosVmPhysSeg *seg = NULL;
if ((newPage == NULL) || (newPaddr == NULL)) {
VM_ERR("new Page invalid");
return;
}
oldPage = LOS_VmPageGet(oldPaddr);
if (oldPage == NULL) {
VM_ERR("invalid paddr %p", oldPaddr);
return;
}
seg = &g_vmPhysSeg[oldPage->segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave);
if (LOS_AtomicRead(&oldPage->refCounts) == 1) {
*newPaddr = oldPaddr;
} else {
newMem = LOS_PaddrToKVaddr(*newPaddr);
oldMem = LOS_PaddrToKVaddr(oldPaddr);
if ((newMem == NULL) || (oldMem == NULL)) {
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
return;
}
if (memcpy_s(newMem, PAGE_SIZE, oldMem, PAGE_SIZE) != EOK) {
VM_ERR("memcpy_s failed");
}
LOS_AtomicInc(&newPage->refCounts);
LOS_AtomicDec(&oldPage->refCounts);
}
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
return;
}
struct VmPhysSeg *OsVmPhysSegGet(LosVmPage *page)
{
if ((page == NULL) || (page->segID >= VM_PHYS_SEG_MAX)) {
return NULL;
}
return (OsGVmPhysSegGet() + page->segID);
}
UINT32 OsVmPagesToOrder(size_t nPages)
{
UINT32 order;
for (order = 0; VM_ORDER_TO_PAGES(order) < nPages; order++);
return order;
}
size_t LOS_PhysPagesFree(LOS_DL_LIST *list)
{
UINT32 intSave;
LosVmPage *page = NULL;
LosVmPage *nPage = NULL;
LosVmPhysSeg *seg = NULL;
size_t count = 0;
if (list == NULL) {
return 0;
}
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(page, nPage, list, LosVmPage, node) {
LOS_ListDelete(&page->node);
if (LOS_AtomicDecRet(&page->refCounts) <= 0) {
seg = &g_vmPhysSeg[page->segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave);
OsVmPhysPagesFreeContiguous(page, ONE_PAGE);
LOS_AtomicSet(&page->refCounts, 0);
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
count++;
}
return count;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

346
kernel/base/vm/los_vm_scan.c Executable file
View File

@@ -0,0 +1,346 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "menuconfig.h"
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "los_vm_filemap.h"
/* unmap a lru page by map record info caller need lru lock */
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info)
{
if (page == NULL || info == NULL) {
VM_ERR("UnmapPage error input null!");
return;
}
page->n_maps--;
LOS_ListDelete(&info->node);
LOS_AtomicDec(&page->vmPage->refCounts);
LOS_ArchMmuUnmap(info->archMmu, info->vaddr, 1);
LOS_MemFree(m_aucSysMem0, info);
}
VOID OsUnmapAllLocked(LosFilePage *page)
{
LosMapInfo *info = NULL;
LosMapInfo *next = NULL;
LOS_DL_LIST *immap = &page->i_mmap;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(info, next, immap, LosMapInfo, node) {
OsUnmapPageLocked(page, info);
}
}
/* add a new lru node to lru list, lruType can be file or anon */
VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType)
{
UINT32 intSave;
LosVmPhysSeg *physSeg = fpage->physSeg;
LosVmPage *page = fpage->vmPage;
LOS_SpinLockSave(&physSeg->lruLock, &intSave);
OsSetPageActive(page);
OsCleanPageReferenced(page);
physSeg->lruSize[lruType]++;
LOS_ListTailInsert(&physSeg->lruList[lruType], &fpage->lru);
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
}
/* dellete a lru node, caller need hold lru_lock */
VOID OsLruCacheDel(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
int type = OsIsPageActive(fpage->vmPage) ? VM_LRU_ACTIVE_FILE : VM_LRU_INACTIVE_FILE;
physSeg->lruSize[type]--;
LOS_ListDelete(&fpage->lru);
}
BOOL OsInactiveListIsLow(LosVmPhysSeg *physSeg)
{
return (physSeg->lruSize[VM_LRU_ACTIVE_FILE] >
physSeg->lruSize[VM_LRU_INACTIVE_FILE]) ? TRUE : FALSE;
}
/* move a page from inactive list to active list head */
STATIC INLINE VOID OsMoveToActiveList(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
physSeg->lruSize[VM_LRU_ACTIVE_FILE]++;
physSeg->lruSize[VM_LRU_INACTIVE_FILE]--;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_ACTIVE_FILE], &fpage->lru);
}
/* move a page from active list to inactive list head */
STATIC INLINE VOID OsMoveToInactiveList(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
physSeg->lruSize[VM_LRU_ACTIVE_FILE]--;
physSeg->lruSize[VM_LRU_INACTIVE_FILE]++;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_INACTIVE_FILE], &fpage->lru);
}
/* move a page to the most active pos in lru list(active head) */
STATIC INLINE VOID OsMoveToActiveHead(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_ACTIVE_FILE], &fpage->lru);
}
/* move a page to the most active pos in lru list(inactive head) */
STATIC INLINE VOID OsMoveToInactiveHead(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_INACTIVE_FILE], &fpage->lru);
}
/* page referced add: (call by page cache get)
----------inactive----------|----------active------------
[ref:0,act:0], [ref:1,act:0]|[ref:0,act:1], [ref:1,act:1]
ref:0, act:0 --> ref:1, act:0
ref:1, act:0 --> ref:0, act:1
ref:0, act:1 --> ref:1, act:1
*/
VOID OsPageRefIncLocked(LosFilePage *fpage)
{
BOOL isOrgActive;
UINT32 intSave;
LosVmPage *page = NULL;
if (fpage == NULL) {
return;
}
LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);
page = fpage->vmPage;
isOrgActive = OsIsPageActive(page);
if (OsIsPageReferenced(page) && !OsIsPageActive(page)) {
OsCleanPageReferenced(page);
OsSetPageActive(page);
} else if (!OsIsPageReferenced(page)) {
OsSetPageReferenced(page);
}
if (!isOrgActive && OsIsPageActive(page)) {
/* move inactive to active */
OsMoveToActiveList(fpage);
/* no change, move head */
} else {
if (OsIsPageActive(page)) {
OsMoveToActiveHead(fpage);
} else {
OsMoveToInactiveHead(fpage);
}
}
LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, intSave);
}
/* page referced dec: (call by thrinker)
----------inactive----------|----------active------------
[ref:0,act:0], [ref:1,act:0]|[ref:0,act:1], [ref:1,act:1]
ref:1, act:1 --> ref:0, act:1
ref:0, act:1 --> ref:1, act:0
ref:1, act:0 --> ref:0, act:0
*/
VOID OsPageRefDecNoLock(LosFilePage *fpage)
{
BOOL isOrgActive;
LosVmPage *page = NULL;
if (fpage == NULL) {
return;
}
page = fpage->vmPage;
isOrgActive = OsIsPageActive(page);
if (!OsIsPageReferenced(page) && OsIsPageActive(page)) {
OsCleanPageActive(page);
OsSetPageReferenced(page);
} else if (OsIsPageReferenced(page)) {
OsCleanPageReferenced(page);
}
if (isOrgActive && !OsIsPageActive(page)) {
OsMoveToInactiveList(fpage);
}
}
VOID OsShrinkActiveList(LosVmPhysSeg *physSeg, int nScan)
{
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
LOS_DL_LIST *activeFile = &physSeg->lruList[VM_LRU_ACTIVE_FILE];
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, activeFile, LosFilePage, lru) {
if (LOS_SpinTrylock(&fpage->mapping->list_lock) != LOS_OK) {
continue;
}
/* happend when caller hold cache lock and try reclaim this page */
if (OsIsPageLocked(fpage->vmPage)) {
LOS_SpinUnlock(&fpage->mapping->list_lock);
continue;
}
if (OsIsPageMapped(fpage) && (fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) {
LOS_SpinUnlock(&fpage->mapping->list_lock);
continue;
}
OsPageRefDecNoLock(fpage);
LOS_SpinUnlock(&fpage->mapping->list_lock);
if (--nScan <= 0) {
break;
}
}
}
int OsShrinkInactiveList(LosVmPhysSeg *physSeg, int nScan, LOS_DL_LIST *list)
{
UINT32 nrReclaimed = 0;
LosVmPage *page = NULL;
SPIN_LOCK_S *flock = NULL;
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
LosFilePage *ftemp = NULL;
LOS_DL_LIST *inactive_file = &physSeg->lruList[VM_LRU_INACTIVE_FILE];
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, inactive_file, LosFilePage, lru) {
flock = &fpage->mapping->list_lock;
if (LOS_SpinTrylock(flock) != LOS_OK) {
continue;
}
page = fpage->vmPage;
if (OsIsPageLocked(page)) {
LOS_SpinUnlock(flock);
continue;
}
if (OsIsPageMapped(fpage) && (OsIsPageDirty(page) || (fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE))) {
LOS_SpinUnlock(flock);
continue;
}
if (OsIsPageDirty(page)) {
ftemp = OsDumpDirtyPage(fpage);
if (ftemp != NULL) {
LOS_ListTailInsert(list, &ftemp->node);
}
}
OsDeletePageCacheLru(fpage);
LOS_SpinUnlock(flock);
nrReclaimed++;
if (--nScan <= 0) {
break;
}
}
return nrReclaimed;
}
bool InactiveListIsLow(LosVmPhysSeg *physSeg)
{
return (physSeg->lruSize[VM_LRU_ACTIVE_FILE] > physSeg->lruSize[VM_LRU_INACTIVE_FILE]) ? TRUE : FALSE;
}
#ifdef LOSCFG_FS_VFS
int OsTryShrinkMemory(size_t nPage)
{
UINT32 intSave;
size_t totalPages;
size_t nReclaimed = 0;
LosVmPhysSeg *physSeg = NULL;
UINT32 index;
LOS_DL_LIST_HEAD(dirtyList);
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
if (nPage <= 0) {
nPage = VM_FILEMAP_MIN_SCAN;
}
if (nPage > VM_FILEMAP_MAX_SCAN) {
nPage = VM_FILEMAP_MAX_SCAN;
}
for (index = 0; index < g_vmPhysSegNum; index++) {
physSeg = &g_vmPhysSeg[index];
LOS_SpinLockSave(&physSeg->lruLock, &intSave);
totalPages = physSeg->lruSize[VM_LRU_ACTIVE_FILE] + physSeg->lruSize[VM_LRU_INACTIVE_FILE];
if (totalPages < VM_FILEMAP_MIN_SCAN) {
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
continue;
}
if (InactiveListIsLow(physSeg)) {
OsShrinkActiveList(physSeg, (nPage < VM_FILEMAP_MIN_SCAN) ? VM_FILEMAP_MIN_SCAN : nPage);
}
nReclaimed += OsShrinkInactiveList(physSeg, nPage, &dirtyList);
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
if (nReclaimed >= nPage) {
break;
}
}
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &dirtyList, LosFilePage, node) {
OsDoFlushDirtyPage(fpage);
}
return nReclaimed;
}
#else
int TryShrinkMemory(size_t nPage)
{
return 0;
}
#endif
#endif

439
kernel/base/vm/los_vm_syscall.c Executable file
View File

@@ -0,0 +1,439 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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.
*/
/**
* @defgroup los_vm_syscall vm syscall definition
* @ingroup kernel
*/
#include "los_typedef.h"
#include "los_vm_syscall.h"
#include "los_vm_common.h"
#include "los_rbtree.h"
#include "los_vm_map.h"
#include "los_vm_dump.h"
#include "los_vm_lock.h"
#include "los_vm_filemap.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
STATUS_T OsCheckMMapParams(VADDR_T vaddr, unsigned prot, unsigned long flags, size_t len, unsigned long pgoff)
{
if ((vaddr != 0) && !LOS_IsUserAddressRange(vaddr, len)) {
return -EINVAL;
}
if (len == 0) {
return -EINVAL;
}
/* we only support some prot and flags */
if ((prot & PROT_SUPPORT_MASK) == 0) {
return -EINVAL;
}
if ((flags & MAP_SUPPORT_MASK) == 0) {
return -EINVAL;
}
if (((flags & MAP_SHARED_PRIVATE) == 0) || ((flags & MAP_SHARED_PRIVATE) == MAP_SHARED_PRIVATE)) {
return -EINVAL;
}
if (((len >> PAGE_SHIFT) + pgoff) < pgoff) {
return -EINVAL;
}
return LOS_OK;
}
STATUS_T OsAnonMMap(LosVmMapRegion *region)
{
LOS_SetRegionTypeAnon(region);
return LOS_OK;
}
VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags, int fd, unsigned long pgoff)
{
STATUS_T status;
VADDR_T resultVaddr;
UINT32 regionFlags;
LosVmMapRegion *newRegion = NULL;
struct file *filep = NULL;
LosVmSpace *vmSpace = OsCurrProcessGet()->vmSpace;
vaddr = ROUNDUP(vaddr, PAGE_SIZE);
len = ROUNDUP(len, PAGE_SIZE);
STATUS_T checkRst = OsCheckMMapParams(vaddr, prot, flags, len, pgoff);
if (checkRst != LOS_OK) {
return checkRst;
}
if (LOS_IsNamedMapping(flags)) {
status = fs_getfilep(fd, &filep);
if (status < 0) {
return -EBADF;
}
}
(VOID)LOS_MuxAcquire(&vmSpace->regionMux);
/* user mode calls mmap to release heap physical memory without releasing heap virtual space */
status = OsUserHeapFree(vmSpace, vaddr, len);
if (status == LOS_OK) {
resultVaddr = vaddr;
goto MMAP_DONE;
}
regionFlags = OsCvtProtFlagsToRegionFlags(prot, flags);
newRegion = LOS_RegionAlloc(vmSpace, vaddr, len, regionFlags, pgoff);
if (newRegion == NULL) {
resultVaddr = (VADDR_T)-ENOMEM;
goto MMAP_DONE;
}
newRegion->regionFlags |= VM_MAP_REGION_FLAG_MMAP;
resultVaddr = newRegion->range.base;
if (LOS_IsNamedMapping(flags)) {
status = OsNamedMMap(filep, newRegion);
} else {
status = OsAnonMMap(newRegion);
}
if (status != LOS_OK) {
LOS_RbDelNode(&vmSpace->regionRbTree, &newRegion->rbNode);
LOS_RegionFree(vmSpace, newRegion);
resultVaddr = (VADDR_T)-ENOMEM;
goto MMAP_DONE;
}
MMAP_DONE:
(VOID)LOS_MuxRelease(&vmSpace->regionMux);
return resultVaddr;
}
STATUS_T LOS_UnMMap(VADDR_T addr, size_t size)
{
if ((addr <= 0) || (size <= 0)) {
return -EINVAL;
}
return OsUnMMap(OsCurrProcessGet()->vmSpace, addr, size);
}
VOID *LOS_DoBrk(VOID *addr)
{
LosVmSpace *space = OsCurrProcessGet()->vmSpace;
size_t size;
VOID *ret = NULL;
LosVmMapRegion *region = NULL;
VOID *alignAddr = NULL;
VADDR_T newBrk, oldBrk;
if (addr == NULL) {
return (void *)(UINTPTR)space->heapNow;
}
if ((UINTPTR)addr < (UINTPTR)space->heapBase) {
return (VOID *)-ENOMEM;
}
size = (UINTPTR)addr - (UINTPTR)space->heapBase;
size = ROUNDUP(size, PAGE_SIZE);
alignAddr = (CHAR *)(UINTPTR)(space->heapBase) + size;
PRINT_INFO("brk addr %p , size 0x%x, alignAddr %p, align %d\n", addr, size, alignAddr, PAGE_SIZE);
if (addr < (VOID *)(UINTPTR)space->heapNow) {
newBrk = LOS_Align((VADDR_T)(UINTPTR)addr, PAGE_SIZE);
oldBrk = LOS_Align(space->heapNow, PAGE_SIZE);
if (LOS_UnMMap(newBrk, (oldBrk - newBrk)) < 0) {
return (void *)(UINTPTR)space->heapNow;
}
space->heapNow = (VADDR_T)(UINTPTR)addr;
return addr;
}
(VOID)LOS_MuxAcquire(&space->regionMux);
if (space->heapBase == space->heapNow) {
region = LOS_RegionAlloc(space, space->heapBase, size,
VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE |
VM_MAP_REGION_FLAG_PERM_USER, 0);
if (region == NULL) {
ret = (VOID *)-ENOMEM;
VM_ERR("LOS_RegionAlloc failed");
goto REGION_ALLOC_FAILED;
}
region->regionFlags |= VM_MAP_REGION_FLAG_HEAP;
space->heap = region;
}
if ((UINTPTR)alignAddr >= space->mapBase) {
VM_ERR("Process heap memory space is insufficient");
goto REGION_ALLOC_FAILED;
}
space->heapNow = (VADDR_T)(UINTPTR)alignAddr;
space->heap->range.size = size;
ret = (VOID *)(UINTPTR)space->heapNow;
REGION_ALLOC_FAILED:
(VOID)LOS_MuxRelease(&space->regionMux);
return ret;
}
int LOS_DoMprotect(VADDR_T vaddr, size_t len, unsigned long prot)
{
LosVmSpace *space = OsCurrProcessGet()->vmSpace;
LosVmMapRegion *region = NULL;
UINT32 vmFlags;
UINT32 count;
int ret;
(VOID)LOS_MuxAcquire(&space->regionMux);
region = LOS_RegionFind(space, vaddr);
if (!IS_ALIGNED(vaddr, PAGE_SIZE) || (region == NULL) || (vaddr > vaddr + len)) {
ret = -EINVAL;
goto OUT_MPROTECT;
}
if ((prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))) {
ret = -EINVAL;
goto OUT_MPROTECT;
}
len = LOS_Align(len, PAGE_SIZE);
/* can't operation cross region */
if (region->range.base + region->range.size < vaddr + len) {
ret = -EINVAL;
goto OUT_MPROTECT;
}
/* if only move some part of region, we need to split first */
if (region->range.size > len) {
OsVmRegionAdjust(space, vaddr, len);
}
vmFlags = OsCvtProtFlagsToRegionFlags(prot, 0);
vmFlags |= (region->regionFlags & VM_MAP_REGION_FLAG_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;
region = LOS_RegionFind(space, vaddr);
if (region == NULL) {
ret = -ENOMEM;
goto OUT_MPROTECT;
}
region->regionFlags = vmFlags;
count = len >> PAGE_SHIFT;
ret = LOS_ArchMmuChangeProt(&space->archMmu, vaddr, count, region->regionFlags);
if (ret) {
ret = -ENOMEM;
goto OUT_MPROTECT;
}
ret = LOS_OK;
OUT_MPROTECT:
#ifdef LOSCFG_VM_OVERLAP_CHECK
if (VmmAspaceRegionsOverlapCheck(aspace) < 0) {
(VOID)OsShellCmdDumpVm(0, NULL);
ret = -ENOMEM;
}
#endif
(VOID)LOS_MuxRelease(&space->regionMux);
return ret;
}
STATUS_T OsMremapCheck(VADDR_T addr, size_t oldLen, VADDR_T newAddr, size_t newLen, unsigned int flags)
{
LosVmSpace *space = OsCurrProcessGet()->vmSpace;
LosVmMapRegion *region = LOS_RegionFind(space, addr);
VADDR_T regionEnd;
if ((region == NULL) || (region->range.base > addr) || (newLen == 0)) {
return -EINVAL;
}
if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) {
return -EINVAL;
}
if (((flags & MREMAP_FIXED) == MREMAP_FIXED) && ((flags & MREMAP_MAYMOVE) == 0)) {
return -EINVAL;
}
if (!IS_ALIGNED(addr, PAGE_SIZE)) {
return -EINVAL;
}
regionEnd = region->range.base + region->range.size;
/* we can't operate across region */
if (oldLen > regionEnd - addr) {
return -EFAULT;
}
/* avoiding overflow */
if (newLen > oldLen) {
if ((addr + newLen) < addr) {
return -EINVAL;
}
}
/* avoid new region overlaping with the old one */
if (flags & MREMAP_FIXED) {
if (((region->range.base + region->range.size) > newAddr) &&
(region->range.base < (newAddr + newLen))) {
return -EINVAL;
}
if (!IS_ALIGNED(newAddr, PAGE_SIZE)) {
return -EINVAL;
}
}
return LOS_OK;
}
VADDR_T LOS_DoMremap(VADDR_T oldAddress, size_t oldSize, size_t newSize, int flags, VADDR_T newAddr)
{
LosVmMapRegion *regionOld = NULL;
LosVmMapRegion *regionNew = NULL;
STATUS_T status;
VADDR_T ret;
LosVmSpace *space = OsCurrProcessGet()->vmSpace;
oldSize = LOS_Align(oldSize, PAGE_SIZE);
newSize = LOS_Align(newSize, PAGE_SIZE);
(VOID)LOS_MuxAcquire(&space->regionMux);
status = OsMremapCheck(oldAddress, oldSize, newAddr, newSize, (unsigned int)flags);
if (status) {
ret = status;
goto OUT_MREMAP;
}
/* if only move some part of region, we need to split first */
status = OsVmRegionAdjust(space, oldAddress, oldSize);
if (status) {
ret = -ENOMEM;
goto OUT_MREMAP;
}
regionOld = LOS_RegionFind(space, oldAddress);
if (regionOld == NULL) {
ret = -ENOMEM;
goto OUT_MREMAP;
}
if ((unsigned int)flags & MREMAP_FIXED) {
regionNew = OsVmRegionDup(space, regionOld, newAddr, newSize);
if (!regionNew) {
ret = -ENOMEM;
goto OUT_MREMAP;
}
status = LOS_ArchMmuMove(&space->archMmu, oldAddress, newAddr, newSize >> PAGE_SHIFT, regionOld->regionFlags);
if (status) {
LOS_RegionFree(space, regionNew);
ret = -ENOMEM;
goto OUT_MREMAP;
}
LOS_RegionFree(space, regionOld);
ret = newAddr;
goto OUT_MREMAP;
}
// take it as shrink operation
if (oldSize > newSize) {
LOS_UnMMap(oldAddress + newSize, oldSize - newSize);
ret = oldAddress;
goto OUT_MREMAP;
}
status = OsIsRegionCanExpand(space, regionOld, newSize);
// we can expand directly.
if (!status) {
regionOld->range.size = newSize;
ret = oldAddress;
goto OUT_MREMAP;
}
if ((unsigned int)flags & MREMAP_MAYMOVE) {
regionNew = OsVmRegionDup(space, regionOld, 0, newSize);
if (regionNew == NULL) {
ret = -ENOMEM;
goto OUT_MREMAP;
}
status = LOS_ArchMmuMove(&space->archMmu, oldAddress, regionNew->range.base, newSize >> PAGE_SHIFT,
regionOld->regionFlags);
if (status) {
LOS_RegionFree(space, regionNew);
ret = -ENOMEM;
goto OUT_MREMAP;
}
LOS_RegionFree(space, regionOld);
ret = regionNew->range.base;
goto OUT_MREMAP;
}
ret = -EINVAL;
OUT_MREMAP:
#ifdef LOSCFG_VM_OVERLAP_CHECK
if (VmmAspaceRegionsOverlapCheck(aspace) < 0) {
(VOID)OsShellCmdDumpVm(0, NULL);
ret = -ENOMEM;
}
#endif
(VOID)LOS_MuxRelease(&space->regionMux);
return ret;
}
VOID LOS_DumpMemRegion(VADDR_T vaddr)
{
LosVmSpace *space = NULL;
space = OsCurrProcessGet()->vmSpace;
if (space == NULL) {
return;
}
if (LOS_IsRangeInSpace(space, ROUNDDOWN(vaddr, MB), MB) == FALSE) {
return;
}
OsDumpPte(vaddr);
OsDumpAspace(space);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

253
kernel/base/vm/oom.c Executable file
View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
*
* 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 "sys_config.h"
#include "los_oom.h"
#include "los_vm_dump.h"
#include "los_vm_lock.h"
#include "los_vm_phys.h"
#include "los_vm_filemap.h"
#include "los_process_pri.h"
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#include "los_swtmr_pri.h"
#endif
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
LITE_OS_SEC_BSS OomCB *g_oomCB = NULL;
static SPIN_LOCK_INIT(g_oomSpinLock);
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomScoreProcess(LosProcessCB *candidateProcess)
{
UINT32 actualPm;
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxAcquire(&candidateProcess->vmSpace->regionMux);
#endif
/* we only consider actual physical memory here. */
OsUProcessPmUsage(candidateProcess->vmSpace, NULL, &actualPm);
#if (LOSCFG_KERNEL_SMP != YES)
(VOID)LOS_MuxRelease(&candidateProcess->vmSpace->regionMux);
#endif
return actualPm;
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomKillProcess(UINTPTR param)
{
/* we will not kill process, and do nothing here */
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OomForceShrinkMemory(VOID)
{
UINT32 i;
UINT32 reclaimMemPages = 0;
/*
* TryShrinkMemory maybe reclaim 0 pages in the first time from active list
* to inactive list, and in the second time reclaim memory from inactive list.
*/
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
reclaimMemPages += OsTryShrinkMemory(0);
}
return reclaimMemPages;
}
LITE_OS_SEC_TEXT_MINOR STATIC BOOL OomReclaimPageCache(VOID)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
BOOL isReclaimMemory = FALSE;
UINT32 reclaimMemPages;
UINT32 i;
for (i = 0; i < MAX_SHRINK_PAGECACHE_TRY; i++) {
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isReclaimMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->reclaimMemThreshold;
if (isReclaimMemory) {
/*
* we do force memory reclaim from page cache here.
* if we get memory, we will reclaim pagecache memory again.
* if there is no memory to reclaim, we will return.
*/
reclaimMemPages = OomForceShrinkMemory();
if (reclaimMemPages > 0) {
continue;
}
}
break;
}
return isReclaimMemory;
}
/*
* check is low memory or not, if low memory, try to kill process.
* return is kill process or not.
*/
LITE_OS_SEC_TEXT_MINOR BOOL OomCheckProcess(VOID)
{
UINT32 totalPm;
UINT32 usedPm;
BOOL isLowMemory = FALSE;
/*
* spinlock the current core schedule, make sure oom process atomic
* spinlock other place entering OomCheckProcess, make sure oom process mutex
*/
LOS_SpinLock(&g_oomSpinLock);
/* first we will check if we need to reclaim pagecache memory */
if (OomReclaimPageCache() == FALSE) {
goto NO_VICTIM_PROCESS;
}
/* get free bytes */
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
isLowMemory = ((totalPm - usedPm) << PAGE_SHIFT) < g_oomCB->lowMemThreshold;
if (isLowMemory) {
PRINTK("[oom] OS is in low memory state\n"
"total physical memory: %#x(byte), used: %#x(byte),"
"free: %#x(byte), low memory threshold: %#x(byte)\n",
totalPm << PAGE_SHIFT, usedPm << PAGE_SHIFT,
(totalPm - usedPm) << PAGE_SHIFT, g_oomCB->lowMemThreshold);
}
NO_VICTIM_PROCESS:
LOS_SpinUnlock(&g_oomSpinLock);
return isLowMemory;
}
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
STATIC VOID OomWriteEvent(VOID)
{
OsWriteResourceEvent(OS_RESOURCE_EVENT_OOM);
}
#endif
LITE_OS_SEC_TEXT_MINOR VOID OomInfodump(VOID)
{
PRINTK("[oom] oom loop task status: %s\n"
" oom low memory threshold: %#x(byte)\n"
" oom reclaim memory threshold: %#x(byte)\n"
" oom check interval: %d(microsecond)\n",
g_oomCB->enabled ? "enabled" : "disabled",
g_oomCB->lowMemThreshold, g_oomCB->reclaimMemThreshold,
g_oomCB->checkInterval);
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetLowMemThreashold(UINT32 lowMemThreshold)
{
if ((lowMemThreshold > OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX)) {
PRINTK("[oom] low memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x](byte)\n",
lowMemThreshold, OOM_DEFAULT_LOW_MEM_THRESHOLD_MIN,
OOM_DEFAULT_LOW_MEM_THRESHOLD_MAX);
} else {
g_oomCB->lowMemThreshold = lowMemThreshold;
PRINTK("[oom] set oom low memory threshold %#x(byte) successful\n",
g_oomCB->lowMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetReclaimMemThreashold(UINT32 reclaimMemThreshold)
{
UINT32 totalPm = 0;
UINT32 usedPm = 0;
OsVmPhysUsedInfoGet(&usedPm, &totalPm);
if ((reclaimMemThreshold >= (totalPm << PAGE_SHIFT)) ||
(reclaimMemThreshold < g_oomCB->lowMemThreshold)) {
PRINTK("[oom] reclaim memory threshold %#x(byte) invalid,"
"should be in [%#x, %#x)(byte)\n",
reclaimMemThreshold, g_oomCB->lowMemThreshold, (totalPm << PAGE_SHIFT));
} else {
g_oomCB->reclaimMemThreshold = reclaimMemThreshold;
PRINTK("[oom] set oom reclaim memory threshold %#x(byte) successful\n",
g_oomCB->reclaimMemThreshold);
}
}
LITE_OS_SEC_TEXT_MINOR VOID OomSetCheckInterval(UINT32 checkInterval)
{
if ((checkInterval >= OOM_CHECK_MIN) && (checkInterval <= OOM_CHECK_MAX)) {
g_oomCB->checkInterval = checkInterval;
PRINTK("[oom] set oom check interval (%d)ms successful\n",
g_oomCB->checkInterval);
} else {
PRINTK("[oom] set oom check interval (%d)ms failed, should be in [%d, %d]\n",
g_oomCB->checkInterval, OOM_CHECK_MIN, OOM_CHECK_MAX);
}
}
LITE_OS_SEC_TEXT_MINOR UINT32 OomTaskInit(VOID)
{
g_oomCB = (OomCB *)LOS_MemAlloc(m_aucSysMem0, sizeof(OomCB));
if (g_oomCB == NULL) {
VM_ERR("oom task init failed, malloc OomCB failed.");
return LOS_NOK;
}
g_oomCB->lowMemThreshold = OOM_DEFAULT_LOW_MEM_THRESHOLD;
g_oomCB->reclaimMemThreshold = OOM_DEFAULT_RECLAIM_MEM_THRESHOLD;
g_oomCB->checkInterval = OOM_DEFAULT_CHECK_INTERVAL;
g_oomCB->processVictimCB = (OomFn)OomKillProcess;
g_oomCB->scoreCB = (OomFn)OomScoreProcess;
g_oomCB->enabled = FALSE;
#ifdef LOSCFG_ENABLE_OOM_LOOP_TASK
g_oomCB->enabled = TRUE;
UINT32 ret = LOS_SwtmrCreate(g_oomCB->checkInterval, LOS_SWTMR_MODE_PERIOD, (SWTMR_PROC_FUNC)OomWriteEvent,
&g_oomCB->swtmrID, (UINTPTR)g_oomCB);
if (ret != LOS_OK) {
return ret;
}
return LOS_SwtmrStart(g_oomCB->swtmrID);
#else
return LOS_OK;
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More