/*并发( 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 , & param ) ;
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 ;
}