first submission
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "los_hook.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_task.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
|
||||
{
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
eventCB->uwEventID = 0;
|
||||
LOS_ListInit(&eventCB->stEventList);
|
||||
OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
UINT32 ret = 0;
|
||||
UINT32 intSave;
|
||||
|
||||
if (eventID == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
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);
|
||||
}
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC_INLINE UINT32 OsEventReadParamCheck(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
if ((eventCB->stEventList.pstNext == NULL) || (eventCB->stEventList.pstPrev == NULL)) {
|
||||
return LOS_ERRNO_EVENT_NOT_INITIALIZED;
|
||||
}
|
||||
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 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeOut)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 intSave;
|
||||
LosTaskCB *runTsk = NULL;
|
||||
|
||||
ret = OsEventReadParamCheck(eventCB, eventMask, mode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
ret = LOS_EventPoll(&(eventCB->uwEventID), eventMask, mode);
|
||||
OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode);
|
||||
if (ret == 0) {
|
||||
if (timeOut == 0) {
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (g_losTaskLock) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_EVENT_READ_IN_LOCK;
|
||||
}
|
||||
runTsk = g_losTask.runTask;
|
||||
runTsk->eventMask = eventMask;
|
||||
runTsk->eventMode = mode;
|
||||
OsSchedTaskWait(&eventCB->stEventList, timeOut);
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_EVENT_READ_TIMEOUT;
|
||||
}
|
||||
|
||||
ret = LOS_EventPoll(&eventCB->uwEventID, eventMask, mode);
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
|
||||
{
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
LosTaskCB *nextTask = (LosTaskCB *)NULL;
|
||||
UINT32 intSave;
|
||||
UINT8 exitFlag = 0;
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
if ((eventCB->stEventList.pstNext == NULL) || (eventCB->stEventList.pstPrev == NULL)) {
|
||||
return LOS_ERRNO_EVENT_NOT_INITIALIZED;
|
||||
}
|
||||
if (events & LOS_ERRTYPE_ERROR) {
|
||||
return LOS_ERRNO_EVENT_SETBIT_INVALID;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
eventCB->uwEventID |= events;
|
||||
OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB);
|
||||
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 (((resumedTask->eventMode & LOS_WAITMODE_OR) && (resumedTask->eventMask & events) != 0) ||
|
||||
((resumedTask->eventMode & LOS_WAITMODE_AND) &&
|
||||
((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {
|
||||
exitFlag = 1;
|
||||
|
||||
OsSchedTaskWake(resumedTask);
|
||||
}
|
||||
resumedTask = nextTask;
|
||||
}
|
||||
|
||||
if (exitFlag == 1) {
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
return LOS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
|
||||
{
|
||||
UINT32 intSave;
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
if (!LOS_ListEmpty(&eventCB->stEventList)) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_EVENT_SHOULD_NOT_DESTROYED;
|
||||
}
|
||||
eventCB->stEventList.pstNext = (LOS_DL_LIST *)NULL;
|
||||
eventCB->stEventList.pstPrev = (LOS_DL_LIST *)NULL;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY, eventCB);
|
||||
return LOS_OK;
|
||||
}
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask)
|
||||
{
|
||||
UINT32 intSave;
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
eventCB->uwEventID &= eventMask;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_EVENT_CLEAR, eventCB);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 "stdarg.h"
|
||||
#include "los_arch.h"
|
||||
#include "los_config.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_mux.h"
|
||||
#include "los_queue.h"
|
||||
#include "los_sem.h"
|
||||
|
||||
#if (LOSCFG_PLATFORM_HWI == 1)
|
||||
#include "los_interrupt.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_KERNEL_TRACE == 1)
|
||||
#include "los_debug.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR == 1)
|
||||
#include "los_swtmr.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_CPUP == 1)
|
||||
#include "los_cpup.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_PLATFORM_EXC == 1)
|
||||
#include "los_exc_info.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BACKTRACE_TYPE != 0)
|
||||
#include "los_backtrace.h"
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_KERNEL_PM == 1)
|
||||
#include "los_pm.h"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_Reboot
|
||||
Description : system exception, die in here, wait for watchdog.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : None
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT VOID LOS_Reboot(VOID)
|
||||
{
|
||||
OsDoExcHook(EXC_REBOOT);
|
||||
HalSysExit();
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT VOID LOS_Panic(const CHAR *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
PRINT_ERR(fmt, ap);
|
||||
va_end(ap);
|
||||
HalSysExit();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsRegister
|
||||
Description : Configuring the maximum number of tasks
|
||||
Input : None
|
||||
Output : None
|
||||
Return : None
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT static VOID OsRegister(VOID)
|
||||
{
|
||||
g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT + 1; /* Reserved 1 for IDLE */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_Start(VOID)
|
||||
{
|
||||
return HalStartSchedule(OsTickHandler);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_KernelInit
|
||||
Description : System kernel initialization function, configure all system modules
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_KernelInit(VOID)
|
||||
{
|
||||
UINT32 ret;
|
||||
PRINTK("entering kernel init...\n");
|
||||
|
||||
#if (LOSCFG_BACKTRACE_TYPE != 0)
|
||||
OSBackTraceInit();
|
||||
#endif
|
||||
|
||||
OsRegister();
|
||||
ret = OsMemSystemInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("OsMemSystemInit error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HalArchInit();
|
||||
|
||||
ret = OsTaskInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("OsTaskInit error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)
|
||||
OsTaskMonInit();
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_CPUP == 1)
|
||||
ret = OsCpupInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("OsCpupInit error\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_IPC_SEM == 1)
|
||||
ret = OsSemInit();
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_IPC_MUX == 1)
|
||||
ret = OsMuxInit();
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_IPC_QUEUE == 1)
|
||||
ret = OsQueueInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("OsQueueInit error\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR == 1)
|
||||
ret = OsSwtmrInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("OsSwtmrInit error\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = OsIdleTaskCreate();
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if (LOSCFG_KERNEL_TRACE == 1)
|
||||
ret = LOS_TraceInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("LOS_TraceInit error\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_KERNEL_PM == 1)
|
||||
ret = OsPmInit();
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Pm init failed!\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOSCFG_TEST
|
||||
//ret = los_TestInit();
|
||||
//if (ret != LOS_OK) {
|
||||
// PRINT_ERR("los_TestInit error\n");
|
||||
// return ret;
|
||||
//}
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_PLATFORM_EXC == 1)
|
||||
OsExcMsgDumpInit();
|
||||
#endif
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "los_config.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_hook.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
#if (LOSCFG_BASE_IPC_MUX == 1)
|
||||
|
||||
LITE_OS_SEC_BSS LosMuxCB* g_allMux = NULL;
|
||||
LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_unusedMuxList;
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsMuxInit
|
||||
Description : Initializes the mutex
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsMuxInit(VOID)
|
||||
{
|
||||
LosMuxCB *muxNode = NULL;
|
||||
UINT32 index;
|
||||
|
||||
LOS_ListInit(&g_unusedMuxList);
|
||||
|
||||
if (LOSCFG_BASE_IPC_MUX_LIMIT == 0) {
|
||||
return LOS_ERRNO_MUX_MAXNUM_ZERO;
|
||||
}
|
||||
|
||||
g_allMux = (LosMuxCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(LosMuxCB)));
|
||||
if (g_allMux == NULL) {
|
||||
return LOS_ERRNO_MUX_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (index = 0; index < LOSCFG_BASE_IPC_MUX_LIMIT; index++) {
|
||||
muxNode = ((LosMuxCB *)g_allMux) + index;
|
||||
muxNode->muxID = index;
|
||||
muxNode->muxStat = OS_MUX_UNUSED;
|
||||
LOS_ListTailInsert(&g_unusedMuxList, &muxNode->muxList);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_MuxCreate
|
||||
Description : Create a mutex
|
||||
Input : None
|
||||
Output : muxHandle ------ Mutex operation handle
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxCreate(UINT32 *muxHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosMuxCB *muxCreated = NULL;
|
||||
LOS_DL_LIST *unusedMux = NULL;
|
||||
UINT32 errNo;
|
||||
UINT32 errLine;
|
||||
|
||||
if (muxHandle == NULL) {
|
||||
return LOS_ERRNO_MUX_PTR_NULL;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (LOS_ListEmpty(&g_unusedMuxList)) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_ALL_BUSY);
|
||||
}
|
||||
|
||||
unusedMux = LOS_DL_LIST_FIRST(&(g_unusedMuxList));
|
||||
LOS_ListDelete(unusedMux);
|
||||
muxCreated = (GET_MUX_LIST(unusedMux));
|
||||
muxCreated->muxCount = 0;
|
||||
muxCreated->muxStat = OS_MUX_USED;
|
||||
muxCreated->priority = 0;
|
||||
muxCreated->owner = (LosTaskCB *)NULL;
|
||||
LOS_ListInit(&muxCreated->muxList);
|
||||
*muxHandle = (UINT32)muxCreated->muxID;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_CREATE, muxCreated);
|
||||
return LOS_OK;
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_MuxDelete
|
||||
Description : Delete a mutex
|
||||
Input : muxHandle ------Mutex operation handle
|
||||
Output : None
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxDelete(UINT32 muxHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosMuxCB *muxDeleted = NULL;
|
||||
UINT32 errNo;
|
||||
UINT32 errLine;
|
||||
|
||||
if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) {
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID);
|
||||
}
|
||||
|
||||
muxDeleted = GET_MUX(muxHandle);
|
||||
intSave = LOS_IntLock();
|
||||
if (muxDeleted->muxStat == OS_MUX_UNUSED) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID);
|
||||
}
|
||||
|
||||
if ((!LOS_ListEmpty(&muxDeleted->muxList)) || muxDeleted->muxCount) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_PENDED);
|
||||
}
|
||||
|
||||
LOS_ListAdd(&g_unusedMuxList, &muxDeleted->muxList);
|
||||
muxDeleted->muxStat = OS_MUX_UNUSED;
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_DELETE, muxDeleted);
|
||||
return LOS_OK;
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
STATIC_INLINE UINT32 OsMuxValidCheck(LosMuxCB *muxPended)
|
||||
{
|
||||
if (muxPended->muxStat == OS_MUX_UNUSED) {
|
||||
return LOS_ERRNO_MUX_INVALID;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_MUX_PEND_INTERR;
|
||||
}
|
||||
|
||||
if (g_losTaskLock) {
|
||||
PRINT_ERR("!!!LOS_ERRNO_MUX_PEND_IN_LOCK!!!\n");
|
||||
return LOS_ERRNO_MUX_PEND_IN_LOCK;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_MuxPend
|
||||
Description : Specify the mutex P operation
|
||||
Input : muxHandle ------ Mutex operation handleone
|
||||
: timeOut ------- waiting time
|
||||
Output : None
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosMuxCB *muxPended = NULL;
|
||||
UINT32 retErr;
|
||||
LosTaskCB *runningTask = NULL;
|
||||
|
||||
if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) {
|
||||
OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
|
||||
}
|
||||
|
||||
muxPended = GET_MUX(muxHandle);
|
||||
intSave = LOS_IntLock();
|
||||
retErr = OsMuxValidCheck(muxPended);
|
||||
if (retErr) {
|
||||
goto ERROR_MUX_PEND;
|
||||
}
|
||||
|
||||
runningTask = (LosTaskCB *)g_losTask.runTask;
|
||||
if (muxPended->muxCount == 0) {
|
||||
muxPended->muxCount++;
|
||||
muxPended->owner = runningTask;
|
||||
muxPended->priority = runningTask->priority;
|
||||
LOS_IntRestore(intSave);
|
||||
goto HOOK;
|
||||
}
|
||||
|
||||
if (muxPended->owner == runningTask) {
|
||||
muxPended->muxCount++;
|
||||
LOS_IntRestore(intSave);
|
||||
goto HOOK;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
retErr = LOS_ERRNO_MUX_UNAVAILABLE;
|
||||
goto ERROR_MUX_PEND;
|
||||
}
|
||||
|
||||
runningTask->taskMux = (VOID *)muxPended;
|
||||
|
||||
if (muxPended->owner->priority > runningTask->priority) {
|
||||
(VOID)OsSchedModifyTaskSchedParam(muxPended->owner, runningTask->priority);
|
||||
}
|
||||
|
||||
OsSchedTaskWait(&muxPended->muxList, timeout);
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended);
|
||||
LOS_Schedule();
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
|
||||
retErr = LOS_ERRNO_MUX_TIMEOUT;
|
||||
goto ERROR_MUX_PEND;
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_OK;
|
||||
|
||||
HOOK:
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended);
|
||||
return LOS_OK;
|
||||
|
||||
ERROR_MUX_PEND:
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(retErr);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_MuxPost
|
||||
Description : Specify the mutex V operation,
|
||||
Input : muxHandle ------ Mutex operation handle
|
||||
Output : None
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxPost(UINT32 muxHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosMuxCB *muxPosted = GET_MUX(muxHandle);
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
LosTaskCB *runningTask = NULL;
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
if ((muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) ||
|
||||
(muxPosted->muxStat == OS_MUX_UNUSED)) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
|
||||
}
|
||||
|
||||
runningTask = (LosTaskCB *)g_losTask.runTask;
|
||||
if ((muxPosted->muxCount == 0) || (muxPosted->owner != runningTask)) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
|
||||
}
|
||||
|
||||
if (--(muxPosted->muxCount) != 0) {
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if ((muxPosted->owner->priority) != muxPosted->priority) {
|
||||
(VOID)OsSchedModifyTaskSchedParam(muxPosted->owner, muxPosted->priority);
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&muxPosted->muxList)) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(muxPosted->muxList)));
|
||||
|
||||
muxPosted->muxCount = 1;
|
||||
muxPosted->owner = resumedTask;
|
||||
muxPosted->priority = resumedTask->priority;
|
||||
resumedTask->taskMux = NULL;
|
||||
|
||||
OsSchedTaskWake(resumedTask);
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
|
||||
LOS_Schedule();
|
||||
} else {
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
#endif /* (LOSCFG_BASE_IPC_MUX == 1) */
|
||||
|
||||
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "securec.h"
|
||||
#include "los_config.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_hook.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_membox.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_task.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
#if (LOSCFG_BASE_IPC_QUEUE == 1)
|
||||
|
||||
LITE_OS_SEC_BSS LosQueueCB *g_allQueue = NULL ;
|
||||
LITE_OS_SEC_BSS LOS_DL_LIST g_freeQueueList;
|
||||
|
||||
/**************************************************************************
|
||||
Function : OsQueueInit
|
||||
Description : queue initial
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
**************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID)
|
||||
{
|
||||
LosQueueCB *queueNode = NULL;
|
||||
UINT16 index;
|
||||
|
||||
if (LOSCFG_BASE_IPC_QUEUE_LIMIT == 0) {
|
||||
return LOS_ERRNO_QUEUE_MAXNUM_ZERO;
|
||||
}
|
||||
|
||||
g_allQueue = (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));
|
||||
if (g_allQueue == NULL) {
|
||||
return LOS_ERRNO_QUEUE_NO_MEMORY;
|
||||
}
|
||||
|
||||
(VOID)memset_s(g_allQueue, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB),
|
||||
0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_QueueCreate
|
||||
Description : Create a queue
|
||||
Input : queueName --- Queue name, less than 4 characters
|
||||
: len --- Queue length
|
||||
: flags --- Queue type, FIFO or PRIO
|
||||
: maxMsgSize --- Maximum message size in byte
|
||||
Output : queueID --- Queue ID
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
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_aucSysMem0, len * msgSize);
|
||||
if (queue == NULL) {
|
||||
return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (LOS_ListEmpty(&g_freeQueueList)) {
|
||||
LOS_IntRestore(intSave);
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, 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->queue = 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);
|
||||
LOS_IntRestore(intSave);
|
||||
|
||||
*queueID = queueCB->queueID;
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_QUEUE_CREATE, queueCB);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueReadParameterCheck(UINT32 queueID, VOID *bufferAddr,
|
||||
UINT32 *bufferSize, UINT32 timeOut)
|
||||
{
|
||||
if (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) {
|
||||
return LOS_ERRNO_QUEUE_READSIZE_ISZERO;
|
||||
}
|
||||
|
||||
if (timeOut != LOS_NO_WAIT) {
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_QUEUE_READ_IN_INTERRUPT;
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueWriteParameterCheck(UINT32 queueID, VOID *bufferAddr,
|
||||
UINT32 *bufferSize, UINT32 timeOut)
|
||||
{
|
||||
if (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;
|
||||
}
|
||||
|
||||
if (timeOut != LOS_NO_WAIT) {
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT;
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
static INLINE VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType,
|
||||
VOID *bufferAddr, UINT32 *bufferSize)
|
||||
{
|
||||
UINT8 *queueNode = NULL;
|
||||
UINT32 msgDataSize;
|
||||
UINT16 queuePosition;
|
||||
errno_t rc;
|
||||
|
||||
/* get the queue position */
|
||||
switch (OS_QUEUE_OPERATE_GET(operateType)) {
|
||||
case OS_QUEUE_READ_HEAD:
|
||||
queuePosition = 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);
|
||||
queuePosition = queueCB->queueHead;
|
||||
break;
|
||||
|
||||
case OS_QUEUE_WRITE_TAIL:
|
||||
queuePosition = queueCB->queueTail;
|
||||
((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_ERR("invalid queue operate type!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
queueNode = &(queueCB->queue[(queuePosition * (queueCB->queueSize))]);
|
||||
|
||||
if (OS_QUEUE_IS_POINT(operateType)) {
|
||||
if (OS_QUEUE_IS_READ(operateType)) {
|
||||
*(UINT32 *)bufferAddr = *(UINT32 *)(VOID *)queueNode;
|
||||
} else {
|
||||
*(UINT32 *)(VOID *)queueNode = *(UINT32 *)bufferAddr; // change to pp when calling OsQueueOperate
|
||||
}
|
||||
} else {
|
||||
if (OS_QUEUE_IS_READ(operateType)) {
|
||||
msgDataSize = *((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32)));
|
||||
rc = memcpy_s((VOID *)bufferAddr, *bufferSize, (VOID *)queueNode, msgDataSize);
|
||||
if (rc != EOK) {
|
||||
PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
*bufferSize = msgDataSize;
|
||||
} else {
|
||||
*((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32))) = *bufferSize;
|
||||
rc = memcpy_s((VOID *)queueNode, queueCB->queueSize, (VOID *)bufferAddr, *bufferSize);
|
||||
if (rc != EOK) {
|
||||
PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 operateType, const UINT32 *bufferSize)
|
||||
{
|
||||
if (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 readWriteTmp = !readWrite;
|
||||
|
||||
UINT32 intSave = LOS_IntLock();
|
||||
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
ret = OsQueueOperateParamCheck(queueCB, 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 (g_losTaskLock) {
|
||||
ret = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
LosTaskCB *runTsk = (LosTaskCB *)g_losTask.runTask;
|
||||
OsSchedTaskWait(&queueCB->readWriteList[readWrite], timeOut);
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
|
||||
ret = LOS_ERRNO_QUEUE_TIMEOUT;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
} else {
|
||||
queueCB->readWriteableCnt[readWrite]--;
|
||||
}
|
||||
|
||||
OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);
|
||||
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->readWriteList[readWriteTmp])) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[readWriteTmp]));
|
||||
OsSchedTaskWake(resumedTask);
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
return LOS_OK;
|
||||
} else {
|
||||
queueCB->readWriteableCnt[readWriteTmp]++;
|
||||
}
|
||||
|
||||
QUEUE_END:
|
||||
LOS_IntRestore(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, OS_QUEUE_NOT_POINT);
|
||||
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, OS_QUEUE_NOT_POINT);
|
||||
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, OS_QUEUE_NOT_POINT);
|
||||
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(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, OS_QUEUE_POINT);
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_QUEUE_READ, (LosQueueCB *)GET_QUEUE_HANDLE(queueID));
|
||||
|
||||
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 operateType;
|
||||
UINT32 size = sizeof(UINT32 *);
|
||||
(VOID)bufferSize;
|
||||
|
||||
ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &size, timeOut);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL, OS_QUEUE_POINT);
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_QUEUE_WRITE, (LosQueueCB *)GET_QUEUE_HANDLE(queueID));
|
||||
|
||||
return OsQueueOperate(queueID, operateType, &bufferAddr, &size, timeOut);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueID,
|
||||
VOID *bufferAddr,
|
||||
UINT32 bufferSize,
|
||||
UINT32 timeOut)
|
||||
{
|
||||
UINT32 size = sizeof(UINT32 *);
|
||||
(VOID)bufferSize;
|
||||
|
||||
if (bufferAddr == NULL) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
|
||||
}
|
||||
|
||||
return LOS_QueueWriteHeadCopy(queueID, &bufferAddr, size, timeOut);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsQueueMailAlloc
|
||||
Description : Mail allocate memory
|
||||
Input : queueID --- QueueID
|
||||
: mailPool --- MailPool
|
||||
: timeOut --- TimeOut
|
||||
Output : None
|
||||
Return : mem:pointer if success otherwise NULL
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT VOID *OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut)
|
||||
{
|
||||
VOID *mem = (VOID *)NULL;
|
||||
UINT32 intSave;
|
||||
LosQueueCB *queueCB = (LosQueueCB *)NULL;
|
||||
LosTaskCB *runTsk = (LosTaskCB *)NULL;
|
||||
|
||||
if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mailPool == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (timeOut != LOS_NO_WAIT) {
|
||||
if (OS_INT_ACTIVE) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
queueCB = GET_QUEUE_HANDLE(queueID);
|
||||
if (queueCB->queueState == OS_QUEUE_UNUSED) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
mem = LOS_MemboxAlloc(mailPool);
|
||||
if (mem == NULL) {
|
||||
if (timeOut == LOS_NO_WAIT) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
runTsk = (LosTaskCB *)g_losTask.runTask;
|
||||
OsSchedTaskWait(&queueCB->memList, timeOut);
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
runTsk->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
|
||||
goto END;
|
||||
} else {
|
||||
/* When enters the current branch, means the current task already got a available membox,
|
||||
* so the runTsk->msg can not be NULL.
|
||||
*/
|
||||
mem = runTsk->msg;
|
||||
runTsk->msg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
END:
|
||||
LOS_IntRestore(intSave);
|
||||
return mem;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsQueueMailFree
|
||||
Description : Mail free memory
|
||||
Input : queueID --- QueueID
|
||||
: mailPool --- MailPool
|
||||
: mailMem --- MailMem
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem)
|
||||
{
|
||||
VOID *mem = (VOID *)NULL;
|
||||
UINT32 intSave;
|
||||
LosQueueCB *queueCB = (LosQueueCB *)NULL;
|
||||
LosTaskCB *resumedTask = (LosTaskCB *)NULL;
|
||||
|
||||
if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_MAIL_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
if (mailPool == NULL) {
|
||||
return LOS_ERRNO_QUEUE_MAIL_PTR_INVALID;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
if (LOS_MemboxFree(mailPool, mailMem)) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_QUEUE_MAIL_FREE_ERROR;
|
||||
}
|
||||
|
||||
queueCB = GET_QUEUE_HANDLE(queueID);
|
||||
if (queueCB->queueState == OS_QUEUE_UNUSED) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_QUEUE_NOT_CREATE;
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->memList)) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->memList));
|
||||
OsSchedTaskWake(resumedTask);
|
||||
mem = LOS_MemboxAlloc(mailPool);
|
||||
if (mem == NULL) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_QUEUE_NO_MEMORY;
|
||||
}
|
||||
resumedTask->msg = mem;
|
||||
LOS_IntRestore(intSave);
|
||||
LOS_Schedule();
|
||||
} else {
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_QueueDelete
|
||||
Description : Delete a queue
|
||||
Input : queueID --- QueueID
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
|
||||
{
|
||||
LosQueueCB *queueCB = NULL;
|
||||
UINT8 *queue = NULL;
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_NOT_FOUND;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
if (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->queue;
|
||||
queueCB->queue = (UINT8 *)NULL;
|
||||
queueCB->queueState = OS_QUEUE_UNUSED;
|
||||
LOS_ListAdd(&g_freeQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
|
||||
LOS_IntRestore(intSave);
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_QUEUE_DELETE, queueCB);
|
||||
|
||||
ret = LOS_MemFree(m_aucSysMem0, (VOID *)queue);
|
||||
return ret;
|
||||
|
||||
QUEUE_END:
|
||||
LOS_IntRestore(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 (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));
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
|
||||
if (queueCB->queueState == OS_QUEUE_UNUSED) {
|
||||
ret = LOS_ERRNO_QUEUE_NOT_CREATE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
queueInfo->queueID = queueID;
|
||||
queueInfo->queueLen = queueCB->queueLen;
|
||||
queueInfo->queueSize = queueCB->queueSize;
|
||||
queueInfo->queueHead = queueCB->queueHead;
|
||||
queueInfo->queueTail = queueCB->queueTail;
|
||||
queueInfo->readableCnt = queueCB->readWriteableCnt[OS_QUEUE_READ];
|
||||
queueInfo->writableCnt = queueCB->readWriteableCnt[OS_QUEUE_WRITE];
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_READ], LosTaskCB, pendList) {
|
||||
queueInfo->waitReadTask |= (1 << tskCB->taskID);
|
||||
}
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_WRITE], LosTaskCB, pendList) {
|
||||
queueInfo->waitWriteTask |= (1 << tskCB->taskID);
|
||||
}
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->memList, LosTaskCB, pendList) {
|
||||
queueInfo->waitMemTask |= (1 << tskCB->taskID);
|
||||
}
|
||||
|
||||
QUEUE_END:
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* (LOSCFG_BASE_IPC_QUEUE == 1) */
|
||||
|
||||
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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_sched.h"
|
||||
#include "los_task.h"
|
||||
#include "los_tick.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_hook.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define OS_PRIORITY_QUEUE_NUM 32
|
||||
#define PRIQUEUE_PRIOR0_BIT 0x80000000U
|
||||
#define OS_SCHED_TIME_SLICES ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE)
|
||||
#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
|
||||
#define OS_TICK_RESPONSE_TIME_MAX LOSCFG_BASE_CORE_TICK_RESPONSE_MAX
|
||||
#if (LOSCFG_BASE_CORE_TICK_RESPONSE_MAX == 0)
|
||||
#error "Must specify the maximum value that tick timer counter supports!"
|
||||
#endif
|
||||
|
||||
STATIC SchedScan g_swtmrScan = NULL;
|
||||
STATIC SortLinkAttribute *g_taskSortLinkList = NULL;
|
||||
STATIC LOS_DL_LIST g_priQueueList[OS_PRIORITY_QUEUE_NUM];
|
||||
STATIC UINT32 g_queueBitmap;
|
||||
|
||||
STATIC UINT32 g_schedResponseID = 0;
|
||||
STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||
STATIC VOID (*SchedRealSleepTimeSet)(UINT64) = NULL;
|
||||
|
||||
UINT32 OsSchedRealSleepTimeSet(VOID (*func)(UINT64))
|
||||
{
|
||||
if (func == NULL) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
SchedRealSleepTimeSet = func;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
STATIC UINT64 g_schedTimerBase;
|
||||
|
||||
VOID OsSchedUpdateSchedTimeBase(VOID)
|
||||
{
|
||||
UINT32 period = 0;
|
||||
|
||||
(VOID)HalGetTickCycle(&period);
|
||||
g_schedTimerBase += period;
|
||||
}
|
||||
|
||||
VOID OsSchedTimerBaseReset(UINT64 currTime)
|
||||
{
|
||||
LOS_ASSERT(currTime > g_schedTimerBase);
|
||||
|
||||
g_schedTimerBase = currTime;
|
||||
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||
}
|
||||
#endif
|
||||
|
||||
UINT64 OsGetCurrSchedTimeCycle(VOID)
|
||||
{
|
||||
if (!g_taskScheduled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 1)
|
||||
return HalGetTickCycle(NULL);
|
||||
#else
|
||||
STATIC UINT64 oldSchedTime = 0;
|
||||
UINT32 period = 0;
|
||||
UINT32 intSave = LOS_IntLock();
|
||||
UINT64 time = HalGetTickCycle(&period);
|
||||
UINT64 schedTime = g_schedTimerBase + time;
|
||||
if (schedTime < oldSchedTime) {
|
||||
/* Turn the timer count */
|
||||
g_schedTimerBase += period;
|
||||
schedTime = g_schedTimerBase + time;
|
||||
}
|
||||
|
||||
LOS_ASSERT(schedTime >= oldSchedTime);
|
||||
|
||||
oldSchedTime = schedTime;
|
||||
LOS_IntRestore(intSave);
|
||||
return schedTime;
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
|
||||
{
|
||||
LOS_ASSERT(currTime >= taskCB->startTime);
|
||||
|
||||
INT32 incTime = currTime - taskCB->startTime;
|
||||
if (taskCB->taskID != g_idleTaskID) {
|
||||
taskCB->timeSlice -= incTime;
|
||||
}
|
||||
taskCB->startTime = currTime;
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate)
|
||||
{
|
||||
UINT64 nextExpireTime = OsGetNextExpireTime(startTime);
|
||||
UINT64 nextResponseTime;
|
||||
BOOL isTimeSlice = FALSE;
|
||||
|
||||
/* The current thread's time slice has been consumed, but the current system lock task cannot
|
||||
* trigger the schedule to release the CPU
|
||||
*/
|
||||
if (taskEndTime < nextExpireTime) {
|
||||
nextExpireTime = taskEndTime;
|
||||
isTimeSlice = TRUE;
|
||||
}
|
||||
|
||||
if ((g_schedResponseTime > nextExpireTime) && ((g_schedResponseTime - nextExpireTime) >= OS_CYCLE_PER_TICK)) {
|
||||
nextResponseTime = nextExpireTime - startTime;
|
||||
if (nextResponseTime > OS_TICK_RESPONSE_TIME_MAX) {
|
||||
if (SchedRealSleepTimeSet != NULL) {
|
||||
SchedRealSleepTimeSet(nextResponseTime);
|
||||
}
|
||||
nextResponseTime = OS_TICK_RESPONSE_TIME_MAX;
|
||||
nextExpireTime = startTime + nextResponseTime;
|
||||
} else if (nextResponseTime < OS_CYCLE_PER_TICK) {
|
||||
if (SchedRealSleepTimeSet != NULL) {
|
||||
SchedRealSleepTimeSet(0);
|
||||
}
|
||||
nextResponseTime = OS_CYCLE_PER_TICK;
|
||||
nextExpireTime = startTime + nextResponseTime;
|
||||
if (nextExpireTime >= g_schedResponseTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* There is no point earlier than the current expiration date */
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTimeSlice) {
|
||||
/* The expiration time of the current system is the thread's slice expiration time */
|
||||
g_schedResponseID = responseID;
|
||||
} else {
|
||||
g_schedResponseID = OS_INVALID;
|
||||
}
|
||||
|
||||
g_schedResponseTime = nextExpireTime;
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
if (timeUpdate) {
|
||||
g_schedTimerBase = OsGetCurrSchedTimeCycle();
|
||||
}
|
||||
#endif
|
||||
HalSysTickReload(nextResponseTime);
|
||||
}
|
||||
|
||||
VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate)
|
||||
{
|
||||
UINT64 endTime;
|
||||
LosTaskCB *runTask = g_losTask.runTask;
|
||||
|
||||
if (runTask->taskID != g_idleTaskID) {
|
||||
INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? OS_SCHED_TIME_SLICES : runTask->timeSlice;
|
||||
endTime = startTime + timeSlice;
|
||||
} else {
|
||||
endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK;
|
||||
}
|
||||
OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, timeUpdate);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsSchedPriQueueEnHead(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.
|
||||
*/
|
||||
if (LOS_ListEmpty(&g_priQueueList[priority])) {
|
||||
g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
|
||||
}
|
||||
|
||||
LOS_ListAdd(&g_priQueueList[priority], priqueueItem);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsSchedPriQueueEnTail(LOS_DL_LIST *priqueueItem, UINT32 priority)
|
||||
{
|
||||
if (LOS_ListEmpty(&g_priQueueList[priority])) {
|
||||
g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
|
||||
}
|
||||
|
||||
LOS_ListTailInsert(&g_priQueueList[priority], priqueueItem);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsSchedPriQueueDelete(LOS_DL_LIST *priqueueItem, UINT32 priority)
|
||||
{
|
||||
LOS_ListDelete(priqueueItem);
|
||||
if (LOS_ListEmpty(&g_priQueueList[priority])) {
|
||||
g_queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> priority);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsSchedWakePendTimeTask(UINT64 currTime, LosTaskCB *taskCB, BOOL *needSchedule)
|
||||
{
|
||||
UINT16 tempStatus = taskCB->taskStatus;
|
||||
if (tempStatus & (OS_TASK_STATUS_PEND | OS_TASK_STATUS_DELAY)) {
|
||||
taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY);
|
||||
if (tempStatus & OS_TASK_STATUS_PEND) {
|
||||
taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
|
||||
LOS_ListDelete(&taskCB->pendList);
|
||||
taskCB->taskMux = NULL;
|
||||
taskCB->taskSem = NULL;
|
||||
}
|
||||
|
||||
if (!(tempStatus & OS_TASK_STATUS_SUSPEND)) {
|
||||
OsSchedTaskEnQueue(taskCB);
|
||||
*needSchedule = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC INLINE BOOL OsSchedScanTimerList(VOID)
|
||||
{
|
||||
BOOL needSchedule = FALSE;
|
||||
LOS_DL_LIST *listObject = &g_taskSortLinkList->sortLink;
|
||||
/*
|
||||
* When task is pended with timeout, the task block is on the timeout sortlink
|
||||
* (per cpu) and ipc(mutex,sem and etc.)'s block at the same time, it can be waken
|
||||
* up by either timeout or corresponding ipc it's waiting.
|
||||
*
|
||||
* Now synchronize sortlink procedure is used, therefore the whole task scan needs
|
||||
* to be protected, preventing another core from doing sortlink deletion at same time.
|
||||
*/
|
||||
|
||||
if (LOS_ListEmpty(listObject)) {
|
||||
return needSchedule;
|
||||
}
|
||||
|
||||
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
||||
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
||||
while (sortList->responseTime <= currTime) {
|
||||
LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
|
||||
OsDeleteNodeSortLink(g_taskSortLinkList, &taskCB->sortList);
|
||||
|
||||
OsSchedWakePendTimeTask(currTime, taskCB, &needSchedule);
|
||||
|
||||
if (LOS_ListEmpty(listObject)) {
|
||||
break;
|
||||
}
|
||||
|
||||
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
||||
}
|
||||
|
||||
return needSchedule;
|
||||
}
|
||||
|
||||
VOID OsSchedTaskEnQueue(LosTaskCB *taskCB)
|
||||
{
|
||||
LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
|
||||
|
||||
if (taskCB->taskID != g_idleTaskID) {
|
||||
if (taskCB->timeSlice > OS_TIME_SLICE_MIN) {
|
||||
OsSchedPriQueueEnHead(&taskCB->pendList, taskCB->priority);
|
||||
} else {
|
||||
taskCB->timeSlice = OS_SCHED_TIME_SLICES;
|
||||
OsSchedPriQueueEnTail(&taskCB->pendList, taskCB->priority);
|
||||
}
|
||||
OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOREADYSTATE, taskCB);
|
||||
}
|
||||
|
||||
taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND |
|
||||
OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
|
||||
|
||||
taskCB->taskStatus |= OS_TASK_STATUS_READY;
|
||||
}
|
||||
|
||||
VOID OsSchedTaskDeQueue(LosTaskCB *taskCB)
|
||||
{
|
||||
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
|
||||
if (taskCB->taskID != g_idleTaskID) {
|
||||
OsSchedPriQueueDelete(&taskCB->pendList, taskCB->priority);
|
||||
}
|
||||
|
||||
taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
|
||||
}
|
||||
}
|
||||
|
||||
VOID OsSchedTaskExit(LosTaskCB *taskCB)
|
||||
{
|
||||
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
|
||||
OsSchedTaskDeQueue(taskCB);
|
||||
} else if (taskCB->taskStatus & OS_TASK_STATUS_PEND) {
|
||||
LOS_ListDelete(&taskCB->pendList);
|
||||
taskCB->taskStatus &= ~OS_TASK_STATUS_PEND;
|
||||
}
|
||||
|
||||
if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
|
||||
OsDeleteSortLink(&taskCB->sortList, OS_SORT_LINK_TASK);
|
||||
taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
VOID OsSchedYield(VOID)
|
||||
{
|
||||
LosTaskCB *runTask = g_losTask.runTask;
|
||||
|
||||
runTask->timeSlice = 0;
|
||||
}
|
||||
|
||||
VOID OsSchedDelay(LosTaskCB *runTask, UINT32 tick)
|
||||
{
|
||||
runTask->taskStatus |= OS_TASK_STATUS_DELAY;
|
||||
runTask->waitTimes = tick;
|
||||
}
|
||||
|
||||
VOID OsSchedTaskWait(LOS_DL_LIST *list, UINT32 ticks)
|
||||
{
|
||||
LosTaskCB *runTask = g_losTask.runTask;
|
||||
|
||||
runTask->taskStatus |= OS_TASK_STATUS_PEND;
|
||||
LOS_ListTailInsert(list, &runTask->pendList);
|
||||
|
||||
if (ticks != LOS_WAIT_FOREVER) {
|
||||
runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;
|
||||
runTask->waitTimes = ticks;
|
||||
}
|
||||
}
|
||||
|
||||
VOID OsSchedTaskWake(LosTaskCB *resumedTask)
|
||||
{
|
||||
LOS_ListDelete(&resumedTask->pendList);
|
||||
resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND;
|
||||
|
||||
if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
|
||||
OsDeleteSortLink(&resumedTask->sortList, OS_SORT_LINK_TASK);
|
||||
resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
|
||||
}
|
||||
|
||||
if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPEND) &&
|
||||
!(resumedTask->taskStatus & OS_TASK_STATUS_RUNNING)) {
|
||||
OsSchedTaskEnQueue(resumedTask);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 priority)
|
||||
{
|
||||
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
|
||||
OsSchedTaskDeQueue(taskCB);
|
||||
taskCB->priority = priority;
|
||||
OsSchedTaskEnQueue(taskCB);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
taskCB->priority = priority;
|
||||
OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority);
|
||||
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask)
|
||||
{
|
||||
OsSchedTaskEnQueue(idleTask);
|
||||
}
|
||||
|
||||
UINT32 OsSchedSwtmrScanRegister(SchedScan func)
|
||||
{
|
||||
if (func == NULL) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
g_swtmrScan = func;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
UINT32 OsTaskNextSwitchTimeGet(VOID)
|
||||
{
|
||||
UINT32 intSave = LOS_IntLock();
|
||||
UINT32 ticks = OsSortLinkGetNextExpireTime(g_taskSortLinkList);
|
||||
LOS_IntRestore(intSave);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
UINT32 OsSchedInit(VOID)
|
||||
{
|
||||
UINT16 pri;
|
||||
for (pri = 0; pri < OS_PRIORITY_QUEUE_NUM; pri++) {
|
||||
LOS_ListInit(&g_priQueueList[pri]);
|
||||
}
|
||||
g_queueBitmap = 0;
|
||||
|
||||
g_taskSortLinkList = OsGetSortLinkAttribute(OS_SORT_LINK_TASK);
|
||||
if (g_taskSortLinkList == NULL) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
OsSortLinkInit(g_taskSortLinkList);
|
||||
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LosTaskCB *OsGetTopTask(VOID)
|
||||
{
|
||||
UINT32 priority;
|
||||
LosTaskCB *newTask = NULL;
|
||||
if (g_queueBitmap) {
|
||||
priority = CLZ(g_queueBitmap);
|
||||
newTask = LOS_DL_LIST_ENTRY(((LOS_DL_LIST *)&g_priQueueList[priority])->pstNext, LosTaskCB, pendList);
|
||||
} else {
|
||||
newTask = OS_TCB_FROM_TID(g_idleTaskID);
|
||||
}
|
||||
|
||||
return newTask;
|
||||
}
|
||||
|
||||
VOID OsSchedStart(VOID)
|
||||
{
|
||||
(VOID)LOS_IntLock();
|
||||
LosTaskCB *newTask = OsGetTopTask();
|
||||
|
||||
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
|
||||
g_losTask.newTask = newTask;
|
||||
g_losTask.runTask = g_losTask.newTask;
|
||||
|
||||
g_taskScheduled = 1;
|
||||
newTask->startTime = OsGetCurrSchedTimeCycle();
|
||||
OsSchedTaskDeQueue(newTask);
|
||||
|
||||
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||
g_schedResponseID = OS_INVALID;
|
||||
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, TRUE);
|
||||
|
||||
PRINTK("Entering scheduler\n");
|
||||
}
|
||||
|
||||
BOOL OsSchedTaskSwitch(VOID)
|
||||
{
|
||||
UINT64 endTime;
|
||||
BOOL isTaskSwitch = FALSE;
|
||||
LosTaskCB *runTask = g_losTask.runTask;
|
||||
OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle());
|
||||
|
||||
if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
|
||||
OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK);
|
||||
} else if (!(runTask->taskStatus & (OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND | OS_TASK_STATUS_UNUSED))) {
|
||||
OsSchedTaskEnQueue(runTask);
|
||||
}
|
||||
|
||||
LosTaskCB *newTask = OsGetTopTask();
|
||||
g_losTask.newTask = newTask;
|
||||
|
||||
if (runTask != newTask) {
|
||||
#if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)
|
||||
OsTaskSwitchCheck();
|
||||
#endif
|
||||
runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
|
||||
newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
|
||||
newTask->startTime = runTask->startTime;
|
||||
isTaskSwitch = TRUE;
|
||||
|
||||
OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN);
|
||||
}
|
||||
|
||||
OsSchedTaskDeQueue(newTask);
|
||||
|
||||
if (newTask->taskID != g_idleTaskID) {
|
||||
endTime = newTask->startTime + newTask->timeSlice;
|
||||
} else {
|
||||
endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK;
|
||||
}
|
||||
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, TRUE);
|
||||
|
||||
return isTaskSwitch;
|
||||
}
|
||||
|
||||
UINT64 LOS_SchedTickTimeoutNsGet(VOID)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT64 responseTime;
|
||||
UINT64 currTime;
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
responseTime = g_schedResponseTime;
|
||||
currTime = OsGetCurrSchedTimeCycle();
|
||||
LOS_IntRestore(intSave);
|
||||
|
||||
if (responseTime > currTime) {
|
||||
responseTime = responseTime - currTime;
|
||||
} else {
|
||||
responseTime = 0; /* Tick interrupt already timeout */
|
||||
}
|
||||
|
||||
return OS_SYS_CYCLE_TO_NS(responseTime, OS_SYS_CLOCK);
|
||||
}
|
||||
|
||||
VOID LOS_SchedTickHandler(VOID)
|
||||
{
|
||||
UINT64 currTime;
|
||||
BOOL needSched = FALSE;
|
||||
|
||||
LOS_ASSERT(g_taskScheduled);
|
||||
|
||||
UINT32 intSave = LOS_IntLock();
|
||||
|
||||
if (g_schedResponseID == OS_INVALID) {
|
||||
if (g_swtmrScan != NULL) {
|
||||
needSched = g_swtmrScan();
|
||||
}
|
||||
|
||||
needSched |= OsSchedScanTimerList();
|
||||
}
|
||||
|
||||
g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||
if (needSched && LOS_CHECK_SCHEDULE) {
|
||||
HalTaskSchedule();
|
||||
} else {
|
||||
currTime = OsGetCurrSchedTimeCycle();
|
||||
OsTimeSliceUpdate(g_losTask.runTask, currTime);
|
||||
OsSchedUpdateExpireTime(currTime, TRUE);
|
||||
}
|
||||
|
||||
// printf("3\r\n");
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
VOID LOS_Schedule(VOID)
|
||||
{
|
||||
if (g_taskScheduled && LOS_CHECK_SCHEDULE) {
|
||||
HalTaskSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "los_arch.h"
|
||||
#include "los_config.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_hook.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
#if (LOSCFG_BASE_IPC_SEM == 1)
|
||||
|
||||
LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_unusedSemList;
|
||||
LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSemInit
|
||||
Description : Initialize the Semaphore doubly linked list
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)
|
||||
{
|
||||
LosSemCB *semNode = NULL;
|
||||
UINT16 index;
|
||||
|
||||
LOS_ListInit(&g_unusedSemList);
|
||||
|
||||
if (LOSCFG_BASE_IPC_SEM_LIMIT == 0) {
|
||||
return LOS_ERRNO_SEM_MAXNUM_ZERO;
|
||||
}
|
||||
|
||||
g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));
|
||||
if (g_allSem == NULL) {
|
||||
return LOS_ERRNO_SEM_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Connect all the semaphore CBs in a doubly linked list. */
|
||||
for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) {
|
||||
semNode = ((LosSemCB *)g_allSem) + index;
|
||||
semNode->semID = index;
|
||||
semNode->semStat = OS_SEM_UNUSED;
|
||||
LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSemCreate
|
||||
Description : create the Semaphore
|
||||
Input : count --- Semaphore count
|
||||
: maxCount --- Max semaphore count for check
|
||||
Output : 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);
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
if (LOS_ListEmpty(&g_unusedSemList)) {
|
||||
LOS_IntRestore(intSave);
|
||||
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 = (UINT32)semCreated->semID;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_CREATE, semCreated);
|
||||
return LOS_OK;
|
||||
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SemCreate
|
||||
Description : Create a semaphore
|
||||
Input : count--------- semaphore count
|
||||
Output : semHandle-----Index of semaphore
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle)
|
||||
{
|
||||
return OsSemCreate(count, OS_SEM_COUNTING_MAX_COUNT, semHandle);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_BinarySemCreate
|
||||
Description : Create a binary semaphore
|
||||
Input : count--------- semaphore count
|
||||
Output : semHandle-----Index of semaphore
|
||||
Return : LOS_OK on success, or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle)
|
||||
{
|
||||
return OsSemCreate(count, OS_SEM_BINARY_MAX_COUNT, semHandle);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SemDelete
|
||||
Description : Delete a semaphore
|
||||
Input : semHandle--------- semaphore operation handle
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semDeleted = NULL;
|
||||
UINT32 errNo;
|
||||
UINT32 errLine;
|
||||
|
||||
if (semHandle >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
semDeleted = GET_SEM(semHandle);
|
||||
intSave = LOS_IntLock();
|
||||
if (semDeleted->semStat == OS_SEM_UNUSED) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&semDeleted->semList)) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);
|
||||
}
|
||||
|
||||
LOS_ListAdd(&g_unusedSemList, &semDeleted->semList);
|
||||
semDeleted->semStat = OS_SEM_UNUSED;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_DELETE, semDeleted);
|
||||
return LOS_OK;
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
STATIC_INLINE UINT32 OsSemValidCheck(LosSemCB *semPended)
|
||||
{
|
||||
if (semPended->semStat == OS_SEM_UNUSED) {
|
||||
return LOS_ERRNO_SEM_INVALID;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n");
|
||||
return LOS_ERRNO_SEM_PEND_INTERR;
|
||||
}
|
||||
|
||||
if (g_losTaskLock) {
|
||||
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n");
|
||||
return LOS_ERRNO_SEM_PEND_IN_LOCK;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SemPend
|
||||
Description : Specified semaphore P operation
|
||||
Input : semHandle --------- semaphore operation handle
|
||||
: timeout --------- waitting time
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semPended = NULL;
|
||||
UINT32 retErr;
|
||||
LosTaskCB *runningTask = NULL;
|
||||
|
||||
if (semHandle >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
semPended = GET_SEM(semHandle);
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
retErr = OsSemValidCheck(semPended);
|
||||
if (retErr) {
|
||||
goto ERROR_SEM_PEND;
|
||||
}
|
||||
|
||||
if (semPended->semCount > 0) {
|
||||
semPended->semCount--;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_PEND, semPended, runningTask);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
retErr = LOS_ERRNO_SEM_UNAVAILABLE;
|
||||
goto ERROR_SEM_PEND;
|
||||
}
|
||||
|
||||
runningTask = (LosTaskCB *)g_losTask.runTask;
|
||||
runningTask->taskSem = (VOID *)semPended;
|
||||
OsSchedTaskWait(&semPended->semList, timeout);
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_PEND, semPended, runningTask);
|
||||
LOS_Schedule();
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
|
||||
retErr = LOS_ERRNO_SEM_TIMEOUT;
|
||||
goto ERROR_SEM_PEND;
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_OK;
|
||||
|
||||
ERROR_SEM_PEND:
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(retErr);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SemPost
|
||||
Description : Specified semaphore V operation
|
||||
Input : semHandle--------- semaphore operation handle
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semPosted = GET_SEM(semHandle);
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
|
||||
if (semHandle >= LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
return LOS_ERRNO_SEM_INVALID;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
|
||||
if (semPosted->semStat == OS_SEM_UNUSED) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
if (semPosted->maxSemCount == semPosted->semCount) {
|
||||
LOS_IntRestore(intSave);
|
||||
OS_RETURN_ERROR(LOS_ERRNO_SEM_OVERFLOW);
|
||||
}
|
||||
if (!LOS_ListEmpty(&semPosted->semList)) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));
|
||||
resumedTask->taskSem = NULL;
|
||||
OsSchedTaskWake(resumedTask);
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_POST, semPosted, resumedTask);
|
||||
LOS_Schedule();
|
||||
} else {
|
||||
semPosted->semCount++;
|
||||
LOS_IntRestore(intSave);
|
||||
OsHookCall(LOS_HOOK_TYPE_SEM_POST, semPosted, resumedTask);
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SemGetValue(UINT32 semHandle, INT32 *currVal)
|
||||
{
|
||||
LosSemCB *sem = GET_SEM(semHandle);
|
||||
|
||||
if (semHandle >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
*currVal = sem->semCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* (LOSCFG_BASE_IPC_SEM == 1) */
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "los_sched.h"
|
||||
#include "los_debug.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
STATIC SortLinkAttribute g_taskSortLink;
|
||||
STATIC SortLinkAttribute g_swtmrSortLink;
|
||||
|
||||
UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
|
||||
{
|
||||
LOS_ListInit(&sortLinkHeader->sortLink);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
|
||||
{
|
||||
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink;
|
||||
|
||||
if (LOS_ListEmpty(head)) {
|
||||
LOS_ListAdd(head, &sortList->sortLinkNode);
|
||||
return;
|
||||
}
|
||||
|
||||
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode);
|
||||
if (listSorted->responseTime > sortList->responseTime) {
|
||||
LOS_ListAdd(head, &sortList->sortLinkNode);
|
||||
return;
|
||||
} else if (listSorted->responseTime == sortList->responseTime) {
|
||||
LOS_ListAdd(head->pstNext, &sortList->sortLinkNode);
|
||||
return;
|
||||
}
|
||||
|
||||
LOS_DL_LIST *prevNode = head->pstPrev;
|
||||
do {
|
||||
listSorted = LOS_DL_LIST_ENTRY(prevNode, SortLinkList, sortLinkNode);
|
||||
if (listSorted->responseTime <= sortList->responseTime) {
|
||||
LOS_ListAdd(prevNode, &sortList->sortLinkNode);
|
||||
break;
|
||||
}
|
||||
|
||||
prevNode = prevNode->pstPrev;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
|
||||
{
|
||||
LOS_ListDelete(&sortList->sortLinkNode);
|
||||
SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME);
|
||||
}
|
||||
|
||||
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime)
|
||||
{
|
||||
UINT64 expirTime = 0;
|
||||
UINT64 nextExpirTime = 0;
|
||||
LOS_DL_LIST *head = &sortHeader->sortLink;
|
||||
LOS_DL_LIST *list = head->pstNext;
|
||||
|
||||
if (LOS_ListEmpty(head)) {
|
||||
return OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK;
|
||||
}
|
||||
|
||||
do {
|
||||
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
|
||||
if (listSorted->responseTime <= startTime) {
|
||||
expirTime = startTime;
|
||||
list = list->pstNext;
|
||||
} else {
|
||||
nextExpirTime = listSorted->responseTime;
|
||||
break;
|
||||
}
|
||||
} while (list != head);
|
||||
|
||||
if (expirTime == 0) {
|
||||
return nextExpirTime;
|
||||
}
|
||||
|
||||
if (nextExpirTime == 0) {
|
||||
return expirTime;
|
||||
}
|
||||
|
||||
if ((nextExpirTime - expirTime) <= OS_US_PER_TICK) {
|
||||
return nextExpirTime;
|
||||
}
|
||||
|
||||
return expirTime;
|
||||
}
|
||||
|
||||
VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type)
|
||||
{
|
||||
UINT32 intSave;
|
||||
SortLinkAttribute *sortLinkHeader = NULL;
|
||||
|
||||
if (type == OS_SORT_LINK_TASK) {
|
||||
sortLinkHeader = &g_taskSortLink;
|
||||
} else if (type == OS_SORT_LINK_SWTMR) {
|
||||
sortLinkHeader = &g_swtmrSortLink;
|
||||
} else {
|
||||
LOS_Panic("Sort link type error : %u\n", type);
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK);
|
||||
OsAddNode2SortLink(sortLinkHeader, node);
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
|
||||
{
|
||||
UINT32 intSave;
|
||||
SortLinkAttribute *sortLinkHeader = NULL;
|
||||
|
||||
if (type == OS_SORT_LINK_TASK) {
|
||||
sortLinkHeader = &g_taskSortLink;
|
||||
} else if (type == OS_SORT_LINK_SWTMR) {
|
||||
sortLinkHeader = &g_swtmrSortLink;
|
||||
} else {
|
||||
LOS_Panic("Sort link type error : %u\n", type);
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (node->responseTime != OS_SORT_LINK_INVALID_TIME) {
|
||||
OsDeleteNodeSortLink(sortLinkHeader, node);
|
||||
}
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
SortLinkAttribute *OsGetSortLinkAttribute(SortLinkType type)
|
||||
{
|
||||
if (type == OS_SORT_LINK_TASK) {
|
||||
return &g_taskSortLink;
|
||||
} else if (type == OS_SORT_LINK_SWTMR) {
|
||||
return &g_swtmrSortLink;
|
||||
}
|
||||
|
||||
PRINT_ERR("Invalid sort link type!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT64 OsGetNextExpireTime(UINT64 startTime)
|
||||
{
|
||||
UINT32 intSave;
|
||||
SortLinkAttribute *taskHeader = &g_taskSortLink;
|
||||
SortLinkAttribute *swtmrHeader = &g_swtmrSortLink;
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime);
|
||||
UINT64 swtmrExpirTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime);
|
||||
LOS_IntRestore(intSave);
|
||||
|
||||
return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime;
|
||||
}
|
||||
|
||||
UINT32 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList)
|
||||
{
|
||||
if (currTime >= targetSortList->responseTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (UINT32)(((targetSortList->responseTime - currTime) * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_CLOCK);
|
||||
}
|
||||
|
||||
UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader)
|
||||
{
|
||||
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink;
|
||||
|
||||
if (LOS_ListEmpty(head)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode);
|
||||
return OsSortLinkGetTargetExpireTime(OsGetCurrSchedTimeCycle(), listSorted);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 "securec.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_swtmr.h"
|
||||
#include "los_task.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_queue.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR == 1)
|
||||
|
||||
LITE_OS_SEC_BSS UINT32 g_swtmrHandlerQueue; /* Software Timer timeout queue ID */
|
||||
LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrCBArray = NULL; /* first address in Timer memory space */
|
||||
LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrFreeList = NULL; /* Free list of Software Timer */
|
||||
LITE_OS_SEC_BSS SortLinkAttribute *g_swtmrSortLinkList = NULL; /* The software timer count list */
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
typedef struct SwtmrAlignDataStr {
|
||||
UINT32 times : 24;
|
||||
UINT32 : 5;
|
||||
UINT32 canMultiple : 1;
|
||||
UINT32 canAlign : 1;
|
||||
UINT32 isAligned : 1;
|
||||
} SwtmrAlignData;
|
||||
LITE_OS_SEC_BSS SwtmrAlignData g_swtmrAlignID[LOSCFG_BASE_CORE_SWTMR_LIMIT] = {0}; /* store swtmr align */
|
||||
#endif
|
||||
|
||||
#define SWTMR_MAX_RUNNING_TICKS 2
|
||||
#define OS_SWTMR_MAX_TIMERID ((0xFFFFFFFF / LOSCFG_BASE_CORE_SWTMR_LIMIT) * LOSCFG_BASE_CORE_SWTMR_LIMIT)
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrTask
|
||||
Description : Swtmr task main loop, handle time-out timer.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : None
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT VOID OsSwtmrTask(VOID)
|
||||
{
|
||||
SwtmrHandlerItem swtmrHandle;
|
||||
UINT32 readSize;
|
||||
UINT32 ret;
|
||||
UINT64 tick;
|
||||
readSize = sizeof(SwtmrHandlerItem);
|
||||
|
||||
for (;;) {
|
||||
ret = LOS_QueueReadCopy(g_swtmrHandlerQueue, &swtmrHandle, &readSize, LOS_WAIT_FOREVER);
|
||||
if ((ret == LOS_OK) && (readSize == sizeof(SwtmrHandlerItem))) {
|
||||
if (swtmrHandle.handler == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tick = LOS_TickCountGet();
|
||||
swtmrHandle.handler(swtmrHandle.arg);
|
||||
tick = LOS_TickCountGet() - tick;
|
||||
|
||||
if (tick >= SWTMR_MAX_RUNNING_TICKS) {
|
||||
PRINT_WARN("timer_handler(%p) cost too many ms(%d)\n",
|
||||
swtmrHandle.handler,
|
||||
(UINT32)((tick * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrTaskCreate
|
||||
Description : Create Software Timer
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID)
|
||||
{
|
||||
UINT32 ret;
|
||||
TSK_INIT_PARAM_S swtmrTask;
|
||||
|
||||
// Ignore the return code when matching CSEC rule 6.6(4).
|
||||
(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_SWTMR_STACK_SIZE;
|
||||
swtmrTask.pcName = "Swt_Task";
|
||||
swtmrTask.usTaskPrio = 0;
|
||||
ret = LOS_TaskCreate(&g_swtmrTaskID, &swtmrTask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
STATIC_INLINE UINT32 OsSwtmrCalcAlignCount(UINT64 currTime, UINT32 interval, UINT32 timerId)
|
||||
{
|
||||
UINT32 count;
|
||||
|
||||
if (interval == 0) {
|
||||
return interval;
|
||||
}
|
||||
SWTMR_CTRL_S *cur = g_swtmrCBArray + timerId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
count = OsSortLinkGetTargetExpireTime(currTime, &cur->stSortList);
|
||||
return (interval - (cur->uwInterval - count) % interval);
|
||||
}
|
||||
|
||||
VOID OsSwtmrFindAlignPos(UINT64 currTime, SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
SWTMR_CTRL_S *minInLarge = (SWTMR_CTRL_S *)NULL;
|
||||
SWTMR_CTRL_S *maxInLittle = (SWTMR_CTRL_S *)NULL;
|
||||
UINT32 currSwtmrTimes, swtmrTimes;
|
||||
UINT32 minInLargeVal = OS_NULL_INT;
|
||||
UINT32 maxInLittleVal = OS_NULL_INT;
|
||||
|
||||
LOS_DL_LIST *listHead = &g_swtmrSortLinkList->sortLink;
|
||||
if (LOS_ListEmpty(listHead)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwtmrAlignData currSwtmrAlgInfo = g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT];
|
||||
currSwtmrTimes = currSwtmrAlgInfo.times;
|
||||
LOS_DL_LIST *listObject = listHead->pstNext;
|
||||
|
||||
do {
|
||||
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject, SortLinkList, sortLinkNode);
|
||||
SWTMR_CTRL_S *cur = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
|
||||
SwtmrAlignData swtmrAlgInfo = g_swtmrAlignID[cur->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT];
|
||||
/* swtmr not start */
|
||||
if ((swtmrAlgInfo.isAligned == 0) || (swtmrAlgInfo.canAlign == 0)) {
|
||||
goto CONTINUE_NEXT_NODE;
|
||||
}
|
||||
/* find same interval timer, directly return */
|
||||
if (cur->uwInterval == swtmr->uwInterval) {
|
||||
swtmr->uwCount = OsSortLinkGetTargetExpireTime(currTime, &cur->stSortList);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((currSwtmrAlgInfo.canMultiple != 1) || (swtmrAlgInfo.times == 0)) {
|
||||
goto CONTINUE_NEXT_NODE;
|
||||
}
|
||||
swtmrTimes = swtmrAlgInfo.times;
|
||||
if (currSwtmrTimes == 0) {
|
||||
return;
|
||||
}
|
||||
if ((swtmrTimes >= currSwtmrTimes) && ((swtmrTimes % currSwtmrTimes) == 0)) {
|
||||
if (minInLargeVal > (swtmrTimes / currSwtmrTimes)) {
|
||||
minInLargeVal = swtmrTimes / currSwtmrTimes;
|
||||
minInLarge = cur;
|
||||
}
|
||||
} else if ((swtmrTimes < currSwtmrTimes) && ((currSwtmrTimes % swtmrTimes) == 0)) {
|
||||
if (maxInLittleVal > (currSwtmrTimes / swtmrTimes)) {
|
||||
maxInLittleVal = currSwtmrTimes / swtmrTimes;
|
||||
maxInLittle = cur;
|
||||
}
|
||||
}
|
||||
CONTINUE_NEXT_NODE:
|
||||
listObject = listObject->pstNext;
|
||||
} while (listObject != listHead);
|
||||
|
||||
if (minInLarge != NULL) {
|
||||
swtmr->uwCount = OsSwtmrCalcAlignCount(currTime, swtmr->uwInterval, minInLarge->usTimerID);
|
||||
} else if (maxInLittle != NULL) {
|
||||
swtmr->uwCount = OsSortLinkGetTargetExpireTime(currTime, &maxInLittle->stSortList);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrStart
|
||||
Description : Start Software Timer
|
||||
Input : swtmr ---------- Need to start Software Timer
|
||||
Output : None
|
||||
Return : None
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
||||
|
||||
swtmr->uwCount = swtmr->uwInterval;
|
||||
swtmr->ucState = OS_SWTMR_STATUS_TICKING;
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
if ((g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].canAlign == 1) &&
|
||||
(g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned == 0)) {
|
||||
g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 1;
|
||||
OsSwtmrFindAlignPos(currTime, swtmr);
|
||||
}
|
||||
#endif
|
||||
OsAdd2SortLink(&swtmr->stSortList, currTime, swtmr->uwCount, OS_SORT_LINK_SWTMR);
|
||||
if (LOS_TaskIsRunning()) {
|
||||
OsSchedUpdateExpireTime(currTime, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrDelete
|
||||
Description : Delete Software Timer
|
||||
Input : swtmr --- Need to delete Software Timer, When using, Ensure that it can't be NULL.
|
||||
Output : None
|
||||
Return : None
|
||||
*****************************************************************************/
|
||||
STATIC_INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
/* insert to free list */
|
||||
swtmr->pstNext = g_swtmrFreeList;
|
||||
g_swtmrFreeList = swtmr;
|
||||
swtmr->ucState = OS_SWTMR_STATUS_UNUSED;
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
(VOID)memset_s((VOID *)&g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT],
|
||||
sizeof(SwtmrAlignData), 0, sizeof(SwtmrAlignData));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
OsDeleteSortLink(&swtmr->stSortList, OS_SORT_LINK_SWTMR);
|
||||
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
||||
|
||||
if (LOS_TaskIsRunning()) {
|
||||
OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle(), TRUE);
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
STATIC VOID OsSwtmrTimeoutHandle(SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
SwtmrHandlerItem swtmrHandler;
|
||||
|
||||
swtmrHandler.handler = swtmr->pfnHandler;
|
||||
swtmrHandler.arg = swtmr->uwArg;
|
||||
|
||||
(VOID)LOS_QueueWriteCopy(g_swtmrHandlerQueue, &swtmrHandler, sizeof(SwtmrHandlerItem), LOS_NO_WAIT);
|
||||
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_PERIOD) {
|
||||
OsSwtmrStart(swtmr);
|
||||
} else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) {
|
||||
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC BOOL OsSwtmrScan(VOID)
|
||||
{
|
||||
BOOL needSchedule = FALSE;
|
||||
LOS_DL_LIST *listObject = &g_swtmrSortLinkList->sortLink;
|
||||
|
||||
if (LOS_ListEmpty(listObject)) {
|
||||
return needSchedule;
|
||||
}
|
||||
|
||||
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
||||
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
||||
while (sortList->responseTime <= currTime) {
|
||||
OsDeleteNodeSortLink(g_swtmrSortLinkList, sortList);
|
||||
|
||||
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
|
||||
OsSwtmrTimeoutHandle(swtmr);
|
||||
|
||||
needSchedule = TRUE;
|
||||
if (LOS_ListEmpty(listObject)) {
|
||||
break;
|
||||
}
|
||||
|
||||
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
||||
}
|
||||
|
||||
return needSchedule;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrGetNextTimeout
|
||||
Description : Get next timeout
|
||||
Input : None
|
||||
Output : None
|
||||
Return : Count of the Timer list
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID)
|
||||
{
|
||||
UINT32 intSave = LOS_IntLock();
|
||||
UINT32 ticks = OsSortLinkGetNextExpireTime(g_swtmrSortLinkList);
|
||||
LOS_IntRestore(intSave);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 OsSwtmrTimeGet(const SWTMR_CTRL_S *swtmr)
|
||||
{
|
||||
return OsSortLinkGetTargetExpireTime(OsGetCurrSchedTimeCycle(), &swtmr->stSortList);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsSwtmrInit
|
||||
Description : Initializes Software Timer
|
||||
Input : None
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID)
|
||||
{
|
||||
UINT32 size;
|
||||
UINT16 index;
|
||||
UINT32 ret;
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
// Ignore the return code when matching CSEC rule 6.6(1).
|
||||
(VOID)memset_s((VOID *)g_swtmrAlignID, sizeof(SwtmrAlignData) * LOSCFG_BASE_CORE_SWTMR_LIMIT,
|
||||
0, sizeof(SwtmrAlignData) * LOSCFG_BASE_CORE_SWTMR_LIMIT);
|
||||
#endif
|
||||
|
||||
size = sizeof(SWTMR_CTRL_S) * LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
SWTMR_CTRL_S *swtmr = (SWTMR_CTRL_S *)LOS_MemAlloc(m_aucSysMem0, size);
|
||||
if (swtmr == NULL) {
|
||||
return LOS_ERRNO_SWTMR_NO_MEMORY;
|
||||
}
|
||||
// Ignore the return code when matching CSEC rule 6.6(3).
|
||||
(VOID)memset_s((VOID *)swtmr, size, 0, size);
|
||||
g_swtmrCBArray = swtmr;
|
||||
g_swtmrFreeList = swtmr;
|
||||
swtmr->usTimerID = 0;
|
||||
SWTMR_CTRL_S *temp = swtmr;
|
||||
swtmr++;
|
||||
for (index = 1; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
|
||||
swtmr->usTimerID = index;
|
||||
temp->pstNext = swtmr;
|
||||
temp = swtmr;
|
||||
}
|
||||
|
||||
ret = LOS_QueueCreate((CHAR *)NULL, OS_SWTMR_HANDLE_QUEUE_SIZE,
|
||||
&g_swtmrHandlerQueue, 0, sizeof(SwtmrHandlerItem));
|
||||
if (ret != LOS_OK) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, swtmr);
|
||||
return LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED;
|
||||
}
|
||||
|
||||
ret = OsSwtmrTaskCreate();
|
||||
if (ret != LOS_OK) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, swtmr);
|
||||
return LOS_ERRNO_SWTMR_TASK_CREATE_FAILED;
|
||||
}
|
||||
|
||||
g_swtmrSortLinkList = OsGetSortLinkAttribute(OS_SORT_LINK_SWTMR);
|
||||
if (g_swtmrSortLinkList == NULL) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, swtmr);
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
ret = OsSortLinkInit(g_swtmrSortLinkList);
|
||||
if (ret != LOS_OK) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, swtmr);
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
ret = OsSchedSwtmrScanRegister((SchedScan)OsSwtmrScan);
|
||||
if (ret != LOS_OK) {
|
||||
(VOID)LOS_MemFree(m_aucSysMem0, swtmr);
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SwtmrCreate
|
||||
Description : Create software timer
|
||||
Input : interval
|
||||
mode
|
||||
handler
|
||||
arg
|
||||
Output : swtmrId
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
|
||||
UINT8 mode,
|
||||
SWTMR_PROC_FUNC handler,
|
||||
UINT32 *swtmrId,
|
||||
UINT32 arg,
|
||||
UINT8 rouses,
|
||||
UINT8 sensitive)
|
||||
#else
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
|
||||
UINT8 mode,
|
||||
SWTMR_PROC_FUNC handler,
|
||||
UINT32 *swtmrId,
|
||||
UINT32 arg)
|
||||
#endif
|
||||
{
|
||||
SWTMR_CTRL_S *swtmr = NULL;
|
||||
UINT32 intSave;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
if ((rouses != OS_SWTMR_ROUSES_IGNORE) && (rouses != OS_SWTMR_ROUSES_ALLOW)) {
|
||||
return OS_ERRNO_SWTMR_ROUSES_INVALID;
|
||||
}
|
||||
|
||||
if ((sensitive != OS_SWTMR_ALIGN_INSENSITIVE) && (sensitive != OS_SWTMR_ALIGN_SENSITIVE)) {
|
||||
return OS_ERRNO_SWTMR_ALIGN_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (g_swtmrFreeList == NULL) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_SWTMR_MAXSIZE;
|
||||
}
|
||||
|
||||
swtmr = g_swtmrFreeList;
|
||||
g_swtmrFreeList = swtmr->pstNext;
|
||||
LOS_IntRestore(intSave);
|
||||
swtmr->pfnHandler = handler;
|
||||
swtmr->ucMode = mode;
|
||||
swtmr->uwInterval = interval;
|
||||
swtmr->pstNext = (SWTMR_CTRL_S *)NULL;
|
||||
swtmr->uwCount = 0;
|
||||
swtmr->uwArg = arg;
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
swtmr->ucRouses = rouses;
|
||||
swtmr->ucSensitive = sensitive;
|
||||
#endif
|
||||
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
||||
*swtmrId = swtmr->usTimerID;
|
||||
SET_SORTLIST_VALUE(&swtmr->stSortList, OS_SORT_LINK_INVALID_TIME);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SwtmrStart
|
||||
Description : Start software timer
|
||||
Input : swtmrId ------- Software timer ID
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT32 swtmrId)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT32 ret = LOS_OK;
|
||||
|
||||
if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
|
||||
return LOS_ERRNO_SWTMR_ID_INVALID;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
SWTMR_CTRL_S *swtmr = g_swtmrCBArray + swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
if (swtmr->usTimerID != swtmrId) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_SWTMR_ID_INVALID;
|
||||
}
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
if ((swtmr->ucSensitive == OS_SWTMR_ALIGN_INSENSITIVE) && (swtmr->ucMode == LOS_SWTMR_MODE_PERIOD)) {
|
||||
UINT32 swtmrAlignIdIndex = swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
g_swtmrAlignID[swtmrAlignIdIndex].canAlign = 1;
|
||||
if ((swtmr->uwInterval % LOS_COMMON_DIVISOR) == 0) {
|
||||
g_swtmrAlignID[swtmrAlignIdIndex].canMultiple = 1;
|
||||
g_swtmrAlignID[swtmrAlignIdIndex].times = swtmr->uwInterval / LOS_COMMON_DIVISOR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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:
|
||||
OsSwtmrStart(swtmr);
|
||||
break;
|
||||
default:
|
||||
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SwtmrStop
|
||||
Description : Stop software timer
|
||||
Input : swtmrId ------- Software timer ID
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT32 swtmrId)
|
||||
{
|
||||
SWTMR_CTRL_S *swtmr = NULL;
|
||||
UINT32 intSave;
|
||||
UINT16 swtmrCbId;
|
||||
UINT32 ret = LOS_OK;
|
||||
|
||||
if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
|
||||
return LOS_ERRNO_SWTMR_ID_INVALID;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
swtmr = g_swtmrCBArray + swtmrCbId;
|
||||
if (swtmr->usTimerID != swtmrId) {
|
||||
LOS_IntRestore(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;
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT32 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;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
swtmr = g_swtmrCBArray + swtmrCbId;
|
||||
|
||||
if (swtmr->usTimerID != swtmrId) {
|
||||
LOS_IntRestore(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;
|
||||
}
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_SwtmrDelete
|
||||
Description : Delete software timer
|
||||
Input : swtmrId ------- Software timer ID
|
||||
Output : None
|
||||
Return : LOS_OK on success or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SwtmrDelete(UINT32 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;
|
||||
}
|
||||
intSave = LOS_IntLock();
|
||||
swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
|
||||
swtmr = g_swtmrCBArray + swtmrCbId;
|
||||
if (swtmr->usTimerID != swtmrId) {
|
||||
LOS_IntRestore(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;
|
||||
}
|
||||
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* (LOSCFG_BASE_CORE_SWTMR == 1) */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.h"
|
||||
#include "los_config.h"
|
||||
#include "los_task.h"
|
||||
#include "los_swtmr.h"
|
||||
#include "los_sched.h"
|
||||
|
||||
|
||||
LITE_OS_SEC_BSS UINT32 g_ticksPerSec;
|
||||
LITE_OS_SEC_BSS UINT32 g_uwCyclePerSec;
|
||||
LITE_OS_SEC_BSS UINT32 g_cyclesPerTick;
|
||||
LITE_OS_SEC_BSS UINT32 g_sysClock;
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == 1)
|
||||
//extern VOID platform_tick_handler(VOID);
|
||||
#endif
|
||||
|
||||
LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
|
||||
{
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
OsSchedUpdateSchedTimeBase();
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == 1)
|
||||
// platform_tick_handler();
|
||||
#endif
|
||||
|
||||
LOS_SchedTickHandler();
|
||||
}
|
||||
|
||||
UINT64 LOS_SysCycleGet(VOID)
|
||||
{
|
||||
return OsGetCurrSchedTimeCycle();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_TickCountGet
|
||||
Description : get current tick
|
||||
Input : None
|
||||
Output : None
|
||||
Return : current tick
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID)
|
||||
{
|
||||
return OsGetCurrSchedTimeCycle() / OS_CYCLE_PER_TICK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_CyclePerTickGet
|
||||
Description : Get System cycle number corresponding to each tick
|
||||
Input : None
|
||||
Output : None
|
||||
Return : cycle number corresponding to each tick
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID)
|
||||
{
|
||||
return g_cyclesPerTick;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_MS2Tick
|
||||
Description : milliseconds convert to Tick
|
||||
Input : millisec ---------- milliseconds
|
||||
Output : None
|
||||
Return : Tick
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec)
|
||||
{
|
||||
if (millisec == OS_NULL_INT) {
|
||||
return OS_NULL_INT;
|
||||
}
|
||||
|
||||
return ((UINT64)millisec * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_MS_PER_SECOND;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : LOS_Tick2MS
|
||||
Description : Tick convert to milliseconds
|
||||
Input : ticks ---------- ticks
|
||||
Output : None
|
||||
Return : milliseconds
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 ticks)
|
||||
{
|
||||
return ((UINT64)ticks * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsCpuTick2MS
|
||||
Description : cycle convert to milliseconds
|
||||
Input : cpuTick ---------- cycle
|
||||
Output : msHi ---------- High 32 milliseconds
|
||||
msLo ---------- Low 32 milliseconds
|
||||
Return : LOS_OK on success ,or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2MS(CpuTick *cpuTick, UINT32 *msHi, UINT32 *msLo)
|
||||
{
|
||||
UINT64 tmpCpuTick;
|
||||
DOUBLE temp;
|
||||
|
||||
if ((cpuTick == NULL) || (msHi == NULL) || (msLo == NULL)) {
|
||||
return LOS_ERRNO_SYS_PTR_NULL;
|
||||
}
|
||||
|
||||
if (g_sysClock == 0) {
|
||||
return LOS_ERRNO_SYS_CLOCK_INVALID;
|
||||
}
|
||||
tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
|
||||
temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_MS_PER_SECOND);
|
||||
|
||||
tmpCpuTick = (UINT64)temp;
|
||||
|
||||
*msLo = (UINT32)tmpCpuTick;
|
||||
*msHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function : OsCpuTick2US
|
||||
Description : cycle convert to Microsecond
|
||||
Input : cpuTick ---------- cycle
|
||||
Output : usHi ---------- High 32 Microsecond
|
||||
usLo ---------- Low 32 Microsecond
|
||||
Return : LOS_OK on success ,or error code on failure
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2US(CpuTick *cpuTick, UINT32 *usHi, UINT32 *usLo)
|
||||
{
|
||||
UINT64 tmpCpuTick;
|
||||
DOUBLE temp;
|
||||
|
||||
if ((cpuTick == NULL) || (usHi == NULL) || (usLo == NULL)) {
|
||||
return LOS_ERRNO_SYS_PTR_NULL;
|
||||
}
|
||||
|
||||
if (g_sysClock == 0) {
|
||||
return LOS_ERRNO_SYS_CLOCK_INVALID;
|
||||
}
|
||||
tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
|
||||
temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_US_PER_SECOND);
|
||||
|
||||
tmpCpuTick = (UINT64)temp;
|
||||
|
||||
*usLo = (UINT32)tmpCpuTick;
|
||||
*usHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 "securec.h"
|
||||
#include "los_interrupt.h"
|
||||
#include "los_context.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_task.h"
|
||||
|
||||
|
||||
/* The magic length is 32 bits, the lower 8 bits are used to save the owner task ID,
|
||||
and the other 24 bits are used to set the magic number for verification. */
|
||||
#define OS_MEMBOX_MAGIC 0xa55a5a00
|
||||
#define OS_MEMBOX_TASKID_BITS 8
|
||||
#define OS_MEMBOX_MAX_TASKID ((1 << OS_MEMBOX_TASKID_BITS) - 1)
|
||||
#define OS_MEMBOX_TASKID_GET(addr) (((UINTPTR)(addr)) & OS_MEMBOX_MAX_TASKID)
|
||||
|
||||
STATIC INLINE VOID OsMemBoxSetMagic(LOS_MEMBOX_NODE *node)
|
||||
{
|
||||
UINT8 taskID = (UINT8)LOS_CurTaskIDGet();
|
||||
node->pstNext = (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID);
|
||||
}
|
||||
|
||||
STATIC INLINE UINT32 OsMemBoxCheckMagic(LOS_MEMBOX_NODE *node)
|
||||
{
|
||||
UINT32 taskID = OS_MEMBOX_TASKID_GET(node->pstNext);
|
||||
if (taskID > (LOSCFG_BASE_CORE_TSK_LIMIT + 1)) {
|
||||
return LOS_NOK;
|
||||
} else {
|
||||
return (node->pstNext == (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID)) ? 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))
|
||||
#define MEMBOX_LOCK(state) ((state) = HalIntLock())
|
||||
#define MEMBOX_UNLOCK(state) HalIntRestore(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 OsMemBoxCheckMagic((LOS_MEMBOX_NODE *)node);
|
||||
}
|
||||
|
||||
#if (LOSCFG_PLATFORM_EXC == 1)
|
||||
STATIC LOS_MEMBOX_INFO *g_memBoxHead = NULL;
|
||||
STATIC VOID OsMemBoxAdd(VOID *pool)
|
||||
{
|
||||
LOS_MEMBOX_INFO *nextPool = g_memBoxHead;
|
||||
LOS_MEMBOX_INFO *curPool = NULL;
|
||||
|
||||
while (nextPool != NULL) {
|
||||
curPool = nextPool;
|
||||
nextPool = nextPool->nextMemBox;
|
||||
}
|
||||
|
||||
if (curPool == NULL) {
|
||||
g_memBoxHead = pool;
|
||||
} else {
|
||||
curPool->nextMemBox = pool;
|
||||
}
|
||||
|
||||
((LOS_MEMBOX_INFO *)pool)->nextMemBox = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE);
|
||||
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;
|
||||
|
||||
#if (LOSCFG_PLATFORM_EXC == 1)
|
||||
OsMemBoxAdd(pool);
|
||||
#endif
|
||||
|
||||
MEMBOX_UNLOCK(intSave);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
OsMemBoxSetMagic(nodeTmp);
|
||||
boxInfo->uwBlkCnt++;
|
||||
}
|
||||
MEMBOX_UNLOCK(intSave);
|
||||
|
||||
return (nodeTmp == NULL) ? NULL : OS_MEMBOX_USER_ADDR(nodeTmp);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if (LOSCFG_PLATFORM_EXC == 1)
|
||||
STATIC VOID OsMemboxExcInfoGetSub(const LOS_MEMBOX_INFO *pool, MemInfoCB *memExcInfo)
|
||||
{
|
||||
LOS_MEMBOX_NODE *node = NULL;
|
||||
UINTPTR poolStart, poolEnd;
|
||||
UINT32 index;
|
||||
UINT32 intSave;
|
||||
|
||||
(VOID)memset_s(memExcInfo, sizeof(MemInfoCB), 0, sizeof(MemInfoCB));
|
||||
|
||||
MEMBOX_LOCK(intSave);
|
||||
memExcInfo->type = MEM_MANG_MEMBOX;
|
||||
memExcInfo->startAddr = (UINTPTR)pool;
|
||||
memExcInfo->size = pool->uwBlkNum * pool->uwBlkSize;
|
||||
memExcInfo->blockSize = pool->uwBlkSize;
|
||||
memExcInfo->size = pool->uwBlkNum; /* Block num */
|
||||
memExcInfo->free = pool->uwBlkNum - pool->uwBlkCnt;
|
||||
|
||||
poolStart = (UINTPTR)pool;
|
||||
poolEnd = poolStart + pool->uwBlkSize * pool->uwBlkNum + sizeof(LOS_MEMBOX_INFO);
|
||||
node = (LOS_MEMBOX_NODE *)(pool + 1);
|
||||
for (index = 0; index < pool->uwBlkNum; ++index, node = OS_MEMBOX_NEXT(node, pool->uwBlkSize)) {
|
||||
if (((UINTPTR)node < poolStart) || ((UINTPTR)node >= poolEnd)) {
|
||||
if (OsMemBoxCheckMagic(node)) {
|
||||
memExcInfo->errorAddr = (UINT32)(UINTPTR)((CHAR *)node + OS_MEMBOX_NODE_HEAD_SIZE);
|
||||
memExcInfo->errorLen = pool->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE;
|
||||
memExcInfo->errorOwner = OS_MEMBOX_TASKID_GET(node->pstNext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MEMBOX_UNLOCK(intSave);
|
||||
}
|
||||
|
||||
UINT32 OsMemboxExcInfoGet(UINT32 memNumMax, MemInfoCB *memExcInfo)
|
||||
{
|
||||
LOS_MEMBOX_INFO *memBox = g_memBoxHead;
|
||||
UINT32 count = 0;
|
||||
UINT8 *buffer = (UINT8 *)memExcInfo;
|
||||
|
||||
while (memBox != NULL) {
|
||||
OsMemboxExcInfoGetSub(memBox, (MemInfoCB *)buffer);
|
||||
count++;
|
||||
buffer += sizeof(MemInfoCB);
|
||||
if (count >= memNumMax) {
|
||||
break;
|
||||
}
|
||||
memBox = memBox->nextMemBox;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user