📄 segmgr.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. * *---------------------------------------------------------------------- *//* * segmgr.c (memory) * * Segment management (Virtual storage version) */#include "segmgr.h"#include <extension/sys/tkse_ssid.h>#include <extension/sys/svc/ifsegment.h>LOCAL W SegSVCentry( VP para, W fn );LOCAL ER segInitialize( void );LOCAL ER segFinish( void );#define TSD_IFM_VAL_3 3U#define TSD_ARM_VAL_7 7U/* * Exclusive control lock * At OS startup, Lock() is called before CreateLock(). * In this case, set initial values to prevent wait sate. */EXPORT FastLock SegLock = { -1, -1 };EXPORT FastLock FsLock = { -1, -1 };/* * Read SYSCONF (with error logs by syslog) */EXPORT ER GetSysConf_log( UB *name, W *val, W n ){ W buf[L_SYSCONF_VAL]; if ( GetSysConf((UB*)name, buf) != n ) { SYSLOG((LOG_ERR, "SegMgr: %s not defined", name)); return E_SYS; } while ( --n >= 0 ) { val[n] = buf[n]; } return E_OK;}/* * Read SYSCONF (with error logs by BMS output) */EXPORT ER GetSysConf_bms( UB *name, W *val, W n ){ W buf[L_SYSCONF_VAL]; if ( GetSysConf((UB*)name, buf) != n ) { BMS_DEBUG_PRINT(("SegMgr: %s not defined\n", name)); return E_SYS; } while ( --n >= 0 ) { val[n] = buf[n]; } return E_OK;}/* * Allocate memory from real memory area (RealMemoryInfo) * Used in initialization processing at startup only. * Cannot be used after initialization of page frames (InitPageFrameEntry) */EXPORT VP AllocRealMem( RealMemoryInfo *meminfo, UW size ){ W i; VP p; /* Round up on an 8-byte basis */ size = (size + TSD_ARM_VAL_7) & ~TSD_ARM_VAL_7; for ( i = 0; i < meminfo->n; ++i ) { if ( size <= meminfo->a[i].b.nbyte ) { p = meminfo->a[i].b.laddr; meminfo->a[i].b.laddr += size; meminfo->a[i].b.nbyte -= size; return p; } } return NULL; /* No free space */}/* ------------------------------------------------------------------------ *//* * Fixed-length memory pool management * * Library for efficiently managing small fixed-length memory blocks * Manages small memory blocks each of which can be accommodated in one page. */typedef struct { QUEUE q; /* Queue for page connection */ UW freeblk; /* Number of free blocks */ VP freelst; /* Free list */} FMB_HDR;/* * Initialize fixed-length memory pool */EXPORT void InitFMB( FMB_Pool *fmbp, UW size ){ /* Round up on a 4-byte basis */ size = (size + TSD_IFM_VAL_3) & ~TSD_IFM_VAL_3; QueInit(&fmbp->q); fmbp->blksz = size; fmbp->maxblk = (PAGESIZE - sizeof(FMB_HDR)) / size;}/* * Obtain fixed-length memory block * To disable writing to disk (page-out) when memory is obtained, * specify "nowrite = TRUE". */EXPORT VP AllocFMB( FMB_Pool *fmbp, BOOL nowrite ){ FMB_HDR *pg; VP alloc; /* Search for pages that have free blocks */ pg = (FMB_HDR*)QueSearchNE(&fmbp->q, &fmbp->q, 0, (W)offsetof(FMB_HDR, freeblk)); if ( (QUEUE*)pg == &fmbp->q ) { /* Obtain new page */ PFE *pfe = GetPFM(PFS_lock, nowrite); if ( pfe == NULL ) { goto err_ret; } pg = PFEtoLADR(pfe); pg->freeblk = fmbp->maxblk; pg->freelst = (VP)((UW)(pg + 1) | 1); QueInsert(&pg->q, &fmbp->q); } /* Obtain free block */ alloc = (VP)((UW)pg->freelst & ~1U); if ( ((UW)pg->freelst & 1U) == 0U ) { /* Fetch from free list */ pg->freelst = *(VP*)alloc; } else { /* Fetch from consecutive free areas located at the end of page */ pg->freelst = (VP)((VB*)pg->freelst + fmbp->blksz); } pg->freeblk--; return alloc;err_ret: DEBUG_PRINT(("AllocFMB Error\n")); return NULL;}/* * Release fixed-length memory block */EXPORT void FreeFMB( FMB_Pool *fmbp, VP adr ){ FMB_HDR *pg = PageAlignL(adr); if ( ++pg->freeblk < fmbp->maxblk ) { /* Connect to free list */ *(VP*)adr = pg->freelst; pg->freelst = adr; } else { /* Release page */ QueRemove(&pg->q); DiscardPageFrame(LADRtoPFE(pg)); }}/* ------------------------------------------------------------------------ *//* * Indirect queue */LOCAL FMB_Pool IndQuePool;/* * Initialize indirect queue */EXPORT void InitIndQue( IndQueTop *top ){ QueInit(&top->q); top->num = 0;}/* * Delete/re-initialize indirect queue */EXPORT void DeleteIndQue( IndQueTop *top ){ QUEUE *q, *nq; nq = top->q.next; while ( (q = nq) != &top->q ) { nq = q->next; FreeFMB(&IndQuePool, q); } InitIndQue(top);}/* * Insert ent at the end of top * To disable writing to disk (page-out) when memory is obtained for indirect queues, * specify "nowrite = TRUE". */EXPORT ER InsertIndQue( IndQueTop *top, VP ent, BOOL nowrite ){ IndQue *q; q = AllocFMB(&IndQuePool, nowrite); if ( q == NULL ) { goto err_ret; } QueInsert(&q->q, &top->q); q->ent = ent; top->num++; return E_OK;err_ret: DEBUG_PRINT(("InsertIndQue err = E_NOMEM\n")); return E_NOMEM;}/* * Delete ent. */EXPORT void RemoveIndQue( IndQueTop *top, VP ent ){ QUEUE *q; for ( q = top->q.next; q != &top->q; q = q->next ) { if ( ((IndQue*)q)->ent == ent ) { QueRemove(q); FreeFMB(&IndQuePool, q); top->num--; break; } }}/* * Return an entry that follows pos. * When "pos = NULL", return the first entry. * If pos is the last entry, return NULL. */EXPORT IndQue* NextIndQue( IndQueTop *top, IndQue *pos ){ VP q; if ( pos == NULL ) { q = top->q.next; } else { q = pos->q.next; } return ( q == top )? NULL: q;}/* ------------------------------------------------------------------------ */IMPORT ER ChkCallPLevel( void ); /* Examine call protection level (T-Kernel/SM) *//* * Extended SVC entry */LOCAL W SegSVCentry( VP para, W fn ){ ER err; /* Examine call protection level */ err = ChkCallPLevel(); if ( err < E_OK ) { goto err_ret; } switch ( fn ) { case SEG_ATTACHFS_FN: { SEG_ATTACHFS_PARA *p = para; err = _AttachFS(p->devname, p->omode, p->pinfo, p->diskinfo); } break; case SEG_DETACHFS_FN: { SEG_DETACHFS_PARA *p = para; err = _DetachFS(p->diskid, p->pinfo, p->eject); } break; case SEG_CHECKFS_FN: { SEG_CHECKFS_PARA *p = para; err = _CheckFS(p->devname, p->omode, p->pinfo); } break; case SEG_INFORMFS_FN: { SEG_INFORMFS_PARA *p = para; err = _InformFS(p->diskid, p->spec); } break; case SEG_SYNCFS_FN: { SEG_SYNCFS_PARA *p = para; err = _SyncFS(p->diskid, p->info); } break; case SEG_MAPDISK_FN: { SEG_MAPDISK_PARA *p = para; err = _MapDisk(p->diskid, p->block, p->mode); } break; case SEG_UNMAPDISK_FN: { SEG_UNMAPDISK_PARA *p = para; err = _UnmapDisk(p->mapid, p->flag); } break; case SEG_NOTIFYDISKERR_FN: { SEG_NOTIFYDISKERR_PARA *p = para; err = _NotifyDiskErr(p->errhdr); } break; case SEG_MAPMEMORY_FN: { SEG_MAPMEMORY_PARA *p = para; err = _MapMemory(p->paddr, p->len, p->attr, p->laddr); } break; case SEG_UNMAPMEMORY_FN: { SEG_UNMAPMEMORY_PARA *p = para; err = _UnmapMemory(p->laddr); } break; case SEG_MAKESPACE_FN: { SEG_MAKESPACE_PARA *p = para; err = _MakeSpace(p->laddr, p->npage, (UW)p->lsid, p->pte); } break; case SEG_UNMAKESPACE_FN: { SEG_UNMAKESPACE_PARA *p = para; err = _UnmakeSpace(p->laddr, p->npage, (UW)p->lsid); } break; case SEG_CHANGESPACE_FN: { SEG_CHANGESPACE_PARA *p = para; err = _ChangeSpace(p->laddr, p->npage, (UW)p->lsid, p->pte); } break; case SEG_LOCKSPACE_FN: { SEG_LOCKSPACE_PARA *p = para; err = _LockSpace(p->laddr, p->len); } break; case SEG_UNLOCKSPACE_FN: { SEG_UNLOCKSPACE_PARA *p = para; err = _UnlockSpace(p->laddr, p->len); } break; case SEG_CNVPHYSICALADDR_FN: { SEG_CNVPHYSICALADDR_PARA *p = para; err = _CnvPhysicalAddr(p->laddr, p->len, p->paddr); } break; case SEG_CHKSPACE_FN: { SEG_CHKSPACE_PARA *p = para; err = _ChkSpace(p->laddr, p->len, p->mode, p->env); } break; case SEG_CHKSPACETSTR_FN: { SEG_CHKSPACETSTR_PARA *p = para; err = _ChkSpaceTstr(p->str, p->max, p->mode, p->env); } break; case SEG_CHKSPACEBSTR_FN: { SEG_CHKSPACEBSTR_PARA *p = para; err = _ChkSpaceBstr(p->str, p->max, p->mode, p->env); } break; case SEG_CHKSPACELEN_FN: { SEG_CHKSPACELEN_PARA *p = para; err = _ChkSpaceLen(p->laddr, p->len, p->mode, p->env, (UW)p->lsid); } break; case SEG_READMEMSPACE_FN: { SEG_READMEMSPACE_PARA *p = para; err = _ReadMemSpace(p->laddr, p->buf, p->len, (UW)p->lsid); } break; case SEG_WRITEMEMSPACE_FN: { SEG_WRITEMEMSPACE_PARA *p = para; err = _WriteMemSpace(p->laddr, p->buf, p->len, (UW)p->lsid); } break; case SEG_SETMEMSPACEB_FN: { SEG_SETMEMSPACEB_PARA *p = para; err = _SetMemSpaceB(p->laddr, p->len, p->data, (UW)p->lsid); } break; default: { err = E_RSFN; } break; }err_ret: return err;}/* * Initialization processing of segment management * Initialization immediately before kernel startup */EXPORT ER init_segmgr( void ){ RealMemoryInfo *meminfo; ER err; /* Set page table corresponding to the entire real memory area, and obtain real memory area information (meminfo). */ err = InitRealMemoryArea(&meminfo); if ( err < E_OK ) { goto err_ret; } /* Initialization related to logical space control */ err = InitLogicalSpace(meminfo); if ( err < E_OK ) { goto err_ret; } /* Generate page frame entry (meminfo cannot be used subsequently) */ err = InitPageFrameEntry(meminfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: BMS_DEBUG_PRINT(("InitSegmentMgr_Part1 err = %d\n", err)); return err;}/* * Initialization processing of segment management * Initialization immediately after kernel startup */EXPORT ER start_segmgr( void ){ T_DSSY dssy; ER err; /* Generate exclusive control lock */ err = CreateLock(&SegLock, (UB*)"Seg"); if ( err < E_OK ) { goto err_ret; } err = CreateLock(&FsLock, (UB*)"SegF"); if ( err < E_OK ) { goto err_ret; } /* Initialize memory pool for indirect link */ InitFMB(&IndQuePool, sizeof(IndQue)); /* Initialization related to disk I/O */ err = InitSegIO(); if ( err < E_OK ) { goto err_ret; } /* Initialize disk map */ err = InitDiskMap(); if ( err < E_OK ) { goto err_ret; } /* Initialize system exception management */ err = InitExcMgr(TRUE); if ( err < E_OK ) { goto err_ret; } /* Initialize memory map for disk I/O */ err = InitMemoryMap(); if ( err < E_OK ) { goto err_ret; } /* Register the manager. */ dssy.ssyatr = TA_NULL; dssy.ssypri = SEG_PRI; dssy.svchdr = (FP)SegSVCentry; dssy.breakfn = NULL; dssy.startupfn = NULL; dssy.cleanupfn = NULL; dssy.eventfn = NULL; dssy.resblksz = 0; err = tk_def_ssy(SEG_SVC, &dssy); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: BMS_DEBUG_PRINT(("InitSegmentMgr_Part2 err = %d\n", err)); return err;}/* * Termination processing of segment management */EXPORT ER finish_segmgr( void ){ return E_OK;}/* * Initialization processing of segment management (Part3) */LOCAL ER segInitialize( void ){ ER err; /* Start cyclic processing task */ err = InitCyclicProcess(); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: BMS_DEBUG_PRINT(("segInitialize err = %d\n", err)); return err;}/* * Termination processing of segment management */LOCAL ER segFinish( void ){ ER err, error = E_OK; /* Deregister the manager. */ err = tk_def_ssy(SEG_SVC, NULL); if ( err < E_OK ) { error = err; } /* Termination processing of system exception management */ err = InitExcMgr(FALSE); if ( err < E_OK ) { error = err; } /* Delete exclusive control lock */ DeleteLock(&SegLock); DeleteLock(&FsLock); return error;}/* * Manager entry */EXPORT ER SegmentMgr( INT ac, UB *av[] ){ ER err; if ( ac >= 0 ) { /* Initialization processing */ err = segInitialize(); if ( err < E_OK ) { (void)segFinish(); } } else { /* Termination processing */ /* If termination processing "segFinish()" is performed here, * it becomes impossible to use CheckSpace() and output syslog(). * Since system termination is performed subsequently, * skip the termination processing of segment management. */ err = E_OK; } return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -