fix: 解决kill进程时无法保证进程的已持有的内核资源合理释放.

背景: 当前信号实现原理是在系统调用结束和中断结束时检查是否有信号处理,
      如果有信号处理就切去处理信号,信号处理结束后回来继续按原来流程执行。
问题:当用户态线程在执行系统调用或缺页异常时,运行在内核态,如果此时有信
      号需要处理,且该线程已经持有了部分内核资源(如:锁,内存等), 此时如
      果有中断发生,则在中断结束时,就会去处理该信号,此时用户态线程持有
      了内核未释放的资源跑到了用户态去运行,如果该线程在用户态出现问题,
      那么它持有的内核资源就无法被释放了。
方案:用户态线程在执行系统调用和缺页异常时暂时屏蔽信号,防止此时有中断去
      处理信号,等系统调用结束或缺页异常结束时再去处理信号。
解决的问题:
  1. 执行系统调用或缺页异常时屏蔽信号,防止中断去处理信号
  2.解决无法kill 因为用户态的锁、ipc等阻塞的用户态线程
  3.进程退出方式转变为: 依次通过kill去杀死该进程的所有线程

Close #I3S0N0

Change-Id: I0c48b9c89382826191b8a9326c71b57ba84124c2
This commit is contained in:
zhushengle 2021-05-20 19:51:25 +08:00 committed by zhushengle
parent 04ecd87a23
commit cf89f016e9
10 changed files with 293 additions and 217 deletions

View File

@ -173,6 +173,7 @@ OsIrqHandler:
POP_FPU_REGS R0
LDR R4, [SP, #0]
#ifdef LOSCFG_KERNEL_VM
/* Obtain the CPSR to determine the mode the system is in when the interrupt is triggered */
LDR R3, [SP, #(11 * 4)]
AND R1, R3, #CPSR_MASK_MODE
@ -187,6 +188,7 @@ OsIrqHandler:
BLX OsSaveSignalContext
MOV SP, R0
1:
#endif
ADD SP, SP, #(2 * 4)
/* load user sp and lr, and jump cpsr */
LDMFD SP, {R13, R14}^

View File

@ -220,7 +220,9 @@ UINT32 OsArmSharedPageFault(UINT32 excType, ExcContext *frame, UINT32 far, UINT3
pfFlags |= user ? VM_MAP_PF_FLAG_USER : 0;
pfFlags |= instructionFault ? VM_MAP_PF_FLAG_INSTRUCTION : 0;
pfFlags |= VM_MAP_PF_FLAG_NOT_PRESENT;
OsSigIntLock();
ret = OsVmPageFaultHandler(far, pfFlags, frame);
OsSigIntUnlock();
break;
}
default:
@ -537,7 +539,9 @@ STATIC VOID OsExcRestore(VOID)
STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
{
UINT32 intSave;
UINT32 currCpu = ArchCurrCpuid();
LosTaskCB *runTask = OsCurrTaskGet();
LosProcessCB *runProcess = OsCurrProcessGet();
if (g_excFromUserMode[ArchCurrCpuid()] == FALSE) {
@ -565,16 +569,28 @@ STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
#endif
#endif
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_SAVE_EXCINFO
OsProcessExitCodeCoreDumpSet(runProcess);
#endif
OsProcessExitCodeSignalSet(runProcess, SIGUSR2);
/* Exception handling All operations should be kept prior to that operation */
OsExcRestore();
/* An exception was raised by a task that is not the current main thread during the exit process of
* the current process.
*/
if ((runProcess->processStatus & OS_PROCESS_FLAG_EXIT) && (runProcess->threadGroupID != runTask->taskID)) {
SCHEDULER_UNLOCK(intSave);
/* Exception handling All operations should be kept prior to that operation */
OsExcRestore();
OsTaskToExit(runTask, OS_PRO_EXIT_OK);
} else {
SCHEDULER_UNLOCK(intSave);
/* kill user exc process */
LOS_Exit(OS_PRO_EXIT_OK);
/* Exception handling All operations should be kept prior to that operation */
OsExcRestore();
/* kill user exc process */
LOS_Exit(OS_PRO_EXIT_OK);
}
/* User mode exception handling failed , which normally does not exist */
g_curNestCount[currCpu]++;
@ -940,7 +956,6 @@ STATIC VOID WaitAllCpuStop(UINT32 cpuID)
STATIC VOID OsWaitOtherCoresHandleExcEnd(UINT32 currCpuID)
{
OsProcessSuspendAllTask();
while (1) {
LOS_SpinLock(&g_excSerializerSpin);
if ((g_currHandleExcCpuID == INVALID_CPUID) || (g_currHandleExcCpuID == currCpuID)) {
@ -967,6 +982,7 @@ STATIC VOID OsCheckAllCpuStatus(VOID)
LOCKDEP_CLEAR_LOCKS();
LOS_SpinLock(&g_excSerializerSpin);
/* Only the current nuclear anomaly */
if (g_currHandleExcCpuID == INVALID_CPUID) {
g_currHandleExcCpuID = currCpuID;
g_currHandleExcPID = OsCurrProcessGet()->processID;
@ -976,13 +992,14 @@ STATIC VOID OsCheckAllCpuStatus(VOID)
HalIrqSendIpi(target, LOS_MP_IPI_HALT);
}
} else if (g_excFromUserMode[currCpuID] == TRUE) {
/* Both cores raise exceptions, and the current core is a user-mode exception.
* Both cores are abnormal and come from the same process
*/
if (OsCurrProcessGet()->processID == g_currHandleExcPID) {
LOS_SpinUnlock(&g_excSerializerSpin);
OsExcRestore();
while (1) {
ret = LOS_TaskSuspend(OsCurrTaskGet()->taskID);
PrintExcInfo("%s supend task :%u failed: 0x%x\n", __FUNCTION__, OsCurrTaskGet()->taskID, ret);
}
ret = LOS_TaskDelete(OsCurrTaskGet()->taskID);
LOS_Panic("%s supend task :%u failed: 0x%x\n", __FUNCTION__, OsCurrTaskGet()->taskID, ret);
}
LOS_SpinUnlock(&g_excSerializerSpin);
@ -1017,10 +1034,6 @@ STATIC VOID OsCheckCpuStatus(VOID)
LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr)
{
#if (LOSCFG_KERNEL_SMP == YES)
UINT16 runCount;
#endif
if ((excBufAddr->regCPSR & CPSR_MASK_MODE) == CPSR_USER_MODE) {
g_minAddr = USER_ASPACE_BASE;
g_maxAddr = USER_ASPACE_BASE + USER_ASPACE_SIZE;
@ -1033,22 +1046,6 @@ LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr)
OsCheckCpuStatus();
if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
while (1) {
OsProcessSuspendAllTask();
#if (LOSCFG_KERNEL_SMP == YES)
LOS_SpinLock(&g_taskSpin);
runCount = OS_PROCESS_GET_RUNTASK_COUNT(OsCurrProcessGet()->processStatus);
LOS_SpinUnlock(&g_taskSpin);
if (runCount == 1) {
break;
}
#else
break;
#endif
}
}
#if (LOSCFG_KERNEL_SMP == YES)
#ifdef LOSCFG_FS_VFS
/* Wait for the end of the Console task to avoid multicore printing code */

View File

@ -325,6 +325,14 @@ _osExceptDataAbortHdl:
#ifdef LOSCFG_KERNEL_VM
_osExcPageFaultReturn:
LDMFD SP!, {R4-R11}
MOV R0, SP
STR R7, [SP, #0]
SUB SP, SP, #(12 * 4) @ sp - sizeof(IrqContext), reserved for signal
MOV R1, SP
BLX OsSaveSignalContext
MOV SP, R0
ADD SP, SP, #(2 * 4)
LDMFD SP, {R13, R14}^
ADD SP, SP, #(2 * 4) @ Jump reserved fileds

View File

@ -179,7 +179,7 @@ STATIC LosProcessCB *OsFindExitChildProcess(const LosProcessCB *processCB, INT32
return NULL;
}
STATIC INLINE VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
{
taskCB->waitID = wakePID;
OsSchedTaskWake(taskCB);
@ -410,7 +410,9 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
processCB->processStatus |= OS_PROCESS_STATUS_ZOMBIES;
#ifdef LOSCFG_KERNEL_VM
(VOID)OsKill(processCB->parentProcessID, SIGCHLD, OS_KERNEL_KILL_PERMISSION);
#endif
LOS_ListHeadInsert(&g_processRecyleList, &processCB->pendList);
OsRunTaskToDelete(runTask);
return;
@ -909,27 +911,6 @@ LITE_OS_SEC_TEXT INT32 LOS_GetProcessPriority(INT32 pid)
return OsGetProcessPriority(LOS_PRIO_PROCESS, pid);
}
LITE_OS_SEC_TEXT VOID OsWaitSignalToWakeProcess(LosProcessCB *processCB)
{
LosTaskCB *taskCB = NULL;
if (processCB == NULL) {
return;
}
/* only suspend process can continue */
if (!(processCB->processStatus & OS_PROCESS_STATUS_PENDING)) {
return;
}
if (!LOS_ListEmpty(&processCB->waitList)) {
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&processCB->waitList));
OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
}
return;
}
STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *processCB)
{
LOS_DL_LIST *head = &processCB->waitList;
@ -1595,9 +1576,9 @@ STATIC UINT32 OsCopyParent(UINT32 flags, LosProcessCB *childProcessCB, LosProces
childProcessCB->priority = runProcessCB->priority;
if (flags & CLONE_PARENT) {
parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID);
parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID);
} else {
parentProcessCB = runProcessCB;
parentProcessCB = runProcessCB;
}
childProcessCB->parentProcessID = parentProcessCB->processID;
LOS_ListTailInsert(&parentProcessCB->childrenList, &childProcessCB->siblingList);
@ -1793,6 +1774,18 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status)
{
UINT32 intSave;
/* The exit of a kernel - state process must be kernel - state and all threads must actively exit */
LosProcessCB *processCB = OsCurrProcessGet();
SCHEDULER_LOCK(intSave);
if (!OsProcessIsUserMode(processCB) && (processCB->threadNumber != 1)) {
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("Kernel-state processes with multiple threads are not allowed to exit directly\n");
return;
}
SCHEDULER_UNLOCK(intSave);
OsTaskExitGroup((UINT32)status);
OsProcessExit(OsCurrTaskGet(), (UINT32)status);
}

View File

@ -46,6 +46,7 @@
#include "los_process_pri.h"
#include "los_vm_map.h"
#include "los_vm_syscall.h"
#include "los_signal.h"
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
@ -267,30 +268,29 @@ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status)
{
UINT32 intSave;
LosProcessCB *runProcess = NULL;
LosTaskCB *mainTask = NULL;
SCHEDULER_LOCK(intSave);
runProcess = OS_PCB_FROM_PID(taskCB->processID);
mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID);
SCHEDULER_UNLOCK(intSave);
LosProcessCB *runProcess = OS_PCB_FROM_PID(taskCB->processID);
LosTaskCB *mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID);
if (mainTask == taskCB) {
OsTaskExitGroup(status);
}
SCHEDULER_LOCK(intSave);
if (runProcess->threadNumber == 1) { /* 1: The last task of the process exits */
SCHEDULER_UNLOCK(intSave);
(VOID)OsProcessExit(taskCB, status);
return;
}
if (taskCB->taskStatus & OS_TASK_FLAG_DETACHED) {
/* The thread being killed must be able to exit automatically and will have the detached property */
OsTaskJoinPostUnsafe(taskCB);
if (taskCB->taskStatus & (OS_TASK_FLAG_DETACHED | OS_TASK_FLAG_EXIT_KILL)) {
UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave);
LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret);
}
OsTaskJoinPostUnsafe(taskCB);
OsSchedResched();
SCHEDULER_UNLOCK(intSave);
return;
@ -536,8 +536,8 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
if (initParam->uwResved & OS_TASK_FLAG_DETACHED) {
taskCB->taskStatus |= OS_TASK_FLAG_DETACHED;
} else {
LOS_ListInit(&taskCB->joinList);
taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
LOS_ListInit(&taskCB->joinList);
}
taskCB->futex.index = OS_INVALID_VALUE;
@ -870,6 +870,7 @@ STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *tas
if (processCB->processMode == OS_USER_MODE) {
OsTaskJoinPostUnsafe(taskCB);
#ifdef LOSCFG_KERNEL_VM
OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
#endif
@ -878,15 +879,16 @@ STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *tas
OsTaskSyncWake(taskCB);
}
LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *taskCB)
LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask)
{
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
OsTaskReleaseHoldLock(processCB, taskCB);
OsTaskStatusUnusedSet(taskCB);
LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID);
LOS_ListDelete(&taskCB->threadList);
OsTaskReleaseHoldLock(processCB, runTask);
OsTaskStatusUnusedSet(runTask);
LOS_ListDelete(&runTask->threadList);
processCB->threadNumber--;
LOS_ListTailInsert(&g_taskRecyleList, &taskCB->pendList);
LOS_ListTailInsert(&g_taskRecyleList, &runTask->pendList);
OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL);
OsSchedResched();
@ -1033,7 +1035,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
}
processCB = OS_PCB_FROM_PID(taskCB->processID);
if (processCB->threadNumber == 1) {
if (processCB->threadNumber == 1) { /* 1: The last task of the process exits */
if (processCB == OsCurrProcessGet()) {
SCHEDULER_UNLOCK(intSave);
OsProcessExit(taskCB, OS_PRO_EXIT_OK);
@ -1399,57 +1401,70 @@ EXIT:
return err;
}
STATIC VOID OsExitGroupActiveTaskKilled(LosProcessCB *processCB, LosTaskCB *taskCB)
{
INT32 ret;
taskCB->taskStatus |= OS_TASK_FLAG_EXIT_KILL;
#if (LOSCFG_KERNEL_SMP == YES)
/* The other core that the thread is running on and is currently running in a non-system call */
if (!taskCB->sig.sigIntLock && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
taskCB->signal = SIGNAL_KILL;
LOS_MpSchedule(taskCB->currCpu);
} else
#endif
{
ret = OsTaskKillUnsafe(taskCB->taskID, SIGKILL);
if (ret != LOS_OK) {
PRINT_ERR("pid %u exit, Exit task group %u kill %u failed! ERROR: %d\n",
taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, ret);
}
}
if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) {
taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN;
LOS_ListInit(&taskCB->joinList);
}
ret = OsTaskJoinPendUnsafe(taskCB);
if (ret != LOS_OK) {
PRINT_ERR("pid %u exit, Exit task group %u to wait others task %u(0x%x) exit failed! ERROR: %d\n",
taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, taskCB->taskStatus, ret);
}
}
LITE_OS_SEC_TEXT VOID OsTaskExitGroup(UINT32 status)
{
LosProcessCB *processCB = NULL;
LosTaskCB *taskCB = NULL;
LOS_DL_LIST *list = NULL;
LOS_DL_LIST *head = NULL;
LosTaskCB *runTask[LOSCFG_KERNEL_CORE_NUM] = { 0 };
UINT32 intSave;
#if (LOSCFG_KERNEL_SMP == YES)
UINT16 cpu;
#endif
LosProcessCB *processCB = OsCurrProcessGet();
LosTaskCB *currTask = OsCurrTaskGet();
SCHEDULER_LOCK(intSave);
processCB = OsCurrProcessGet();
if (processCB->processStatus & OS_PROCESS_FLAG_EXIT) {
if ((processCB->processStatus & OS_PROCESS_FLAG_EXIT) || !OsProcessIsUserMode(processCB)) {
SCHEDULER_UNLOCK(intSave);
return;
}
processCB->processStatus |= OS_PROCESS_FLAG_EXIT;
runTask[ArchCurrCpuid()] = OsCurrTaskGet();
runTask[ArchCurrCpuid()]->sig.sigprocmask = OS_INVALID_VALUE;
processCB->threadGroupID = currTask->taskID;
list = &processCB->threadSiblingList;
head = list;
LOS_DL_LIST *list = &processCB->threadSiblingList;
LOS_DL_LIST *head = list;
do {
taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
if ((taskCB->taskStatus & (OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT)) &&
!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
OsTaskDeleteInactive(processCB, taskCB);
} else {
#if (LOSCFG_KERNEL_SMP == YES)
if (taskCB->currCpu != ArchCurrCpuid()) {
taskCB->signal = SIGNAL_KILL;
runTask[taskCB->currCpu] = taskCB;
LOS_MpSchedule(taskCB->currCpu);
if (taskCB != currTask) {
OsExitGroupActiveTaskKilled(processCB, taskCB);
} else {
/* Skip the current task */
list = list->pstNext;
}
#endif
list = list->pstNext;
}
} while (head != list->pstNext);
#if (LOSCFG_KERNEL_SMP == YES)
for (cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
if ((cpu == ArchCurrCpuid()) || (runTask[cpu] == NULL)) {
continue;
}
(VOID)OsTaskSyncWait(runTask[cpu]);
}
#endif
processCB->threadGroupID = OsCurrTaskGet()->taskID;
SCHEDULER_UNLOCK(intSave);
LOS_ASSERT(processCB->threadNumber == 1);
@ -1462,38 +1477,6 @@ LITE_OS_SEC_TEXT VOID OsExecDestroyTaskGroup(VOID)
OsTaskCBRecycleToFree();
}
LITE_OS_SEC_TEXT VOID OsProcessSuspendAllTask(VOID)
{
LosProcessCB *process = NULL;
LosTaskCB *taskCB = NULL;
LosTaskCB *runTask = NULL;
LOS_DL_LIST *list = NULL;
LOS_DL_LIST *head = NULL;
UINT32 intSave;
UINT32 ret;
SCHEDULER_LOCK(intSave);
process = OsCurrProcessGet();
runTask = OsCurrTaskGet();
list = &process->threadSiblingList;
head = list;
do {
taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList);
if (taskCB != runTask) {
ret = OsTaskSuspend(taskCB);
if ((ret != LOS_OK) && (ret != LOS_ERRNO_TSK_ALREADY_SUSPENDED)) {
PRINT_ERR("process(%d) suspend all task(%u) failed! ERROR: 0x%x\n",
process->processID, taskCB->taskID, ret);
}
}
list = list->pstNext;
} while (head != list->pstNext);
SCHEDULER_UNLOCK(intSave);
return;
}
UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB)
{
if (taskCB == NULL) {
@ -1640,6 +1623,11 @@ LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events)
(VOID)LOS_EventWrite(&g_resourceEvent, events);
}
LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events)
{
(VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL);
}
STATIC VOID OsResourceRecoveryTask(VOID)
{
UINT32 ret;

View File

@ -448,7 +448,6 @@ extern UINT32 OsUserInitProcess(VOID);
extern VOID OsTaskSchedQueueDequeue(LosTaskCB *taskCB, UINT16 status);
extern VOID OsTaskSchedQueueEnqueue(LosTaskCB *taskCB, UINT16 status);
extern INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size);
extern VOID OsWaitSignalToWakeProcess(LosProcessCB *processCB);
extern UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name,
LosVmSpace *oldAspace, UINTPTR oldFiles);
extern UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize);
@ -463,6 +462,8 @@ extern INT32 OsSetCurrProcessGroupID(UINT32 gid);
extern UINT32 OsGetKernelInitProcessID(VOID);
extern VOID OsSetSigHandler(UINTPTR addr);
extern UINTPTR OsGetSigHandler(VOID);
extern VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID);
#ifdef __cplusplus
#if __cplusplus
}

