|
|
/*并发(Concurrent):多个线程在单个核心运行,同一时间只能一个线程运行,内核不停切换线程,
|
|
|
看起来像同时运行,实际上是线程不停切换
|
|
|
并行(Parallel)每个线程分配给独立的CPU核心,线程同时运行
|
|
|
单核CPU多个进程或多个线程内能实现并发(微观上的串行,宏观上的并行)
|
|
|
多核CPU线程间可以实现宏观和微观上的并行
|
|
|
LITE_OS_SEC_BSS 和 LITE_OS_SEC_DATA_INIT 是告诉编译器这些全局变量放在哪个数据段
|
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
|
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
*
|
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
|
* conditions and the following disclaimer.
|
|
|
*
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
|
* provided with the distribution.
|
|
|
*
|
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
|
* to endorse or promote products derived from this software without specific prior written
|
|
|
* permission.
|
|
|
*
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
*/
|
|
|
|
|
|
#include "los_process_pri.h"
|
|
|
#include "los_sched_pri.h"
|
|
|
#include "los_task_pri.h"
|
|
|
#include "los_hw_pri.h"
|
|
|
#include "los_sem_pri.h"
|
|
|
#include "los_mp.h"
|
|
|
#include "los_exc.h"
|
|
|
#include "asm/page.h"
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
#include "fs/fd_table.h"
|
|
|
#include "fs/fs_operation.h"
|
|
|
#endif
|
|
|
#include "time.h"
|
|
|
#include "user_copy.h"
|
|
|
#include "los_signal.h"
|
|
|
#ifdef LOSCFG_SECURITY_VID
|
|
|
#include "vid_api.h"
|
|
|
#endif
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
#include "capability_api.h"
|
|
|
#endif
|
|
|
#include "los_swtmr_pri.h"
|
|
|
#include "los_vm_map.h"
|
|
|
#include "los_vm_phys.h"
|
|
|
#include "los_vm_syscall.h"
|
|
|
|
|
|
|
|
|
LITE_OS_SEC_BSS LosProcessCB *g_processCBArray = NULL;///< 进程池数组
|
|
|
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_freeProcess;///< 空闲状态下的进程链表
|
|
|
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_processRecycleList;///< 需要回收的进程列表
|
|
|
LITE_OS_SEC_BSS UINT32 g_userInitProcess = OS_INVALID_VALUE;
|
|
|
LITE_OS_SEC_BSS UINT32 g_kernelInitProcess = OS_INVALID_VALUE;
|
|
|
LITE_OS_SEC_BSS UINT32 g_kernelIdleProcess = OS_INVALID_VALUE;
|
|
|
LITE_OS_SEC_BSS UINT32 g_processMaxNum;///< 进程最大数量,默认64个
|
|
|
LITE_OS_SEC_BSS ProcessGroup *g_processGroup = NULL;///< 全局进程组,负责管理所有进程组
|
|
|
//将进程插入到空闲的链表中//
|
|
|
STATIC INLINE VOID OsInsertPCBToFreeList(LosProcessCB *processCB)
|
|
|
{
|
|
|
UINT32 pid = processCB->processID;//获取进程ID
|
|
|
(VOID)memset_s(processCB, sizeof(LosProcessCB), 0, sizeof(LosProcessCB));//进程描述符数据清0
|
|
|
processCB->processID = pid;//进程ID
|
|
|
processCB->processStatus = OS_PROCESS_FLAG_UNUSED;//设置为进程未使用
|
|
|
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;//timeID初始化值
|
|
|
LOS_ListTailInsert(&g_freeProcess, &processCB->pendList);//进程节点挂入g_freeProcess以分配给后续进程使用
|
|
|
}
|
|
|
|
|
|
STATIC ProcessGroup *OsCreateProcessGroup(UINT32 pid)
|
|
|
{
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
ProcessGroup *group = LOS_MemAlloc(m_aucSysMem1, sizeof(ProcessGroup));
|
|
|
if (group == NULL) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
group->groupID = pid;
|
|
|
LOS_ListInit(&group->processList);
|
|
|
LOS_ListInit(&group->exitProcessList);
|
|
|
|
|
|
processCB = OS_PCB_FROM_PID(pid);
|
|
|
LOS_ListTailInsert(&group->processList, &processCB->subordinateGroupList);
|
|
|
processCB->group = group;
|
|
|
processCB->processStatus |= OS_PROCESS_FLAG_GROUP_LEADER;
|
|
|
if (g_processGroup != NULL) {
|
|
|
LOS_ListTailInsert(&g_processGroup->groupList, &group->groupList);
|
|
|
}
|
|
|
|
|
|
return group;
|
|
|
}
|
|
|
/* 退出进程组,参数是进程地址和进程组地址的地址 */
|
|
|
STATIC VOID OsExitProcessGroup(LosProcessCB *processCB, ProcessGroup **group)
|
|
|
{
|
|
|
LosProcessCB *groupProcessCB = OS_PCB_FROM_PID(processCB->group->groupID);
|
|
|
|
|
|
LOS_ListDelete(&processCB->subordinateGroupList);//从进程组进程链表上摘出去
|
|
|
if (LOS_ListEmpty(&processCB->group->processList) && LOS_ListEmpty(&processCB->group->exitProcessList)) {
|
|
|
LOS_ListDelete(&processCB->group->groupList);
|
|
|
groupProcessCB->processStatus &= ~OS_PROCESS_FLAG_GROUP_LEADER;
|
|
|
*group = processCB->group;
|
|
|
if (OsProcessIsUnused(groupProcessCB) && !(groupProcessCB->processStatus & OS_PROCESS_FLAG_EXIT)) {
|
|
|
LOS_ListDelete(&groupProcessCB->pendList);//进程从全局进程链表上摘除
|
|
|
OsInsertPCBToFreeList(groupProcessCB);//释放进程的资源,回到freelist再利用
|
|
|
}
|
|
|
}
|
|
|
|
|
|
processCB->group = NULL;
|
|
|
}
|
|
|
/*通过指定组ID找到进程组 */
|
|
|
STATIC ProcessGroup *OsFindProcessGroup(UINT32 gid)
|
|
|
{
|
|
|
ProcessGroup *group = NULL;
|
|
|
if (g_processGroup->groupID == gid) {
|
|
|
return g_processGroup;
|
|
|
}
|
|
|
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(group, &g_processGroup->groupList, ProcessGroup, groupList) {
|
|
|
if (group->groupID == gid) {
|
|
|
return group;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
PRINT_INFO("%s is find group : %u failed!\n", __FUNCTION__, gid);
|
|
|
return NULL;
|
|
|
}
|
|
|
/*给指定进程组发送信号 */
|
|
|
STATIC INT32 OsSendSignalToSpecifyProcessGroup(ProcessGroup *group, siginfo_t *info, INT32 permission)
|
|
|
{
|
|
|
INT32 ret, success, err;
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
|
|
|
success = 0;
|
|
|
ret = -LOS_ESRCH;
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(childCB, &(group->processList), LosProcessCB, subordinateGroupList) {
|
|
|
if (childCB->processID == 0) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
err = OsDispatch(childCB->processID, info, permission);
|
|
|
success |= !err;
|
|
|
ret = err;
|
|
|
}
|
|
|
/* At least one success. */
|
|
|
return success ? LOS_OK : ret;
|
|
|
}
|
|
|
//创建进程组//
|
|
|
LITE_OS_SEC_TEXT INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission)
|
|
|
{
|
|
|
INT32 ret, success, err;
|
|
|
ProcessGroup *group = NULL;
|
|
|
|
|
|
success = 0;
|
|
|
err = OsSendSignalToSpecifyProcessGroup(g_processGroup, info, permission);
|
|
|
success |= !err;
|
|
|
ret = err;
|
|
|
/* all processes group */
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(group, &g_processGroup->groupList, ProcessGroup, groupList) {
|
|
|
/* all processes in the process group. */
|
|
|
err = OsSendSignalToSpecifyProcessGroup(group, info, permission);
|
|
|
success |= !err;
|
|
|
ret = err;
|
|
|
}
|
|
|
return success ? LOS_OK : ret;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission)
|
|
|
{
|
|
|
ProcessGroup *group = NULL;
|
|
|
/* Send SIG to all processes in process group PGRP.
|
|
|
If PGRP is zero, send SIG to all processes in
|
|
|
the current process's process group. */
|
|
|
group = OsFindProcessGroup(pid ? -pid : LOS_GetCurrProcessGroupID());
|
|
|
if (group == NULL) {
|
|
|
return -LOS_ESRCH;
|
|
|
}
|
|
|
/* all processes in the process group. */
|
|
|
return OsSendSignalToSpecifyProcessGroup(group, info, permission);
|
|
|
}
|
|
|
|
|
|
STATIC LosProcessCB *OsFindGroupExitProcess(ProcessGroup *group, INT32 pid)
|
|
|
{
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(childCB, &(group->exitProcessList), LosProcessCB, subordinateGroupList) {
|
|
|
if ((childCB->processID == pid) || (pid == OS_INVALID_VALUE)) {
|
|
|
return childCB;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
PRINT_INFO("%s find exit process : %d failed in group : %u\n", __FUNCTION__, pid, group->groupID);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsFindChildProcess(const LosProcessCB *processCB, INT32 childPid)
|
|
|
{
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
|
|
|
if (childPid < 0) {
|
|
|
goto ERR;
|
|
|
}
|
|
|
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(childCB, &(processCB->childrenList), LosProcessCB, siblingList) {
|
|
|
if (childCB->processID == childPid) {
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ERR:
|
|
|
PRINT_INFO("%s is find the child : %d failed in parent : %u\n", __FUNCTION__, childPid, processCB->processID);
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
STATIC LosProcessCB *OsFindExitChildProcess(const LosProcessCB *processCB, INT32 childPid)
|
|
|
{
|
|
|
LosProcessCB *exitChild = NULL;
|
|
|
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(exitChild, &(processCB->exitChildList), LosProcessCB, siblingList) {
|
|
|
if ((childPid == OS_INVALID_VALUE) || (exitChild->processID == childPid)) {
|
|
|
return exitChild;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
PRINT_INFO("%s is find the exit child : %d failed in parent : %u\n", __FUNCTION__, childPid, processCB->processID);
|
|
|
return NULL;
|
|
|
}
|
|
|
/* 唤醒等待wakePID结束的任务 */
|
|
|
VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
|
|
|
{
|
|
|
taskCB->waitID = wakePID;
|
|
|
OsSchedTaskWake(taskCB);
|
|
|
#ifdef LOSCFG_KERNEL_SMP
|
|
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
|
|
#endif
|
|
|
}
|
|
|
/* 唤醒等待参数进程结束的任务 */
|
|
|
STATIC BOOL OsWaitWakeSpecifiedProcess(LOS_DL_LIST *head, const LosProcessCB *processCB, LOS_DL_LIST **anyList)
|
|
|
{
|
|
|
LOS_DL_LIST *list = head;
|
|
|
LosTaskCB *taskCB = NULL;
|
|
|
UINT32 pid = 0;
|
|
|
BOOL find = FALSE;
|
|
|
|
|
|
while (list->pstNext != head) {//遍历等待链表 processCB->waitList
|
|
|
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list));
|
|
|
if ((taskCB->waitFlag == OS_PROCESS_WAIT_PRO) && (taskCB->waitID == processCB->processID)) {
|
|
|
if (pid == 0) {
|
|
|
pid = processCB->processID;
|
|
|
find = TRUE;
|
|
|
} else {
|
|
|
pid = OS_INVALID_VALUE;
|
|
|
}
|
|
|
|
|
|
OsWaitWakeTask(taskCB, pid);//唤醒这个任务,此时会切到 LOS_Wait runTask->waitFlag = 0;处运行
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (taskCB->waitFlag != OS_PROCESS_WAIT_PRO) {
|
|
|
*anyList = list;
|
|
|
break;
|
|
|
}
|
|
|
list = list->pstNext;
|
|
|
}
|
|
|
|
|
|
return find;
|
|
|
}
|
|
|
/* 检查父进程的等待任务并唤醒父进程去处理等待任务 */
|
|
|
STATIC VOID OsWaitCheckAndWakeParentProcess(LosProcessCB *parentCB, const LosProcessCB *processCB)
|
|
|
{
|
|
|
LOS_DL_LIST *head = &parentCB->waitList;
|
|
|
LOS_DL_LIST *list = NULL;
|
|
|
LosTaskCB *taskCB = NULL;
|
|
|
BOOL findSpecified = FALSE;
|
|
|
|
|
|
if (LOS_ListEmpty(&parentCB->waitList)) {
|
|
|
return;//检查是否有正在等待子进程退出的任务,若没有则退出
|
|
|
}
|
|
|
|
|
|
findSpecified = OsWaitWakeSpecifiedProcess(head, processCB, &list);//找到指定的任务
|
|
|
if (findSpecified == TRUE) {
|
|
|
/* No thread is waiting for any child process to finish */
|
|
|
if (LOS_ListEmpty(&parentCB->waitList)) {//没有线程正在等待任何子进程结束
|
|
|
return;
|
|
|
} else if (!LOS_ListEmpty(&parentCB->childrenList)) {
|
|
|
/* Other child processes exist, and other threads that are waiting
|
|
|
* for the child to finish continue to wait
|
|
|
*///存在其他子进程,正在等待它们的子进程结束而将继续等待
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Waiting threads are waiting for a specified child process to finish */
|
|
|
if (list == NULL) {//等待线程正在等待指定的子进程结束
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
/* No child processes exist and all waiting threads are awakened */
|
|
|
if (findSpecified == TRUE) {//所有等待的任务都唤醒
|
|
|
while (list->pstNext != head) {
|
|
|
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list));
|
|
|
OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
while (list->pstNext != head) {//处理 OS_PROCESS_WAIT_GID 标签
|
|
|
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list));
|
|
|
if (taskCB->waitFlag == OS_PROCESS_WAIT_GID) {
|
|
|
if (taskCB->waitID != processCB->group->groupID) {
|
|
|
list = list->pstNext;
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (findSpecified == FALSE) {
|
|
|
OsWaitWakeTask(taskCB, processCB->processID);
|
|
|
findSpecified = TRUE;
|
|
|
} else {
|
|
|
OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
|
|
|
}
|
|
|
|
|
|
if (!LOS_ListEmpty(&parentCB->childrenList)) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
/* 回收指定进程的资源 */
|
|
|
LITE_OS_SEC_TEXT VOID OsProcessResourcesToFree(LosProcessCB *processCB)
|
|
|
{
|
|
|
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {
|
|
|
PRINT_ERR("The process(%d) has no permission to release process(%d) resources!\n",
|
|
|
OsCurrProcessGet()->processID, processCB->processID);
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
if (OsProcessIsUserMode(processCB)) {
|
|
|
delete_files(processCB->files);
|
|
|
}
|
|
|
processCB->files = NULL;
|
|
|
#endif
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
if (processCB->user != NULL) {
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, processCB->user);//删除用户
|
|
|
processCB->user = NULL;//重置指针为空
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
OsSwtmrRecycle(processCB->processID);
|
|
|
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_VID
|
|
|
if (processCB->timerIdMap.bitMap != NULL) {
|
|
|
VidMapDestroy(processCB);
|
|
|
processCB->timerIdMap.bitMap = NULL;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_LITEIPC
|
|
|
if (OsProcessIsUserMode(processCB)) {
|
|
|
LiteIpcPoolDelete(&(processCB->ipcInfo));
|
|
|
(VOID)memset_s(&(processCB->ipcInfo), sizeof(ProcIpcInfo), 0, sizeof(ProcIpcInfo));
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT STATIC VOID OsRecycleZombiesProcess(LosProcessCB *childCB, ProcessGroup **group)
|
|
|
{
|
|
|
OsExitProcessGroup(childCB, group);//退出进程组
|
|
|
LOS_ListDelete(&childCB->siblingList);//从父亲大人的子孙链表上摘除
|
|
|
if (childCB->processStatus & OS_PROCESS_STATUS_ZOMBIES) {
|
|
|
childCB->processStatus &= ~OS_PROCESS_STATUS_ZOMBIES;//去掉僵死标签
|
|
|
childCB->processStatus |= OS_PROCESS_FLAG_UNUSED;//贴上没使用标签,进程由进程池分配,进程退出后重新回到空闲进程池
|
|
|
}
|
|
|
|
|
|
LOS_ListDelete(&childCB->pendList);//将自己从阻塞链表上摘除
|
|
|
if (childCB->processStatus & OS_PROCESS_FLAG_EXIT) {
|
|
|
LOS_ListHeadInsert(&g_processRecycleList, &childCB->pendList);//从头部插入,注意g_processRecyleList挂的是pendList节点,所以要通过OS_PCB_FROM_PENDLIST找.
|
|
|
} else if (childCB->processStatus & OS_PROCESS_FLAG_GROUP_LEADER) {
|
|
|
LOS_ListTailInsert(&g_processRecycleList, &childCB->pendList);//从尾部插入
|
|
|
} else {
|
|
|
OsInsertPCBToFreeList(childCB);//直接插到freeList中去,可用于重新分配了。
|
|
|
}
|
|
|
}
|
|
|
/*! 当一个进程自然退出的时候,它的孩子进程由两位老祖宗收养 */
|
|
|
STATIC VOID OsDealAliveChildProcess(LosProcessCB *processCB)
|
|
|
{
|
|
|
UINT32 parentID;
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
LosProcessCB *parentCB = NULL;
|
|
|
LOS_DL_LIST *nextList = NULL;
|
|
|
LOS_DL_LIST *childHead = NULL;
|
|
|
|
|
|
if (!LOS_ListEmpty(&processCB->childrenList)) {//如果存在孩子进程
|
|
|
childHead = processCB->childrenList.pstNext;//获取孩子链表
|
|
|
LOS_ListDelete(&(processCB->childrenList));//清空自己的孩子链表
|
|
|
if (OsProcessIsUserMode(processCB)) {//是用户态进程
|
|
|
parentID = g_userInitProcess;
|
|
|
} else {
|
|
|
parentID = g_kernelInitProcess;
|
|
|
}
|
|
|
|
|
|
for (nextList = childHead; ;) {//遍历孩子链表
|
|
|
childCB = OS_PCB_FROM_SIBLIST(nextList);//找到孩子的真身//找到孩子的真身
|
|
|
childCB->parentProcessID = parentID;
|
|
|
nextList = nextList->pstNext;//找下一个孩子进程
|
|
|
if (nextList == childHead) {//所以孩子都完成操作
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
parentCB = OS_PCB_FROM_PID(parentID);
|
|
|
LOS_ListTailInsertList(&parentCB->childrenList, childHead);
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
/*! 回收指定进程的已经退出的孩子进程所占资源 */
|
|
|
STATIC VOID OsChildProcessResourcesFree(const LosProcessCB *processCB)
|
|
|
{
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
ProcessGroup *group = NULL;
|
|
|
|
|
|
while (!LOS_ListEmpty(&((LosProcessCB *)processCB)->exitChildList)) {//遍历直到没有了退出的孩子进程
|
|
|
childCB = LOS_DL_LIST_ENTRY(processCB->exitChildList.pstNext, LosProcessCB, siblingList);//获取孩子进程
|
|
|
OsRecycleZombiesProcess(childCB, &group);//其中会将childCB从exitChildList链表上摘出去
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, group);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status)
|
|
|
{
|
|
|
LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID);//释放孩子进程的资源
|
|
|
|
|
|
LosProcessCB *parentCB = NULL;
|
|
|
|
|
|
LOS_ASSERT(processCB->processStatus & OS_PROCESS_STATUS_RUNNING);
|
|
|
|
|
|
OsChildProcessResourcesFree(processCB);
|
|
|
|
|
|
/* is a child process */
|
|
|
if (processCB->parentProcessID != OS_INVALID_VALUE) {
|
|
|
parentCB = OS_PCB_FROM_PID(processCB->parentProcessID);
|
|
|
LOS_ListDelete(&processCB->siblingList);
|
|
|
if (!OsProcessExitCodeSignalIsSet(processCB)) {
|
|
|
OsProcessExitCodeSet(processCB, status);
|
|
|
}
|
|
|
LOS_ListTailInsert(&parentCB->exitChildList, &processCB->siblingList);
|
|
|
LOS_ListDelete(&processCB->subordinateGroupList);
|
|
|
LOS_ListTailInsert(&processCB->group->exitProcessList, &processCB->subordinateGroupList);
|
|
|
|
|
|
OsWaitCheckAndWakeParentProcess(parentCB, processCB);
|
|
|
|
|
|
OsDealAliveChildProcess(processCB);
|
|
|
|
|
|
processCB->processStatus |= OS_PROCESS_STATUS_ZOMBIES;
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
(VOID)OsKill(processCB->parentProcessID, SIGCHLD, OS_KERNEL_KILL_PERMISSION);
|
|
|
#endif
|
|
|
LOS_ListHeadInsert(&g_processRecycleList, &processCB->pendList);
|
|
|
OsRunTaskToDelete(runTask);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
LOS_Panic("pid : %u is the root process exit!\n", processCB->processID);
|
|
|
return;
|
|
|
}
|
|
|
/*! 进程模块初始化,被编译放在代码段 .init 中*/
|
|
|
STATIC UINT32 OsProcessInit(VOID)
|
|
|
{
|
|
|
UINT32 index;
|
|
|
UINT32 size;
|
|
|
|
|
|
g_processMaxNum = LOSCFG_BASE_CORE_PROCESS_LIMIT;//默认支持64个进程
|
|
|
size = g_processMaxNum * sizeof(LosProcessCB);
|
|
|
|
|
|
g_processCBArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);// 进程池,占用内核堆,内存池分配
|
|
|
if (g_processCBArray == NULL) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
(VOID)memset_s(g_processCBArray, size, 0, size);//安全方式重置清0
|
|
|
|
|
|
LOS_ListInit(&g_freeProcess);//进程空闲链表初始化,创建一个进程时从g_freeProcess中申请一个进程描述符使用
|
|
|
LOS_ListInit(&g_processRecycleList);//进程回收链表初始化,回收完成后进入g_freeProcess等待再次被申请使用
|
|
|
|
|
|
for (index = 0; index < g_processMaxNum; index++) {//进程池循环创建
|
|
|
g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum-1]赋值
|
|
|
g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;
|
|
|
LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);
|
|
|
}
|
|
|
|
|
|
g_kernelIdleProcess = 0; /* 0: The idle process ID of the kernel-mode process is fixed at 0 */
|
|
|
LOS_ListDelete(&OS_PCB_FROM_PID(g_kernelIdleProcess)->pendList);
|
|
|
|
|
|
g_userInitProcess = 1; /* 1: The root process ID of the user-mode process is fixed at 1 */
|
|
|
LOS_ListDelete(&OS_PCB_FROM_PID(g_userInitProcess)->pendList);
|
|
|
|
|
|
g_kernelInitProcess = 2; /* 2: The root process ID of the kernel-mode process is fixed at 2 */
|
|
|
LOS_ListDelete(&OS_PCB_FROM_PID(g_kernelInitProcess)->pendList);
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
/*! 进程回收再利用过程*/
|
|
|
LITE_OS_SEC_TEXT VOID OsProcessCBRecycleToFree(VOID)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
while (!LOS_ListEmpty(&g_processRecycleList)) {//循环任务回收链表,直到为空
|
|
|
processCB = OS_PCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_processRecycleList));
|
|
|
if (!(processCB->processStatus & OS_PROCESS_FLAG_EXIT)) {//进程没有退出标签
|
|
|
break;
|
|
|
}
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
OsTaskCBRecycleToFree();
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
processCB->processStatus &= ~OS_PROCESS_FLAG_EXIT;
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
LosVmSpace *space = NULL;
|
|
|
if (OsProcessIsUserMode(processCB)) {//进程是否是用户态进程
|
|
|
space = processCB->vmSpace;//只有用户态的进程才需要释放虚拟内存空间
|
|
|
}
|
|
|
processCB->vmSpace = NULL;
|
|
|
#endif
|
|
|
/* OS_PROCESS_FLAG_GROUP_LEADER: The lead process group cannot be recycled without destroying the PCB.
|
|
|
* !OS_PROCESS_FLAG_UNUSED: Parent process does not reclaim child process resources.
|
|
|
*/
|
|
|
LOS_ListDelete(&processCB->pendList);//将进程从进程链表上摘除
|
|
|
if ((processCB->processStatus & OS_PROCESS_FLAG_GROUP_LEADER) ||
|
|
|
(processCB->processStatus & OS_PROCESS_STATUS_ZOMBIES)) {
|
|
|
LOS_ListTailInsert(&g_processRecycleList, &processCB->pendList);//将进程挂到进程回收链表上,
|
|
|
} else {
|
|
|
/* Clear the bottom 4 bits of process status */
|
|
|
OsInsertPCBToFreeList(processCB);//进程回到可分配池中,再分配利用
|
|
|
}
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
(VOID)LOS_VmSpaceFree(space);//释放用户态进程的虚拟内存空间,因为内核只有一个虚拟空间,因此不需要释放虚拟空间.
|
|
|
#endif
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
}
|
|
|
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
}
|
|
|
/*! 删除PCB块 其实是 PCB块回归进程池,先进入回收链表*/
|
|
|
STATIC VOID OsDeInitPCB(LosProcessCB *processCB)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
ProcessGroup *group = NULL;
|
|
|
|
|
|
if (processCB == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
OsProcessResourcesToFree(processCB);//释放进程所占用的资源
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
if (processCB->parentProcessID != OS_INVALID_VALUE) {
|
|
|
LOS_ListDelete(&processCB->siblingList);//将进程从兄弟链表中摘除
|
|
|
processCB->parentProcessID = OS_INVALID_VALUE;
|
|
|
}
|
|
|
|
|
|
if (processCB->group != NULL) {
|
|
|
OsExitProcessGroup(processCB, &group);
|
|
|
}
|
|
|
|
|
|
processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;//设置进程状态为非初始化
|
|
|
processCB->processStatus |= OS_PROCESS_FLAG_EXIT;//设置进程状态为退出
|
|
|
LOS_ListHeadInsert(&g_processRecycleList, &processCB->pendList);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, group);
|
|
|
OsWriteResourceEvent(OS_RESOURCE_EVENT_FREE);
|
|
|
return;
|
|
|
}
|
|
|
/*! 设置进程的名字*/
|
|
|
UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name)
|
|
|
{
|
|
|
errno_t errRet;
|
|
|
|
|
|
if (processCB == NULL) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if (name != NULL) {
|
|
|
errRet = strncpy_s(processCB->processName, OS_PCB_NAME_LEN, name, OS_PCB_NAME_LEN - 1);
|
|
|
if (errRet == EOK) {
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
switch (processCB->processMode) {
|
|
|
case OS_KERNEL_MODE:
|
|
|
errRet = snprintf_s(processCB->processName, OS_PCB_NAME_LEN, OS_PCB_NAME_LEN - 1,
|
|
|
"KerProcess%u", processCB->processID);
|
|
|
break;
|
|
|
default:
|
|
|
errRet = snprintf_s(processCB->processName, OS_PCB_NAME_LEN, OS_PCB_NAME_LEN - 1,
|
|
|
"UserProcess%u", processCB->processID);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (errRet < 0) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
/*! 初始化PCB(进程控制块)*/
|
|
|
STATIC UINT32 OsInitPCB(LosProcessCB *processCB, UINT32 mode, UINT16 priority, const CHAR *name)
|
|
|
{
|
|
|
processCB->processMode = mode; //用户态进程还是内核态进程
|
|
|
processCB->processStatus = OS_PROCESS_STATUS_INIT; //进程初始状态
|
|
|
processCB->parentProcess = NULL;
|
|
|
processCB->threadGroup = NULL;
|
|
|
processCB->umask = OS_PROCESS_DEFAULT_UMASK; //掩码
|
|
|
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
|
|
|
|
|
|
LOS_ListInit(&processCB->threadSiblingList);//初始化孩子任务/线程链表,上面挂的都是由此fork的孩子线程 见于 OsTaskCBInit LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList));
|
|
|
LOS_ListInit(&processCB->childrenList); //初始化孩子进程链表,上面挂的都是由此fork的孩子进程 见于 OsCopyParent LOS_ListTailInsert(&parentProcessCB->childrenList, &childProcessCB->siblingList);
|
|
|
LOS_ListInit(&processCB->exitChildList); //初始化记录退出孩子进程链表,上面挂的是哪些exit 见于 OsProcessNaturalExit LOS_ListTailInsert(&parentCB->exitChildList, &processCB->siblingList);
|
|
|
LOS_ListInit(&(processCB->waitList)); //初始化等待任务链表 上面挂的是处于等待的 见于 OsWaitInsertWaitLIstInOrder LOS_ListHeadInsert(&processCB->waitList, &runTask->pendList);
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
if (OsProcessIsUserMode(processCB)) {//如果是用户态进程
|
|
|
processCB->vmSpace = OsCreateUserVmSpace();//创建用户空间
|
|
|
if (processCB->vmSpace == NULL) {
|
|
|
processCB->processStatus = OS_PROCESS_FLAG_UNUSED;
|
|
|
return LOS_ENOMEM;
|
|
|
}//在鸿蒙内核态进程只有kprocess 和 kidle 两个
|
|
|
} else {
|
|
|
processCB->vmSpace = LOS_GetKVmSpace();
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_VID
|
|
|
status_t status = VidMapListInit(processCB);
|
|
|
if (status != LOS_OK) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
#endif
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
OsInitCapability(processCB);//初始化进程安全相关功能
|
|
|
#endif
|
|
|
|
|
|
if (OsSetProcessName(processCB, name) != LOS_OK) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
//创建用户
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
STATIC User *OsCreateUser(UINT32 userID, UINT32 gid, UINT32 size)//参数size 表示组数量
|
|
|
{ //(size - 1) * sizeof(UINT32) 用于 user->groups[..],这种设计节约了内存,不造成不需要的浪费
|
|
|
User *user = LOS_MemAlloc(m_aucSysMem1, sizeof(User) + (size - 1) * sizeof(UINT32));
|
|
|
if (user == NULL) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
user->userID = userID;
|
|
|
user->effUserID = userID;
|
|
|
user->gid = gid;
|
|
|
user->effGid = gid;
|
|
|
user->groupNumber = size;//用户组数量
|
|
|
user->groups[0] = gid; //用户组列表,一个用户可以属于多个用户组
|
|
|
return user;
|
|
|
}
|
|
|
/*! 检查参数群组ID是否在当前用户所属群组中*/
|
|
|
LITE_OS_SEC_TEXT BOOL LOS_CheckInGroups(UINT32 gid)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
UINT32 count;
|
|
|
User *user = NULL;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
user = OsCurrUserGet();//当前进程所属用户
|
|
|
for (count = 0; count < user->groupNumber; count++) {//循环对比
|
|
|
if (user->groups[count] == gid) {
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return FALSE;
|
|
|
}
|
|
|
#endif
|
|
|
/*! 获取当前进程的用户ID*/
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetUserID(VOID)
|
|
|
{
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
UINT32 intSave;
|
|
|
INT32 uid;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
uid = (INT32)OsCurrUserGet()->userID;
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return uid;
|
|
|
#else
|
|
|
return 0;
|
|
|
#endif
|
|
|
}
|
|
|
/*! 获取当前进程的用户组ID*/
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetGroupID(VOID)
|
|
|
{
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
UINT32 intSave;
|
|
|
INT32 gid;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
gid = (INT32)OsCurrUserGet()->gid;
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
return gid;
|
|
|
#else
|
|
|
return 0;
|
|
|
#endif
|
|
|
}
|
|
|
/*! 进程创建初始化*/
|
|
|
STATIC UINT32 OsProcessCreateInit(LosProcessCB *processCB, UINT32 flags, const CHAR *name, UINT16 priority)
|
|
|
{
|
|
|
ProcessGroup *group = NULL;
|
|
|
UINT32 ret = OsInitPCB(processCB, flags, priority, name);
|
|
|
if (ret != LOS_OK) {
|
|
|
goto EXIT;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_LITEIPC
|
|
|
if (OsProcessIsUserMode(processCB)) {
|
|
|
ret = LiteIpcPoolInit(&(processCB->ipcInfo));
|
|
|
if (ret != LOS_OK) {
|
|
|
ret = LOS_ENOMEM;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
processCB->files = alloc_files();
|
|
|
if (processCB->files == NULL) {
|
|
|
ret = LOS_ENOMEM;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
group = OsCreateProcessGroup(processCB->processID);
|
|
|
if (group == NULL) {
|
|
|
ret = LOS_ENOMEM;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
processCB->user = OsCreateUser(0, 0, 1);
|
|
|
if (processCB->user == NULL) {
|
|
|
ret = LOS_ENOMEM;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
|
|
EXIT:
|
|
|
OsDeInitPCB(processCB);
|
|
|
return ret;
|
|
|
}
|
|
|
/*! 创建2,0号进程,即内核态进程的老祖宗*/
|
|
|
LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
|
|
|
{
|
|
|
UINT32 ret = OsProcessInit();
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
LosProcessCB *kerInitProcess = OS_PCB_FROM_PID(g_kernelInitProcess);
|
|
|
ret = OsProcessCreateInit(kerInitProcess, OS_KERNEL_MODE, "KProcess", 0);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;//去掉初始化标签
|
|
|
g_processGroup = kerInitProcess->group;
|
|
|
LOS_ListInit(&g_processGroup->groupList);
|
|
|
OsCurrProcessSet(kerInitProcess);
|
|
|
|
|
|
LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);
|
|
|
ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, OS_TASK_PRIORITY_LOWEST, "KIdle");//创建内核态0号进程
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
idleProcess->parentProcessID = kerInitProcess->processID;
|
|
|
LOS_ListTailInsert(&kerInitProcess->childrenList, &idleProcess->siblingList);
|
|
|
idleProcess->group = kerInitProcess->group;
|
|
|
LOS_ListTailInsert(&kerInitProcess->group->processList, &idleProcess->subordinateGroupList);
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
idleProcess->user = kerInitProcess->user;
|
|
|
#endif
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
idleProcess->files = kerInitProcess->files;
|
|
|
#endif
|
|
|
|
|
|
ret = OsIdleTaskCreate();
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
idleProcess->threadGroupID = OsPercpuGet()->idleTaskID;
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
/// 进程调度参数检查
|
|
|
STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
|
|
|
{
|
|
|
if (OS_PID_CHECK_INVALID(pid)) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if (which != LOS_PRIO_PROCESS) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if (prio > OS_PROCESS_PRIORITY_LOWEST) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if (policy != LOS_SCHED_RR) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio)
|
|
|
{
|
|
|
LosProcessCB *runProcess = OsCurrProcessGet();
|
|
|
|
|
|
/* always trust kernel process */
|
|
|
if (!OsProcessIsUserMode(runProcess)) {
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
/* user mode process can reduce the priority of itself */
|
|
|
if ((runProcess->processID == processCB->processID) && (prio > processCB->priority)) {
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
/* user mode process with privilege of CAP_SCHED_SETPRIORITY can change the priority */
|
|
|
if (IsCapPermit(CAP_SCHED_SETPRIORITY)) {
|
|
|
return TRUE;
|
|
|
}
|
|
|
return FALSE;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
|
|
|
{
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
BOOL needSched = FALSE;
|
|
|
UINT32 intSave;
|
|
|
INT32 ret;
|
|
|
|
|
|
ret = OsProcessSchedlerParamCheck(which, pid, prio, policy);
|
|
|
if (ret != LOS_OK) {
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
processCB = OS_PCB_FROM_PID(pid);
|
|
|
if (OsProcessIsInactive(processCB)) {
|
|
|
ret = LOS_ESRCH;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
if (!OsProcessCapPermitCheck(processCB, prio)) {
|
|
|
ret = LOS_EPERM;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
needSched = OsSchedModifyProcessSchedParam(processCB, policy, prio);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
|
|
if (needSched && OS_SCHEDULER_ACTIVE) {
|
|
|
LOS_Schedule();
|
|
|
}
|
|
|
return LOS_OK;
|
|
|
|
|
|
EXIT:
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio)
|
|
|
{
|
|
|
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, policy);
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
|
|
|
if (OS_PID_CHECK_INVALID(pid)) {
|
|
|
return -LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
|
|
|
if (OsProcessIsUnused(processCB)) {
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return -LOS_ESRCH;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
return LOS_SCHED_RR;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio)
|
|
|
{
|
|
|
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, LOS_GetProcessScheduler(pid));
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
|
|
|
{
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
INT32 prio;
|
|
|
UINT32 intSave;
|
|
|
(VOID)which;
|
|
|
|
|
|
if (OS_PID_CHECK_INVALID(pid)) {
|
|
|
return -LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if (which != LOS_PRIO_PROCESS) {
|
|
|
return -LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
processCB = OS_PCB_FROM_PID(pid);
|
|
|
if (OsProcessIsUnused(processCB)) {
|
|
|
prio = -LOS_ESRCH;
|
|
|
goto OUT;
|
|
|
}
|
|
|
|
|
|
prio = (INT32)processCB->priority;
|
|
|
|
|
|
OUT:
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return prio;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetProcessPriority(INT32 pid)
|
|
|
{
|
|
|
return OsGetProcessPriority(LOS_PRIO_PROCESS, pid);
|
|
|
}
|
|
|
|
|
|
STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *processCB)
|
|
|
{
|
|
|
LOS_DL_LIST *head = &processCB->waitList;
|
|
|
LOS_DL_LIST *list = head;
|
|
|
LosTaskCB *taskCB = NULL;
|
|
|
|
|
|
if (runTask->waitFlag == OS_PROCESS_WAIT_GID) {
|
|
|
while (list->pstNext != head) {
|
|
|
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list));
|
|
|
if (taskCB->waitFlag == OS_PROCESS_WAIT_PRO) {
|
|
|
list = list->pstNext;
|
|
|
continue;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
} else if (runTask->waitFlag == OS_PROCESS_WAIT_ANY) {
|
|
|
while (list->pstNext != head) {
|
|
|
taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list));
|
|
|
if (taskCB->waitFlag != OS_PROCESS_WAIT_ANY) {
|
|
|
list = list->pstNext;
|
|
|
continue;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
/* if runTask->waitFlag == OS_PROCESS_WAIT_PRO,
|
|
|
* this node is inserted directly into the header of the waitList
|
|
|
*/
|
|
|
|
|
|
(VOID)OsSchedTaskWait(list->pstNext, LOS_WAIT_FOREVER, TRUE);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcessCB **child)
|
|
|
{
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
ProcessGroup *group = NULL;
|
|
|
LosTaskCB *runTask = OsCurrTaskGet();
|
|
|
UINT32 ret;
|
|
|
|
|
|
if (pid > 0) {
|
|
|
/* Wait for the child process whose process number is pid. */
|
|
|
childCB = OsFindExitChildProcess(processCB, pid);
|
|
|
if (childCB != NULL) {
|
|
|
goto WAIT_BACK;
|
|
|
}
|
|
|
|
|
|
ret = OsFindChildProcess(processCB, pid);
|
|
|
if (ret != LOS_OK) {
|
|
|
return LOS_ECHILD;
|
|
|
}
|
|
|
runTask->waitFlag = OS_PROCESS_WAIT_PRO;
|
|
|
runTask->waitID = pid;
|
|
|
} else if (pid == 0) {
|
|
|
/* Wait for any child process in the same process group */
|
|
|
childCB = OsFindGroupExitProcess(processCB->group, OS_INVALID_VALUE);
|
|
|
if (childCB != NULL) {
|
|
|
goto WAIT_BACK;
|
|
|
}
|
|
|
runTask->waitID = processCB->group->groupID;
|
|
|
runTask->waitFlag = OS_PROCESS_WAIT_GID;
|
|
|
} else if (pid == -1) {
|
|
|
/* Wait for any child process */
|
|
|
childCB = OsFindExitChildProcess(processCB, OS_INVALID_VALUE);
|
|
|
if (childCB != NULL) {
|
|
|
goto WAIT_BACK;
|
|
|
}
|
|
|
runTask->waitID = pid;
|
|
|
runTask->waitFlag = OS_PROCESS_WAIT_ANY;
|
|
|
} else { /* pid < -1 */
|
|
|
/* Wait for any child process whose group number is the pid absolute value. */
|
|
|
group = OsFindProcessGroup(-pid);
|
|
|
if (group == NULL) {
|
|
|
return LOS_ECHILD;
|
|
|
}
|
|
|
|
|
|
childCB = OsFindGroupExitProcess(group, OS_INVALID_VALUE);
|
|
|
if (childCB != NULL) {
|
|
|
goto WAIT_BACK;
|
|
|
}
|
|
|
|
|
|
runTask->waitID = -pid;
|
|
|
runTask->waitFlag = OS_PROCESS_WAIT_GID;
|
|
|
}
|
|
|
|
|
|
WAIT_BACK:
|
|
|
*child = childCB;
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intSave, INT32 *status, siginfo_t *info)
|
|
|
{
|
|
|
ProcessGroup *group = NULL;
|
|
|
UINT32 pid = childCB->processID;
|
|
|
UINT16 mode = childCB->processMode;
|
|
|
INT32 exitCode = childCB->exitCode;
|
|
|
UINT32 uid = 0;
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
if (childCB->user != NULL) {
|
|
|
uid = childCB->user->userID;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
OsRecycleZombiesProcess((LosProcessCB *)childCB, &group);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
if (status != NULL) {
|
|
|
if (mode == OS_USER_MODE) {
|
|
|
(VOID)LOS_ArchCopyToUser((VOID *)status, (const VOID *)(&(exitCode)), sizeof(INT32));
|
|
|
} else {
|
|
|
*status = exitCode;
|
|
|
}
|
|
|
}
|
|
|
/* get signal info */
|
|
|
if (info != NULL) {
|
|
|
siginfo_t tempinfo = { 0 };
|
|
|
|
|
|
tempinfo.si_signo = SIGCHLD;
|
|
|
tempinfo.si_errno = 0;
|
|
|
tempinfo.si_pid = pid;
|
|
|
tempinfo.si_uid = uid;
|
|
|
/*
|
|
|
* Process exit code
|
|
|
* 31 15 8 7 0
|
|
|
* | | exit code | core dump | signal |
|
|
|
*/
|
|
|
if ((exitCode & 0x7f) == 0) {
|
|
|
tempinfo.si_code = CLD_EXITED;
|
|
|
tempinfo.si_status = (exitCode >> 8U);
|
|
|
} else {
|
|
|
tempinfo.si_code = (exitCode & 0x80) ? CLD_DUMPED : CLD_KILLED;
|
|
|
tempinfo.si_status = (exitCode & 0x7f);
|
|
|
}
|
|
|
|
|
|
if (mode == OS_USER_MODE) {
|
|
|
(VOID)LOS_ArchCopyToUser((VOID *)(info), (const VOID *)(&(tempinfo)), sizeof(siginfo_t));
|
|
|
} else {
|
|
|
(VOID)memcpy_s((VOID *)(info), sizeof(siginfo_t), (const VOID *)(&(tempinfo)), sizeof(siginfo_t));
|
|
|
}
|
|
|
}
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, group);
|
|
|
return pid;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsWaitChildProcessCheck(LosProcessCB *processCB, INT32 pid, LosProcessCB **childCB)
|
|
|
{
|
|
|
if (LOS_ListEmpty(&(processCB->childrenList)) && LOS_ListEmpty(&(processCB->exitChildList))) {
|
|
|
return LOS_ECHILD;
|
|
|
}
|
|
|
|
|
|
return OsWaitSetFlag(processCB, pid, childCB);
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsWaitOptionsCheck(UINT32 options)
|
|
|
{
|
|
|
UINT32 flag = LOS_WAIT_WNOHANG | LOS_WAIT_WUNTRACED | LOS_WAIT_WCONTINUED;
|
|
|
|
|
|
flag = ~flag & options;
|
|
|
if (flag != 0) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if ((options & (LOS_WAIT_WCONTINUED | LOS_WAIT_WUNTRACED)) != 0) {
|
|
|
return LOS_EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
if (OS_INT_ACTIVE) {
|
|
|
return LOS_EINTR;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC INT32 OsWait(INT32 pid, USER INT32 *status, USER siginfo_t *info, UINT32 options, VOID *rusage)
|
|
|
{
|
|
|
(VOID)rusage;
|
|
|
UINT32 ret;
|
|
|
UINT32 intSave;
|
|
|
LosProcessCB *childCB = NULL;
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
LosTaskCB *runTask = NULL;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
processCB = OsCurrProcessGet();
|
|
|
runTask = OsCurrTaskGet();
|
|
|
|
|
|
ret = OsWaitChildProcessCheck(processCB, pid, &childCB);
|
|
|
if (ret != LOS_OK) {
|
|
|
pid = -ret;
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
if (childCB != NULL) {
|
|
|
return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info);
|
|
|
}
|
|
|
|
|
|
if ((options & LOS_WAIT_WNOHANG) != 0) {
|
|
|
runTask->waitFlag = 0;
|
|
|
pid = 0;
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
OsWaitInsertWaitListInOrder(runTask, processCB);
|
|
|
|
|
|
runTask->waitFlag = 0;
|
|
|
if (runTask->waitID == OS_INVALID_VALUE) {
|
|
|
pid = -LOS_ECHILD;
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
childCB = OS_PCB_FROM_PID(runTask->waitID);
|
|
|
if (!(childCB->processStatus & OS_PROCESS_STATUS_ZOMBIES)) {
|
|
|
pid = -LOS_ESRCH;
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info);
|
|
|
|
|
|
ERROR:
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return pid;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage)
|
|
|
{
|
|
|
(VOID)rusage;
|
|
|
UINT32 ret;
|
|
|
|
|
|
ret = OsWaitOptionsCheck(options);
|
|
|
if (ret != LOS_OK) {
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
return OsWait(pid, status, NULL, options, NULL);
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsWaitidOptionsCheck(UINT32 options)
|
|
|
{
|
|
|
UINT32 flag = LOS_WAIT_WNOHANG | LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WEXITED | LOS_WAIT_WNOWAIT;
|
|
|
|
|
|
flag = ~flag & options;
|
|
|
if ((flag != 0) || (options == 0)) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* only support LOS_WAIT_WNOHANG | LOS_WAIT_WEXITED
|
|
|
* notsupport LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WNOWAIT
|
|
|
*/
|
|
|
if ((options & (LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WNOWAIT)) != 0) {
|
|
|
return LOS_EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
if (OS_INT_ACTIVE) {
|
|
|
return LOS_EINTR;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_Waitid(INT32 pid, USER siginfo_t *info, UINT32 options, VOID *rusage)
|
|
|
{
|
|
|
(VOID)rusage;
|
|
|
UINT32 ret;
|
|
|
|
|
|
/* check options value */
|
|
|
ret = OsWaitidOptionsCheck(options);
|
|
|
if (ret != LOS_OK) {
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
return OsWait(pid, NULL, info, options, NULL);
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsSetProcessGroupCheck(const LosProcessCB *processCB, UINT32 gid)
|
|
|
{
|
|
|
LosProcessCB *runProcessCB = OsCurrProcessGet();
|
|
|
LosProcessCB *groupProcessCB = OS_PCB_FROM_PID(gid);
|
|
|
|
|
|
if (OsProcessIsInactive(processCB)) {
|
|
|
return LOS_ESRCH;
|
|
|
}
|
|
|
|
|
|
if (!OsProcessIsUserMode(processCB) || !OsProcessIsUserMode(groupProcessCB)) {
|
|
|
return LOS_EPERM;
|
|
|
}
|
|
|
|
|
|
if (runProcessCB->processID == processCB->parentProcessID) {
|
|
|
if (processCB->processStatus & OS_PROCESS_FLAG_ALREADY_EXEC) {
|
|
|
return LOS_EACCES;
|
|
|
}
|
|
|
} else if (processCB->processID != runProcessCB->processID) {
|
|
|
return LOS_ESRCH;
|
|
|
}
|
|
|
|
|
|
/* Add the process to another existing process group */
|
|
|
if (processCB->processID != gid) {
|
|
|
if (!(groupProcessCB->processStatus & OS_PROCESS_FLAG_GROUP_LEADER)) {
|
|
|
return LOS_EPERM;
|
|
|
}
|
|
|
|
|
|
if ((groupProcessCB->parentProcessID != processCB->parentProcessID) && (gid != processCB->parentProcessID)) {
|
|
|
return LOS_EPERM;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsSetProcessGroupIDUnsafe(UINT32 pid, UINT32 gid, ProcessGroup **group)
|
|
|
{
|
|
|
ProcessGroup *oldGroup = NULL;
|
|
|
ProcessGroup *newGroup = NULL;
|
|
|
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
|
|
|
UINT32 ret = OsSetProcessGroupCheck(processCB, gid);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
if (processCB->group->groupID == gid) {
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
oldGroup = processCB->group;
|
|
|
OsExitProcessGroup(processCB, group);
|
|
|
|
|
|
newGroup = OsFindProcessGroup(gid);
|
|
|
if (newGroup != NULL) {
|
|
|
LOS_ListTailInsert(&newGroup->processList, &processCB->subordinateGroupList);
|
|
|
processCB->group = newGroup;
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
newGroup = OsCreateProcessGroup(gid);
|
|
|
if (newGroup == NULL) {
|
|
|
LOS_ListTailInsert(&oldGroup->processList, &processCB->subordinateGroupList);
|
|
|
processCB->group = oldGroup;
|
|
|
if (*group != NULL) {
|
|
|
LOS_ListTailInsert(&g_processGroup->groupList, &oldGroup->groupList);
|
|
|
processCB = OS_PCB_FROM_PID(oldGroup->groupID);
|
|
|
processCB->processStatus |= OS_PROCESS_FLAG_GROUP_LEADER;
|
|
|
*group = NULL;
|
|
|
}
|
|
|
return LOS_EPERM;
|
|
|
}
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsSetProcessGroupID(UINT32 pid, UINT32 gid)
|
|
|
{
|
|
|
ProcessGroup *group = NULL;
|
|
|
UINT32 ret;
|
|
|
UINT32 intSave;
|
|
|
|
|
|
if ((OS_PID_CHECK_INVALID(pid)) || (OS_PID_CHECK_INVALID(gid))) {
|
|
|
return -LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
ret = OsSetProcessGroupIDUnsafe(pid, gid, &group);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, group);
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsSetCurrProcessGroupID(UINT32 gid)
|
|
|
{
|
|
|
return OsSetProcessGroupID(OsCurrProcessGet()->processID, gid);
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetProcessGroupID(UINT32 pid)
|
|
|
{
|
|
|
INT32 gid;
|
|
|
UINT32 intSave;
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
|
|
|
if (OS_PID_CHECK_INVALID(pid)) {
|
|
|
return -LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
processCB = OS_PCB_FROM_PID(pid);
|
|
|
if (OsProcessIsUnused(processCB)) {
|
|
|
gid = -LOS_ESRCH;
|
|
|
goto EXIT;
|
|
|
}
|
|
|
|
|
|
gid = (INT32)processCB->group->groupID;
|
|
|
|
|
|
EXIT:
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return gid;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetCurrProcessGroupID(VOID)
|
|
|
{
|
|
|
return LOS_GetProcessGroupID(OsCurrProcessGet()->processID);
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_VM
|
|
|
STATIC LosProcessCB *OsGetFreePCB(VOID)
|
|
|
{
|
|
|
LosProcessCB *processCB = NULL;
|
|
|
UINT32 intSave;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
if (LOS_ListEmpty(&g_freeProcess)) {
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
PRINT_ERR("No idle PCB in the system!\n");
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
processCB = OS_PCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_freeProcess));
|
|
|
LOS_ListDelete(&processCB->pendList);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
return processCB;
|
|
|
}
|
|
|
|
|
|
STATIC VOID *OsUserInitStackAlloc(LosProcessCB *processCB, UINT32 *size)
|
|
|
{
|
|
|
LosVmMapRegion *region = NULL;
|
|
|
UINT32 stackSize = ALIGN(OS_USER_TASK_STACK_SIZE, PAGE_SIZE);
|
|
|
|
|
|
region = LOS_RegionAlloc(processCB->vmSpace, 0, stackSize,
|
|
|
VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ |
|
|
|
VM_MAP_REGION_FLAG_PERM_WRITE, 0);
|
|
|
if (region == NULL) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
LOS_SetRegionTypeAnon(region);
|
|
|
region->regionFlags |= VM_MAP_REGION_FLAG_STACK;
|
|
|
|
|
|
*size = stackSize;
|
|
|
|
|
|
return (VOID *)(UINTPTR)region->range.base;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name,
|
|
|
LosVmSpace *oldSpace, UINTPTR oldFiles)
|
|
|
{
|
|
|
UINT32 ret;
|
|
|
const CHAR *processName = NULL;
|
|
|
|
|
|
if ((processCB == NULL) || (name == NULL)) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
processName = strrchr(name, '/');
|
|
|
processName = (processName == NULL) ? name : (processName + 1); /* 1: Do not include '/' */
|
|
|
|
|
|
ret = (UINT32)OsSetTaskName(OsCurrTaskGet(), processName, TRUE);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_LITEIPC
|
|
|
ret = LiteIpcPoolInit(&(processCB->ipcInfo));
|
|
|
if (ret != LOS_OK) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
processCB->sigHandler = 0;
|
|
|
OsCurrTaskGet()->sig.sigprocmask = 0;
|
|
|
|
|
|
LOS_VmSpaceFree(oldSpace);
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
CloseOnExec((struct files_struct *)oldFiles);
|
|
|
delete_files_snapshot((struct files_struct *)oldFiles);
|
|
|
#endif
|
|
|
|
|
|
OsSwtmrRecycle(processCB->processID);
|
|
|
processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_VID
|
|
|
VidMapDestroy(processCB);
|
|
|
ret = VidMapListInit(processCB);
|
|
|
if (ret != LOS_OK) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
processCB->processStatus &= ~OS_PROCESS_FLAG_EXIT;
|
|
|
processCB->processStatus |= OS_PROCESS_FLAG_ALREADY_EXEC;
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
|
|
|
if (entry == NULL) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
if ((sp == 0) || (LOS_Align(sp, LOSCFG_STACK_POINT_ALIGN_SIZE) != sp)) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
if ((mapBase == 0) || (mapSize == 0) || (sp <= mapBase) || (sp > (mapBase + mapSize))) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
LosTaskCB *taskCB = OsCurrTaskGet();
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
taskCB->userMapBase = mapBase;
|
|
|
taskCB->userMapSize = mapSize;
|
|
|
taskCB->taskEntry = (TSK_ENTRY_FUNC)entry;
|
|
|
|
|
|
TaskContext *taskContext = (TaskContext *)OsTaskStackInit(taskCB->taskID, taskCB->stackSize,
|
|
|
(VOID *)taskCB->topOfStack, FALSE);
|
|
|
OsUserTaskStackInit(taskContext, (UINTPTR)taskCB->taskEntry, sp);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsUserInitProcessStart(UINT32 processID, TSK_INIT_PARAM_S *param)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
UINT32 taskID;
|
|
|
INT32 ret;
|
|
|
|
|
|
taskID = OsCreateUserTask(processID, param);
|
|
|
if (taskID == OS_INVALID_VALUE) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
ret = LOS_SetTaskScheduler(taskID, LOS_SCHED_RR, OS_TASK_PRIORITY_LOWEST);
|
|
|
if (ret != LOS_OK) {
|
|
|
PRINT_ERR("User init process set scheduler failed! ERROR:%d \n", ret);
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(taskID), OS_PRO_EXIT_OK, intSave);
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsLoadUserInit(LosProcessCB *processCB)
|
|
|
{
|
|
|
/* userInitTextStart -----
|
|
|
* | user text |
|
|
|
*
|
|
|
* | user data | initSize
|
|
|
* userInitBssStart ---
|
|
|
* | user bss | initBssSize
|
|
|
* userInitEnd --- -----
|
|
|
*/
|
|
|
errno_t errRet;
|
|
|
INT32 ret;
|
|
|
CHAR *userInitTextStart = (CHAR *)&__user_init_entry;
|
|
|
CHAR *userInitBssStart = (CHAR *)&__user_init_bss;
|
|
|
CHAR *userInitEnd = (CHAR *)&__user_init_end;
|
|
|
UINT32 initBssSize = userInitEnd - userInitBssStart;
|
|
|
UINT32 initSize = userInitEnd - userInitTextStart;
|
|
|
VOID *userBss = NULL;
|
|
|
VOID *userText = NULL;
|
|
|
|
|
|
if ((LOS_Align((UINTPTR)userInitTextStart, PAGE_SIZE) != (UINTPTR)userInitTextStart) ||
|
|
|
(LOS_Align((UINTPTR)userInitEnd, PAGE_SIZE) != (UINTPTR)userInitEnd)) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
if ((initSize == 0) || (initSize <= initBssSize)) {
|
|
|
return LOS_EINVAL;
|
|
|
}
|
|
|
|
|
|
userText = LOS_PhysPagesAllocContiguous(initSize >> PAGE_SHIFT);
|
|
|
if (userText == NULL) {
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
errRet = memcpy_s(userText, initSize, (VOID *)&__user_init_load_addr, initSize - initBssSize);
|
|
|
if (errRet != EOK) {
|
|
|
PRINT_ERR("Load user init text, data and bss failed! err : %d\n", errRet);
|
|
|
goto ERROR;
|
|
|
}
|
|
|
ret = LOS_VaddrToPaddrMmap(processCB->vmSpace, (VADDR_T)(UINTPTR)userInitTextStart, LOS_PaddrQuery(userText),
|
|
|
initSize, VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE |
|
|
|
VM_MAP_REGION_FLAG_FIXED | VM_MAP_REGION_FLAG_PERM_EXECUTE |
|
|
|
VM_MAP_REGION_FLAG_PERM_USER);
|
|
|
if (ret < 0) {
|
|
|
PRINT_ERR("Mmap user init text, data and bss failed! err : %d\n", ret);
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
/* The User init boot segment may not actually exist */
|
|
|
if (initBssSize != 0) {
|
|
|
userBss = (VOID *)((UINTPTR)userText + userInitBssStart - userInitTextStart);
|
|
|
errRet = memset_s(userBss, initBssSize, 0, initBssSize);
|
|
|
if (errRet != EOK) {
|
|
|
PRINT_ERR("memset user init bss failed! err : %d\n", errRet);
|
|
|
goto ERROR;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
|
|
ERROR:
|
|
|
(VOID)LOS_PhysPagesFreeContiguous(userText, initSize >> PAGE_SHIFT);
|
|
|
return LOS_NOK;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
|
|
|
{
|
|
|
UINT32 ret;
|
|
|
UINT32 size;
|
|
|
TSK_INIT_PARAM_S param = { 0 };
|
|
|
VOID *stack = NULL;
|
|
|
|
|
|
LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess);
|
|
|
ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = OsLoadUserInit(processCB);
|
|
|
if (ret != LOS_OK) {
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
stack = OsUserInitStackAlloc(processCB, &size);
|
|
|
if (stack == NULL) {
|
|
|
PRINT_ERR("Alloc user init process user stack failed!\n");
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
param.pfnTaskEntry = (TSK_ENTRY_FUNC)(CHAR *)&__user_init_entry;
|
|
|
param.userParam.userSP = (UINTPTR)stack + size;
|
|
|
param.userParam.userMapBase = (UINTPTR)stack;
|
|
|
param.userParam.userMapSize = size;
|
|
|
param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
|
|
|
ret = OsUserInitProcessStart(g_userInitProcess, ¶m);
|
|
|
if (ret != LOS_OK) {
|
|
|
(VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);
|
|
|
goto ERROR;
|
|
|
}
|
|
|
|
|
|
return LOS_OK;
|
|
|
|
|
|
ERROR:
|
|
|
OsDeInitPCB(processCB);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB)
|
|
|
{
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
UINT32 size = sizeof(User) + sizeof(UINT32) * (parentCB->user->groupNumber - 1);
|
|
|
childCB->user = LOS_MemAlloc(m_aucSysMem1, size);
|
|
|
if (childCB->user == NULL) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
|
|
|
(VOID)memcpy_s(childCB->user, size, parentCB->user, size);
|
|
|
#endif
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size,
|
|
|
TSK_INIT_PARAM_S *childPara)
|
|
|
{
|
|
|
LosTaskCB *mainThread = NULL;
|
|
|
UINT32 intSave;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
mainThread = OsCurrTaskGet();
|
|
|
|
|
|
if (OsProcessIsUserMode(childProcessCB)) {
|
|
|
childPara->pfnTaskEntry = mainThread->taskEntry;
|
|
|
childPara->uwStackSize = mainThread->stackSize;
|
|
|
childPara->userParam.userArea = mainThread->userArea;
|
|
|
childPara->userParam.userMapBase = mainThread->userMapBase;
|
|
|
childPara->userParam.userMapSize = mainThread->userMapSize;
|
|
|
} else {
|
|
|
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
|
|
|
childPara->uwStackSize = size;
|
|
|
}
|
|
|
childPara->pcName = (CHAR *)name;
|
|
|
childPara->policy = mainThread->policy;
|
|
|
childPara->usTaskPrio = mainThread->priority;
|
|
|
childPara->processID = childProcessCB->processID;
|
|
|
if (mainThread->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
|
|
|
childPara->uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
|
|
|
} else if (mainThread->taskStatus & OS_TASK_FLAG_DETACHED) {
|
|
|
childPara->uwResved = OS_TASK_FLAG_DETACHED;
|
|
|
}
|
|
|
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
|
|
|
{
|
|
|
LosTaskCB *runTask = OsCurrTaskGet();
|
|
|
TSK_INIT_PARAM_S childPara = { 0 };
|
|
|
UINT32 ret;
|
|
|
UINT32 intSave;
|
|
|
UINT32 taskID;
|
|
|
|
|
|
OsInitCopyTaskParam(childProcessCB, name, entry, size, &childPara);
|
|
|
|
|
|
ret = LOS_TaskCreateOnly(&taskID, &childPara);
|
|
|
if (ret != LOS_OK) {
|
|
|
if (ret == LOS_ERRNO_TSK_TCB_UNAVAILABLE) {
|
|
|
return LOS_EAGAIN;
|
|
|
}
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
|
|
|
LosTaskCB *childTaskCB = OS_TCB_FROM_TID(taskID);
|
|
|
childTaskCB->taskStatus = runTask->taskStatus;
|
|
|
if (childTaskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
|
|
|
childTaskCB->taskStatus &= ~OS_TASK_STATUS_RUNNING;
|
|
|
} else {
|
|
|
if (OS_SCHEDULER_ACTIVE) {
|
|
|
LOS_Panic("Clone thread status not running error status: 0x%x\n", childTaskCB->taskStatus);
|
|
|
}
|
|
|
childTaskCB->taskStatus &= ~OS_TASK_STATUS_UNUSED;
|
|
|
childProcessCB->priority = OS_PROCESS_PRIORITY_LOWEST;
|
|
|
}
|
|
|
|
|
|
if (OsProcessIsUserMode(childProcessCB)) {
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
OsUserCloneParentStack(childTaskCB->stackPointer, runTask->topOfStack, runTask->stackSize);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
}
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyParent(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
|
|
|
{
|
|
|
UINT32 ret;
|
|
|
UINT32 intSave;
|
|
|
LosProcessCB *parentProcessCB = NULL;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
childProcessCB->priority = runProcessCB->priority;
|
|
|
|
|
|
if (flags & CLONE_PARENT) {
|
|
|
parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID);
|
|
|
} else {
|
|
|
parentProcessCB = runProcessCB;
|
|
|
}
|
|
|
childProcessCB->parentProcessID = parentProcessCB->processID;
|
|
|
LOS_ListTailInsert(&parentProcessCB->childrenList, &childProcessCB->siblingList);
|
|
|
childProcessCB->group = parentProcessCB->group;
|
|
|
LOS_ListTailInsert(&parentProcessCB->group->processList, &childProcessCB->subordinateGroupList);
|
|
|
ret = OsCopyUser(childProcessCB, parentProcessCB);
|
|
|
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyMM(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
|
|
|
{
|
|
|
status_t status;
|
|
|
UINT32 intSave;
|
|
|
|
|
|
if (!OsProcessIsUserMode(childProcessCB)) {
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
if (flags & CLONE_VM) {
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
childProcessCB->vmSpace->archMmu.virtTtb = runProcessCB->vmSpace->archMmu.virtTtb;
|
|
|
childProcessCB->vmSpace->archMmu.physTtb = runProcessCB->vmSpace->archMmu.physTtb;
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
status = LOS_VmSpaceClone(runProcessCB->vmSpace, childProcessCB->vmSpace);
|
|
|
if (status != LOS_OK) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyFile(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
|
|
|
{
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
if (flags & CLONE_FILES) {
|
|
|
childProcessCB->files = runProcessCB->files;
|
|
|
} else {
|
|
|
childProcessCB->files = dup_fd(runProcessCB->files);
|
|
|
}
|
|
|
if (childProcessCB->files == NULL) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
childProcessCB->consoleID = runProcessCB->consoleID;
|
|
|
childProcessCB->umask = runProcessCB->umask;
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsForkInitPCB(UINT32 flags, LosProcessCB *child, const CHAR *name, UINTPTR sp, UINT32 size)
|
|
|
{
|
|
|
UINT32 ret;
|
|
|
LosProcessCB *run = OsCurrProcessGet();
|
|
|
|
|
|
ret = OsInitPCB(child, run->processMode, OS_PROCESS_PRIORITY_LOWEST, name);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = OsCopyParent(flags, child, run);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
return OsCopyTask(flags, child, name, sp, size);
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *run)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
UINT32 ret;
|
|
|
ProcessGroup *group = NULL;
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
if (run->group->groupID == OS_USER_PRIVILEGE_PROCESS_GROUP) {
|
|
|
ret = OsSetProcessGroupIDUnsafe(child->processID, child->processID, &group);
|
|
|
if (ret != LOS_OK) {
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
OsSchedTaskEnQueue(OS_TCB_FROM_TID(child->threadGroupID));
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
|
|
(VOID)LOS_MemFree(m_aucSysMem1, group);
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC UINT32 OsCopyProcessResources(UINT32 flags, LosProcessCB *child, LosProcessCB *run)
|
|
|
{
|
|
|
UINT32 ret;
|
|
|
|
|
|
ret = OsCopyMM(flags, child, run);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = OsCopyFile(flags, child, run);
|
|
|
if (ret != LOS_OK) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_LITEIPC
|
|
|
if (OsProcessIsUserMode(child)) {
|
|
|
ret = LiteIpcPoolReInit(&child->ipcInfo, (const ProcIpcInfo *)(&run->ipcInfo));
|
|
|
if (ret != LOS_OK) {
|
|
|
return LOS_ENOMEM;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#ifdef LOSCFG_SECURITY_CAPABILITY
|
|
|
OsCopyCapability(run, child);
|
|
|
#endif
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
|
|
|
STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 size)
|
|
|
{
|
|
|
UINT32 intSave, ret, processID;
|
|
|
LosProcessCB *run = OsCurrProcessGet();
|
|
|
|
|
|
LosProcessCB *child = OsGetFreePCB();
|
|
|
if (child == NULL) {
|
|
|
return -LOS_EAGAIN;
|
|
|
}
|
|
|
processID = child->processID;
|
|
|
|
|
|
ret = OsForkInitPCB(flags, child, name, sp, size);
|
|
|
if (ret != LOS_OK) {
|
|
|
goto ERROR_INIT;
|
|
|
}
|
|
|
|
|
|
ret = OsCopyProcessResources(flags, child, run);
|
|
|
if (ret != LOS_OK) {
|
|
|
goto ERROR_TASK;
|
|
|
}
|
|
|
|
|
|
ret = OsChildSetProcessGroupAndSched(child, run);
|
|
|
if (ret != LOS_OK) {
|
|
|
goto ERROR_TASK;
|
|
|
}
|
|
|
|
|
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
|
|
if (OS_SCHEDULER_ACTIVE) {
|
|
|
LOS_Schedule();
|
|
|
}
|
|
|
|
|
|
return processID;
|
|
|
|
|
|
ERROR_TASK:
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(child->threadGroupID), OS_PRO_EXIT_OK, intSave);
|
|
|
ERROR_INIT:
|
|
|
OsDeInitPCB(child);
|
|
|
return -ret;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size)
|
|
|
{
|
|
|
UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_VM;
|
|
|
|
|
|
if (flags & (~cloneFlag)) {
|
|
|
PRINT_WARN("Clone dont support some flags!\n");
|
|
|
}
|
|
|
|
|
|
return OsCopyProcess(cloneFlag & flags, NULL, sp, size);
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_Fork(UINT32 flags, const CHAR *name, const TSK_ENTRY_FUNC entry, UINT32 stackSize)
|
|
|
{
|
|
|
UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_FILES;
|
|
|
|
|
|
if (flags & (~cloneFlag)) {
|
|
|
PRINT_WARN("Clone dont support some flags!\n");
|
|
|
}
|
|
|
|
|
|
flags |= CLONE_FILES;
|
|
|
return OsCopyProcess(cloneFlag & flags, name, (UINTPTR)entry, stackSize);
|
|
|
}
|
|
|
#else
|
|
|
LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT INT32 LOS_GetUsedPIDList(UINT32 *pidList, INT32 pidMaxNum)
|
|
|
{
|
|
|
LosProcessCB *pcb = NULL;
|
|
|
INT32 num = 0;
|
|
|
UINT32 intSave;
|
|
|
UINT32 pid = 1;
|
|
|
|
|
|
if (pidList == NULL) {
|
|
|
return 0;
|
|
|
}
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
while (OsProcessIDUserCheckInvalid(pid) == false) {
|
|
|
pcb = OS_PCB_FROM_PID(pid);
|
|
|
pid++;
|
|
|
if (OsProcessIsUnused(pcb)) {
|
|
|
continue;
|
|
|
}
|
|
|
pidList[num] = pcb->processID;
|
|
|
num++;
|
|
|
if (num >= pidMaxNum) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
return num;
|
|
|
}
|
|
|
|
|
|
#ifdef LOSCFG_FS_VFS
|
|
|
LITE_OS_SEC_TEXT struct fd_table_s *LOS_GetFdTable(UINT32 pid)
|
|
|
{
|
|
|
LosProcessCB *pcb = NULL;
|
|
|
struct files_struct *files = NULL;
|
|
|
|
|
|
if (OS_PID_CHECK_INVALID(pid)) {
|
|
|
return NULL;
|
|
|
}
|
|
|
pcb = OS_PCB_FROM_PID(pid);
|
|
|
files = pcb->files;
|
|
|
if (files == NULL) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
return files->fdt;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 LOS_GetCurrProcessID(VOID)
|
|
|
{
|
|
|
return OsCurrProcessGet()->processID;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT VOID OsProcessExit(LosTaskCB *runTask, INT32 status)
|
|
|
{
|
|
|
UINT32 intSave;
|
|
|
LOS_ASSERT(runTask == OsCurrTaskGet());
|
|
|
|
|
|
OsTaskResourcesToFree(runTask);
|
|
|
OsProcessResourcesToFree(OsCurrProcessGet());
|
|
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
OsProcessNaturalExit(runTask, status);
|
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 LOS_GetSystemProcessMaximum(VOID)
|
|
|
{
|
|
|
return g_processMaxNum;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 OsGetUserInitProcessID(VOID)
|
|
|
{
|
|
|
return g_userInitProcess;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 OsGetKernelInitProcessID(VOID)
|
|
|
{
|
|
|
return g_kernelInitProcess;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINT32 OsGetIdleProcessID(VOID)
|
|
|
{
|
|
|
return g_kernelIdleProcess;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT VOID OsSetSigHandler(UINTPTR addr)
|
|
|
{
|
|
|
OsCurrProcessGet()->sigHandler = addr;
|
|
|
}
|
|
|
|
|
|
LITE_OS_SEC_TEXT UINTPTR OsGetSigHandler(VOID)
|
|
|
{
|
|
|
return OsCurrProcessGet()->sigHandler;
|
|
|
}
|
|
|
|