📄 procmap.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. * *---------------------------------------------------------------------- *//* * procmap.c (memory) * * Segment management (Virtual storage version) * Process map */#include "segmgr.h"#include "prcinfo.h"#include <extension/sys/tkse_ssid.h>/* * Model-based support for object formats *//* ELF is basically supported by all models. */#define ELF_SUPPORT 1#define TSD_WLM_POS_0 0#define TSD_WLM_POS_1 1#define TSD_WLM_POS_2 2#define TSD_LSP_POS_2 2#define TSD_LPF_ERR_M1 (-1)#define TSD_MPR_ERR_M1 (-1)#define TSD_CSP_VAL_M1 (-1)#define TSD_SPS_VAL_2 2/* * Default user stack size */EXPORT W DefaultStackSize; /* Byte *//* * Object format */typedef enum { UNKNOWN, AOUT, COFF, ELF } OBJ_TYP;typedef struct { OBJ_TYP typ; /* Object format */ unsigned int sysproc:1; /* If system process is specified: 1 */ OBJ_HDR hdr; /* Object header */} OBJ_INF;typedef struct { W fd; /* File descriptor */ W fdtype; /* File type */ ID mid[N_LDMID]; /* File map ID */ VP loadadr; /* Load address */ UH dpage; /* Number of disk map pages */ UH mpage; /* Number of memory map pages */ FP entry; /* Program entry */ TC name[L_FNM]; /* Name */} SysProgInfo;LOCAL WER OpenProgFile( POBJ_HDR *pohdr, TC *name, OBJ_INF *obj, BzRead *bzr );LOCAL ER demand_load( LDINFO *li, UW lsid, UW mode, OBJ_INF *obj, W nent, FP *entry, BzRead *bzr );LOCAL ER direct_load( LDINFO *li, UW lsid, UB mode, OBJ_INF *obj, FP *entry, BzRead *bzr );LOCAL ER loadprogfile( POBJ_HDR *pohdr, UW lsid, UW mode, LDINFO *inf, TC *name, FP *entry );LOCAL ER unloadprogfile( LDINFO *inf, UW lsid );LOCAL DYNLD* newDynld( PRCMINFO *pmi );LOCAL void freeDynld( DYNLD *dynld );LOCAL DYNLD* searchDynld( W loadid, PRCMINFO *pmi );LOCAL SysProgInfo* searchProgID( void );LOCAL ER SysProgStartup( TC *name, TC *arg, FP entry );/* * Open executable file * Note that name has a length of L_FNM. */LOCAL WER OpenProgFile( POBJ_HDR *pohdr, TC *name, OBJ_INF *obj, BzRead *bzr ){ W rsz, expsz; UB* buf; TC namebuf[L_FNM + 1]; ER err; memset(bzr, 0, (size_t)sizeof(BzRead)); obj->sysproc = 0; /* Open executable file */ err = ExecFileOpen(pohdr); if ( err < E_OK ) { goto err_ret1; } /* Obtain file name (process name) */ err = ExecFileGetName(pohdr, namebuf); if ( err < E_OK ) { goto err_ret2; } if ( name != NULL ) { tc_strncpy(name, namebuf, L_FNM); } /* Read header information */ err = ExecFileRead(pohdr, (VB*)&obj->hdr, sizeof(OBJ_HDR), 0, &rsz, NULL); if ( err < E_OK ) { goto err_ret2; } if ( rsz < (W)sizeof(OBJ_HDR) ) { err = E_REC; goto err_ret2; } /* Decompress the file if it is compressed. */ if ( ((err == BzRT1 )||( err == BzRT2)) /* Special compression format record */ && ((obj->hdr.bz.magic1 == BzMAGIC1 ) || (obj->hdr.bz.magic1 == BzMAGIC1S)) && (obj->hdr.bz.magic2 == BzMAGIC2 ) && (obj->hdr.bz.magic3 == BzMAGIC3 ) && ((W)obj->hdr.bz.expsz > rsz )) { expsz = (W)obj->hdr.bz.expsz; if ( obj->hdr.bz.magic1 == BzMAGIC1S ) { obj->sysproc = 1; } /* Buffer for decompression */ buf = Vmalloc((size_t)(expsz + rsz)); if ( buf == NULL ) { err = E_SYSMEM; goto err_ret2; } /* Load record data */ err = ExecFileRead(pohdr, (VB*)buf + expsz, rsz, 0, (W*)NULL, (VP)&bzr->recSubType); if ( err < E_OK ) { goto err_ret3; } /* Decompress */ err = buffer_uncompress(buf, buf + expsz + sizeof(Bz_HDR), expsz, rsz - (W)sizeof(Bz_HDR)); if ( err < E_OK ) { goto err_ret3; } /* Replace object header information with decompressed data. */ memcpy(&obj->hdr, buf, (size_t)sizeof(OBJ_HDR)); bzr->recBuf = buf; bzr->recLen = expsz; } /* Check object format */ obj->typ = UNKNOWN;#if AOUT_SUPPORT if (( obj->hdr.aout.a_magic == OMAGIC ) ||( obj->hdr.aout.a_magic == ZMAGIC )) { obj->typ = AOUT; }#endif#if ELF_SUPPORT if (( obj->hdr.elf.e_ident[EI_MAG0] == ELFMAG0 ) &&( obj->hdr.elf.e_ident[EI_MAG1] == ELFMAG1 ) &&( obj->hdr.elf.e_ident[EI_MAG2] == ELFMAG2 ) &&( obj->hdr.elf.e_ident[EI_MAG3] == ELFMAG3 )) { obj->typ = ELF; }#endif return pohdr->desc;err_ret3: Vfree(buf);err_ret2: ExecFileClose(pohdr);err_ret1: DEBUG_PRINT(("OpenProgFile err = %d\n", err)); return err;}/* * Load executable file */EXPORT ER ReadProgFile( POBJ_HDR *pohdr, W ofs, VB *adr, W sz, BzRead *bzr ){ W rsz; ER err; if ( bzr->recBuf == NULL ) { /* Uncompressed format */ err = ExecFileRead(pohdr, adr, sz, ofs, &rsz, NULL); if ( err < E_OK ) { goto err_ret; } if ( rsz < sz ) { err = E_REC; goto err_ret; } } else { /* Compression format */ if ( sz > bzr->recLen ) { err = E_REC; goto err_ret; } memcpy(adr, bzr->recBuf + ofs, (size_t)sz); } return E_OK;err_ret: DEBUG_PRINT(("ReadProgFile err = %d\n", err)); return err;}/* * On-demand loading * lsid == 0 Not acceptable * lsid != 0 Load into local space */LOCAL ER demand_load( LDINFO *li, UW lsid, UW mode, OBJ_INF *obj, W nent, FP *entry, BzRead *bzr ){ PhyBlk *pb; ID did; W ofs, rsz, n; ER err; /* Obtain disk block structure */ pb = Imalloc(sizeof(PhyBlk) * (UW)(nent + 1)); if ( pb == NULL ) { err = E_SYSMEM; goto err_ret1; } did = ExecFileRecInfo(&li->pohdr, &ofs, &rsz, pb, nent, &n); if ( did < E_OK ) { err = did; goto err_ret2; } pb[n].len = 0; if ( ofs != 0 ) { err = E_REC; goto err_ret2; } switch ( obj->typ ) {#if AOUT_SUPPORT case AOUT: err = DemandLoad_aout(li, lsid, mode, &obj->hdr.aout, did, pb, entry, bzr); break;#endif#if COFF_SUPPORT case COFF: err = DemandLoad_coff(li, lsid, mode, &obj->hdr.coff, did, pb, entry, bzr); break;#endif#if ELF_SUPPORT case ELF: err = DemandLoad_elf(li, lsid, mode, &obj->hdr.elf, did, pb, entry, bzr); break;#endif default: /* Object format error (unsupported format) */ err = E_REC; break; } if ( err < E_OK ) { goto err_ret2; } Ifree(pb); return E_OK;err_ret2: Ifree(pb);err_ret1: DEBUG_PRINT(("demand_load err = %d\n", err)); return err;}/* * Global loading * lsid == 0 Load into system space * lsid != 0 Load into local space */LOCAL ER direct_load( LDINFO *li, UW lsid, UB mode, OBJ_INF *obj, FP *entry, BzRead *bzr ){ ER err; switch ( obj->typ ) {#if AOUT_SUPPORT case AOUT: err = DirectLoad_aout(li, lsid, mode, &obj->hdr.aout, entry, bzr); break;#endif#if COFF_SUPPORT case COFF: err = DirectLoad_coff(li, lsid, mode, &obj->hdr.coff, entry, bzr); break;#endif#if ELF_SUPPORT case ELF: err = DirectLoad_elf(li, lsid, mode, &obj->hdr.elf, entry, bzr); break;#endif default: /* Object format error (unsupported format) */ err = E_REC; break; } if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("direct_load err = %d\n", err)); return err;}/* * Process mapping */EXPORT ER MapProc( PINFO *pinfo, POBJ_HDR *pohdr, FP *entry ){IMPORT W ForceLoadFlag; /* debug.c forced load flag */ LDINFO *li = &pinfo->ldinfo; /* ldinfo has been cleared to 0. */ UW lsid = GetLSID_pinfo(pinfo); UW mode; OBJ_INF obj; BzRead bzr; ID did; W nent; ID oldrid; T_TSKSPC curspc; ER err; /* Check access right */ err = ExecFileCheck(pohdr); if ( err < E_OK ) { goto err_ret1; } /* To record that the initial process (INIT) opened an executable file, temporarily change resource IDs in its current task. */ oldrid = tk_set_rid(TSK_SELF, INIT_PINFO->resid); if ( oldrid < E_OK ) { err = ERtoERR(oldrid); goto err_ret1; } /* Open executable file */ err = OpenProgFile(pohdr, pinfo->name, &obj, &bzr); if ( err < E_OK ) { goto err_ret2; } li->pohdr = *pohdr; pohdr = &li->pohdr; if ((pohdr->type & (TPA_LINK | TMA_LINK)) != 0) { li->lnk = *(pohdr->src.lnk); } else { memset(&li->lnk, 0, sizeof(LINK)); } /* If the object has a specified system process, reflect it in pinfo. */ mode = ( (pinfo->sysproc |= obj.sysproc) != 0 )? (UW)LDMD_SYS: (UW)LDMD_USR; /* Obtain disk ID */ did = ExecFileRecInfo(&li->pohdr, NULL, NULL, NULL, 0, &nent); if ( did < E_OK ) { err = did; goto err_ret3; } /* Change to logical space of process (pinfo) to be loaded */ err = ChangeLogicalSpace(&curspc, GetTSKSPC_pinfo(pinfo)); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret3; } err = TSD_MPR_ERR_M1; if ( (did > 0) && !isRemovableDisk(did) &&( bzr.recBuf == NULL ) &&( ForceLoadFlag == 0 )) { /* On-demand loading */ err = demand_load(li, lsid, mode, &obj, nent, entry, &bzr); /* (err < E_OK) If files cannot be loaded on demand, load them all at once. */ } if ( err < E_OK ) { /* Global loading */ err = direct_load(li, lsid, (UB)mode, &obj, entry, &bzr); if ( err < E_OK ) { goto err_ret4; } } /* Turn back to original logical space. */ ChangeLogicalSpace(NULL, curspc); /* Release memory for decompression */ if ( bzr.recBuf != NULL ) { Vfree(bzr.recBuf); } /* If files are not loaded on demand, close executable files. */ if ( li->dpage == 0U ) { ExecFileClose(pohdr); } /* Return resource ID */ tk_set_rid(TSK_SELF, oldrid);#ifdef MaxStackSize if ( li->stacksz > MaxStackSize ) { err = E_REC; goto err_ret5; }#endif /* Initialize local memory space */ err = InitLocalMemory(pinfo); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret5; } return E_OK;err_ret5: UnmapProc(pinfo); goto err_ret1;err_ret4: ChangeLogicalSpace(NULL, curspc);err_ret3: if ( bzr.recBuf != NULL ) { Vfree(bzr.recBuf); } ExecFileClose(pohdr);err_ret2: tk_set_rid(TSK_SELF, oldrid);err_ret1: DEBUG_PRINT(("MapProc err = %d\n", err)); return err;}/* * Process unmapping */EXPORT ER UnmapProc( PINFO *pinfo ){ LDINFO *li = &pinfo->ldinfo; UW lsid = GetLSID_pinfo(pinfo); ID oldrid; W i; ER err, error; err = error = E_OK; for ( i = 0; i < N_LDMID; ++i ) { if ( li->mid[i] == 0 ) { continue; } /* Reset disk map */ err = UnmapDisk(li->mid[i], MD_RDONLY); if ( err < E_OK ) { error = err; } } if ( li->dpage > 0U ) { /* Since the initial process (INIT) opens an executable file, temporarily change resource IDs in its current task. */ oldrid = tk_set_rid(TSK_SELF, INIT_PINFO->resid); if ( err < E_OK ) { error = ERtoERR(err); } else { /* Close executable file */ err = ExecFileClose(&li->pohdr); if ( err < E_OK ) { error = err; } /* Return resource ID */ tk_set_rid(TSK_SELF, oldrid); } } /* Reset memory map */ err = UnmakeSpace((VB*)li->topadr + (li->dpage * (UW)PAGESIZE), (W)li->mpage, (W)lsid); if ( err < E_OK ) { error = ERtoERR(err); }#ifdef DEBUG if ( error < E_OK ) { DEBUG_PRINT(("UnmapProc err = %d\n", error)); }#endif return error;}/* * Stack mapping */EXPORT ER MapStack( PINFO *pinfo, W stksz, VP *laddr ){#define INIT_STACKSZ 128 /* Although the size depends on the CPU, allocate an appropriate size. */ UW lsid = GetLSID_pinfo(pinfo); UW npage = PageCount((UW)stksz) + 1U; VB *p; T_TSKSPC curspc; ER err; if ( stksz < INIT_STACKSZ ) { err = E_PAR; goto err_ret1; } /* Allocate a stack area on user space */ p = AllocMemorySpace((W)npage, lsid); if ( p == NULL ) { err = E_NOMEM; goto err_ret1; } /* Set memory space */ err = MakeSpace(p + PAGESIZE, (W)npage - 1, (W)lsid, (UW)PTE_UMEM_NC); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret2; } /* To set task startup parameters, make access to the user stack at task * startup (tk_sta_tsk). Since occurrence of page fault leads to system down, * perform page-in beforehand. In a strict sense, even if page-in is performed * at this point, page-out may occur (leading to system down) until * tk_sta_tsk() processing is performed. However, such a possibility is * considered low and therefore specific measures are not taken here. */ err = ChangeLogicalSpace(&curspc, GetTSKSPC_lsid(lsid)); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret3; } memset(p + PAGESIZE + stksz - INIT_STACKSZ, 0, (size_t)INIT_STACKSZ); ChangeLogicalSpace(NULL, curspc); *laddr = p + PAGESIZE; return E_OK;err_ret3: UnmakeSpace(p + PAGESIZE, (W)npage - 1, (W)lsid);err_ret2: FreeMemorySpace(p, lsid);err_ret1: DEBUG_PRINT(("MapStack err = %d\n", err)); return err;}/* * Stack unmapping */EXPORT ER UnmapStack( PINFO *pinfo, VP laddr ){ UW lsid = GetLSID_pinfo(pinfo); VB *p = laddr; UW npage; ER err; /* Release stack area from user space. */ npage = (UW)FreeMemorySpace(p - PAGESIZE, lsid); if ( npage <= 0U ) { err = E_SYS; goto err_ret; } /* Remove memory space. */ err = UnmakeSpace(p, (W)npage - 1, (W)lsid); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("UnmapStack err = %d\n", err)); return err;}/* ======================================================================== *//* * Program loading * Used in dynamic loading and system program loading * * lsid = 0 Load into system space (system program loading) * lsid > 0 Load into local space (dynamic loading) */LOCAL ER loadprogfile( POBJ_HDR *pohdr, UW lsid, UW mode, LDINFO *inf, TC *name, FP *entry ){IMPORT W ForceLoadFlag; /* debug.c forced load flag */ OBJ_INF obj; BzRead bzr; ID did; W nent; ER err; memset(inf, 0, (size_t)sizeof(LDINFO)); /* Open executable file */ err = OpenProgFile(pohdr, name, &obj, &bzr); if ( err < E_OK ) { goto err_ret1; } inf->pohdr = *pohdr; /* Obtain disk ID */ did = ExecFileRecInfo(&inf->pohdr, NULL, NULL, NULL, 0, &nent); if ( did < E_OK ) { err = did; goto err_ret2; } err = TSD_LPF_ERR_M1; if ( (did > 0) && ((lsid > 0U) || isMemoryDisk(did)) && (!isRemovableDisk(did)) && (bzr.recBuf == NULL) && (ForceLoadFlag == 0) ) { /* On-demand loading */ err = demand_load(inf, lsid, mode, &obj, nent, entry, &bzr); /* (err < E_OK) If files cannot be loaded on demand, load them all at once. */ } if ( err < E_OK ) { /* Global loading */ err = direct_load(inf, lsid, (UB)mode, &obj, entry, &bzr); if ( err < E_OK ) { goto err_ret2; } } /* Release memory for decompression */ if ( bzr.recBuf != NULL ) { Vfree(bzr.recBuf); } /* If files are not loaded on demand, close executable files. */ if ( inf->dpage == 0U ) { ExecFileClose(&inf->pohdr); memset(&inf->pohdr, 0, sizeof(POBJ_HDR)); } return E_OK;err_ret2: if ( bzr.recBuf != NULL ) { Vfree(bzr.recBuf); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -