📄 prcmgr.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * prcmgr.c (proc) * * Process/task manager */#include "prcmgr.h"#include <longlong.h>#include <sys/imalloc.h>#include <sys/commarea.h>#include <tm/tmonitor.h>#include <sys/syslog.h>#include <extension/sys/tkse_ssid.h>#include <extension/sys/svc/ifproctask.h>#include <sys/memdef.h>#include <sys/bdm.h>#define TSD_GSS_VAL_1000 1000#define TSD_GPP_VAL_M1 (-1)#define TSD_TPI_MSK_0XFFFF0000 0xffff0000U#define TSD_TWF_VAL_0X00000001 0x00000001U#define TSD_TCB_VAL_2 2#define TSD_KTK_VAL_M1 (-1)#define TSD_CSR_VAL_2 2#define TSD_PTM_MST_8 8#define TSD_PTM_SSS_32768 32768#define TSD_NPI_MSK_0X7FFF 0x7fffU#define TSD_TSM_VAL_M1 (-1)#define MIN_ABSGRP_PRI 0#define MAX_ABSGRP_PRI 127#define MIN_RRGRP1_PRI (MAX_ABSGRP_PRI + 1)#define MAX_RRGRP1_PRI 191#define MIN_RRGRP2_PRI (MAX_RRGRP1_PRI + 1)#define MAX_RRGRP2_PRI 255#define PRI_ADJVAL 8 /* Priority adjustment value (TK <> TK/SE) */#define MAX_ABSGRP_TSKPRI (MAX_ABSGRP_PRI + PRI_ADJVAL) /* Absolute priority group(task priorty) */#define RRGRP1_TSKPRI 138 /* Round robin group 1(task priorty) */#define RRGRP2_TSKPRI 139 /* Round robin group 2(task priorty) */#define ABSGRP_STIME 10#define TSD_KSP_RTN_128 128#define TSD_KTK_TID_M1 (-1)#define TSD_CPS_VAL_M1 (-1)#define TSD_CPS_MSK_2 2#define TSD_KPS_VAL_50 50#define TSD_KPS_TDT_10 10#define TSD_KPS_VAL_40 40#define TSD_KPS_TDT_50 50Inline PINFO* SearchPinfo( ID pid );Inline W CLAMP(W val, W minv, W maxv);LOCAL ID NewProcID( void );LOCAL ER _GetPidToPinfo(W pid, PINFO **ppi);LOCAL PINFO* _GetPinfo(ID taskid);LOCAL UW _GetLSID(PINFO *pinfo);LOCAL VP _GetUATB(UW lsid);LOCAL void sendEmg( PINFO *pi );LOCAL WER chgEmgEntry( PINFO *pi, W pid, W t_mask );LOCAL WER _tkse_req_emg( ID pid, W t_mask );LOCAL void CallStartUp(PINFO *pi);LOCAL void CallCleanUp(PINFO *pi);LOCAL PRI SE_K__Pri(W pri, W *slt);LOCAL W K_SE_Pri(PRI pri, W slt);LOCAL ER CheckPri(W old_pri, W new_pri);LOCAL ER RefTask(ID tid, T_RTSK *rtsk);LOCAL W GetPri(ID tskid);LOCAL ER ChangePri(ID tid, W pri);LOCAL UW GetSysSec( void );LOCAL void FinishProc(PINFO *pi);LOCAL void ExitTask(PINFO *pi, ID tskid);LOCAL void KillTasks(PINFO *pi, ID mytid, W exit_kind, W exit_code);LOCAL void TermChild(PINFO *parpi, ID mytid);LOCAL ER CreateTask(PINFO *pi, FP entry, W pri, VP caller_gp);LOCAL WER CreateProcess(POBJ_HDR* pohdr, W pri, MESSAGE *msg, UW mode);LOCAL WER _tkse_cre_prc2(LINK* lnk, PRI pri, MESSAGE *msg);LOCAL WER _tkse_cre_sysprc(LINK* lnk, PRI pri, MESSAGE *msg);LOCAL WER _tkse_cre_prc(T_CPRC *pk_cprc, MESSAGE *msg);LOCAL void _tkse_ext_prc(W exit_code);LOCAL ER _tkse_ter_prc(ID pid, W abort_code, W opt);LOCAL WER chg_pri_task( W tid, W new_pri, W opt );LOCAL WER chg_pri_proc( W pid, W new_pri, W opt );LOCAL WER _tkse_chg_pri(ID id, PRI new_pri, W opt);LOCAL WER _tkse_prc_sts(ID pid, P_STATE *buff, TC *path);LOCAL ER _tkse_get_inf(ID pid, P_INFO *buff);LOCAL WER _tkse_cre_dbg(LINK *lnk, ID pri, MESSAGE *msg);LOCAL WER _tkse_set_dbg(ID pid, W mode);LOCAL WER pi_link( PINFO *pi, W item, LINK *buf, W len );LOCAL WER pi_cinf( PINFO *pi, W item, P_CREINF *buf, W len );LOCAL WER pi_task( PINFO *pi, W item, VP buf, W len );LOCAL WER _tkse_prc_inf( ID pid, W item, VP buf, W len );LOCAL WER _tkse_crs_tsk(FP entry, PRI pri, W arg, VP caller_gp);LOCAL WER _tkse_cre_tsk(FP entry, PRI pri, VP caller_gp);LOCAL WER _tkse_sta_tsk(ID id, W arg);LOCAL void _tkse_ext_tsk(void);LOCAL ER _tkse_ter_tsk(ID tid);LOCAL ER _tkse_dly_tsk(RELTIM dlytim);LOCAL ER _tkse_slp_tsk(TMO tmout);LOCAL ER _tkse_wup_tsk(ID tid);LOCAL WER _tkse_can_wup(ID tid);LOCAL WER _tkse_get_tid(void);LOCAL ER _tkse_wai_fflock( void );LOCAL ER _tkse_wup_fflock( ID tid );LOCAL WER _tkse_lod_mod2( LINK *lnk, P_DYNLDINF *info );LOCAL WER _tkse_lod_mod( T_LMOD *pk_mod, P_DYNLDINF *info );LOCAL ER _tkse_unl_mod( ID loadid );LOCAL WER ProcSVCentry(VP para, W fn, VP caller_gp);LOCAL void ProcStartUp( ID resid, W pid );LOCAL void ProcCleanUp( ID resid, W pid );LOCAL void ProcBreak(ID taskid);LOCAL void KillProcess( UW sysproc );/* Message management internal IF */IMPORT ER _tkse_snd_msg(ID pid, MESSAGE *msg, W opt, W msgflg);IMPORT W MAX_MSGSZ; /* Maximum size of individual message */LOCAL W MaxProc; /* Maximum number of processes */EXPORT W MAX_SUBTASKS = TSD_PTM_MST_8; /* Maximum number of subtasks */LOCAL W SYS_STKSZ = TSD_PTM_SSS_32768; /* System stack size */EXPORT PINFO *TopPI; /* Start of PINFO[] */LOCAL QUEUE FreePI; /* Empty PINFO queue */EXPORT QUEUE UsedPI; /* PINFO queue in use */EXPORT W PINFO_sz; /* PINFO size */LOCAL ID LastProcID; /* Last process ID */#define PRC_DMY_PRI (140) /* Priority at the time of process generation *//* * Termination type (exit_kind) */#define EXIT_ABORT (MS_ABORT)#define EXIT_NORM (MS_EXIT)#define EXIT_TERM (MS_TERM)#define EXIT_TERM_TASK (0x00)#define EXIT_TERM_CHILD (0x10)#define EXIT_FORCE (0x11)/* * PINFO exclusive access lock */LOCAL FastLock _PinfoLock;/* * Exclusive control lock for process management * (*) Do not lock ProcMgrLock within PINFO lock. * When it is necessary to lock ProcMgrLock and PINFO at the same time, * lock ProcMgrLock and then PINFO. */EXPORT FastLock ProcMgrLock;/*====================================================================== Process-related utility======================================================================*//* Search for PINFO based on process ID*/Inline PINFO* SearchPinfo( ID pid ){ PINFO *pi; pi = (PINFO*)QueSearch(&UsedPI, &UsedPI, pid, (W)offsetof(PINFO, procid)); return ( pi == (PINFO*)&UsedPI )? NULL: pi;}/* Allocate new process ID Due to limitations on wsnd_evt(), a process ID must be 0x7fff or smaller.*/LOCAL ID NewProcID( void ){ ID pid = LastProcID; do { pid = (ID)((UW)(pid + 1) & TSD_NPI_MSK_0X7FFF); } while (( SearchPinfo(pid) != NULL )||( pid == 0 )); LastProcID = pid; return pid;}/* Fetch process management information based on process ID (without locks).*/LOCAL ER _GetPidToPinfo(W pid, PINFO **ppi){ PINFO *pi; ER err; if ( pid < TSD_GPP_VAL_M1 ) { return E_ID; } if ( pid > 0 ) { pi = SearchPinfo(pid); if ( pi == NULL ) { return E_NOEXS; } } else { err = GetMyPinfo(&pi); if ( err < E_OK ) { return err; } if ( pid == TSD_GPP_VAL_M1 ) { pi = pi->parent; /* Parent */ if ( pi == NULL ) { return E_NOEXS; } } } *ppi = pi; return E_OK;}/* Fetch process management information based on task ID (without locks).*/LOCAL PINFO* _GetPinfo(ID taskid){ ID resid; PRCMINFO *info; ER err; resid = tk_get_rid(taskid); if ( resid == __CommArea->SysResID ) { T_RTSK ref; tk_ref_tsk(taskid, &ref); if ( ref.exinf != PRCTSK_EXINF ) { return NULL; /* Non-process */ } } err = tk_get_res(resid, PM_SVC, (VP*)&info); if ( err < E_OK ) { return NULL; } return info->pinfo;}/* Fetch process space ID (LSID)*/LOCAL UW _GetLSID(PINFO *pinfo){ return GetLSID_pinfo(pinfo);}/* Fetch unique logical space table*/LOCAL VP _GetUATB(UW lsid){ return GetUATB_lsid(lsid);}/*====================================================================== Process termination notification======================================================================*/#define N_EMG 5typedef struct emglst EMGLST;struct emglst { EMGLST *next; /* Link to next list */ struct emgent { W pid; /* Destination process ID of termination notification */ W t_mask; /* Type of termination to be notified */ } ent[N_EMG];};/* Send process termination notification and delete the list.*/LOCAL void sendEmg( PINFO *pi ){ EXITMSG msg; EMGLST *p, *q; W i, mask; switch ( pi->exitkind ) { case EXIT_NORM: msg.kind = MS_EXIT; break; case EXIT_TERM: case EXIT_TERM_CHILD: msg.kind = MS_TERM; break; default: msg.kind = MS_ABORT; break; } msg.type = MS_SYS2; msg.size = (W)(sizeof(EXITMSG) - offsetof(EXITMSG, kind)); msg.pid = pi->procid; msg.code = pi->exitcode; mask = (W)MSGMASK(msg.kind); p = pi->emg_lst; while ( p != NULL ) { for ( i = 0; i < N_EMG; ++i ) { if (( p->ent[i].pid == 0 ) ||( (p->ent[i].t_mask & mask) == 0 )) { continue; } _tkse_snd_msg(p->ent[i].pid, (MESSAGE*)&msg, NOWAIT, TSD_TSM_VAL_M1); } q = p; p = p->next; Vfree(q); } pi->emg_lst = NULL;}/* Refer to/update a process termination notification list.*/LOCAL WER chgEmgEntry( PINFO *pi, W pid, W t_mask ){ W old_mask = 0; EMGLST *p, *free_p = NULL; W i, free_i = 0; for ( p = pi->emg_lst; p != NULL; p = p->next ) { for ( i = 0; i < N_EMG; ++i ) { if ( p->ent[i].pid == pid ) { old_mask = p->ent[i].t_mask; if ( t_mask > 0 ) { p->ent[i].t_mask = t_mask; /* Change */ } else if ( t_mask == 0 ) { p->ent[i].pid = 0; /* Delete */ } return old_mask; } if ( p->ent[i].pid == 0 ) { /* Empty entry */ free_p = p; free_i = i; } } } if ( t_mask <= 0 ) { return old_mask; } if ( free_p == NULL ) { /* Add new EMGLST */ p = Vcalloc(1, sizeof(EMGLST)); if ( p == NULL ) { return E_NOMEM; } p->next = pi->emg_lst; pi->emg_lst = p; free_p = p; free_i = 0; } /* Add */ free_p->ent[free_i].pid = pid; free_p->ent[free_i].t_mask = t_mask; return old_mask;}/* Set/refer to process termination notification*/LOCAL WER _tkse_req_emg( ID pid, W t_mask ){ PINFO *mypi, *pi; W old_mask; ER err; /* Parameter check */ if (( t_mask >= 0 )&&( ((UW)t_mask & ~(UW)(MM_ABORT|MM_EXIT|MM_TERM)) != 0 )) { err = E_PAR; goto err_ret1; } Lock(&ProcMgrLock); err = GetMyPinfo(&mypi); if ( err < E_OK ) { goto err_ret2; } err = GetPidToPinfo(pid, &pi); if ( err < E_OK ) { goto err_ret2; } if ( pi == mypi ) { err = E_ILUSE; goto err_ret2; } /* Set/refer to */ old_mask = chgEmgEntry(pi, mypi->procid, t_mask); if ( old_mask < E_OK ) { err = old_mask; goto err_ret2; } if ( t_mask > 0 ) { if ( old_mask == 0 ) { mypi->emg_cnt++; /* Add */ } } else if ( t_mask == 0 ) { if ( old_mask != 0 ) { mypi->emg_cnt--; /* Delete */ } } Unlock(&ProcMgrLock); return old_mask;err_ret2: Unlock(&ProcMgrLock);err_ret1: return err;}/*====================================================================== Common processing======================================================================*//* Execute process startup functions*/LOCAL void CallStartUp(PINFO *pi){ tk_sta_ssy(0, pi->resid, pi->procid);}/* Execute process cleanup functions*/LOCAL void CallCleanUp(PINFO *pi){ tk_cln_ssy(0, pi->resid, pi->procid);}/* Change process priority*/Inline W CLAMP(W val, W minv, W maxv){ return (val < minv) ? minv : ((val > maxv) ? maxv : val);}/* TK/SE = > TK priority */LOCAL PRI SE_K__Pri(W pri, W *slt){ if ((pri < MIN_ABSGRP_PRI )||( pri > MAX_RRGRP2_PRI)) { return E_PAR; } if (pri < MIN_RRGRP1_PRI) { *slt = ABSGRP_STIME; return pri + PRI_ADJVAL; } if (pri < MIN_RRGRP2_PRI) { *slt = MIN_RRGRP2_PRI - pri; return RRGRP1_TSKPRI; } *slt = (MAX_RRGRP2_PRI + 1) - pri; return RRGRP2_TSKPRI;}/* TK = > TK/SE priority */LOCAL W K_SE_Pri(PRI pri, W slt){ if (pri == RRGRP1_TSKPRI) { return CLAMP((MAX_RRGRP1_PRI + 1) - slt, MIN_RRGRP1_PRI, MAX_RRGRP1_PRI); } if (pri == RRGRP2_TSKPRI) { return CLAMP((MAX_RRGRP2_PRI + 1) - slt, MIN_RRGRP2_PRI, MAX_RRGRP2_PRI); } if (pri <= MAX_ABSGRP_TSKPRI) { return CLAMP(pri - PRI_ADJVAL, MIN_ABSGRP_PRI, MAX_ABSGRP_PRI); } return TSD_KSP_RTN_128; /* Invalid */}/* Check changes to priority (within the same group)*/LOCAL ER CheckPri(W old_pri, W new_pri){ if (new_pri < 0 ) { return E_PAR; } if (old_pri < MIN_RRGRP1_PRI) { if (new_pri >= MIN_RRGRP1_PRI) { return E_PAR; } } else if (old_pri < MIN_RRGRP2_PRI) { if ((new_pri < MIN_RRGRP1_PRI )||( new_pri >= MIN_RRGRP2_PRI)) { return E_PAR; } } else { if ((new_pri < MIN_RRGRP2_PRI )||( new_pri > MAX_RRGRP2_PRI)) { return E_PAR; } } return E_OK;}/* Fetch task state*/LOCAL ER RefTask(ID tid, T_RTSK *rtsk){ return tk_ref_tsk(tid, rtsk);}/* Fetch priority*/LOCAL W GetPri(ID tskid){ ER err; T_RTSK rtsk; err = RefTask(tskid, &rtsk); return (err != 0) ? err : K_SE_Pri(rtsk.tskpri, (W)rtsk.slicetime);}/* Set priority*/LOCAL ER ChangePri(ID tid, W pri){ ER er; W slt; return ( (er = tk_chg_pri(tid, SE_K__Pri(pri, &slt))) || (er = tk_chg_slt(tid, (UW)slt)) ) ? er : E_OK;}/* Fetch system time (second)*/LOCAL UW GetSysSec( void ){ SYSTIM now; longlong ll; tk_get_tim(&now); hilo_ll(ll, now.hi, now.lo); return (UW)lltol(li_div(ll, TSD_GSS_VAL_1000));}/* Check if a task is included in current process.*/EXPORT BOOL CheckSubTask(ID tid){ PINFO *pi; W i; pi = GetPinfo(TSK_SELF); if ( pi == NULL ) { return FALSE; } for (i = 0;(( i < MAX_SUBTASKS )&&( pi->tsk[i].tskid != tid)); i++){ ; } return ( i < MAX_SUBTASKS );}/* Process termination processing*/LOCAL void FinishProc(PINFO *pi){ PINFO *cpi, *ppi; PRCMINFO *info; QUEUE *q; W i; /* Release in-process resources: Execute cleanup() function for all managers. */ CallCleanUp(pi); /* PRCMINFO is cleared by execution of cleanup function. Set pinfo again because it is used to refer to PINFO in subsequent processing. */ tk_get_res(pi->resid, PM_SVC, (VP*)&info); info->pinfo = pi; Lock(&ProcMgrLock); LockPinfo(); /* Stop profile */ pi_profil(pi, NULL); /* Change the number of child processes of a parent process. */ ppi = pi->parent; if (ppi &&( ppi->nchild > 0)) { ppi->nchild--; } i = (W)(pi->nchild + pi->emg_cnt); if ( i > 0 ) { for ( q = ( pi->emg_cnt == 0U )? pi->q.next: UsedPI.next; q != &UsedPI; q = q->next ) { cpi = (PINFO*)q; if ( cpi->parent == pi ) { /* Change a parent process of child processes. */ cpi->parent = ppi; ppi->nchild++; if ( --i == 0 ) { break; } } if ( cpi->emg_lst != NULL ) { /* Reset process termination notification */ if ( chgEmgEntry(cpi, pi->procid, 0) > 0 ) { if ( --i == 0 ) { break; } } } } } /* Delete from queue */ QueRemove(&pi->q); UnlockPinfo();#if VIRTUAL_ADDRESS /* Delete address space of process */ UnmapProc(pi);#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -