add OpenHarmony 1.0 baseline
This commit is contained in:
349
kernel/base/ipc/los_event.c
Executable file
349
kernel/base/ipc/los_event.c
Executable file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_event_pri.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "los_spinlock.h"
|
||||
#include "los_mp.h"
|
||||
#include "los_percpu_pri.h"
|
||||
|
||||
#if (LOSCFG_BASE_CORE_SWTMR == YES)
|
||||
#include "los_exc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
eventCB->uwEventID = 0;
|
||||
LOS_ListInit(&eventCB->stEventList);
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
if (ptr == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
|
||||
if (eventMask == 0) {
|
||||
return LOS_ERRNO_EVENT_EVENTMASK_INVALID;
|
||||
}
|
||||
|
||||
if (eventMask & LOS_ERRTYPE_ERROR) {
|
||||
return LOS_ERRNO_EVENT_SETBIT_INVALID;
|
||||
}
|
||||
|
||||
if (((mode & LOS_WAITMODE_OR) && (mode & LOS_WAITMODE_AND)) ||
|
||||
(mode & ~(LOS_WAITMODE_OR | LOS_WAITMODE_AND | LOS_WAITMODE_CLR)) ||
|
||||
!(mode & (LOS_WAITMODE_OR | LOS_WAITMODE_AND))) {
|
||||
return LOS_ERRNO_EVENT_FLAGS_INVALID;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
UINT32 ret = 0;
|
||||
|
||||
LOS_ASSERT(OsIntLocked());
|
||||
LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
|
||||
|
||||
if (mode & LOS_WAITMODE_OR) {
|
||||
if ((*eventID & eventMask) != 0) {
|
||||
ret = *eventID & eventMask;
|
||||
}
|
||||
} else {
|
||||
if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {
|
||||
ret = *eventID & eventMask;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret && (mode & LOS_WAITMODE_CLR)) {
|
||||
*eventID = *eventID & ~ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
UINT32 ret;
|
||||
LosTaskCB *runTask = NULL;
|
||||
|
||||
ret = OsEventParamCheck(eventCB, eventMask, mode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;
|
||||
}
|
||||
|
||||
runTask = OsCurrTaskGet();
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
|
||||
OsBackTrace();
|
||||
return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
|
||||
UINT32 timeout, BOOL once)
|
||||
{
|
||||
UINT32 ret = 0;
|
||||
LosTaskCB *runTask = OsCurrTaskGet();
|
||||
|
||||
if (once == FALSE) {
|
||||
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (timeout == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!OsPreemptableInSched()) {
|
||||
return LOS_ERRNO_EVENT_READ_IN_LOCK;
|
||||
}
|
||||
|
||||
runTask->eventMask = eventMask;
|
||||
runTask->eventMode = mode;
|
||||
runTask->taskEvent = eventCB;
|
||||
ret = OsTaskWait(&eventCB->stEventList, timeout, TRUE);
|
||||
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
|
||||
runTask->taskEvent = NULL;
|
||||
return LOS_ERRNO_EVENT_READ_TIMEOUT;
|
||||
}
|
||||
|
||||
ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout,
|
||||
BOOL once)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 intSave;
|
||||
|
||||
ret = OsEventReadCheck(eventCB, eventMask, mode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
|
||||
{
|
||||
UINT8 exitFlag = 0;
|
||||
|
||||
if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) ||
|
||||
((resumedTask->eventMode & LOS_WAITMODE_AND) &&
|
||||
((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {
|
||||
exitFlag = 1;
|
||||
|
||||
resumedTask->taskEvent = NULL;
|
||||
OsTaskWake(resumedTask);
|
||||
}
|
||||
|
||||
return exitFlag;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
|
||||
{
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
LosTaskCB *nextTask = NULL;
|
||||
BOOL schedFlag = FALSE;
|
||||
|
||||
eventCB->uwEventID |= events;
|
||||
if (!LOS_ListEmpty(&eventCB->stEventList)) {
|
||||
for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);
|
||||
&resumedTask->pendList != &eventCB->stEventList;) {
|
||||
nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);
|
||||
if (OsEventResume(resumedTask, eventCB, events)) {
|
||||
schedFlag = TRUE;
|
||||
}
|
||||
if (once == TRUE) {
|
||||
break;
|
||||
}
|
||||
resumedTask = nextTask;
|
||||
}
|
||||
}
|
||||
|
||||
if ((exitFlag != NULL) && (schedFlag == TRUE)) {
|
||||
*exitFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT8 exitFlag = 0;
|
||||
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
|
||||
if (events & LOS_ERRTYPE_ERROR) {
|
||||
return LOS_ERRNO_EVENT_SETBIT_INVALID;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsEventWriteUnsafe(eventCB, events, once, &exitFlag);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
if (exitFlag == 1) {
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 intSave;
|
||||
|
||||
ret = OsEventParamCheck((VOID *)eventID, eventMask, mode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsEventPoll(eventID, eventMask, mode);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
|
||||
{
|
||||
return OsEventRead(eventCB, eventMask, mode, timeout, FALSE);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
|
||||
{
|
||||
return OsEventWrite(eventCB, events, FALSE);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
|
||||
UINT32 timeout)
|
||||
{
|
||||
return OsEventRead(eventCB, eventMask, mode, timeout, TRUE);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events)
|
||||
{
|
||||
return OsEventWrite(eventCB, events, TRUE);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (!LOS_ListEmpty(&eventCB->stEventList)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY;
|
||||
}
|
||||
|
||||
eventCB->uwEventID = 0;
|
||||
LOS_ListDelInit(&eventCB->stEventList);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
if (eventCB == NULL) {
|
||||
return LOS_ERRNO_EVENT_PTR_NULL;
|
||||
}
|
||||
SCHEDULER_LOCK(intSave);
|
||||
eventCB->uwEventID &= events;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_COMPAT_POSIX
|
||||
LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB,
|
||||
UINT32 eventMask, UINT32 mode, UINT32 timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 intSave;
|
||||
|
||||
ret = OsEventReadCheck(eventCB, eventMask, mode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
if (*cond->realValue != cond->value) {
|
||||
eventCB->uwEventID &= cond->clearEvent;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
ret = OsEventReadImp(eventCB, eventMask, mode, timeout, FALSE);
|
||||
OUT:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
944
kernel/base/ipc/los_futex.c
Executable file
944
kernel/base/ipc/los_futex.c
Executable file
@@ -0,0 +1,944 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_futex_pri.h"
|
||||
#include "los_process_pri.h"
|
||||
#include "los_sys_pri.h"
|
||||
#include "los_sched_pri.h"
|
||||
#include "los_mp.h"
|
||||
#include "los_exc.h"
|
||||
#include "los_mux_pri.h"
|
||||
#include "user_copy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList)
|
||||
#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList)
|
||||
#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE
|
||||
#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE)
|
||||
|
||||
typedef struct {
|
||||
LosMux listLock;
|
||||
LOS_DL_LIST lockList;
|
||||
} FutexHash;
|
||||
|
||||
#define FUTEX_INDEX_MAX 128
|
||||
FutexHash g_futexHash[FUTEX_INDEX_MAX];
|
||||
|
||||
STATIC INT32 OsFutexLock(LosMux *lock)
|
||||
{
|
||||
UINT32 ret = LOS_MuxLock(lock, LOS_WAIT_FOREVER);
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Futex lock failed! ERROR: 0x%x!\n", ret);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexUnlock(LosMux *lock)
|
||||
{
|
||||
UINT32 ret = LOS_MuxUnlock(lock);
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Futex unlock failed! ERROR: 0x%x!\n", ret);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
UINT32 OsFutexInit(VOID)
|
||||
{
|
||||
INT32 count;
|
||||
UINT32 ret;
|
||||
|
||||
for (count = 0; count < FUTEX_INDEX_MAX; count++) {
|
||||
LOS_ListInit(&g_futexHash[count].lockList);
|
||||
ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
#ifdef LOS_FUTEX_DEBUG
|
||||
STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList)
|
||||
{
|
||||
FutexNode *tempNode = NULL;
|
||||
FutexNode *lastNode = NULL;
|
||||
LosTaskCB *taskCB = NULL;
|
||||
LOS_DL_LIST *queueList = NULL;
|
||||
|
||||
tempNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
||||
PRINTK("key : 0x%x : ->", tempNode->key);
|
||||
|
||||
for (queueList = &tempNode->queueList; ;) {
|
||||
lastNode = OS_FUTEX_FROM_QUEUELIST(queueList);
|
||||
if (!LOS_ListEmpty(&(lastNode->pendList))) {
|
||||
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(lastNode->pendList)));
|
||||
PRINTK(" %d(%d) ->", taskCB->taskID, taskCB->priority);
|
||||
} else {
|
||||
taskCB = LOS_DL_LIST_ENTRY(lastNode, LosTaskCB, futex);
|
||||
PRINTK(" %d(%d) ->", taskCB->taskID, -1);
|
||||
}
|
||||
queueList = queueList->pstNext;
|
||||
if (queueList == &tempNode->queueList) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRINTK("\n");
|
||||
}
|
||||
|
||||
VOID OsFutexHashShow(VOID)
|
||||
{
|
||||
LOS_DL_LIST *futexList = NULL;
|
||||
INT32 count;
|
||||
/* The maximum number of barrels of a hash table */
|
||||
INT32 hashNodeMax = FUTEX_INDEX_MAX;
|
||||
PRINTK("################los_futex_pri.hash ######################\n");
|
||||
for (count = 0; count < hashNodeMax; count++) {
|
||||
futexList = &(g_futexHash[count].lockList);
|
||||
if (LOS_ListEmpty(futexList)) {
|
||||
continue;
|
||||
}
|
||||
PRINTK("hash -> index : %d\n", count);
|
||||
for (futexList = futexList->pstNext;
|
||||
futexList != &(g_futexHash[count].lockList);
|
||||
futexList = futexList->pstNext) {
|
||||
OsFutexShowTaskNodeAttr(futexList);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC UINT32 OsFutexGetTick(UINT32 absTime)
|
||||
{
|
||||
UINT32 interval;
|
||||
|
||||
/* the values not less than per Millisecond */
|
||||
if (absTime < OS_SYS_MS_PER_SECOND) {
|
||||
interval = OS_SYS_MS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
|
||||
} else {
|
||||
interval = absTime / OS_SYS_MS_PER_SECOND;
|
||||
}
|
||||
|
||||
interval = LOS_MS2Tick(interval);
|
||||
if (interval == 0) {
|
||||
interval = 1;
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsFutexSetKey(UINTPTR futexKey, FutexNode *node)
|
||||
{
|
||||
node->key = futexKey;
|
||||
node->index = futexKey / OS_FUTEX_KEY_BASE;
|
||||
node->pid = LOS_GetCurrProcessID();
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsFutexDeinitFutexNode(FutexNode *node)
|
||||
{
|
||||
node->index = OS_INVALID_VALUE;
|
||||
node->pid = 0;
|
||||
LOS_ListDelete(&node->queueList);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsFutexReplaceQueueListHeadNode(FutexNode *oldHeadNode, FutexNode *newHeadNode)
|
||||
{
|
||||
LOS_DL_LIST *futexList = oldHeadNode->futexList.pstPrev;
|
||||
LOS_ListDelete(&oldHeadNode->futexList);
|
||||
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsFutexDeleteKeyFromFutexList(FutexNode *node)
|
||||
{
|
||||
LOS_ListDelete(&node->futexList);
|
||||
}
|
||||
|
||||
STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
||||
{
|
||||
FutexNode *nextNode = NULL;
|
||||
|
||||
if (node->index >= FUTEX_INDEX_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOS_ListEmpty(&node->queueList)) {
|
||||
OsFutexDeleteKeyFromFutexList(node);
|
||||
if (queueFlags != NULL) {
|
||||
*queueFlags = TRUE;
|
||||
}
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
/* FutexList is not NULL, but the header node of queueList */
|
||||
if (node->futexList.pstNext != NULL) {
|
||||
if (isDeleteHead == TRUE) {
|
||||
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList));
|
||||
OsFutexReplaceQueueListHeadNode(node, nextNode);
|
||||
if (headNode != NULL) {
|
||||
*headNode = nextNode;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXIT:
|
||||
OsFutexDeinitFutexNode(node);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
|
||||
{
|
||||
FutexHash *hashNode = NULL;
|
||||
UINT32 index = node->key / OS_FUTEX_KEY_BASE;
|
||||
|
||||
if (index >= FUTEX_INDEX_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
hashNode = &g_futexHash[index];
|
||||
if (OsMuxLockUnsafe(&hashNode->listLock, LOS_WAIT_FOREVER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->index != index) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
OsFutexDeleteKeyNodeFromHash(node, isDeleteHead, headNode, queueFlags);
|
||||
|
||||
EXIT:
|
||||
if (OsMuxUnlockUnsafe(OsCurrTaskGet(), &hashNode->listLock, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead)
|
||||
{
|
||||
FutexNode *tempNode = (FutexNode *)node;
|
||||
FutexNode *nextNode = NULL;
|
||||
BOOL queueFlag = FALSE;
|
||||
|
||||
while (LOS_ListEmpty(&(tempNode->pendList))) { /* already weak */
|
||||
if (!LOS_ListEmpty(&(tempNode->queueList))) { /* It's not a head node */
|
||||
nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&(tempNode->queueList)));
|
||||
}
|
||||
|
||||
OsFutexDeleteKeyNodeFromHash(tempNode, isDeleteHead, headNode, &queueFlag);
|
||||
if (queueFlag) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tempNode = nextNode;
|
||||
}
|
||||
|
||||
return tempNode;
|
||||
}
|
||||
|
||||
STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node)
|
||||
{
|
||||
FutexNode *headNode = NULL;
|
||||
FutexNode *tailNode = NULL;
|
||||
LOS_DL_LIST *futexList = NULL;
|
||||
FutexHash *hashNode = &g_futexHash[node->index];
|
||||
|
||||
if (LOS_ListEmpty(&hashNode->lockList)) {
|
||||
LOS_ListHeadInsert(&(hashNode->lockList), &(node->futexList));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
headNode = OS_FUTEX_FROM_FUTEXLIST(LOS_DL_LIST_FIRST(&(hashNode->lockList)));
|
||||
/* The small key is at the front of the queue */
|
||||
if (node->key < headNode->key) {
|
||||
LOS_ListHeadInsert(&(hashNode->lockList), &(node->futexList));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
tailNode = OS_FUTEX_FROM_FUTEXLIST(LOS_DL_LIST_LAST(&(hashNode->lockList)));
|
||||
if (node->key > tailNode->key) {
|
||||
LOS_ListTailInsert(&(hashNode->lockList), &(node->futexList));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
for (futexList = hashNode->lockList.pstNext;
|
||||
futexList != &(hashNode->lockList);
|
||||
futexList = futexList->pstNext) {
|
||||
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
||||
if (node->key > headNode->key) {
|
||||
continue;
|
||||
} else if (node->key < headNode->key) {
|
||||
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
|
||||
break;
|
||||
}
|
||||
|
||||
LOS_ListTailInsert(&(headNode->futexList), &(node->futexList));
|
||||
break;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
|
||||
{
|
||||
LOS_DL_LIST *listHead = queueList;
|
||||
LOS_DL_LIST *listTail = queueList->pstPrev;
|
||||
FutexNode *tempNode = NULL;
|
||||
LosTaskCB *taskTail = NULL;
|
||||
|
||||
for (; listHead != listTail; listTail = listTail->pstPrev) {
|
||||
tempNode = OS_FUTEX_FROM_QUEUELIST(listTail);
|
||||
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
|
||||
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
|
||||
if (runTask->priority >= taskTail->priority) {
|
||||
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
|
||||
return LOS_OK;
|
||||
} else if (runTask->priority < taskTail->priority) {
|
||||
if (listTail->pstPrev == listHead) {
|
||||
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexInsertFindFromFrontToBack(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node)
|
||||
{
|
||||
LOS_DL_LIST *listHead = queueList;
|
||||
LOS_DL_LIST *listTail = queueList->pstPrev;
|
||||
FutexNode *tempNode = NULL;
|
||||
LosTaskCB *taskHead = NULL;
|
||||
|
||||
for (; listHead != listTail; listHead = listHead->pstNext) {
|
||||
tempNode = OS_FUTEX_FROM_QUEUELIST(listHead);
|
||||
tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
|
||||
taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));
|
||||
/* High priority comes before low priority,
|
||||
* in the case of the same priority, after the current node
|
||||
*/
|
||||
if (runTask->priority >= taskHead->priority) {
|
||||
if (listHead->pstNext == listTail) {
|
||||
LOS_ListHeadInsert(&(tempNode->queueList), &(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
continue;
|
||||
} else if (runTask->priority < taskHead->priority) {
|
||||
LOS_ListTailInsert(&(tempNode->queueList), &(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexRecycleAndFindHeadNode(FutexNode *headNode, FutexNode *node, FutexNode **firstNode)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
*firstNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(headNode, NULL, TRUE);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
/* The head node is removed and there was originally only one node under the key */
|
||||
if (*firstNode == NULL) {
|
||||
OsFutexInsertNewFutexKeyToHash(node);
|
||||
LOS_ListInit(&(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node, const LosTaskCB *run)
|
||||
{
|
||||
LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));
|
||||
LOS_DL_LIST *queueList = &((*firstNode)->queueList);
|
||||
FutexNode *tailNode = NULL;
|
||||
LosTaskCB *taskTail = NULL;
|
||||
|
||||
if (run->priority < taskHead->priority) {
|
||||
/* The one with the highest priority is inserted at the top of the queue */
|
||||
LOS_ListTailInsert(queueList, &(node->queueList));
|
||||
OsFutexReplaceQueueListHeadNode(*firstNode, node);
|
||||
*firstNode = node;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (LOS_ListEmpty(queueList) && (run->priority >= taskHead->priority)) {
|
||||
/* Insert the next position in the queue with equal priority */
|
||||
LOS_ListHeadInsert(queueList, &(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));
|
||||
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));
|
||||
if ((run->priority >= taskTail->priority) ||
|
||||
((run->priority - taskHead->priority) > (taskTail->priority - run->priority))) {
|
||||
return OsFutexInsertFindFormBackToFront(queueList, run, node);
|
||||
}
|
||||
|
||||
return OsFutexInsertFindFromFrontToBack(queueList, run, node);
|
||||
}
|
||||
|
||||
STATIC FutexNode *OsFindFutexNode(const FutexNode *node)
|
||||
{
|
||||
FutexHash *hashNode = &g_futexHash[node->index];
|
||||
LOS_DL_LIST *futexList = &(hashNode->lockList);
|
||||
FutexNode *headNode = NULL;
|
||||
|
||||
for (futexList = futexList->pstNext;
|
||||
futexList != &(hashNode->lockList);
|
||||
futexList = futexList->pstNext) {
|
||||
headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);
|
||||
if ((headNode->key == node->key) && (headNode->pid == node->pid)) {
|
||||
return headNode;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFindAndInsertToHash(FutexNode *node)
|
||||
{
|
||||
FutexNode *headNode = NULL;
|
||||
FutexNode *firstNode = NULL;
|
||||
UINT32 intSave;
|
||||
INT32 ret;
|
||||
|
||||
headNode = OsFindFutexNode(node);
|
||||
if (headNode == NULL) {
|
||||
OsFutexInsertNewFutexKeyToHash(node);
|
||||
LOS_ListInit(&(node->queueList));
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
ret = OsFutexRecycleAndFindHeadNode(headNode, node, &firstNode);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
} else if (firstNode == NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsFutexInsertTasktoPendList(&firstNode, node, OsCurrTaskGet());
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexWaitParmaCheck(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
|
||||
{
|
||||
UINTPTR futexKey = (UINTPTR)userVaddr;
|
||||
UINT32 lockVal;
|
||||
INT32 ret;
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_EINTR;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
PRINT_ERR("Futex wait parma check failed! error flags: 0x%x\n", flags);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((futexKey % sizeof(INT32)) || (futexKey < OS_FUTEX_KEY_BASE) || (futexKey >= OS_FUTEX_KEY_MAX)) {
|
||||
PRINT_ERR("Futex wait parma check failed! error futex key: 0x%x\n", futexKey);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (!absTime) {
|
||||
PRINT_ERR("Futex wait parma check failed! error absTime: %u\n", absTime);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
ret = LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32));
|
||||
if (ret) {
|
||||
PRINT_ERR("Futex wait parma check failed! copy from user failed!\n");
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (lockVal != val) {
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexDeleteTimeoutTaskNode(FutexHash *hashNode, FutexNode *node)
|
||||
{
|
||||
UINT32 intSave;
|
||||
if (OsFutexLock(&hashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (node->index < FUTEX_INDEX_MAX) {
|
||||
SCHEDULER_LOCK(intSave);
|
||||
(VOID)OsFutexDeleteAlreadyWakeTaskAndGetNext(node, NULL, TRUE);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
|
||||
#ifdef LOS_FUTEX_DEBUG
|
||||
OsFutexHashShow();
|
||||
#endif
|
||||
|
||||
if (OsFutexUnlock(&hashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
return LOS_ETIMEDOUT;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexInserTaskToHash(LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey)
|
||||
{
|
||||
INT32 ret;
|
||||
*taskCB = OsCurrTaskGet();
|
||||
*node = &((*taskCB)->futex);
|
||||
OsFutexSetKey(futexKey, *node);
|
||||
|
||||
ret = OsFindAndInsertToHash(*node);
|
||||
if (ret) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
LOS_ListInit(&((*node)->pendList));
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexWaitTask(const UINT32 timeOut, const UINT32 *userVaddr)
|
||||
{
|
||||
INT32 futexRet;
|
||||
UINT32 intSave;
|
||||
LosTaskCB *taskCB = NULL;
|
||||
FutexNode *node = NULL;
|
||||
UINTPTR futexKey = (UINTPTR)userVaddr;
|
||||
UINT32 index = futexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexHash *hashNode = &g_futexHash[index];
|
||||
|
||||
if (OsFutexLock(&hashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (OsFutexInserTaskToHash(&taskCB, &node, futexKey)) {
|
||||
goto EXIT_ERR;
|
||||
}
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsTaskWait(&(node->pendList), timeOut, FALSE);
|
||||
OsPercpuGet()->taskLockCnt++;
|
||||
LOS_SpinUnlock(&g_taskSpin);
|
||||
|
||||
#ifdef LOS_FUTEX_DEBUG
|
||||
OsFutexHashShow();
|
||||
#endif
|
||||
|
||||
futexRet = OsFutexUnlock(&hashNode->listLock);
|
||||
if (futexRet) {
|
||||
OsPercpuGet()->taskLockCnt--;
|
||||
LOS_IntRestore(intSave);
|
||||
goto EXIT_UNLOCK_ERR;
|
||||
}
|
||||
|
||||
LOS_SpinLock(&g_taskSpin);
|
||||
OsPercpuGet()->taskLockCnt--;
|
||||
|
||||
/*
|
||||
* it will immediately do the scheduling, so there's no need to release the
|
||||
* task spinlock. when this task's been rescheduled, it will be holding the spinlock.
|
||||
*/
|
||||
OsSchedResched();
|
||||
|
||||
if (taskCB->taskStatus & OS_TASK_STATUS_TIMEOUT) {
|
||||
taskCB->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return OsFutexDeleteTimeoutTaskNode(hashNode, node);
|
||||
}
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
|
||||
EXIT_ERR:
|
||||
futexRet = OsFutexUnlock(&hashNode->listLock);
|
||||
EXIT_UNLOCK_ERR:
|
||||
if (futexRet) {
|
||||
return futexRet;
|
||||
}
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime)
|
||||
{
|
||||
INT32 ret;
|
||||
UINT32 timeOut = LOS_WAIT_FOREVER;
|
||||
|
||||
ret = OsFutexWaitParmaCheck(userVaddr, flags, val, absTime);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if (absTime != LOS_WAIT_FOREVER) {
|
||||
timeOut = OsFutexGetTick(absTime);
|
||||
}
|
||||
|
||||
return OsFutexWaitTask(timeOut, userVaddr);
|
||||
}
|
||||
|
||||
/* Check to see if the task to be awakened has timed out
|
||||
* if time out, to weak next pend task.
|
||||
*/
|
||||
STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNumber,
|
||||
FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny)
|
||||
{
|
||||
INT32 count;
|
||||
LosTaskCB *taskCB = NULL;
|
||||
FutexNode *node = headNode;
|
||||
for (count = 0; count < wakeNumber; count++) {
|
||||
/* Ensure the integrity of the head */
|
||||
*nextNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(node, NULL, FALSE);
|
||||
if (*nextNode == NULL) {
|
||||
/* The last node in queuelist is invalid or the entire list is invalid */
|
||||
return;
|
||||
}
|
||||
node = *nextNode;
|
||||
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(node->pendList)));
|
||||
OsTaskWake(taskCB);
|
||||
*wakeAny = TRUE;
|
||||
*nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&(node->queueList)));
|
||||
if (node != headNode) {
|
||||
OsFutexDeinitFutexNode(node);
|
||||
}
|
||||
|
||||
if (LOS_ListEmpty(&headNode->queueList)) {
|
||||
/* Wakes up the entire linked list node */
|
||||
*nextNode = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
node = *nextNode;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny)
|
||||
{
|
||||
UINT32 intSave;
|
||||
FutexNode *node = NULL;
|
||||
FutexNode *headNode = NULL;
|
||||
UINT32 index = futexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexHash *hashNode = &g_futexHash[index];
|
||||
FutexNode tempNode = {
|
||||
.key = futexKey,
|
||||
.index = index,
|
||||
.pid = LOS_GetCurrProcessID(),
|
||||
};
|
||||
|
||||
node = OsFindFutexNode(&tempNode);
|
||||
if (node == NULL) {
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
headNode = node;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny);
|
||||
if ((*newHeadNode) != NULL) {
|
||||
OsFutexReplaceQueueListHeadNode(headNode, *newHeadNode);
|
||||
OsFutexDeinitFutexNode(headNode);
|
||||
} else if (headNode->index < FUTEX_INDEX_MAX) {
|
||||
OsFutexDeleteKeyFromFutexList(headNode);
|
||||
OsFutexDeinitFutexNode(headNode);
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber)
|
||||
{
|
||||
INT32 ret, futexRet;
|
||||
UINTPTR futexKey = (UINTPTR)userVaddr;
|
||||
FutexHash *hashNode = NULL;
|
||||
INT32 index = futexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexNode *headNode = NULL;
|
||||
BOOL wakeAny = FALSE;
|
||||
|
||||
if (!(flags & FUTEX_WAKE)) {
|
||||
PRINT_ERR("Futex wake param check failed! error flags: 0x%x\n", flags);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((futexKey % sizeof(INT32)) || (futexKey < OS_FUTEX_KEY_BASE) || (futexKey >= OS_FUTEX_KEY_MAX)) {
|
||||
PRINT_ERR("Futex wake param check failed! error futex key: 0x%x\n", futexKey);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
hashNode = &g_futexHash[index];
|
||||
if (OsFutexLock(&hashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
ret = OsFutexWakeTask(futexKey, wakeNumber, &headNode, &wakeAny);
|
||||
if (ret) {
|
||||
goto EXIT_ERR;
|
||||
}
|
||||
|
||||
#ifdef LOS_FUTEX_DEBUG
|
||||
OsFutexHashShow();
|
||||
#endif
|
||||
|
||||
futexRet = OsFutexUnlock(&hashNode->listLock);
|
||||
if (futexRet) {
|
||||
goto EXIT_UNLOCK_ERR;
|
||||
}
|
||||
|
||||
if (wakeAny == TRUE) {
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
|
||||
EXIT_ERR:
|
||||
futexRet = OsFutexUnlock(&hashNode->listLock);
|
||||
EXIT_UNLOCK_ERR:
|
||||
if (futexRet) {
|
||||
return futexRet;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexRequeueInsertNewKey(UINTPTR newFutexKey, INT32 newIndex, FutexNode *oldHeadNode)
|
||||
{
|
||||
INT32 ret;
|
||||
UINT32 intSave;
|
||||
LosTaskCB *task = NULL;
|
||||
FutexNode *nextNode = NULL;
|
||||
FutexNode newTempNode = {
|
||||
.key = newFutexKey,
|
||||
.index = newIndex,
|
||||
.pid = LOS_GetCurrProcessID(),
|
||||
};
|
||||
LOS_DL_LIST *queueList = &oldHeadNode->queueList;
|
||||
FutexNode *newHeadNode = OsFindFutexNode(&newTempNode);
|
||||
if (newHeadNode == NULL) {
|
||||
OsFutexInsertNewFutexKeyToHash(oldHeadNode);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
do {
|
||||
nextNode = OS_FUTEX_FROM_QUEUELIST(queueList);
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (LOS_ListEmpty(&nextNode->pendList)) {
|
||||
queueList = queueList->pstNext;
|
||||
OsFutexDeinitFutexNode(nextNode);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if (queueList->pstNext != NULL) {
|
||||
continue;
|
||||
} else {
|
||||
return LOS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
task = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(nextNode->pendList)));
|
||||
queueList = queueList->pstNext;
|
||||
LOS_ListDelete(&nextNode->queueList);
|
||||
ret = OsFutexInsertTasktoPendList(&newHeadNode, nextNode, task);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Futex requeue insert new key failed!\n");
|
||||
}
|
||||
} while (queueList->pstNext != NULL);
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC VOID OsFutexRequeueSplitTwoLists(FutexHash *oldHashNode, FutexNode *oldHeadNode, UINTPTR futexKey, INT32 count)
|
||||
{
|
||||
LOS_DL_LIST *queueList = &oldHeadNode->queueList;
|
||||
FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));
|
||||
INT32 newIndex = futexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexNode *nextNode = NULL;
|
||||
FutexNode *newHeadNode = NULL;
|
||||
LOS_DL_LIST *futexList = NULL;
|
||||
BOOL IsAll = FALSE;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
nextNode = OS_FUTEX_FROM_QUEUELIST(queueList);
|
||||
nextNode->key = futexKey;
|
||||
nextNode->index = newIndex;
|
||||
if (queueList->pstNext == &oldHeadNode->queueList) {
|
||||
IsAll = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
queueList = queueList->pstNext;
|
||||
}
|
||||
|
||||
futexList = oldHeadNode->futexList.pstPrev;
|
||||
LOS_ListDelete(&oldHeadNode->futexList);
|
||||
if (IsAll == TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
newHeadNode = OS_FUTEX_FROM_QUEUELIST(queueList);
|
||||
LOS_ListHeadInsert(futexList, &newHeadNode->futexList);
|
||||
oldHeadNode->queueList.pstPrev = &nextNode->queueList;
|
||||
nextNode->queueList.pstNext = &oldHeadNode->queueList;
|
||||
newHeadNode->queueList.pstPrev = &tailNode->queueList;
|
||||
tailNode->queueList.pstNext = &newHeadNode->queueList;
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, INT32 wakeNumber,
|
||||
UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny)
|
||||
{
|
||||
INT32 ret;
|
||||
FutexNode *oldHeadNode = NULL;
|
||||
INT32 oldIndex = oldFutexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexHash *oldHashNode = &g_futexHash[oldIndex];
|
||||
FutexNode oldTempNode = {
|
||||
.key = oldFutexKey,
|
||||
.index = oldIndex,
|
||||
.pid = LOS_GetCurrProcessID(),
|
||||
};
|
||||
|
||||
if (wakeNumber > 0) {
|
||||
ret = OsFutexWakeTask(oldFutexKey, wakeNumber, &oldHeadNode, wakeAny);
|
||||
if ((ret != LOS_OK) || (oldHeadNode == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (requeueCount <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oldHeadNode == NULL) {
|
||||
oldHeadNode = OsFindFutexNode(&oldTempNode);
|
||||
if (oldHeadNode == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
OsFutexRequeueSplitTwoLists(oldHashNode, oldHeadNode, newFutexKey, requeueCount);
|
||||
|
||||
return oldHeadNode;
|
||||
}
|
||||
|
||||
STATIC INT32 OsFutexRequeueParamCheck(UINTPTR oldFutexKey, UINTPTR newFutexKey)
|
||||
{
|
||||
if (oldFutexKey == newFutexKey) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((oldFutexKey % sizeof(INT32)) || (oldFutexKey < OS_FUTEX_KEY_BASE) || (oldFutexKey >= OS_FUTEX_KEY_MAX)) {
|
||||
PRINT_ERR("Futex requeue param check failed! error old futex key: 0x%x\n", oldFutexKey);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((newFutexKey % sizeof(INT32)) || (newFutexKey < OS_FUTEX_KEY_BASE) || (newFutexKey >= OS_FUTEX_KEY_MAX)) {
|
||||
PRINT_ERR("Futex requeue param check failed! error new futex key: 0x%x\n", newFutexKey);
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr)
|
||||
{
|
||||
INT32 ret;
|
||||
UINTPTR oldFutexKey = (UINTPTR)userVaddr;
|
||||
UINTPTR newFutexKey = (UINTPTR)newUserVaddr;
|
||||
INT32 oldIndex = oldFutexKey / OS_FUTEX_KEY_BASE;
|
||||
INT32 newIndex = newFutexKey / OS_FUTEX_KEY_BASE;
|
||||
FutexHash *oldHashNode = NULL;
|
||||
FutexHash *newHashNode = NULL;
|
||||
FutexNode *oldHeadNode = NULL;
|
||||
BOOL wakeAny = FALSE;
|
||||
|
||||
if (OsFutexRequeueParamCheck(oldFutexKey, newFutexKey)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
oldHashNode = &g_futexHash[oldIndex];
|
||||
if (OsFutexLock(&oldHashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
oldHeadNode = OsFutexRequeueRemoveOldKeyAndGetHead(oldFutexKey, wakeNumber, newFutexKey, count, &wakeAny);
|
||||
if (oldHeadNode == NULL) {
|
||||
(VOID)OsFutexUnlock(&oldHashNode->listLock);
|
||||
if (wakeAny == TRUE) {
|
||||
ret = LOS_OK;
|
||||
goto EXIT;
|
||||
}
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
newHashNode = &g_futexHash[newIndex];
|
||||
if (oldIndex != newIndex) {
|
||||
if (OsFutexUnlock(&oldHashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (OsFutexLock(&newHashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = OsFutexRequeueInsertNewKey(newFutexKey, newIndex, oldHeadNode);
|
||||
|
||||
if (OsFutexUnlock(&newHashNode->listLock)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
if (wakeAny == TRUE) {
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
90
kernel/base/ipc/los_ipcdebug.c
Executable file
90
kernel/base/ipc/los_ipcdebug.c
Executable file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_ipcdebug_pri.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_DEBUG_QUEUE)
|
||||
|
||||
VOID OsArraySortByTime(UINT32 *sortArray, UINT32 start, UINT32 end, const IpcSortParam *sortParam,
|
||||
OsCompareFunc compareFunc)
|
||||
{
|
||||
UINT32 left = start;
|
||||
UINT32 right = end;
|
||||
UINT32 idx = start;
|
||||
UINT32 pivot = sortArray[start];
|
||||
|
||||
while (left < right) {
|
||||
while ((left < right) && (sortArray[right] < sortParam->ipcDebugCBCnt) && (pivot < sortParam->ipcDebugCBCnt) &&
|
||||
compareFunc(sortParam, sortArray[right], pivot)) {
|
||||
right--;
|
||||
}
|
||||
|
||||
if (left < right) {
|
||||
sortArray[left] = sortArray[right];
|
||||
idx = right;
|
||||
left++;
|
||||
}
|
||||
|
||||
while ((left < right) && (sortArray[left] < sortParam->ipcDebugCBCnt) && (pivot < sortParam->ipcDebugCBCnt) &&
|
||||
compareFunc(sortParam, pivot, sortArray[left])) {
|
||||
left++;
|
||||
}
|
||||
|
||||
if (left < right) {
|
||||
sortArray[right] = sortArray[left];
|
||||
idx = left;
|
||||
right--;
|
||||
}
|
||||
}
|
||||
|
||||
sortArray[idx] = pivot;
|
||||
|
||||
if (start < idx) {
|
||||
OsArraySortByTime(sortArray, start, idx - 1, sortParam, compareFunc);
|
||||
}
|
||||
if (idx < end) {
|
||||
OsArraySortByTime(sortArray, idx + 1, end, sortParam, compareFunc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
612
kernel/base/ipc/los_mux.c
Executable file
612
kernel/base/ipc/los_mux.c
Executable file
@@ -0,0 +1,612 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_mux_pri.h"
|
||||
#include "los_bitmap.h"
|
||||
#include "los_spinlock.h"
|
||||
#include "los_mp.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "los_exc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if (LOSCFG_BASE_IPC_MUX == YES)
|
||||
#define MUTEXATTR_TYPE_MASK 0x0FU
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrInit(LosMuxAttr *attr)
|
||||
{
|
||||
if (attr == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
attr->protocol = LOS_MUX_PRIO_INHERIT;
|
||||
attr->prioceiling = OS_TASK_PRIORITY_LOWEST;
|
||||
attr->type = LOS_MUX_DEFAULT;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy(LosMuxAttr *attr)
|
||||
{
|
||||
if (attr == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType(const LosMuxAttr *attr, INT32 *outType)
|
||||
{
|
||||
INT32 type;
|
||||
|
||||
if ((attr == NULL) || (outType == NULL)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK);
|
||||
if ((type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
*outType = type;
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType(LosMuxAttr *attr, INT32 type)
|
||||
{
|
||||
if ((attr == NULL) || (type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
attr->type = (UINT8)((attr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol(const LosMuxAttr *attr, INT32 *protocol)
|
||||
{
|
||||
if ((attr != NULL) && (protocol != NULL)) {
|
||||
*protocol = attr->protocol;
|
||||
} else {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol(LosMuxAttr *attr, INT32 protocol)
|
||||
{
|
||||
if (attr == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
case LOS_MUX_PRIO_NONE:
|
||||
case LOS_MUX_PRIO_INHERIT:
|
||||
case LOS_MUX_PRIO_PROTECT:
|
||||
attr->protocol = (UINT8)protocol;
|
||||
return LOS_OK;
|
||||
default:
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling(const LosMuxAttr *attr, INT32 *prioceiling)
|
||||
{
|
||||
if (attr == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (prioceiling != NULL) {
|
||||
*prioceiling = attr->prioceiling;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioceiling)
|
||||
{
|
||||
if ((attr == NULL) ||
|
||||
(prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
|
||||
(prioceiling > OS_TASK_PRIORITY_LOWEST)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
attr->prioceiling = (UINT8)prioceiling;
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling(LosMux *mutex, INT32 prioceiling, INT32 *oldPrioceiling)
|
||||
{
|
||||
INT32 ret;
|
||||
INT32 retLock;
|
||||
if ((mutex == NULL) ||
|
||||
(prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
|
||||
(prioceiling > OS_TASK_PRIORITY_LOWEST)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
retLock = LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
|
||||
if (retLock != LOS_OK) {
|
||||
return retLock;
|
||||
}
|
||||
|
||||
if (oldPrioceiling != NULL) {
|
||||
*oldPrioceiling = mutex->attr.prioceiling;
|
||||
}
|
||||
|
||||
ret = LOS_MuxAttrSetPrioceiling(&mutex->attr, prioceiling);
|
||||
|
||||
retLock = LOS_MuxUnlock(mutex);
|
||||
if ((ret == LOS_OK) && (retLock != LOS_OK)) {
|
||||
return retLock;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling(const LosMux *mutex, INT32 *prioceiling)
|
||||
{
|
||||
if ((mutex != NULL) && (prioceiling != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
|
||||
*prioceiling = mutex->attr.prioceiling;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT BOOL LOS_MuxIsValid(const LosMux *mutex)
|
||||
{
|
||||
if ((mutex != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC UINT32 OsCheckMutexAttr(const LosMuxAttr *attr)
|
||||
{
|
||||
if (((INT8)(attr->type) < LOS_MUX_NORMAL) || (attr->type > LOS_MUX_ERRORCHECK)) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
if (((INT8)(attr->prioceiling) < OS_TASK_PRIORITY_HIGHEST) || (attr->prioceiling > OS_TASK_PRIORITY_LOWEST)) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
if (((INT8)(attr->protocol) < LOS_MUX_PRIO_NONE) || (attr->protocol > LOS_MUX_PRIO_PROTECT)) {
|
||||
return LOS_NOK;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (attr == NULL) {
|
||||
(VOID)LOS_MuxAttrInit(&mutex->attr);
|
||||
} else {
|
||||
(VOID)memcpy_s(&mutex->attr, sizeof(LosMuxAttr), attr, sizeof(LosMuxAttr));
|
||||
}
|
||||
|
||||
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
mutex->muxCount = 0;
|
||||
mutex->owner = NULL;
|
||||
LOS_ListInit(&mutex->muxList);
|
||||
mutex->magic = OS_MUX_MAGIC;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
|
||||
{
|
||||
UINT32 intSave;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (mutex->magic != OS_MUX_MAGIC) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
if (mutex->muxCount != 0) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_EBUSY;
|
||||
}
|
||||
|
||||
(VOID)memset_s(mutex, sizeof(LosMux), 0, sizeof(LosMux));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask, LosTaskCB *owner)
|
||||
{
|
||||
if ((owner->priority > runTask->priority) && (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT)) {
|
||||
LOS_BitmapSet(&(owner->priBitMap), owner->priority);
|
||||
OsTaskPriModify(owner, runTask->priority);
|
||||
}
|
||||
}
|
||||
|
||||
VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner)
|
||||
{
|
||||
UINT16 bitMapPri;
|
||||
|
||||
if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner->priority >= taskCB->priority) {
|
||||
bitMapPri = LOS_LowBitGet(owner->priBitMap);
|
||||
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
|
||||
LOS_BitmapClr(&(owner->priBitMap), bitMapPri);
|
||||
OsTaskPriModify(owner, bitMapPri);
|
||||
}
|
||||
} else {
|
||||
if (LOS_HighBitGet(owner->priBitMap) != taskCB->priority) {
|
||||
LOS_BitmapClr(&(owner->priBitMap), taskCB->priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC LOS_DL_LIST *OsMuxPendFindPosSub(const LosTaskCB *runTask, const LosMux *mutex)
|
||||
{
|
||||
LosTaskCB *pendedTask = NULL;
|
||||
LOS_DL_LIST *node = NULL;
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, &(mutex->muxList), LosTaskCB, pendList) {
|
||||
if (pendedTask->priority < runTask->priority) {
|
||||
continue;
|
||||
} else if (pendedTask->priority > runTask->priority) {
|
||||
node = &pendedTask->pendList;
|
||||
break;
|
||||
} else {
|
||||
node = pendedTask->pendList.pstNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
STATIC LOS_DL_LIST *OsMuxPendFindPos(const LosTaskCB *runTask, LosMux *mutex)
|
||||
{
|
||||
LosTaskCB *pendedTask1 = NULL;
|
||||
LosTaskCB *pendedTask2 = NULL;
|
||||
LOS_DL_LIST *node = NULL;
|
||||
|
||||
if (LOS_ListEmpty(&mutex->muxList)) {
|
||||
node = &mutex->muxList;
|
||||
} else {
|
||||
pendedTask1 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&mutex->muxList));
|
||||
pendedTask2 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_LAST(&mutex->muxList));
|
||||
if ((pendedTask1 != NULL) && (pendedTask1->priority > runTask->priority)) {
|
||||
node = mutex->muxList.pstNext;
|
||||
} else if ((pendedTask2 != NULL) && (pendedTask2->priority <= runTask->priority)) {
|
||||
node = &mutex->muxList;
|
||||
} else {
|
||||
node = OsMuxPendFindPosSub(runTask, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
LOS_DL_LIST *node = NULL;
|
||||
LosTaskCB *owner = NULL;
|
||||
|
||||
if ((mutex->muxList.pstPrev == NULL) || (mutex->muxList.pstNext == NULL)) {
|
||||
/* This is for mutex macro initialization. */
|
||||
mutex->muxCount = 0;
|
||||
mutex->owner = NULL;
|
||||
LOS_ListInit(&mutex->muxList);
|
||||
}
|
||||
|
||||
if (mutex->muxCount == 0) {
|
||||
mutex->muxCount++;
|
||||
mutex->owner = (VOID *)runTask;
|
||||
LOS_ListTailInsert(&runTask->lockList, &mutex->holdList);
|
||||
if ((runTask->priority > mutex->attr.prioceiling) && (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT)) {
|
||||
LOS_BitmapSet(&runTask->priBitMap, runTask->priority);
|
||||
OsTaskPriModify(runTask, mutex->attr.prioceiling);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (((LosTaskCB *)mutex->owner == runTask) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
|
||||
mutex->muxCount++;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (!OsPreemptableInSched()) {
|
||||
return LOS_EDEADLK;
|
||||
}
|
||||
|
||||
OsMuxBitmapSet(mutex, runTask, (LosTaskCB *)mutex->owner);
|
||||
|
||||
owner = (LosTaskCB *)mutex->owner;
|
||||
runTask->taskMux = (VOID *)mutex;
|
||||
node = OsMuxPendFindPos(runTask, mutex);
|
||||
|
||||
ret = OsTaskWait(node, timeout, TRUE);
|
||||
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
|
||||
runTask->taskMux = NULL;
|
||||
ret = LOS_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (timeout != LOS_WAIT_FOREVER) {
|
||||
OsMuxBitmapRestore(mutex, runTask, owner);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT32 OsMuxLockUnsafe(LosMux *mutex, UINT32 timeout)
|
||||
{
|
||||
LosTaskCB *runTask = OsCurrTaskGet();
|
||||
|
||||
if (mutex->magic != OS_MUX_MAGIC) {
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((mutex->attr.type == LOS_MUX_ERRORCHECK) && (mutex->muxCount != 0) && (mutex->owner == (VOID *)runTask)) {
|
||||
return LOS_EDEADLK;
|
||||
}
|
||||
|
||||
return OsMuxPendOp(runTask, mutex, timeout);
|
||||
}
|
||||
|
||||
UINT32 OsMuxTrylockUnsafe(LosMux *mutex, UINT32 timeout)
|
||||
{
|
||||
LosTaskCB *runTask = OsCurrTaskGet();
|
||||
|
||||
if (mutex->magic != OS_MUX_MAGIC) {
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((mutex->owner != NULL) && ((LosTaskCB *)mutex->owner != runTask)) {
|
||||
return LOS_EBUSY;
|
||||
}
|
||||
if ((mutex->attr.type != LOS_MUX_RECURSIVE) && (mutex->muxCount != 0)) {
|
||||
return LOS_EBUSY;
|
||||
}
|
||||
|
||||
return OsMuxPendOp(runTask, mutex, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
|
||||
{
|
||||
LosTaskCB *runTask = NULL;
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_EINTR;
|
||||
}
|
||||
|
||||
runTask = (LosTaskCB *)OsCurrTaskGet();
|
||||
/* DO NOT Call blocking API in system tasks */
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
|
||||
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
|
||||
OsBackTrace();
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsMuxLockUnsafe(mutex, timeout);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxTrylock(LosMux *mutex)
|
||||
{
|
||||
LosTaskCB *runTask = NULL;
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_EINTR;
|
||||
}
|
||||
|
||||
runTask = (LosTaskCB *)OsCurrTaskGet();
|
||||
/* DO NOT Call blocking API in system tasks */
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
|
||||
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
|
||||
OsBackTrace();
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsMuxTrylockUnsafe(mutex, 0);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC VOID OsMuxPostOpSub(LosTaskCB *taskCB, LosMux *mutex)
|
||||
{
|
||||
LosTaskCB *pendedTask = NULL;
|
||||
UINT16 bitMapPri;
|
||||
|
||||
if (!LOS_ListEmpty(&mutex->muxList)) {
|
||||
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(pendedTask, (&mutex->muxList), LosTaskCB, pendList) {
|
||||
if (bitMapPri != pendedTask->priority) {
|
||||
LOS_BitmapClr(&taskCB->priBitMap, pendedTask->priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
bitMapPri = LOS_LowBitGet(taskCB->priBitMap);
|
||||
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);
|
||||
OsTaskPriModify((LosTaskCB *)mutex->owner, bitMapPri);
|
||||
}
|
||||
|
||||
STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
|
||||
{
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
|
||||
if (LOS_ListEmpty(&mutex->muxList)) {
|
||||
LOS_ListDelete(&mutex->holdList);
|
||||
mutex->owner = NULL;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));
|
||||
if (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT) {
|
||||
if (resumedTask->priority > taskCB->priority) {
|
||||
if (LOS_HighBitGet(taskCB->priBitMap) != resumedTask->priority) {
|
||||
LOS_BitmapClr(&taskCB->priBitMap, resumedTask->priority);
|
||||
}
|
||||
} else if (taskCB->priBitMap != 0) {
|
||||
OsMuxPostOpSub(taskCB, mutex);
|
||||
}
|
||||
}
|
||||
mutex->muxCount = 1;
|
||||
mutex->owner = (VOID *)resumedTask;
|
||||
resumedTask->taskMux = NULL;
|
||||
LOS_ListDelete(&mutex->holdList);
|
||||
LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);
|
||||
OsTaskWake(resumedTask);
|
||||
if (needSched != NULL) {
|
||||
*needSched = TRUE;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
|
||||
{
|
||||
UINT16 bitMapPri;
|
||||
|
||||
if (mutex->magic != OS_MUX_MAGIC) {
|
||||
return LOS_EBADF;
|
||||
}
|
||||
|
||||
if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (mutex->muxCount == 0) {
|
||||
return LOS_EPERM;
|
||||
}
|
||||
|
||||
if ((LosTaskCB *)mutex->owner != taskCB) {
|
||||
return LOS_EPERM;
|
||||
}
|
||||
|
||||
if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
|
||||
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);
|
||||
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
|
||||
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);
|
||||
OsTaskPriModify(taskCB, bitMapPri);
|
||||
}
|
||||
}
|
||||
|
||||
/* Whether a task block the mutex lock. */
|
||||
return OsMuxPostOp(taskCB, mutex, needSched);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
|
||||
{
|
||||
LosTaskCB *runTask = NULL;
|
||||
BOOL needSched = FALSE;
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_EINTR;
|
||||
}
|
||||
|
||||
runTask = (LosTaskCB *)OsCurrTaskGet();
|
||||
/* DO NOT Call blocking API in system tasks */
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
|
||||
PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
|
||||
OsBackTrace();
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsMuxUnlockUnsafe(runTask, mutex, &needSched);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if (needSched == TRUE) {
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* (LOSCFG_BASE_IPC_MUX == YES) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
504
kernel/base/ipc/los_queue.c
Executable file
504
kernel/base/ipc/los_queue.c
Executable file
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_queue_pri.h"
|
||||
#include "los_queue_debug_pri.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "los_spinlock.h"
|
||||
#include "los_mp.h"
|
||||
#include "los_percpu_pri.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if (LOSCFG_BASE_IPC_QUEUE == YES)
|
||||
#if (LOSCFG_BASE_IPC_QUEUE_LIMIT <= 0)
|
||||
#error "queue maxnum cannot be zero"
|
||||
#endif /* LOSCFG_BASE_IPC_QUEUE_LIMIT <= 0 */
|
||||
|
||||
LITE_OS_SEC_BSS LosQueueCB *g_allQueue = NULL;
|
||||
LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_freeQueueList;
|
||||
|
||||
/*
|
||||
* Description : queue initial
|
||||
* Return : LOS_OK on success or error code on failure
|
||||
*/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID)
|
||||
{
|
||||
LosQueueCB *queueNode = NULL;
|
||||
UINT32 index;
|
||||
UINT32 size;
|
||||
|
||||
size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB);
|
||||
/* system resident memory, don't free */
|
||||
g_allQueue = (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, size);
|
||||
if (g_allQueue == NULL) {
|
||||
return LOS_ERRNO_QUEUE_NO_MEMORY;
|
||||
}
|
||||
(VOID)memset_s(g_allQueue, size, 0, size);
|
||||
LOS_ListInit(&g_freeQueueList);
|
||||
for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
|
||||
queueNode = ((LosQueueCB *)g_allQueue) + index;
|
||||
queueNode->queueID = index;
|
||||
LOS_ListTailInsert(&g_freeQueueList, &queueNode->readWriteList[OS_QUEUE_WRITE]);
|
||||
}
|
||||
|
||||
if (OsQueueDbgInitHook() != LOS_OK) {
|
||||
return LOS_ERRNO_QUEUE_NO_MEMORY;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName, UINT16 len, UINT32 *queueID,
|
||||
UINT32 flags, UINT16 maxMsgSize)
|
||||
{
|
||||
LosQueueCB *queueCB = NULL;
|
||||
UINT32 intSave;
|
||||
LOS_DL_LIST *unusedQueue = NULL;
|
||||
UINT8 *queue = NULL;
|
||||
UINT16 msgSize;
|
||||
|
||||
(VOID)queueName;
|
||||
(VOID)flags;
|
||||
|
||||
if (queueID == NULL) {
|
||||
return LOS_ERRNO_QUEUE_CREAT_PTR_NULL;
|
||||
}
|
||||
|
||||
if (maxMsgSize > (OS_NULL_SHORT - sizeof(UINT32))) {
|
||||
return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;
|
||||
}
|
||||
|
||||
if ((len == 0) || (maxMsgSize == 0)) {
|
||||
return LOS_ERRNO_QUEUE_PARA_ISZERO;
|
||||
}
|
||||
|
||||
msgSize = maxMsgSize + sizeof(UINT32);
|
||||
/*
|
||||
* Memory allocation is time-consuming, to shorten the time of disable interrupt,
|
||||
* move the memory allocation to here.
|
||||
*/
|
||||
queue = (UINT8 *)LOS_MemAlloc(m_aucSysMem1, (UINT32)len * msgSize);
|
||||
if (queue == NULL) {
|
||||
return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (LOS_ListEmpty(&g_freeQueueList)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OsQueueCheckHook();
|
||||
(VOID)LOS_MemFree(m_aucSysMem1, queue);
|
||||
return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
unusedQueue = LOS_DL_LIST_FIRST(&g_freeQueueList);
|
||||
LOS_ListDelete(unusedQueue);
|
||||
queueCB = GET_QUEUE_LIST(unusedQueue);
|
||||
queueCB->queueLen = len;
|
||||
queueCB->queueSize = msgSize;
|
||||
queueCB->queueHandle = queue;
|
||||
queueCB->queueState = OS_QUEUE_INUSED;
|
||||
queueCB->readWriteableCnt[OS_QUEUE_READ] = 0;
|
||||
queueCB->readWriteableCnt[OS_QUEUE_WRITE] = len;
|
||||
queueCB->queueHead = 0;
|
||||
queueCB->queueTail = 0;
|
||||
LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_READ]);
|
||||
LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_WRITE]);
|
||||
LOS_ListInit(&queueCB->memList);
|
||||
|
||||
OsQueueDbgUpdateHook(queueCB->queueID, OsCurrTaskGet()->taskEntry);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
*queueID = queueCB->queueID;
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC LITE_OS_SEC_TEXT UINT32 OsQueueReadParameterCheck(UINT32 queueID, const VOID *bufferAddr,
|
||||
const UINT32 *bufferSize, UINT32 timeout)
|
||||
{
|
||||
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_INVALID;
|
||||
}
|
||||
if ((bufferAddr == NULL) || (bufferSize == NULL)) {
|
||||
return LOS_ERRNO_QUEUE_READ_PTR_NULL;
|
||||
}
|
||||
|
||||
if ((*bufferSize == 0) || (*bufferSize > (OS_NULL_SHORT - sizeof(UINT32)))) {
|
||||
return LOS_ERRNO_QUEUE_READSIZE_IS_INVALID;
|
||||
}
|
||||
|
||||
OsQueueDbgTimeUpdateHook(queueID);
|
||||
|
||||
if (timeout != LOS_NO_WAIT) {
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_QUEUE_READ_IN_INTERRUPT;
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC LITE_OS_SEC_TEXT UINT32 OsQueueWriteParameterCheck(UINT32 queueID, const VOID *bufferAddr,
|
||||
const UINT32 *bufferSize, UINT32 timeout)
|
||||
{
|
||||
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_INVALID;
|
||||
}
|
||||
|
||||
if (bufferAddr == NULL) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
|
||||
}
|
||||
|
||||
if (*bufferSize == 0) {
|
||||
return LOS_ERRNO_QUEUE_WRITESIZE_ISZERO;
|
||||
}
|
||||
|
||||
OsQueueDbgTimeUpdateHook(queueID);
|
||||
|
||||
if (timeout != LOS_NO_WAIT) {
|
||||
if (OS_INT_ACTIVE) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT;
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize)
|
||||
{
|
||||
UINT8 *queueNode = NULL;
|
||||
UINT32 msgDataSize;
|
||||
UINT16 queuePosion;
|
||||
|
||||
/* get the queue position */
|
||||
switch (OS_QUEUE_OPERATE_GET(operateType)) {
|
||||
case OS_QUEUE_READ_HEAD:
|
||||
queuePosion = queueCB->queueHead;
|
||||
((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
|
||||
break;
|
||||
case OS_QUEUE_WRITE_HEAD:
|
||||
(queueCB->queueHead == 0) ? (queueCB->queueHead = queueCB->queueLen - 1) : (--queueCB->queueHead);
|
||||
queuePosion = queueCB->queueHead;
|
||||
break;
|
||||
case OS_QUEUE_WRITE_TAIL:
|
||||
queuePosion = queueCB->queueTail;
|
||||
((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
|
||||
break;
|
||||
default: /* read tail, reserved. */
|
||||
PRINT_ERR("invalid queue operate type!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
queueNode = &(queueCB->queueHandle[(queuePosion * (queueCB->queueSize))]);
|
||||
|
||||
if (OS_QUEUE_IS_READ(operateType)) {
|
||||
if (memcpy_s(&msgDataSize, sizeof(UINT32), queueNode + queueCB->queueSize - sizeof(UINT32),
|
||||
sizeof(UINT32)) != EOK) {
|
||||
PRINT_ERR("get msgdatasize failed\n");
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(bufferAddr, *bufferSize, queueNode, msgDataSize) != EOK) {
|
||||
PRINT_ERR("copy message to buffer failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
*bufferSize = msgDataSize;
|
||||
} else {
|
||||
if (memcpy_s(queueNode, queueCB->queueSize, bufferAddr, *bufferSize) != EOK) {
|
||||
PRINT_ERR("store message failed\n");
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(queueNode + queueCB->queueSize - sizeof(UINT32), sizeof(UINT32), bufferSize,
|
||||
sizeof(UINT32)) != EOK) {
|
||||
PRINT_ERR("store message size failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 queueID,
|
||||
UINT32 operateType, const UINT32 *bufferSize)
|
||||
{
|
||||
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
|
||||
return LOS_ERRNO_QUEUE_NOT_CREATE;
|
||||
}
|
||||
|
||||
if (OS_QUEUE_IS_READ(operateType) && (*bufferSize < (queueCB->queueSize - sizeof(UINT32)))) {
|
||||
return LOS_ERRNO_QUEUE_READ_SIZE_TOO_SMALL;
|
||||
} else if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout)
|
||||
{
|
||||
LosQueueCB *queueCB = NULL;
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
UINT32 ret;
|
||||
UINT32 readWrite = OS_QUEUE_READ_WRITE_GET(operateType);
|
||||
UINT32 intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
ret = OsQueueOperateParamCheck(queueCB, queueID, operateType, bufferSize);
|
||||
if (ret != LOS_OK) {
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if (queueCB->readWriteableCnt[readWrite] == 0) {
|
||||
if (timeout == LOS_NO_WAIT) {
|
||||
ret = OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if (!OsPreemptableInSched()) {
|
||||
ret = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
ret = OsTaskWait(&queueCB->readWriteList[readWrite], timeout, TRUE);
|
||||
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
|
||||
ret = LOS_ERRNO_QUEUE_TIMEOUT;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
} else {
|
||||
queueCB->readWriteableCnt[readWrite]--;
|
||||
}
|
||||
|
||||
OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->readWriteList[!readWrite])) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[!readWrite]));
|
||||
OsTaskWake(resumedTask);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
return LOS_OK;
|
||||
} else {
|
||||
queueCB->readWriteableCnt[!readWrite]++;
|
||||
}
|
||||
|
||||
QUEUE_END:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID,
|
||||
VOID *bufferAddr,
|
||||
UINT32 *bufferSize,
|
||||
UINT32 timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 operateType;
|
||||
|
||||
ret = OsQueueReadParameterCheck(queueID, bufferAddr, bufferSize, timeout);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD);
|
||||
return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueID,
|
||||
VOID *bufferAddr,
|
||||
UINT32 bufferSize,
|
||||
UINT32 timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 operateType;
|
||||
|
||||
ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeout);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_HEAD);
|
||||
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueID,
|
||||
VOID *bufferAddr,
|
||||
UINT32 bufferSize,
|
||||
UINT32 timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 operateType;
|
||||
|
||||
ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeout);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL);
|
||||
return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout)
|
||||
{
|
||||
return LOS_QueueReadCopy(queueID, bufferAddr, &bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout)
|
||||
{
|
||||
if (bufferAddr == NULL) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
|
||||
}
|
||||
bufferSize = sizeof(CHAR *);
|
||||
return LOS_QueueWriteCopy(queueID, &bufferAddr, bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueID,
|
||||
VOID *bufferAddr,
|
||||
UINT32 bufferSize,
|
||||
UINT32 timeout)
|
||||
{
|
||||
if (bufferAddr == NULL) {
|
||||
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
|
||||
}
|
||||
bufferSize = sizeof(CHAR *);
|
||||
return LOS_QueueWriteHeadCopy(queueID, &bufferAddr, bufferSize, timeout);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
|
||||
{
|
||||
LosQueueCB *queueCB = NULL;
|
||||
UINT8 *queue = NULL;
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_NOT_FOUND;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
|
||||
ret = LOS_ERRNO_QUEUE_NOT_CREATE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_READ])) {
|
||||
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_WRITE])) {
|
||||
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&queueCB->memList)) {
|
||||
ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
if ((queueCB->readWriteableCnt[OS_QUEUE_WRITE] + queueCB->readWriteableCnt[OS_QUEUE_READ]) !=
|
||||
queueCB->queueLen) {
|
||||
ret = LOS_ERRNO_QUEUE_IN_TSKWRITE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
queue = queueCB->queueHandle;
|
||||
queueCB->queueHandle = NULL;
|
||||
queueCB->queueState = OS_QUEUE_UNUSED;
|
||||
queueCB->queueID = SET_QUEUE_ID(GET_QUEUE_COUNT(queueCB->queueID) + 1, GET_QUEUE_INDEX(queueCB->queueID));
|
||||
OsQueueDbgUpdateHook(queueCB->queueID, NULL);
|
||||
|
||||
LOS_ListTailInsert(&g_freeQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
ret = LOS_MemFree(m_aucSysMem1, (VOID *)queue);
|
||||
return ret;
|
||||
|
||||
QUEUE_END:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT32 ret = LOS_OK;
|
||||
LosQueueCB *queueCB = NULL;
|
||||
LosTaskCB *tskCB = NULL;
|
||||
|
||||
if (queueInfo == NULL) {
|
||||
return LOS_ERRNO_QUEUE_PTR_NULL;
|
||||
}
|
||||
|
||||
if (GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {
|
||||
return LOS_ERRNO_QUEUE_INVALID;
|
||||
}
|
||||
|
||||
(VOID)memset_s((VOID *)queueInfo, sizeof(QUEUE_INFO_S), 0, sizeof(QUEUE_INFO_S));
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
|
||||
if ((queueCB->queueID != queueID) || (queueCB->queueState == OS_QUEUE_UNUSED)) {
|
||||
ret = LOS_ERRNO_QUEUE_NOT_CREATE;
|
||||
goto QUEUE_END;
|
||||
}
|
||||
|
||||
queueInfo->uwQueueID = queueID;
|
||||
queueInfo->usQueueLen = queueCB->queueLen;
|
||||
queueInfo->usQueueSize = queueCB->queueSize;
|
||||
queueInfo->usQueueHead = queueCB->queueHead;
|
||||
queueInfo->usQueueTail = queueCB->queueTail;
|
||||
queueInfo->usReadableCnt = queueCB->readWriteableCnt[OS_QUEUE_READ];
|
||||
queueInfo->usWritableCnt = queueCB->readWriteableCnt[OS_QUEUE_WRITE];
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_READ], LosTaskCB, pendList) {
|
||||
queueInfo->uwWaitReadTask |= 1ULL << tskCB->taskID;
|
||||
}
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_WRITE], LosTaskCB, pendList) {
|
||||
queueInfo->uwWaitWriteTask |= 1ULL << tskCB->taskID;
|
||||
}
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->memList, LosTaskCB, pendList) {
|
||||
queueInfo->uwWaitMemTask |= 1ULL << tskCB->taskID;
|
||||
}
|
||||
|
||||
QUEUE_END:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* (LOSCFG_BASE_IPC_QUEUE == YES) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
208
kernel/base/ipc/los_queue_debug.c
Executable file
208
kernel/base/ipc/los_queue_debug.c
Executable file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_queue_debug_pri.h"
|
||||
#include "los_hw_pri.h"
|
||||
#include "los_ipcdebug_pri.h"
|
||||
#ifdef LOSCFG_SHELL
|
||||
#include "shcmd.h"
|
||||
#endif /* LOSCFG_SHELL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef LOSCFG_DEBUG_QUEUE
|
||||
|
||||
typedef struct {
|
||||
TSK_ENTRY_FUNC creater; /* The task entry who created this queue */
|
||||
UINT64 lastAccessTime; /* The last access time */
|
||||
} QueueDebugCB;
|
||||
STATIC QueueDebugCB *g_queueDebugArray = NULL;
|
||||
|
||||
STATIC BOOL QueueCompareValue(const IpcSortParam *sortParam, UINT32 left, UINT32 right)
|
||||
{
|
||||
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
|
||||
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
|
||||
}
|
||||
|
||||
UINT32 OsQueueDbgInit(VOID)
|
||||
{
|
||||
UINT32 size = LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(QueueDebugCB);
|
||||
/* system resident memory, don't free */
|
||||
g_queueDebugArray = (QueueDebugCB *)LOS_MemAlloc(m_aucSysMem1, size);
|
||||
if (g_queueDebugArray == NULL) {
|
||||
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
|
||||
return LOS_NOK;
|
||||
}
|
||||
(VOID)memset_s(g_queueDebugArray, size, 0, size);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
VOID OsQueueDbgTimeUpdate(UINT32 queueID)
|
||||
{
|
||||
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueID)];
|
||||
queueDebug->lastAccessTime = LOS_TickCountGet();
|
||||
return;
|
||||
}
|
||||
|
||||
VOID OsQueueDbgUpdate(UINT32 queueID, TSK_ENTRY_FUNC entry)
|
||||
{
|
||||
QueueDebugCB *queueDebug = &g_queueDebugArray[GET_QUEUE_INDEX(queueID)];
|
||||
queueDebug->creater = entry;
|
||||
queueDebug->lastAccessTime = LOS_TickCountGet();
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsQueueInfoOutPut(const LosQueueCB *node)
|
||||
{
|
||||
PRINTK("Queue ID <0x%x> may leak, queue len is 0x%x, "
|
||||
"readable cnt:0x%x, writeable cnt:0x%x, ",
|
||||
node->queueID,
|
||||
node->queueLen,
|
||||
node->readWriteableCnt[OS_QUEUE_READ],
|
||||
node->readWriteableCnt[OS_QUEUE_WRITE]);
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsQueueOpsOutput(const QueueDebugCB *node)
|
||||
{
|
||||
PRINTK("TaskEntry of creater:0x%p, Latest operation time: 0x%llx\n",
|
||||
node->creater, node->lastAccessTime);
|
||||
}
|
||||
|
||||
STATIC VOID SortQueueIndexArray(UINT32 *indexArray, UINT32 count)
|
||||
{
|
||||
LosQueueCB queueNode = {0};
|
||||
QueueDebugCB queueDebugNode = {0};
|
||||
UINT32 index, intSave;
|
||||
IpcSortParam queueSortParam;
|
||||
queueSortParam.buf = (CHAR *)g_queueDebugArray;
|
||||
queueSortParam.ipcDebugCBSize = sizeof(QueueDebugCB);
|
||||
queueSortParam.ipcDebugCBCnt = LOSCFG_BASE_IPC_SEM_LIMIT;
|
||||
queueSortParam.sortElemOff = OFFSET_OF_FIELD(QueueDebugCB, lastAccessTime);
|
||||
|
||||
if (count > 0) {
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsArraySortByTime(indexArray, 0, count - 1, &queueSortParam, QueueCompareValue);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
for (index = 0; index < count; index++) {
|
||||
SCHEDULER_LOCK(intSave);
|
||||
(VOID)memcpy_s(&queueNode, sizeof(LosQueueCB),
|
||||
GET_QUEUE_HANDLE(indexArray[index]), sizeof(LosQueueCB));
|
||||
(VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB),
|
||||
&g_queueDebugArray[indexArray[index]], sizeof(QueueDebugCB));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if (queueNode.queueState == OS_QUEUE_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
OsQueueInfoOutPut(&queueNode);
|
||||
OsQueueOpsOutput(&queueDebugNode);
|
||||
}
|
||||
}
|
||||
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, indexArray);
|
||||
}
|
||||
|
||||
VOID OsQueueCheck(VOID)
|
||||
{
|
||||
LosQueueCB queueNode = {0};
|
||||
QueueDebugCB queueDebugNode = {0};
|
||||
UINT32 index, intSave;
|
||||
UINT32 count = 0;
|
||||
|
||||
/*
|
||||
* This return value does not need to be judged immediately,
|
||||
* and the following code logic has already distinguished the return value from null and non-empty,
|
||||
* and there is no case of accessing the null pointer.
|
||||
*/
|
||||
UINT32 *indexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(UINT32));
|
||||
|
||||
for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
|
||||
SCHEDULER_LOCK(intSave);
|
||||
(VOID)memcpy_s(&queueNode, sizeof(LosQueueCB),
|
||||
GET_QUEUE_HANDLE(index), sizeof(LosQueueCB));
|
||||
(VOID)memcpy_s(&queueDebugNode, sizeof(QueueDebugCB),
|
||||
&g_queueDebugArray[index], sizeof(QueueDebugCB));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if ((queueNode.queueState == OS_QUEUE_UNUSED) ||
|
||||
((queueNode.queueState == OS_QUEUE_INUSED) && (queueDebugNode.creater == NULL))) {
|
||||
continue;
|
||||
}
|
||||
if ((queueNode.queueState == OS_QUEUE_INUSED) &&
|
||||
(queueNode.queueLen == queueNode.readWriteableCnt[OS_QUEUE_WRITE]) &&
|
||||
LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_READ]) &&
|
||||
LOS_ListEmpty(&queueNode.readWriteList[OS_QUEUE_WRITE]) &&
|
||||
LOS_ListEmpty(&queueNode.memList)) {
|
||||
PRINTK("Queue ID <0x%x> may leak, No task uses it, "
|
||||
"QueueLen is 0x%x, ",
|
||||
queueNode.queueID,
|
||||
queueNode.queueLen);
|
||||
OsQueueOpsOutput(&queueDebugNode);
|
||||
} else {
|
||||
if (indexArray != NULL) {
|
||||
*(indexArray + count) = index;
|
||||
count++;
|
||||
} else {
|
||||
OsQueueInfoOutPut(&queueNode);
|
||||
OsQueueOpsOutput(&queueDebugNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (indexArray != NULL) {
|
||||
SortQueueIndexArray(indexArray, count);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_SHELL_CMD_DEBUG
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdQueueInfoGet(UINT32 argc, const CHAR **argv)
|
||||
{
|
||||
if (argc > 0) {
|
||||
PRINTK("\nUsage: queue\n");
|
||||
return OS_ERROR;
|
||||
}
|
||||
PRINTK("used queues information: \n");
|
||||
OsQueueCheck();
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
SHELLCMD_ENTRY(queue_shellcmd, CMD_TYPE_EX, "queue", 0, (CmdCallBackFunc)OsShellCmdQueueInfoGet);
|
||||
#endif /* LOSCFG_SHELL */
|
||||
#endif /* LOSCFG_DEBUG_QUEUE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
298
kernel/base/ipc/los_sem.c
Executable file
298
kernel/base/ipc/los_sem.c
Executable file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_sem_pri.h"
|
||||
#include "los_sem_debug_pri.h"
|
||||
#include "los_err_pri.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "los_exc.h"
|
||||
#include "los_spinlock.h"
|
||||
#include "los_mp.h"
|
||||
#include "los_percpu_pri.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if (LOSCFG_BASE_IPC_SEM == YES)
|
||||
|
||||
#if (LOSCFG_BASE_IPC_SEM_LIMIT <= 0)
|
||||
#error "sem maxnum cannot be zero"
|
||||
#endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */
|
||||
|
||||
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList;
|
||||
LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;
|
||||
|
||||
/*
|
||||
* Description : Initialize the semaphore doubly linked list
|
||||
* Return : LOS_OK on success, or error code on failure
|
||||
*/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)
|
||||
{
|
||||
LosSemCB *semNode = NULL;
|
||||
UINT32 index;
|
||||
|
||||
LOS_ListInit(&g_unusedSemList);
|
||||
/* system resident memory, don't free */
|
||||
g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));
|
||||
if (g_allSem == NULL) {
|
||||
return LOS_ERRNO_SEM_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) {
|
||||
semNode = ((LosSemCB *)g_allSem) + index;
|
||||
semNode->semID = SET_SEM_ID(0, index);
|
||||
semNode->semStat = OS_SEM_UNUSED;
|
||||
LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);
|
||||
}
|
||||
|
||||
if (OsSemDbgInitHook() != LOS_OK) {
|
||||
return LOS_ERRNO_SEM_NO_MEMORY;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Description : Create a semaphore,
|
||||
* Input : count --- semaphore count,
|
||||
* maxCount --- Max number of available semaphores,
|
||||
* semHandle --- Index of semaphore,
|
||||
* Return : LOS_OK on success ,or error code on failure
|
||||
*/
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semCreated = NULL;
|
||||
LOS_DL_LIST *unusedSem = NULL;
|
||||
UINT32 errNo;
|
||||
UINT32 errLine;
|
||||
|
||||
if (semHandle == NULL) {
|
||||
return LOS_ERRNO_SEM_PTR_NULL;
|
||||
}
|
||||
|
||||
if (count > maxCount) {
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW);
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
if (LOS_ListEmpty(&g_unusedSemList)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OsSemInfoGetFullDataHook();
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY);
|
||||
}
|
||||
|
||||
unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList);
|
||||
LOS_ListDelete(unusedSem);
|
||||
semCreated = GET_SEM_LIST(unusedSem);
|
||||
semCreated->semCount = count;
|
||||
semCreated->semStat = OS_SEM_USED;
|
||||
semCreated->maxSemCount = maxCount;
|
||||
LOS_ListInit(&semCreated->semList);
|
||||
*semHandle = semCreated->semID;
|
||||
|
||||
OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count);
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle)
|
||||
{
|
||||
return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle)
|
||||
{
|
||||
return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semDeleted = NULL;
|
||||
UINT32 errNo;
|
||||
UINT32 errLine;
|
||||
|
||||
if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
semDeleted = GET_SEM(semHandle);
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
if (!LOS_ListEmpty(&semDeleted->semList)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);
|
||||
}
|
||||
|
||||
LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);
|
||||
semDeleted->semStat = OS_SEM_UNUSED;
|
||||
semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));
|
||||
|
||||
OsSemDbgUpdateHook(semDeleted->semID, NULL, 0);
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
|
||||
ERR_HANDLER:
|
||||
OS_RETURN_ERROR_P2(errLine, errNo);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosSemCB *semPended = GET_SEM(semHandle);
|
||||
UINT32 retErr = LOS_OK;
|
||||
LosTaskCB *runTask = NULL;
|
||||
|
||||
if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
|
||||
}
|
||||
|
||||
if (OS_INT_ACTIVE) {
|
||||
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n");
|
||||
OsBackTrace();
|
||||
return LOS_ERRNO_SEM_PEND_INTERR;
|
||||
}
|
||||
|
||||
runTask = OsCurrTaskGet();
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
|
||||
OsBackTrace();
|
||||
return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
if ((semPended->semStat == OS_SEM_UNUSED) || (semPended->semID != semHandle)) {
|
||||
retErr = LOS_ERRNO_SEM_INVALID;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
/* Update the operate time, no matter the actual Pend success or not */
|
||||
OsSemDbgTimeUpdateHook(semHandle);
|
||||
|
||||
if (semPended->semCount > 0) {
|
||||
semPended->semCount--;
|
||||
goto OUT;
|
||||
} else if (!timeout) {
|
||||
retErr = LOS_ERRNO_SEM_UNAVAILABLE;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (!OsPreemptableInSched()) {
|
||||
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n");
|
||||
OsBackTrace();
|
||||
retErr = LOS_ERRNO_SEM_PEND_IN_LOCK;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
runTask->taskSem = (VOID *)semPended;
|
||||
retErr = OsTaskWait(&semPended->semList, timeout, TRUE);
|
||||
if (retErr == LOS_ERRNO_TSK_TIMEOUT) {
|
||||
runTask->taskSem = NULL;
|
||||
retErr = LOS_ERRNO_SEM_TIMEOUT;
|
||||
}
|
||||
|
||||
OUT:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return retErr;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
|
||||
{
|
||||
LosSemCB *semPosted = NULL;
|
||||
LosTaskCB *resumedTask = NULL;
|
||||
|
||||
if (GET_SEM_INDEX(semHandle) >= LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
return LOS_ERRNO_SEM_INVALID;
|
||||
}
|
||||
|
||||
semPosted = GET_SEM(semHandle);
|
||||
if ((semPosted->semID != semHandle) || (semPosted->semStat == OS_SEM_UNUSED)) {
|
||||
return LOS_ERRNO_SEM_INVALID;
|
||||
}
|
||||
|
||||
/* Update the operate time, no matter the actual Post success or not */
|
||||
OsSemDbgTimeUpdateHook(semHandle);
|
||||
|
||||
if (semPosted->semCount == OS_SEM_COUNT_MAX) {
|
||||
return LOS_ERRNO_SEM_OVERFLOW;
|
||||
}
|
||||
if (!LOS_ListEmpty(&semPosted->semList)) {
|
||||
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));
|
||||
resumedTask->taskSem = NULL;
|
||||
OsTaskWake(resumedTask);
|
||||
if (needSched != NULL) {
|
||||
*needSched = TRUE;
|
||||
}
|
||||
} else {
|
||||
semPosted->semCount++;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
BOOL needSched = FALSE;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsSemPostUnsafe(semHandle, &needSched);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if (needSched) {
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
LOS_Schedule();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* (LOSCFG_BASE_IPC_SEM == YES) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
311
kernel/base/ipc/los_sem_debug.c
Executable file
311
kernel/base/ipc/los_sem_debug.c
Executable file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_sem_debug_pri.h"
|
||||
#include "stdlib.h"
|
||||
#include "los_typedef.h"
|
||||
#include "los_task_pri.h"
|
||||
#include "los_ipcdebug_pri.h"
|
||||
#ifdef LOSCFG_SHELL
|
||||
#include "shcmd.h"
|
||||
#endif /* LOSCFG_SHELL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define OS_ALL_SEM_MASK 0xffffffff
|
||||
|
||||
#if defined(LOSCFG_DEBUG_SEMAPHORE) || defined(LOSCFG_SHELL_CMD_DEBUG)
|
||||
STATIC VOID OsSemPendedTaskNamePrint(LosSemCB *semNode)
|
||||
{
|
||||
LosTaskCB *tskCB = NULL;
|
||||
CHAR *nameArr[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
|
||||
UINT32 i, intSave;
|
||||
UINT32 num = 0;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if ((semNode->semStat == OS_SEM_UNUSED) || (LOS_ListEmpty(&semNode->semList))) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return;
|
||||
}
|
||||
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &semNode->semList, LosTaskCB, pendList) {
|
||||
nameArr[num++] = tskCB->taskName;
|
||||
if (num == LOSCFG_BASE_CORE_TSK_LIMIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
PRINTK("Pended task list : ");
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i == 0) {
|
||||
PRINTK("%s\n", nameArr[i]);
|
||||
} else {
|
||||
PRINTK(", %s", nameArr[i]);
|
||||
}
|
||||
}
|
||||
PRINTK("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOSCFG_DEBUG_SEMAPHORE
|
||||
|
||||
typedef struct {
|
||||
UINT16 origSemCount; /* Number of orignal available semaphores */
|
||||
UINT64 lastAccessTime; /* The last operation time */
|
||||
TSK_ENTRY_FUNC creater; /* The task entry who created this sem */
|
||||
} SemDebugCB;
|
||||
STATIC SemDebugCB *g_semDebugArray = NULL;
|
||||
|
||||
STATIC BOOL SemCompareValue(const IpcSortParam *sortParam, UINT32 left, UINT32 right)
|
||||
{
|
||||
return (*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, left)) >
|
||||
*((UINT64 *)(VOID *)SORT_ELEM_ADDR(sortParam, right)));
|
||||
}
|
||||
|
||||
UINT32 OsSemDbgInit(VOID)
|
||||
{
|
||||
UINT32 size = LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(SemDebugCB);
|
||||
/* system resident memory, don't free */
|
||||
g_semDebugArray = (SemDebugCB *)LOS_MemAlloc(m_aucSysMem1, size);
|
||||
if (g_semDebugArray == NULL) {
|
||||
PRINT_ERR("%s: malloc failed!\n", __FUNCTION__);
|
||||
return LOS_NOK;
|
||||
}
|
||||
(VOID)memset_s(g_semDebugArray, size, 0, size);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
VOID OsSemDbgTimeUpdate(UINT32 semID)
|
||||
{
|
||||
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semID)];
|
||||
semDebug->lastAccessTime = LOS_TickCountGet();
|
||||
return;
|
||||
}
|
||||
|
||||
VOID OsSemDbgUpdate(UINT32 semID, TSK_ENTRY_FUNC creater, UINT16 count)
|
||||
{
|
||||
SemDebugCB *semDebug = &g_semDebugArray[GET_SEM_INDEX(semID)];
|
||||
semDebug->creater = creater;
|
||||
semDebug->lastAccessTime = LOS_TickCountGet();
|
||||
semDebug->origSemCount = count;
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC VOID OsSemSort(UINT32 *semIndexArray, UINT32 usedCount)
|
||||
{
|
||||
UINT32 i, intSave;
|
||||
LosSemCB *semCB = NULL;
|
||||
LosSemCB semNode = {0};
|
||||
SemDebugCB semDebug = {0};
|
||||
IpcSortParam semSortParam;
|
||||
semSortParam.buf = (CHAR *)g_semDebugArray;
|
||||
semSortParam.ipcDebugCBSize = sizeof(SemDebugCB);
|
||||
semSortParam.ipcDebugCBCnt = LOSCFG_BASE_IPC_SEM_LIMIT;
|
||||
semSortParam.sortElemOff = OFFSET_OF_FIELD(SemDebugCB, lastAccessTime);
|
||||
|
||||
/* It will Print out ALL the Used Semaphore List. */
|
||||
PRINTK("Used Semaphore List: \n");
|
||||
PRINTK("\r\n SemID Count OriginalCount Creater(TaskEntry) LastAccessTime\n");
|
||||
PRINTK(" ------ ------ ------------- ------------------ -------------- \n");
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsArraySortByTime(semIndexArray, 0, usedCount - 1, &semSortParam, SemCompareValue);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
for (i = 0; i < usedCount; i++) {
|
||||
semCB = GET_SEM(semIndexArray[i]);
|
||||
SCHEDULER_LOCK(intSave);
|
||||
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
|
||||
(VOID)memcpy_s(&semDebug, sizeof(SemDebugCB), &g_semDebugArray[semIndexArray[i]], sizeof(SemDebugCB));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if ((semNode.semStat != OS_SEM_USED) || (semDebug.creater == NULL)) {
|
||||
continue;
|
||||
}
|
||||
PRINTK(" 0x%-07x0x%-07u0x%-14u%-22p0x%llx\n", semNode.semID, semDebug.origSemCount,
|
||||
semNode.semCount, semDebug.creater, semDebug.lastAccessTime);
|
||||
if (!LOS_ListEmpty(&semNode.semList)) {
|
||||
OsSemPendedTaskNamePrint(semCB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 OsSemInfoGetFullData(VOID)
|
||||
{
|
||||
UINT32 usedSemCnt = 0;
|
||||
LosSemCB *semNode = NULL;
|
||||
SemDebugCB *semDebug = NULL;
|
||||
UINT32 i;
|
||||
UINT32 *semIndexArray = NULL;
|
||||
UINT32 count, intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
/* Get the used semaphore count. */
|
||||
for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) {
|
||||
semNode = GET_SEM(i);
|
||||
semDebug = &g_semDebugArray[i];
|
||||
if ((semNode->semStat == OS_SEM_USED) && (semDebug->creater != NULL)) {
|
||||
usedSemCnt++;
|
||||
}
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
if (usedSemCnt > 0) {
|
||||
semIndexArray = (UINT32 *)LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, usedSemCnt * sizeof(UINT32));
|
||||
if (semIndexArray == NULL) {
|
||||
PRINTK("LOS_MemAlloc failed in %s \n", __func__);
|
||||
return LOS_NOK;
|
||||
}
|
||||
|
||||
/* Fill the semIndexArray with the real index. */
|
||||
count = 0;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
for (i = 0; i < LOSCFG_BASE_IPC_SEM_LIMIT; i++) {
|
||||
semNode = GET_SEM(i);
|
||||
semDebug = &g_semDebugArray[i];
|
||||
if ((semNode->semStat != OS_SEM_USED) || (semDebug->creater == NULL)) {
|
||||
continue;
|
||||
}
|
||||
*(semIndexArray + count) = i;
|
||||
count++;
|
||||
/* if the count is touched usedSemCnt break. */
|
||||
if (count >= usedSemCnt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OsSemSort(semIndexArray, count);
|
||||
|
||||
/* free the index array. */
|
||||
(VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, semIndexArray);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
#endif /* LOSCFG_DEBUG_SEMAPHORE */
|
||||
|
||||
#ifdef LOSCFG_SHELL_CMD_DEBUG
|
||||
STATIC UINT32 OsSemInfoOutput(size_t semID)
|
||||
{
|
||||
UINT32 loop, semCnt, intSave;
|
||||
LosSemCB *semCB = NULL;
|
||||
LosSemCB semNode = {0};
|
||||
|
||||
if (semID == OS_ALL_SEM_MASK) {
|
||||
for (loop = 0, semCnt = 0; loop < LOSCFG_BASE_IPC_SEM_LIMIT; loop++) {
|
||||
semCB = GET_SEM(loop);
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (semCB->semStat == OS_SEM_USED) {
|
||||
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
semCnt++;
|
||||
PRINTK("\r\n SemID Count\n ---------- -----\n");
|
||||
PRINTK(" 0x%08x %u\n", semNode.semID, semNode.semCount);
|
||||
continue;
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
PRINTK(" SemUsingNum : %u\n\n", semCnt);
|
||||
return LOS_OK;
|
||||
} else {
|
||||
if (GET_SEM_INDEX(semID) >= LOSCFG_BASE_IPC_SEM_LIMIT) {
|
||||
PRINTK("\nInvalid semphore id!\n");
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
semCB = GET_SEM(semID);
|
||||
SCHEDULER_LOCK(intSave);
|
||||
(VOID)memcpy_s(&semNode, sizeof(LosSemCB), semCB, sizeof(LosSemCB));
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
if ((semNode.semID != semID) || (semNode.semStat != OS_SEM_USED)) {
|
||||
PRINTK("\nThe semphore is not in use!\n");
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
PRINTK("\r\n SemID Count\n ---------- -----\n");
|
||||
PRINTK(" 0x%08x 0x%u\n", semNode.semID, semNode.semCount);
|
||||
|
||||
if (LOS_ListEmpty(&semNode.semList)) {
|
||||
PRINTK("No task is pended on this semphore!\n");
|
||||
return LOS_OK;
|
||||
} else {
|
||||
OsSemPendedTaskNamePrint(semCB);
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdSemInfoGet(UINT32 argc, const CHAR **argv)
|
||||
{
|
||||
size_t semID;
|
||||
CHAR *endPtr = NULL;
|
||||
UINT32 ret;
|
||||
|
||||
if (argc > 1) {
|
||||
#ifdef LOSCFG_DEBUG_SEMAPHORE
|
||||
PRINTK("\nUsage: sem [fulldata|ID]\n");
|
||||
#else
|
||||
PRINTK("\nUsage: sem [ID]\n");
|
||||
#endif
|
||||
return OS_ERROR;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
semID = OS_ALL_SEM_MASK;
|
||||
} else {
|
||||
#ifdef LOSCFG_DEBUG_SEMAPHORE
|
||||
if (strcmp(argv[0], "fulldata") == 0) {
|
||||
ret = OsSemInfoGetFullData();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
semID = strtoul(argv[0], &endPtr, 0);
|
||||
if ((endPtr == NULL) || (*endPtr != 0)) {
|
||||
PRINTK("\nsem ID can't access %s.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = OsSemInfoOutput(semID);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SHELLCMD_ENTRY(sem_shellcmd, CMD_TYPE_EX, "sem", 1, (CmdCallBackFunc)OsShellCmdSemInfoGet);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
691
kernel/base/ipc/los_signal.c
Executable file
691
kernel/base/ipc/los_signal.c
Executable file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_signal.h"
|
||||
#include "pthread.h"
|
||||
#include "los_process_pri.h"
|
||||
#include "los_hw_pri.h"
|
||||
#include "user_copy.h"
|
||||
#ifdef LOSCFG_SECURITY_CAPABILITY
|
||||
#include "capability_api.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int raise(int sig)
|
||||
{
|
||||
(VOID)sig;
|
||||
PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
|
||||
#define UINT64_BIT_SIZE 64
|
||||
|
||||
int OsSigIsMember(const sigset_t *set, int signo)
|
||||
{
|
||||
int ret = LOS_NOK;
|
||||
/* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
|
||||
signo -= 1;
|
||||
/* Verify the signal */
|
||||
if (GOOD_SIGNO(signo)) {
|
||||
/* Check if the signal is in the set */
|
||||
ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
|
||||
{
|
||||
bool masked = FALSE;
|
||||
sig_cb *sigcb = &stcb->sig;
|
||||
|
||||
OS_RETURN_IF_NULL(sigcb);
|
||||
/* If signo is 0, not send signal, just check process or pthread exist */
|
||||
if (info->si_signo == 0) {
|
||||
return 0;
|
||||
}
|
||||
masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);
|
||||
if (masked) {
|
||||
/* If signal is in wait list and mask list, need unblock it */
|
||||
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) {
|
||||
OsTaskWake(stcb);
|
||||
OsSigEmptySet(&sigcb->sigwaitmask);
|
||||
} else {
|
||||
OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);
|
||||
}
|
||||
} else {
|
||||
/* unmasked signal actions */
|
||||
OsSigAddSet(&sigcb->sigFlag, info->si_signo);
|
||||
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->si_signo)) {
|
||||
OsTaskWake(stcb);
|
||||
OsSigEmptySet(&sigcb->sigwaitmask);
|
||||
}
|
||||
}
|
||||
(void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
|
||||
{
|
||||
sigset_t unmaskset;
|
||||
|
||||
rtcb->sig.sigprocmask = set;
|
||||
unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);
|
||||
if (unmaskset != NULL_SIGNAL_SET) {
|
||||
/* pendlist do */
|
||||
rtcb->sig.sigFlag |= unmaskset;
|
||||
rtcb->sig.sigPendFlag ^= unmaskset;
|
||||
}
|
||||
}
|
||||
|
||||
int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset)
|
||||
{
|
||||
LosTaskCB *spcb = NULL;
|
||||
sigset_t oldSigprocmask;
|
||||
int ret = LOS_OK;
|
||||
unsigned int intSave;
|
||||
sigset_t set;
|
||||
int retVal;
|
||||
|
||||
if (setl != NULL) {
|
||||
retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t));
|
||||
if (retVal != 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
SCHEDULER_LOCK(intSave);
|
||||
spcb = OsCurrTaskGet();
|
||||
/* If requested, copy the old mask to user. */
|
||||
oldSigprocmask = spcb->sig.sigprocmask;
|
||||
|
||||
/* If requested, modify the current signal mask. */
|
||||
if (setl != NULL) {
|
||||
/* Okay, determine what we are supposed to do */
|
||||
switch (how) {
|
||||
/* Set the union of the current set and the signal
|
||||
* set pointed to by set as the new sigprocmask.
|
||||
*/
|
||||
case SIG_BLOCK:
|
||||
spcb->sig.sigprocmask |= set;
|
||||
break;
|
||||
/* Set the intersection of the current set and the
|
||||
* signal set pointed to by set as the new sigprocmask.
|
||||
*/
|
||||
case SIG_UNBLOCK:
|
||||
spcb->sig.sigprocmask &= ~(set);
|
||||
break;
|
||||
/* Set the signal set pointed to by set as the new sigprocmask. */
|
||||
case SIG_SETMASK:
|
||||
spcb->sig.sigprocmask = set;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
/* If pending mask not in sigmask, need set sigflag. */
|
||||
OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
if (oldset != NULL) {
|
||||
retVal = LOS_ArchCopyToUser(&(oldset->sig[0]), &oldSigprocmask, sizeof(sigset_t));
|
||||
if (retVal != 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Visit the main thread last (if present) */
|
||||
LosTaskCB *taskCB = NULL;
|
||||
LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {
|
||||
ret = handler(taskCB, arg);
|
||||
OS_RETURN_IF(ret != 0, ret);
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
|
||||
{
|
||||
struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
|
||||
int ret;
|
||||
int isMember;
|
||||
|
||||
if (tcb == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the default tcb is not setted, then set this one as default. */
|
||||
if (!info->defaultTcb) {
|
||||
info->defaultTcb = tcb;
|
||||
}
|
||||
|
||||
isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);
|
||||
if (isMember && (!info->awakenedTcb)) {
|
||||
/* This means the task is waiting for this signal. Stop looking for it and use this tcb.
|
||||
* The requirement is: if more than one task in this task group is waiting for the signal,
|
||||
* then only one indeterminate task in the group will receive the signal.
|
||||
*/
|
||||
ret = OsTcbDispatch(tcb, info->sigInfo);
|
||||
OS_RETURN_IF(ret < 0, ret);
|
||||
|
||||
/* set this tcb as awakenedTcb */
|
||||
info->awakenedTcb = tcb;
|
||||
OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
|
||||
}
|
||||
/* Is this signal unblocked on this thread? */
|
||||
isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);
|
||||
if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {
|
||||
/* if unblockedTcb of this signal is not setted, then set it. */
|
||||
if (!info->unblockedTcb) {
|
||||
info->unblockedTcb = tcb;
|
||||
}
|
||||
|
||||
ret = OsTcbDispatch(tcb, info->sigInfo);
|
||||
OS_RETURN_IF(ret < 0, ret);
|
||||
/* set this tcb as receivedTcb */
|
||||
info->receivedTcb = tcb;
|
||||
OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
|
||||
}
|
||||
return 0; /* Keep searching */
|
||||
}
|
||||
|
||||
static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
|
||||
{
|
||||
struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
|
||||
|
||||
if ((tcb != NULL) && (info != NULL) && (info->sigInfo != NULL)) {
|
||||
sig_cb *sigcb = &tcb->sig;
|
||||
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, info->sigInfo->si_signo)) {
|
||||
OsTaskWake(tcb);
|
||||
OsSigEmptySet(&sigcb->sigwaitmask);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
|
||||
{
|
||||
LosTaskCB *tcb = NULL;
|
||||
|
||||
if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {
|
||||
if (info->unblockedTcb) {
|
||||
tcb = info->unblockedTcb;
|
||||
} else if (info->defaultTcb) {
|
||||
tcb = info->defaultTcb;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
/* Deliver the signal to the selected task */
|
||||
(void)OsTcbDispatch(tcb, sigInfo);
|
||||
}
|
||||
}
|
||||
|
||||
int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
|
||||
{
|
||||
int ret;
|
||||
struct ProcessSignalInfo info = {
|
||||
.sigInfo = sigInfo,
|
||||
.defaultTcb = NULL,
|
||||
.unblockedTcb = NULL,
|
||||
.awakenedTcb = NULL,
|
||||
.receivedTcb = NULL
|
||||
};
|
||||
|
||||
/* visit all taskcb and dispatch signal */
|
||||
if ((info.sigInfo != NULL) && (info.sigInfo->si_signo == SIGKILL)) {
|
||||
(void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
|
||||
OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);
|
||||
OsWaitSignalToWakeProcess(spcb);
|
||||
return 0;
|
||||
} else {
|
||||
ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
SigProcessLoadTcb(&info, sigInfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OsSigEmptySet(sigset_t *set)
|
||||
{
|
||||
*set = NULL_SIGNAL_SET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Privilege process can't send to kernel and privilege process */
|
||||
static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
|
||||
{
|
||||
UINT32 gid = spcb->group->groupID;
|
||||
|
||||
if (gid == OS_KERNEL_PROCESS_GROUP) {
|
||||
return -EPERM;
|
||||
} else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
|
||||
{
|
||||
LosProcessCB *spcb = OS_PCB_FROM_PID(pid);
|
||||
if (OsProcessIsUnused(spcb)) {
|
||||
return -ESRCH;
|
||||
}
|
||||
#ifdef LOSCFG_SECURITY_CAPABILITY
|
||||
LosProcessCB *current = OsCurrProcessGet();
|
||||
|
||||
/* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
|
||||
if (OsProcessIsInactive(spcb)) {
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/* Kernel process always has kill permission and user process should check permission */
|
||||
if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {
|
||||
if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
|
||||
return -EPERM;
|
||||
}
|
||||
return OsSigProcessSend(spcb, info);
|
||||
}
|
||||
|
||||
int OsKill(pid_t pid, int sig, int permission)
|
||||
{
|
||||
siginfo_t info;
|
||||
int ret;
|
||||
|
||||
/* Make sure that the para is valid */
|
||||
if (!GOOD_SIGNO(sig) || pid < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (OsProcessIDUserCheckInvalid(pid)) {
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/* Create the siginfo structure */
|
||||
info.si_signo = sig;
|
||||
info.si_code = SI_USER;
|
||||
info.si_value.sival_ptr = NULL;
|
||||
|
||||
/* Send the signal */
|
||||
ret = OsDispatch(pid, &info, permission);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsKillLock(pid_t pid, int sig)
|
||||
{
|
||||
int ret;
|
||||
unsigned int intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsPthreadKill(UINT32 tid, int signo)
|
||||
{
|
||||
LosTaskCB *stcb = NULL;
|
||||
siginfo_t info;
|
||||
|
||||
int ret;
|
||||
UINT32 intSave;
|
||||
|
||||
/* Make sure that the signal is valid */
|
||||
OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
|
||||
if (OS_TID_CHECK_INVALID(tid)) {
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/* Create the siginfo structure */
|
||||
info.si_signo = signo;
|
||||
info.si_code = SI_USER;
|
||||
info.si_value.sival_ptr = NULL;
|
||||
/* Keep things stationary through the following */
|
||||
SCHEDULER_LOCK(intSave);
|
||||
/* Get the TCB associated with the thread */
|
||||
stcb = OsGetTaskCB(tid);
|
||||
OS_GOTO_EXIT_IF(stcb == NULL, -ESRCH);
|
||||
|
||||
ret = OsUserTaskOperatePermissionsCheck(stcb);
|
||||
OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
|
||||
|
||||
/* Dispatch the signal to thread, bypassing normal task group thread
|
||||
* dispatch rules. */
|
||||
ret = OsTcbDispatch(stcb, &info);
|
||||
EXIT:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsSigAddSet(sigset_t *set, int signo)
|
||||
{
|
||||
/* Verify the signal */
|
||||
if (!GOOD_SIGNO(signo)) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
|
||||
signo -= 1;
|
||||
/* Add the signal to the set */
|
||||
*set |= SIGNO2SET((unsigned int)signo);
|
||||
return LOS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int OsSigPending(sigset_t *set)
|
||||
{
|
||||
LosTaskCB *tcb = NULL;
|
||||
unsigned int intSave;
|
||||
|
||||
if (set == NULL) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
tcb = OsCurrTaskGet();
|
||||
*set = tcb->sig.sigPendFlag;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC int FindFirstSetedBit(UINT64 n)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (n == 0) {
|
||||
return -1;
|
||||
}
|
||||
for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
|
||||
return (count < UINT64_BIT_SIZE) ? count : (-1);
|
||||
}
|
||||
|
||||
int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
|
||||
{
|
||||
LosTaskCB *task = NULL;
|
||||
sig_cb *sigcb = NULL;
|
||||
int ret;
|
||||
|
||||
task = OsCurrTaskGet();
|
||||
sigcb = &task->sig;
|
||||
|
||||
if (sigcb->waitList.pstNext == NULL) {
|
||||
LOS_ListInit(&sigcb->waitList);
|
||||
}
|
||||
/* If pendingflag & set > 0, shound clear pending flag */
|
||||
sigset_t clear = sigcb->sigPendFlag & *set;
|
||||
if (clear) {
|
||||
sigcb->sigPendFlag ^= clear;
|
||||
ret = FindFirstSetedBit((UINT64)clear) + 1;
|
||||
} else {
|
||||
OsSigAddSet(set, SIGKILL);
|
||||
OsSigAddSet(set, SIGSTOP);
|
||||
|
||||
sigcb->sigwaitmask |= *set;
|
||||
ret = OsTaskWait(&sigcb->waitList, timeout, TRUE);
|
||||
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
sigcb->sigwaitmask = NULL_SIGNAL_SET;
|
||||
}
|
||||
if (info != NULL) {
|
||||
(void) memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
|
||||
{
|
||||
int ret;
|
||||
unsigned int intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
|
||||
ret = OsSigTimedWaitNoLock(set, info, timeout);
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int OsPause(void)
|
||||
{
|
||||
LosTaskCB *spcb = NULL;
|
||||
sigset_t oldSigprocmask;
|
||||
|
||||
spcb = OsCurrTaskGet();
|
||||
oldSigprocmask = spcb->sig.sigprocmask;
|
||||
return OsSigSuspend(&oldSigprocmask);
|
||||
}
|
||||
|
||||
int OsSigSuspend(const sigset_t *set)
|
||||
{
|
||||
unsigned int intSave;
|
||||
LosTaskCB *rtcb = NULL;
|
||||
unsigned int sigTempProcMask;
|
||||
sigset_t setSuspend;
|
||||
int ret;
|
||||
|
||||
if (set == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
SCHEDULER_LOCK(intSave);
|
||||
rtcb = OsCurrTaskGet();
|
||||
sigTempProcMask = rtcb->sig.sigprocmask;
|
||||
|
||||
/* Wait signal calc */
|
||||
setSuspend = FULL_SIGNAL_SET & (~(*set));
|
||||
|
||||
/* If pending mask not in sigmask, need set sigflag */
|
||||
OsSigMaskSwitch(rtcb, *set);
|
||||
ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
|
||||
if (ret < 0) {
|
||||
PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
|
||||
}
|
||||
/* Restore old sigprocmask */
|
||||
OsSigMaskSwitch(rtcb, sigTempProcMask);
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
|
||||
{
|
||||
UINTPTR addr;
|
||||
sigaction_t action;
|
||||
|
||||
if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (sig == SIGSYS) {
|
||||
addr = OsGetSigHandler();
|
||||
if (addr == 0) {
|
||||
OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);
|
||||
return LOS_OK;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
void OsSaveSignalContext(unsigned int *sp)
|
||||
{
|
||||
UINTPTR sigHandler;
|
||||
UINT32 intSave;
|
||||
LosTaskCB *task = NULL;
|
||||
LosProcessCB *process = NULL;
|
||||
sig_cb *sigcb = NULL;
|
||||
unsigned long cpsr;
|
||||
|
||||
OS_RETURN_IF_VOID(sp == NULL);
|
||||
cpsr = OS_SYSCALL_GET_CPSR(sp);
|
||||
|
||||
OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));
|
||||
SCHEDULER_LOCK(intSave);
|
||||
task = OsCurrTaskGet();
|
||||
process = OsCurrProcessGet();
|
||||
sigcb = &task->sig;
|
||||
|
||||
if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
|
||||
sigHandler = OsGetSigHandler();
|
||||
if (sigHandler == 0) {
|
||||
sigcb->sigFlag = 0;
|
||||
process->sigShare = 0;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
|
||||
return;
|
||||
}
|
||||
/* One pthread do the share signal */
|
||||
sigcb->sigFlag |= process->sigShare;
|
||||
unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1;
|
||||
OsProcessExitCodeSignalSet(process, signo);
|
||||
sigcb->context.CPSR = cpsr;
|
||||
sigcb->context.PC = sp[REG_PC];
|
||||
sigcb->context.USP = sp[REG_SP];
|
||||
sigcb->context.ULR = sp[REG_LR];
|
||||
sigcb->context.R0 = sp[REG_R0];
|
||||
sigcb->context.R1 = sp[REG_R1];
|
||||
sigcb->context.R2 = sp[REG_R2];
|
||||
sigcb->context.R3 = sp[REG_R3];
|
||||
sigcb->context.R7 = sp[REG_R7];
|
||||
sigcb->context.R12 = sp[REG_R12];
|
||||
sp[REG_PC] = sigHandler;
|
||||
sp[REG_R0] = signo;
|
||||
sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
|
||||
/* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
|
||||
sigcb->sigFlag ^= 1ULL << (signo - 1);
|
||||
sigcb->context.count++;
|
||||
}
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
|
||||
void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7)
|
||||
{
|
||||
UINTPTR sigHandler;
|
||||
LosTaskCB *task = NULL;
|
||||
LosProcessCB *process = NULL;
|
||||
sig_cb *sigcb = NULL;
|
||||
unsigned long cpsr;
|
||||
UINT32 intSave;
|
||||
TaskIrqContext *context = (TaskIrqContext *)(sp);
|
||||
|
||||
OS_RETURN_IF_VOID(sp == NULL);
|
||||
cpsr = context->CPSR;
|
||||
OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
task = OsCurrTaskGet();
|
||||
process = OsCurrProcessGet();
|
||||
sigcb = &task->sig;
|
||||
if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
|
||||
sigHandler = OsGetSigHandler();
|
||||
if (sigHandler == 0) {
|
||||
sigcb->sigFlag = 0;
|
||||
process->sigShare = 0;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
PRINT_ERR("The current process pid =%d starts fail!\n", task->processID);
|
||||
return;
|
||||
}
|
||||
sigcb->sigFlag |= process->sigShare;
|
||||
unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1;
|
||||
OsProcessExitCodeSignalSet(process, signo);
|
||||
(VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize));
|
||||
sigcb->context.R7 = r7;
|
||||
context->PC = sigHandler;
|
||||
context->R0 = signo;
|
||||
context->R1 = (UINT32)(UINTPTR)sigcb->sigunbinfo.si_value.sival_ptr;
|
||||
/* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
|
||||
sigcb->sigFlag ^= 1ULL << (signo - 1);
|
||||
sigcb->context.count++;
|
||||
}
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
|
||||
void OsRestorSignalContext(unsigned int *sp)
|
||||
{
|
||||
LosTaskCB *task = NULL; /* Do not adjust this statement */
|
||||
LosProcessCB *process = NULL;
|
||||
sig_cb *sigcb = NULL;
|
||||
UINT32 intSave;
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
task = OsCurrTaskGet();
|
||||
sigcb = &task->sig;
|
||||
|
||||
if (sigcb->context.count != 1) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
PRINT_ERR("sig error count : %d\n", sigcb->context.count);
|
||||
return;
|
||||
}
|
||||
|
||||
process = OsCurrProcessGet();
|
||||
sp[REG_PC] = sigcb->context.PC;
|
||||
OS_SYSCALL_SET_CPSR(sp, sigcb->context.CPSR);
|
||||
sp[REG_SP] = sigcb->context.USP;
|
||||
sp[REG_LR] = sigcb->context.ULR;
|
||||
sp[REG_R0] = sigcb->context.R0;
|
||||
sp[REG_R1] = sigcb->context.R1;
|
||||
sp[REG_R2] = sigcb->context.R2;
|
||||
sp[REG_R3] = sigcb->context.R3;
|
||||
sp[REG_R7] = sigcb->context.R7;
|
||||
sp[REG_R12] = sigcb->context.R12;
|
||||
sigcb->context.count--;
|
||||
process->sigShare = 0;
|
||||
OsProcessExitCodeSignalClear(process);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
Reference in New Issue
Block a user