View File

@ -135,11 +135,12 @@ typedef struct sq_queue_s sq_queue_t;
typedef struct {
sigset_t sigFlag;
sigset_t sigPendFlag;
sigset_t sigprocmask; /* Signals that are blocked */
sigset_t sigprocmask; /* Signals that are blocked */
sq_queue_t sigactionq;
LOS_DL_LIST waitList;
sigset_t sigwaitmask; /* Waiting for pending signals */
siginfo_t sigunbinfo; /* Signal info when task unblocked */
sigset_t sigwaitmask; /* Waiting for pending signals */
siginfo_t sigunbinfo; /* Signal info when task unblocked */
unsigned int sigIntLock;
void *sigContext;
unsigned int count;
} sig_cb;
@ -163,6 +164,9 @@ int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout);
int OsPause(void);
int OsSigPending(sigset_t *set);
int OsSigSuspend(const sigset_t *set);
VOID OsSigIntLock(VOID);
VOID OsSigIntUnlock(VOID);
INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo);
#ifdef __cplusplus
#if __cplusplus

View File

@ -208,7 +208,15 @@ extern SPIN_LOCK_S g_taskSpin;
*
* The task is no-delete system task, like resourceTask.
*/
#define OS_TASK_FLAG_NO_DELETE 0x2000U
#define OS_TASK_FLAG_NO_DELETE 0x2000U
/**
* @ingroup los_task
* Flag that indicates the task property.
*
* Kills the thread during process exit.
*/
#define OS_TASK_FLAG_EXIT_KILL 0x4000U
/**
* @ingroup los_task
@ -216,7 +224,7 @@ extern SPIN_LOCK_S g_taskSpin;
*
* Specifies the process creation task.
*/
#define OS_TASK_FLAG_SPECIFIES_PROCESS 0x4000U
#define OS_TASK_FLAG_SPECIFIES_PROCESS 0x0U
/**
* @ingroup los_task
@ -453,47 +461,23 @@ STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
return FALSE;
}
STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
return TRUE;
}
return FALSE;
}
#define OS_TID_CHECK_INVALID(taskID) ((UINT32)(taskID) >= g_taskMaxNum)
/* get task info */
#define OS_ALL_TASK_MASK 0xFFFFFFFF
extern UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB);
extern VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB);
extern UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB);
extern BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask);
extern VOID OsTaskSchedule(LosTaskCB *, LosTaskCB *);
extern VOID OsTaskContextLoad(LosTaskCB *newTask);
extern VOID OsIdleTask(VOID);
extern UINT32 OsIdleTaskCreate(VOID);
extern UINT32 OsTaskInit(VOID);
extern UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv);
extern UINT32 OsShellCmdTskInfoGet(UINT32 taskID, VOID *seqfile, UINT16 flag);
extern LosTaskCB *OsGetMainTask(VOID);
extern VOID OsSetMainTask(VOID);
extern UINT32 OsGetIdleTaskId(VOID);
extern VOID OsTaskEntry(UINT32 taskID);
extern SortLinkAttribute *OsTaskSortLinkGet(VOID);
extern VOID OsTaskProcSignal(VOID);
extern UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave);
extern VOID OsTaskResourcesToFree(LosTaskCB *taskCB);
extern VOID OsRunTaskToDelete(LosTaskCB *taskCB);
extern UINT32 OsTaskSyncWait(const LosTaskCB *taskCB);
extern UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam);
extern INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName);
extern VOID OsTaskCBRecycleToFree(VOID);
extern VOID OsTaskExitGroup(UINT32 status);
extern VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status);
extern VOID OsExecDestroyTaskGroup(VOID);
extern VOID OsProcessSuspendAllTask(VOID);
extern UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB);
extern VOID OsWriteResourceEvent(UINT32 events);
extern UINT32 OsResourceFreeTaskCreate(VOID);
#define OS_TASK_WAIT_ANYPROCESS (1 << 0U)
#define OS_TASK_WAIT_PROCESS (1 << 1U)
#define OS_TASK_WAIT_GID (1 << 2U)
#ifdef LOSCFG_DEBUG_VERSION
#define OS_TASK_WAIT_SEM (OS_TASK_WAIT_GID + 1)
#define OS_TASK_WAIT_QUEUE (OS_TASK_WAIT_SEM + 1)
#define OS_TASK_WAIT_JOIN (OS_TASK_WAIT_QUEUE + 1)
@ -530,6 +514,39 @@ STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
#endif
}
extern UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB);
extern VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB);
extern UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB);
extern BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask);
extern VOID OsTaskSchedule(LosTaskCB *, LosTaskCB *);
extern VOID OsTaskContextLoad(LosTaskCB *newTask);
extern VOID OsIdleTask(VOID);
extern UINT32 OsIdleTaskCreate(VOID);
extern UINT32 OsTaskInit(VOID);
extern UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv);
extern UINT32 OsShellCmdTskInfoGet(UINT32 taskID, VOID *seqfile, UINT16 flag);
extern LosTaskCB *OsGetMainTask(VOID);
extern VOID OsSetMainTask(VOID);
extern UINT32 OsGetIdleTaskId(VOID);
extern VOID OsTaskEntry(UINT32 taskID);
extern SortLinkAttribute *OsTaskSortLinkGet(VOID);
extern VOID OsTaskProcSignal(VOID);
extern UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave);
extern VOID OsTaskResourcesToFree(LosTaskCB *taskCB);
extern VOID OsRunTaskToDelete(LosTaskCB *taskCB);
extern UINT32 OsTaskSyncWait(const LosTaskCB *taskCB);
extern UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam);
extern INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName);
extern VOID OsTaskCBRecycleToFree(VOID);
extern VOID OsTaskExitGroup(UINT32 status);
extern VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status);
extern VOID OsExecDestroyTaskGroup(VOID);
extern UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB);
extern VOID OsWriteResourceEvent(UINT32 events);
extern VOID OsWriteResourceEventUnsafe(UINT32 events);
extern UINT32 OsResourceFreeTaskCreate(VOID);
#ifdef LOSCFG_DEBUG_VERSION
STATIC INLINE VOID OsTraceTaskSchedule(LosTaskCB *newTask, LosTaskCB *runTask)
{
(VOID)newTask;
@ -542,8 +559,6 @@ STATIC INLINE VOID OsTraceTaskSchedule(LosTaskCB *newTask, LosTaskCB *runTask)
#else
#define OsTaskWaitSetPendMask(mask, lockID, timeout)
#define OsTaskWakeClearPendMask(taskCB)
#define OsTraceTaskSchedule(newTask, runTask)
#endif

View File

@ -38,7 +38,9 @@
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_api.h"
#endif
#include "los_atomic.h"
#ifdef LOSCFG_KERNEL_VM
int raise(int sig)
{
@ -65,6 +67,57 @@ int OsSigIsMember(const sigset_t *set, int signo)
return ret;
}
STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
{
sig_cb *sigcb = &taskCB->sig;
if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
{
if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_PID(taskCB->processID))) {
return 0;
}
if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) {
return 0;
}
switch (taskCB->waitFlag) {
case OS_TASK_WAIT_PROCESS:
case OS_TASK_WAIT_GID:
case OS_TASK_WAIT_ANYPROCESS:
OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
break;
case OS_TASK_WAIT_JOIN:
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
break;
case OS_TASK_WAIT_SIGNAL:
OsSigWaitTaskWake(taskCB, signo);
break;
case OS_TASK_WAIT_LITEIPC:
taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND;
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
break;
case OS_TASK_WAIT_FUTEX:
OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
OsTaskWakeClearPendMask(taskCB);
OsSchedTaskWake(taskCB);
break;
default:
break;
}
return 0;
}
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
{
bool masked = FALSE;
@ -78,24 +131,17 @@ int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
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)) {
OsTaskWakeClearPendMask(stcb);
OsSchedTaskWake(stcb);
OsSigEmptySet(&sigcb->sigwaitmask);
} else {
if (LOS_ListEmpty(&sigcb->waitList) ||
(!LOS_ListEmpty(&sigcb->waitList) && !OsSigIsMember(&sigcb->sigwaitmask, info->si_signo))) {
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)) {
OsTaskWakeClearPendMask(stcb);
OsSchedTaskWake(stcb);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
(void) memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), info, sizeof(siginfo_t));
return 0;
return OsPendingTaskWake(stcb, info->si_signo);
}
void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
@ -231,15 +277,7 @@ 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)) {
OsTaskWakeClearPendMask(tcb);
OsSchedTaskWake(tcb);
OsSigEmptySet(&sigcb->sigwaitmask);
}
}
return 0;
return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
}
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
@ -276,9 +314,8 @@ int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
/* visit all taskcb and dispatch signal */
if (info.sigInfo->si_signo == SIGKILL) {
(void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);
OsWaitSignalToWakeProcess(spcb);
(void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
return 0;
} else {
ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);
@ -316,14 +353,14 @@ int OsDispatch(pid_t pid, siginfo_t *info, int permission)
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;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
LosProcessCB *current = OsCurrProcessGet();
/* 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)) {
@ -371,11 +408,27 @@ int OsKillLock(pid_t pid, int sig)
return ret;
}
INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
{
siginfo_t info;
LosTaskCB *taskCB = OsGetTaskCB(taskID);
INT32 ret = OsUserTaskOperatePermissionsCheck(taskCB);
if (ret != LOS_OK) {
return -ret;
}
/* Create the siginfo structure */
info.si_signo = signo;
info.si_code = SI_USER;
info.si_value.sival_ptr = NULL;
/* Dispatch the signal to thread, bypassing normal task group thread
* dispatch rules. */
return OsTcbDispatch(taskCB, &info);
}
int OsPthreadKill(UINT32 tid, int signo)
{
LosTaskCB *stcb = NULL;
siginfo_t info;
int ret;
UINT32 intSave;
@ -385,23 +438,9 @@ int OsPthreadKill(UINT32 tid, int signo)
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:
ret = OsTaskKillUnsafe(tid, signo);
SCHEDULER_UNLOCK(intSave);
return ret;
}
@ -556,6 +595,22 @@ int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
return LOS_OK;
}
VOID OsSigIntLock(VOID)
{
LosTaskCB *task = OsCurrTaskGet();
sig_cb *sigcb = &task->sig;
(VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
}
VOID OsSigIntUnlock(VOID)
{
LosTaskCB *task = OsCurrTaskGet();
sig_cb *sigcb = &task->sig;
(VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
}
VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
{
UINTPTR sigHandler;
@ -565,6 +620,16 @@ VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
LosProcessCB *process = OsCurrProcessGet();
sig_cb *sigcb = &task->sig;
/* A thread is not allowed to interrupt the processing of its signals during a system call */
if (sigcb->sigIntLock > 0) {
return sp;
}
if (task->taskStatus & OS_TASK_FLAG_EXIT_KILL) {
OsTaskToExit(task, 0);
return sp;
}
SCHEDULER_LOCK(intSave);
if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
sigHandler = OsGetSigHandler();
@ -618,3 +683,4 @@ VOID *OsRestorSignalContext(VOID *sp)
return saveContext;
}
#endif

View File

@ -118,6 +118,7 @@ VOID OsArmA32SyscallHandle(TaskContext *regs)
return;
}
OsSigIntLock();
switch (nArgs) {
case ARG_NUM_0:
case ARG_NUM_1:
@ -136,6 +137,7 @@ VOID OsArmA32SyscallHandle(TaskContext *regs)
}
regs->R0 = ret;
OsSigIntUnlock();
return;
}