diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index 0ff89df5d68324ef513ce66a719cc96f80a88a31..67b7ab645d7de18c1646d20eb22e00fb71cf738a 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -498,6 +498,7 @@ LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB) OsTaskKernelResourcesToFree(syncSignal, topOfStack); SCHEDULER_LOCK(intSave); + OsClearSigInfoTmpList(&(taskCB->sig)); OsInsertTCBToFreeList(taskCB); SCHEDULER_UNLOCK(intSave); } diff --git a/kernel/base/include/los_signal.h b/kernel/base/include/los_signal.h index aa113374a98fc4c97dd2e5e06f52ba645333f6d6..eabc2b097e33f5780deb7ef4879436445f635767 100644 --- a/kernel/base/include/los_signal.h +++ b/kernel/base/include/los_signal.h @@ -132,6 +132,11 @@ struct sq_queue_s { }; typedef struct sq_queue_s sq_queue_t; +typedef struct SigInfoListNode { + struct SigInfoListNode *next; + siginfo_t info; +} SigInfoListNode; + typedef struct { sigset_t sigFlag; sigset_t sigPendFlag; @@ -140,6 +145,7 @@ typedef struct { LOS_DL_LIST waitList; sigset_t sigwaitmask; /* Waiting for pending signals */ siginfo_t sigunbinfo; /* Signal info when task unblocked */ + SigInfoListNode *tmpInfoListHead; /* Signal info List */ unsigned int sigIntLock; void *sigContext; unsigned int count; @@ -167,6 +173,7 @@ int OsSigSuspend(const sigset_t *set); VOID OsSigIntLock(VOID); VOID OsSigIntUnlock(VOID); INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo); +VOID OsClearSigInfoTmpList(sig_cb *sigcb); #ifdef __cplusplus #if __cplusplus diff --git a/kernel/base/ipc/los_signal.c b/kernel/base/ipc/los_signal.c index 0203722ac1263fb81dd2e889b3095566595418fc..b598cae638817394c3ebc32bf726a3342c76e610 100644 --- a/kernel/base/ipc/los_signal.c +++ b/kernel/base/ipc/los_signal.c @@ -67,11 +67,60 @@ int OsSigIsMember(const sigset_t *set, int signo) return ret; } +STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo) +{ + SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead; + SigInfoListNode **prevHook = &sigcb->tmpInfoListHead; + INT32 isFirstDel = 1; + while (tmpInfoNode != NULL) { + if (tmpInfoNode->info.si_signo == signo) { + /* In some case, many siginfos have same signo, only last one inserted list need copy to unbinfo. */ + if (isFirstDel) { + /* copy tmpinfo to unbinfo. */ + (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t)); + isFirstDel = 0; + } + /* delete tmpinfo from tmpList. */ + *prevHook = tmpInfoNode->next; + (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode); + tmpInfoNode = *prevHook; + continue; + } + prevHook = &tmpInfoNode->next; + tmpInfoNode = tmpInfoNode->next; + } + + return; +} + +STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info) +{ + SigInfoListNode *tmp = (SigInfoListNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(SigInfoListNode)); + if (tmp == NULL) { + return LOS_NOK; + } + (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t)); + tmp->next = sigcb->tmpInfoListHead; + sigcb->tmpInfoListHead = tmp; + + return LOS_OK; +} + +VOID OsClearSigInfoTmpList(sig_cb *sigcb) +{ + while (sigcb->tmpInfoListHead != NULL) { + SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead; + sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next; + (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode); + } +} + STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo) { sig_cb *sigcb = &taskCB->sig; if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) { + OsMoveTmpInfoToUnbInfo(sigcb, signo); OsTaskWakeClearPendMask(taskCB); OsSchedTaskWake(taskCB); OsSigEmptySet(&sigcb->sigwaitmask); @@ -141,7 +190,10 @@ int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info) /* unmasked signal actions */ OsSigAddSet(&sigcb->sigFlag, info->si_signo); } - (void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t)); + + if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) { + return -ENOMEM; + } return OsPendingTaskWake(stcb, info->si_signo); } @@ -516,6 +568,7 @@ int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout) if (clear) { sigcb->sigPendFlag ^= clear; ret = FindFirstSetedBit((UINT64)clear) + 1; + OsMoveTmpInfoToUnbInfo(sigcb, ret); } else { OsSigAddSet(set, SIGKILL); OsSigAddSet(set, SIGSTOP); @@ -529,7 +582,7 @@ int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout) sigcb->sigwaitmask = NULL_SIGNAL_SET; } if (info != NULL) { - (void) memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t)); + (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t)); } return ret; } @@ -669,6 +722,7 @@ VOID *OsSaveSignalContext(VOID *sp, VOID *newSp) sigcb->sigFlag |= process->sigShare; UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1; UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); + OsMoveTmpInfoToUnbInfo(sigcb, signo); OsProcessExitCodeSignalSet(process, signo); sigcb->sigContext = sp;