📄 page.c
字号:
* Page files: Release page files. */ W n = (W)pte.c.pfa - PB_BASE; if ( n > 0 ) { FreePageFile(n); } } return E_OK;}/* * Lock page frame. */EXPORT void LockPageFrame( PFE *pfe ){ if ( pfe == NULL ) { return; /* Not to be managed */ } if ( pfe->stat != PFS_lock ) { MovePageFrame(pfe, PFS_lock); }}/* * Unlock page frame. */EXPORT void UnlockPageFrame( PFE *pfe ){ if ( pfe == NULL ) { return; /* Not to be managed */ } if ( pfe->dbn_id == PAGEFILE_ID ) { /* Page file */ MovePageFrame(pfe, PFS_use); } else { /* Disk map */ CheckStateDiskMap(pfe); }}/* * Number of lock counts */EXPORT W LockCount( PFE *pfe, VP laddr, UW lsid, W cnt ){ W lkcnt = E_MACV; /* If page files are not to be managed, return 1 to indicate they are resident. */ if ( pfe == NULL ) { return 1; } if ( pfe->dbn_id == PAGEFILE_ID ) { /* Page file */ PFE_ETC etc; etc.w = pfe->etc; lkcnt = (W)etc.p.lkcnt + cnt; if (( lkcnt < 0 )||( lkcnt > MaxLockCount )) { goto err_ret1; } etc.p.lkcnt = lkcnt; pfe->etc = etc.w; } else { /* Disk map */ MEL *mel; for ( mel = pfe->md.mel; mel != NULL; mel = mel->next_me ) { ME *me = mel->me; VB *addr; if ( !me->mapped ) { continue; /* Already unmapped */ } addr = PageAlignL(me->mode.addr); if (( lsid != me->mode.space ) ||( (VB*)laddr < addr ) ||( (VB*)laddr >= (addr + (me->npage * (UW)PAGESIZE )))) { continue; /* Not to be managed */ } lkcnt = (W)mel->lkcnt + cnt; if (( lkcnt < 0 )||( lkcnt > MaxLockCount )) { goto err_ret1; } mel->lkcnt = (UB)lkcnt; break; } } if ( lkcnt < E_OK ) { goto err_ret0; } return lkcnt;err_ret1: lkcnt = E_LIMIT;err_ret0: DEBUG_PRINT(("LockCount err = %d\n", lkcnt)); return lkcnt;}/* ------------------------------------------------------------------------ *//* * Statistical information *//* * Obtain memory statistical information */EXPORT void GetMemInfo( MemoryInfo *info ){ LockSEG(); info->page_frame.total = MaxPages; info->page_frame.resident = LockPFE_Q.diskmap + LockPFE_Q.other; info->page_frame.unresident = UsePFE_Q.other + FreePFE_Q.other; info->page_frame.diskcache = UsePFE_Q.diskmap + FreePFE_Q.diskmap; GetPageFileInfo(&info->page_file.total, &info->page_file.use); info->safetymargin = (UW)SafetyMargin; UnlockSEG();}/* * Number of pages allocatable as general-purpose memory */EXPORT W AvailablePages( void ){ UW pgf_total, pgf_use; W npage; LockSEG(); GetPageFileInfo(&pgf_total, &pgf_use); npage = (W)(pgf_total - pgf_use + UsePFE_Q.diskmap + FreePFE_Q.diskmap + UninitPageCount); UnlockSEG(); npage -= SafetyMargin; if ( npage < 0 ) { npage = 0; } return npage;}/* * Number of pages that can be made resident */EXPORT W LockablePages( W *nopgout_p ){ UW pgf_total, pgf_use; W npage, pgf_free, nopgout; nopgout = 0; GetPageFileInfo(&pgf_total, &pgf_use); pgf_free = pgf_total - pgf_use; /* Number of pages (included in non-resident memory) that can be paged out */ npage = UsePFE_Q.other + FreePFE_Q.other; if ( npage > pgf_free ) { nopgout = npage - pgf_free; npage = pgf_free; } npage += UsePFE_Q.diskmap + FreePFE_Q.diskmap + UninitPageCount; /* leaving the safety margin for the disabled part to resident */ npage -= SafetyMargin; if ( npage < 0 ) { nopgout += npage; if ( nopgout < 0 ) { nopgout = 0; } npage = 0; } if ( nopgout_p != NULL ) { *nopgout_p = nopgout; } return npage;}/* * Maximum number of preload pages (1 to MaxPageIO) */EXPORT W MaxPreLoad( void ){ UW n; n = UninitPageCount + FreePFE_Q.diskmap + FreePFE_Q.other + 1U; if ( n > MaxPageIO ) { n = MaxPageIO; } return (W)n;}/* ------------------------------------------------------------------------ *//* * Initialization processing *//* * Generate page frame entry * (before kernel startup) */EXPORT ER InitPageFrameEntry( RealMemoryInfo *meminfo ){ W dbh_limit; VP tbl_top, laddr; UW n, i; ER err; /* Obtain SYSCONF definition information. */ err = GetSysConf_bms((UB*)"LimitDBH", &dbh_limit, 1); if ( err < E_OK ) { goto err_ret; } err = GetSysConf_bms((UB*)"SafetyMargin", &SafetyMargin, 1); if ( err < E_OK ) { SafetyMargin = TSD_IPE_SAF_32; } /* Total amount of memory (number of bytes) */ n = 0U; for ( i = 0U; i < (UW)meminfo->n; ++i ) { n += meminfo->a[i].b.nbyte; } /* Exclude a memory area for management table to determine the number of pages provisionally. */ n -= sizeof(PFE); MaxDBH = MaxPages = n / ((UW)PAGESIZE + sizeof(PFE) + sizeof(DBH)); if ( MaxDBH > (UW)dbh_limit ) { MaxDBH = (UW)dbh_limit; MaxPages = (n - (sizeof(DBH) * MaxDBH)) / ((UW)PAGESIZE + sizeof(PFE)); } /* Reserve area for management table */ n = (sizeof(PFE) * (MaxPages + 1)) + (sizeof(DBH) * MaxDBH); tbl_top = AllocRealMem(meminfo, n); if ( tbl_top == NULL ) { err = E_NOMEM; goto err_ret; } /* Round off memory area on a page basis. */ n = 0U; for ( i = 0U; i < (UW)meminfo->n; ++i ) { laddr = PageAlignU(meminfo->a[i].b.laddr); meminfo->a[i].p.npage = (meminfo->a[i].b.nbyte - ((UW)laddr - (UW)meminfo->a[i].b.laddr)) / (UW)PAGESIZE; meminfo->a[i].p.laddr = laddr; n += meminfo->a[i].p.npage; /* Count of all pages */ if ( n > MaxPages ) { meminfo->a[i].p.npage -= n - MaxPages; n = MaxPages; } } MaxPages = n; /* Total number of pages */ MemInfo = meminfo; /* Frame memory information */ /* Generate PFE table */ PageFrameEntry = tbl_top; tbl_top = (VP)((PFE*)tbl_top + MaxPages + 1); /* Generate/initialize DBH table */ DiskBlockHash = tbl_top; tbl_top = (VP)((DBH*)tbl_top + MaxDBH); memset_w(DiskBlockHash, 0, (size_t)MaxDBH); /* Initialize page management queue */ InitUninitPages(); /* Uninitialized page */ InitPFE_Q(&LockPFE_Q); /* Queue for lock page */ InitPFE_Q(&UsePFE_Q); /* Queue for page in use */ InitPFE_Q(&FreePFE_Q); /* Queue for free page */ return E_OK;err_ret: BMS_DEBUG_PRINT(("InitPageFrameEntry err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * Cyclic processing */LOCAL ID CycTskID; /* Cyclic processing task ID */LOCAL W SyncPeriod; /* Operation cycle *//* * Check access to page in use */LOCAL void AccessCheck( void ){ PFE *pfe, *npfe; npfe = NextPFE_Q(&UsePFE_Q, NULL); while ( (pfe = npfe) != NULL ) { npfe = NextPFE_Q(&UsePFE_Q, pfe); if ( pfe->dbn_id == PAGEFILE_ID ) { /* Page file */ CheckAccessPageFile(pfe); } else { /* Disk map */ CheckAccessDiskMap(pfe); } }}/* * Cyclic processing task */LOCAL void CyclicProcess( void ){ for ( ;; ) { tk_dly_tsk((RELTIM)(SyncPeriod / TSD_CIP_DIV_2)); /* Synchronize file system */ LockSEG(); (void)SyncDisk(NULL, 0, SYNCONLY); UnlockSEG(); tk_dly_tsk((RELTIM)(SyncPeriod / TSD_CIP_DIV_2)); /* Check access */ LockSEG(); AccessCheck(); UnlockSEG(); }}/* * Start cyclic processing task */EXPORT ER InitCyclicProcess( void ){ T_CTSK ctsk; ER err; /* Obtain SYSCONF definition information. */ err = GetSysConf_bms((UB*)"SyncPeriod", &SyncPeriod, 1); if ( err < E_OK ) { goto err_ret; } if ( SyncPeriod <= 0 ) { return E_OK; /* Do not perform cyclic processing */ } /* Start cyclic processing task */ SetOBJNAME(ctsk.exinf, "SCyc"); ctsk.task = CyclicProcess; ctsk.itskpri = TSD_ICP_ITP_136; ctsk.stksz = TSD_ICP_STK_2048; ctsk.tskatr = TA_HLNG|TA_RNG0; err = tk_cre_tsk(&ctsk); if ( err < E_OK ) { goto err_ret; } CycTskID = err; err = tk_sta_tsk(CycTskID, 0); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: BMS_DEBUG_PRINT(("InitCyclicProcess err = %d\n", err)); return err;}/* ======================================================================== *//* * Debug support function */#if DEBUGFUNC_SUPPORT#define M(i, c) ( ( (i) != 0 )? (c): '-' )/* * opt = 1 Disk map * 2 Page file * 4 Other */LOCAL BOOL dumpPF1( PFE *pfe, UW opt ){ if ( pfe->md.w == 0U ) { if ( (opt & TSD_DP1_MSK_4) == 0U ) { return FALSE; } } else if ( pfe->dbn_id == PAGEFILE_ID ) { if ( (opt & TSD_DP1_MSK_2) == 0U ) { return FALSE; } } else { if ( (opt & TSD_DP1_MSK_1) == 0U ) { return FALSE; } } printf(" [%4d] %08x s:%d r:%d %c%c%c d:%2d %08x (%4d) h:%4d e:%03x", PFEtoPFN(pfe), /* Page frame number */ PFEtoLADR(pfe), /* Page frame address */ pfe->stat, /* Usage state */ pfe->rank, /* Usage rank */ M(pfe->reg, 'R'), /* Queue registration state */ M(pfe->upd, 'U'), /* Update state */ M(pfe->err, 'E'), /* I/O error state */ pfe->dbn_id, pfe->dbn_no, /* Disk blocks to be used */ DBHindex(pfe->dbn_no), /* Hash value */ pfe->dbh, /* Disk block hash */ pfe->etc /* PFE_ETC information */ ); if ( pfe->md.w == 0U ) { printf(" -:"); } else if ( pfe->dbn_id == PAGEFILE_ID ) { printf(" p:%3d %08x", pfe->md.page.lsid, /* Logical space */ pfe->md.page.pn * (UW)PAGESIZE /* Address */ ); } else { MEL *mel; for ( mel = pfe->md.mel; mel != NULL; mel = mel->next_me ) { printf(" %c:%d %d:%08x", ( mel->me->mapped != 0 )? 'm': 'u', mel->me->mapid, mel->me->mode.space, mel->me->mode.addr ); } } printf("\n"); if ( DumpMore(1) ) { return TRUE; } return FALSE;}LOCAL BOOL dumpPFque( PFE_Q *pfe_q, UW opt ){ PFE *pfe = NULL; while ( (pfe = NextPFE_Q(pfe_q, pfe)) != NULL ) { if ( dumpPF1(pfe, opt) ) { return TRUE; } } return FALSE;}LOCAL BOOL dumpPFuninit( UW opt ){ PFN pfn; PFE *pfe; for ( pfn = UninitPageQ->next; pfn != 0; pfn = pfe->next ) { pfe = PFNtoPFE(pfn); printf(" [%4d] - [%4d] s:%d\n", pfn, pfn + pfe->dbn_no - 1U, pfe->stat); if ( DumpMore(1) ) { return TRUE; } } return FALSE;}LOCAL BOOL dumpPFhash( UW opt ){ PFN pfn; PFE *pfe; W i; for ( i = 0; i < MaxDBH; ++i ) { pfn = DiskBlockHash[i]; while ( pfn != 0 ) { pfe = PFNtoPFE(pfn); if ( dumpPF1(pfe, opt) ) { return TRUE; } pfn = pfe->dbh; } } return FALSE;}/* * Indicate state of page frames * opt = 0x0F000 Lock page * 0x00F00 Page in use * 0x000F0 Unused page * 0x0000F Uninitialized page * 0xF0000 Hash table */EXPORT void DumpPF( UW opt ){ printf("PAGE FRAME: Total = %d MaxDBH = %d\n", MaxPages, MaxDBH); printf(" lock use free uninit\n" " diskmap %4d %4d %4d\n" " other %4d %4d %4d %4d\n", LockPFE_Q.diskmap, UsePFE_Q.diskmap, FreePFE_Q.diskmap, LockPFE_Q.other, UsePFE_Q.other, FreePFE_Q.other, UninitPageCount); DumpMore(0); if ( (opt & TSD_DPP_MSK_0XF000) != 0U ) { /* Indicate state of lock page */ if ( dumpPFque(&LockPFE_Q, TSD_DPP_VAL_MC1) ) { return; } } if ( (opt & TSD_DPP_MSK_0X0F00) != 0U ) { /* Indicate state of page in use */ if ( dumpPFque(&UsePFE_Q, TSD_DPP_VAL_MC2) != 0 ) { return; } } if ( (opt & TSD_DPP_MSK_0X00F0) != 0U ) { /* Indicate state of unused page */ if ( dumpPFque(&FreePFE_Q, TSD_DPP_VAL_MC3) != 0 ) { return; } } if ( (opt & TSD_DPP_MSK_0X000F) != 0U ) { /* Indicate state of uninitialized page */ if ( dumpPFuninit(TSD_DPP_VAL_MC4) != 0 ) { return; } } if ( (opt & TSD_DPP_MSK_0XF0000) != 0U ) { /* Indicate state of hash table */ if ( dumpPFhash(TSD_DPP_VAL_MC5) != 0 ) { return; } }}/* * Indicate general information on segment management */EXPORT void DumpSegInfo( void ){ UW n; printf("SegMgr:\n"); /* Hash hit rate */ n = HashHitCount + HashMissCount; printf(" Hash Hit = %d/%d [%d%%]\n", HashHitCount, n, ( n > 0 )? HashHitCount * TSD_DSI_VAL_100 / n: 0); /* Number of intercepted pages */ printf(" Snatch = %d\n", SnatchCount); /* Page frame address */ printf(" Page Frame:\n"); for ( n = 0; n < MemInfo->n; n++ ) { printf(" [%d] 0x%08x - %d page\n", n, MemInfo->a[n].p.laddr, MemInfo->a[n].p.npage); } /* Reset counter */ HashHitCount = 0; HashMissCount = 0; SnatchCount = 0;}#endif /* DEBUGFUNC_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -