⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 segio.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- *    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. * *---------------------------------------------------------------------- *//* *	segio.c (memory) * *	Segment management (Virtual storage version) *	Disk input/output and page file management */#include "segmgr.h"#include <bitop.h>#define TSD_ISI_VAL_5	5#define TSD_DPF_VAL_100	100#define TSD_OPF_VAL_7	7U#define TSD_OPF_VAL_8	8U#define TSD_EBN_RTN_M1	(-1)Inline void releaseDiskEntry( DE *de );LOCAL DBN PageFileDBN( DBN pf_dbn );LOCAL W AllocPageFile( void );LOCAL W getErrorBlockNo( DBN dbn, PhyBlk *pb );LOCAL void CallErrHdr( PFE *pfe, ER err );LOCAL DE* getDiskEntry( void );LOCAL UW MaxDiskEntry;		/* Maximum number of DiskEntry */EXPORT DE *DiskEntryTable;	/* DiskEntry table */LOCAL UW MaxErrHdrEntry;	/* Maximum number of ErrorHandlerEntry */LOCAL EHE *ErrHdrEntryTable;	/* ErrorHandlerEntry table *//* * The device is removable: TRUE */EXPORT BOOL isRemovableDisk( ID did ){	DE	*de = toDiskEntry(did);	return (BOOL)de->info.removable;}/* * The memory disk can be directly mapped: TRUE */EXPORT BOOL isMemoryDisk( ID did ){	DE	*de = toDiskEntry(did);	return ( de->memadr != INVADR );}/* * Narrow down blocks *	Starting from pgofs-th page of pb block list, narrow down to pgsiz pages,  *	and return the block list as a return value. *	If the blocks cannot be narrowed down, return NULL. *	It is necessary to use Ifree() to free the returned block list after it is used.  */EXPORT PhyBlk* CutPhyBlks( ID did, PhyBlk *pb, UW pgofs, UW pgsiz ){	DE	*de = toDiskEntry(did);	PhyBlk	*cut_pb, *top;	UW	n1, n2, i;#define TSD_CPB_VAL_2	2U	n1 = pgofs * de->blkcnt;	while ( n1 >= pb->len ) {		if ( pb->len == 0U ) {			goto err_ret;		}		n1 -= pb->len;		pb++;	}	top = pb;	n2 = n1 + (pgsiz * de->blkcnt);	while ( n2 > pb->len ) {		if ( pb->len == 0U ) {			goto err_ret;		}		n2 -= pb->len;		pb++;	}	i = (UW)(pb - top);	cut_pb = Imalloc((i + TSD_CPB_VAL_2) * sizeof(PhyBlk));	if ( cut_pb == NULL ) {		goto err_ret;	}	memcpy(cut_pb, top, (size_t)((i + 1U) * sizeof(PhyBlk)));	cut_pb[i].len = n2;	cut_pb[0].len -= n1;	cut_pb[0].blk += n1;	cut_pb[i + 1].len = 0U;	return cut_pb;err_ret:	DEBUG_PRINT(("CutPhyBlks Error\n"));	return NULL;}/* ------------------------------------------------------------------------ *//* *	Page file management *//* * Page file management information */typedef struct {	W	fd;		/* File descriptor */	PhyBlk	*pb;		/* Physical block structure */	UW	npage;		/* Total number of pages */	UW	use;		/* Number of pages in use */	UB	*usemap;	/* Bit map of pages in use */	DE	*de;		/* Disk information */} PageFileInfo;LOCAL	PageFileInfo	pfinfo;/* * Upper number limit of pages per page file *	Upper limit depends on the structure of PTE and DBN. */#define	PageFileLimit	( (((UW)MAX_PFA) - ((UW)PB_BASE) - 1U) & 0x7fffffffU )/* * Information on disk that contains page files */#define	PageFileDE()	( pfinfo.de )/* * Obtain usage state of page files */EXPORT void GetPageFileInfo( UW *total, UW *use ){	*total = pfinfo.npage;	*use   = pfinfo.use;}/* * Determine DBN of real disk block from page file DBN. */LOCAL DBN PageFileDBN( DBN pf_dbn ){	PhyBlk	*pb = pfinfo.pb;	W	blk = (pf_dbn.no - 1) * pfinfo.de->blkcnt;	DBN	dbn;	while ( (UW)blk >= pb->len ) {		blk -= (W)pb->len;		pb++;	}	dbn.no = (W)pb->blk + blk;	dbn.id = (UB)toDiskID(pfinfo.de);	return dbn;}/* * Obtain page file *	Return page file block number. */LOCAL W AllocPageFile( void ){	W	i;	ER	err;	/* To increase processing speed when page files are used up */	if ( pfinfo.use >= pfinfo.npage ) {		err = E_NOMEM;		goto err_ret;	}	i = BitSearch0(pfinfo.usemap, 0, (W)pfinfo.npage);	if ( i < 0 ) {		err = E_NOMEM;		goto err_ret;	}	BitSet(pfinfo.usemap, (UW)i);	pfinfo.use++;	return i + 1;err_ret:	DEBUG_PRINT(("AllocPageFile err = %d\n", err));	return err;}/* * Release page file */EXPORT void FreePageFile( W pfbn ){	BitClr(pfinfo.usemap, (UW)(pfbn - 1));	pfinfo.use--;}/* * Open page file *	Called from system initialization process (INIT=IMS). */EXPORT ER OpenPageFile( LINK *lnk ){	W	fd;	PhyBlk	*pb;	UW	npage;	UB	*usemap;	DE	*de;	W	nent, ofs, rsz, i, n;	ER	err;	if ( pfinfo.fd > 0 ) {		err = E_BUSY;		goto err_ret1;	}	/* Open page file */	fd = tkse_opn_fil(lnk, F_UPDATE|F_EXCL, NULL);	if ( fd < E_OK ) {		err = fd;		goto err_ret1;	}	/* Obtain disk block structure. */	err = tkse_GetRecInfo(fd, NULL, NULL, NULL, 0, &nent);	if ( err < E_OK ) {		goto err_ret2;	}	if ( nent <= 0 ) {		err = E_REC;		goto err_ret2;	}	pb = Imalloc((UW)nent * sizeof(PhyBlk));	if ( pb == NULL ) {		err = E_SYSMEM;		goto err_ret2;	}	err = tkse_GetRecInfo(fd, &ofs, &rsz, pb, nent, &nent);	if ( err < E_OK ) {		goto err_ret3;	}	/* Obtain disk information (Obtain AttachFS information). */	de = toDiskEntry((ID)err);	/* Combine blocks on a page basis, and discard the remaining blocks. */	npage = 0;	i = (ofs + de->info.blocksize - 1) / de->info.blocksize;	rsz -= (i * de->info.blocksize) - ofs;	rsz /= de->info.blocksize;	/* Number of valid record blocks */	pb[0].blk += (UW)i;			/* Discard remaining blocks. */	pb[0].len -= (UW)i;	for ( i = 0; i < nent; ++i ) {		n = (W)pb[i].len;		if ( n > rsz ) {			n = rsz;		}		rsz -= n;		n /= de->blkcnt;		/* Number of valid pages */		pb[i].len = (UW)n * (UW)de->blkcnt;	/* Discard remaining blocks. */		npage += (UW)n;	}	if ( npage > PageFileLimit ) {		npage = PageFileLimit;	}	/* Generate bit map of pages in use */	usemap = Icalloc(1, (npage + TSD_OPF_VAL_7) / TSD_OPF_VAL_8);	if ( usemap == NULL ) {		err = E_SYSMEM;		goto err_ret3;	}	/* Set page file management information */	LockSEG();	pfinfo.fd     = fd;	pfinfo.pb     = pb;	pfinfo.npage  = npage;	pfinfo.use    = 0;	pfinfo.usemap = usemap;	pfinfo.de     = de;	UnlockSEG();	return E_OK;err_ret3:	Ifree(pb);err_ret2:	(void)tkse_cls_fil(fd) ;err_ret1:	DEBUG_PRINT(("OpenPageFile err = %d\n", err));	return err;}/* * Close page file *	Called form system initialization process (INIT=IMS) * *	force = FALSE	Do not close if remaining blocks are in use. *	force = TRUE	Forcedly close even if remaining blocks are in use. *			However, subsequent operation is not guaranteed. *			System must be shut down immediately. */EXPORT ER ClosePageFile( BOOL force ){	W	fd;	ER	err, error = E_OK;	LockSEG();	if ( !force &&( pfinfo.use > 0U )) {		/* File pages cannot be closed because remaining blocks are in use. */		error = E_BUSY;		fd = 0;	} else {		/* Clear page file management information. */		fd = pfinfo.fd;		pfinfo.fd    = 0;		pfinfo.npage = 0;	}	UnlockSEG();	if ( fd > 0 ) {		/* Close page file. */		err = tkse_cls_fil(fd);		if ( err < E_OK ) {			error = err;		}		Ifree(pfinfo.pb);		Ifree(pfinfo.usemap);	}#ifdef DEBUG	if ( error < E_OK ) {		DEBUG_PRINT(("ClosePageFile err = %d\n", error));	}#endif	return error;}/* * Page in from page file. */EXPORT ER PageInPageFile( PTH *pth, VP laddr, UW lsid ){	PTE	pte;	DBN	dbn;	PFE	*pfe;	VP	p;	ER	err;	pte.w = GetPTE(pth);	dbn.id = PAGEFILE_ID;	dbn.no = pte.c.pfa - PB_BASE;	/* Obtain page frame. */	err = GetPageFrame(&pfe, dbn, NULL, MapRankMM0);	if ( err < E_OK ) {		goto err_ret1;	}	/* Update page frame information. */	pfe->md.page.lsid = lsid;	pfe->md.page.pn = (UW)laddr / (UW)PAGESIZE;	if ( isClearP(pte.w) ) {		/* Clear page frame. */		bzero(p = PFEtoLADR(pfe), (size_t)PAGESIZE);		WriteBackDCachePage(p, 0);		pfe->upd = TRUE;	} else if (( err == 0 )&&( dbn.no > 0 )) {		/* Load from page file. */		err = ReadWritePFE(pfe, TDC_READ);		if ( err < E_OK ) {			goto err_ret2;		}	}#if PT_Update == 0	/* If MMU does not have update flags, release page files to be written	   at the time of page-out. */	pfe->upd = TRUE;	if ( dbn.no > 0 ) {#else	/* If page files have been used up,	   actively release page files. */	if (( dbn.no > 0 )&&( pfinfo.use >= pfinfo.npage )) {#endif		FreePageFile(dbn.no);		pfe->dbn_no = 0;  /* Page file not allocated */		pfe->upd = TRUE;  /* Need to write at the time of page-out. */	}	if ( isLocalSpace(laddr) != 0 ) {		/* Update process statistical information */		PINFO *pinfo = GetPINFO_lsid(lsid);		if ( pinfo != NULL ) {			pinfo->allocpage++;		}	}	/* Register page frame */	RegistPageFrame(pfe, PFS_use);	/* Update page table */	pte.c.pfa = PFEtoPFA(pfe);	pte.w &= ~(UW)(PT_Clear | PT_Update);	pte.w |= (PT_Present | PT_Valid);	SetPTE(pth, pte.w, TRUE);	return E_OK;err_ret2:	UngetPageFrame(pfe);err_ret1:	DEBUG_PRINT(("PageInPageFile err = %d\n", err));	return err;}/* * Page out to page file *	When "nowrite = TRUE", return E_BUSY instead of *	writing page frames to the disk (page-out). */EXPORT ER PageOutPageFile( PFE *pfe, BOOL nowrite ){	VP	laddr;	UW	lsid;	PTH	pth;	PTE	pte;	ER	err;	/* Logical address */	laddr = (VP)(pfe->md.page.pn * PAGESIZE);	lsid = pfe->md.page.lsid;	InitPTH(&pth, laddr, lsid);	err = NextPTE(&pth);	if ( err < E_OK ) {		goto err_ret1;	}	/* Set pages to absent. */	pte.w = ChgPTE(&pth, 0U, ~(UW)(PT_Present|PT_Valid|PT_Update), TRUE);	if ( isUpdateP(pte.w) ) {		pfe->upd = TRUE;	}	/* If no change has been made, it is unnecessary to write. */	if ( pfe->upd != 0 ) {		if ( nowrite != 0 ) {			err = E_BUSY;			goto err_ret2;		}		if ( pfe->dbn_no == 0 ) {			/* Allocate new page file */			err = AllocPageFile();			if ( err < E_OK ) {				goto err_ret2;			}			pfe->dbn_no = err;			RegistDBH(pfe);		}		/* Write to page file */		err = ReadWritePFE(pfe, TDC_WRITE);		if ( err < E_OK ) {			goto err_ret2;		}	}	if ( isLocalSpace(laddr) != 0 ) {		/* Update process statistical information */		PINFO *pinfo = GetPINFO_lsid(lsid);		if ( pinfo != NULL ) {			pinfo->allocpage--;			pinfo->poutcount++;		}	}	/* Update map identification information */	pfe->md.w = 0;	/* Update page table */	pte.w = 0;	pte.c.pfa = pfe->dbn_no + PB_BASE;	(void)ChgPTE(&pth, pte.w, ~(UW)PT_Address, TRUE);	EndPTH(&pth, FALSE);	return E_OK;err_ret2:	/* Reset page table */	(void)ChgPTE(&pth, pte.w & (PT_Present|PT_Valid|PT_Update), ~0U, TRUE);err_ret1:#ifdef DEBUG	if ( !(nowrite &&( err == E_BUSY)) ) {		DEBUG_PRINT(("PageOutPageFile nowrite = %d err = %d\n",							nowrite, err));	}#endif	return err;}/* * Check the state of access by pfe (PFS_use) page frames, and if there is no access, * link pfe again to an unused (PFS_free) page frame queue. * PT_Accessed in the page table is cleared.  * * If page tables have been updated, release page files. */EXPORT void CheckAccessPageFile( PFE *pfe ){	VP	laddr;	PTE	pte;	laddr = (VP)(pfe->md.page.pn * PAGESIZE);	pte.w = CHG_PTE(laddr, pfe->md.page.lsid, 0U, ~(UW)PT_Accessed, TRUE);	if ( !isAccessedP(pte.w) ) {		/* Since there was no access, suspend pages. */		(void)CHG_PTE(laddr, pfe->md.page.lsid, 0, ~(UW)PT_Present, TRUE);		MovePageFrame(pfe, PFS_free);	}	if ( isUpdateP(pte.w) &&( pfe->dbn_no > 0 )) {		/* If page tables have been updated, release page files. */		FreePageFile(pfe->dbn_no);		RemoveDBH(pfe);		pfe->dbn_no = 0; /* Page file not allocated */	}}/* ------------------------------------------------------------------------ *//* *	Error handler-related *//* * Search for error handler */EXPORT FP SearchErrHdr( ID tid ){	EHE	*ehe;	for ( ehe = ErrHdrEntryTable;			ehe < &ErrHdrEntryTable[MaxErrHdrEntry]; ++ehe ) {		if ( ehe->tid == tid ) {			return ehe->errhdr;		}	}	return NULL;  /* Unregistered */}/* * Fetch error occurrence block number */LOCAL W getErrorBlockNo( DBN dbn, PhyBlk *pb ){	DE	*de = toDiskEntry(dbn.id);	W	no = dbn.no;	W	top, end;	while ( pb->len > 0U ) {		top = (W)pb->blk;		end = (W)(pb->blk + pb->len - 1U);		/* For an unmapped block, use a mapped block		   number in the same page. */		if (( no >= BLKTOP(de, top))		  &&( no <  (BLKTOP(de, end) + de->blkcnt) )) {			if ( no < top ) {				return top;			}			if ( no > end ) {				return end;			}			return no;		}		pb++;	}	return TSD_EBN_RTN_M1;}/* * Call error handler */LOCAL void CallErrHdr( PFE *pfe, ER err ){	DiskErrInfo	errinfo;	FP		errhdr;	MEL		*mel;	ME		*me;	DBN		dbn;	dbn.id = pfe->dbn_id;	dbn.no = pfe->dbn_no;	/* Common section of error information */	errinfo.err = ERtoERR(err);	errinfo.diskid = (ID)dbn.id;	/* Call the error handler for each MapEntry where pfe are mapped. */	for ( mel = pfe->md.mel; mel != NULL; mel = mel->next_me ) {		me = mel->me;		/* Check if the error handler has been registered. */		errhdr = SearchErrHdr(me->tid);		if ( errhdr == NULL ) {			continue;  /* Unregistered */		}		/* Set error information and call the error handler. */		errinfo.taskid = me->tid;		errinfo.mode = me->mode;		errinfo.mode.addr = mappingAddress(me, pfe);		errinfo.blk = (UW)getErrorBlockNo(dbn, me->pb);		(*errhdr)(&errinfo);	}}/* * Register/deregister disk error handler *	Define disk error handler *	When "errhdr = NULL", reset definitions of error handler. */EXPORT ER _NotifyDiskErr( FP errhdr ){	EHE	*ehe, *free;	ID	mytid = GetMyTid();	ER	err;	LockSEG();	/* Search for free entry */	free = NULL;	for ( ehe = ErrHdrEntryTable;			ehe < &ErrHdrEntryTable[MaxErrHdrEntry]; ++ehe ) {		if ( ehe->tid == mytid ) {			if ( errhdr != NULL ) {				/* Reregister */				ehe->errhdr = errhdr;			} else {				/* Deregister */				ehe->tid = 0;			}			UnlockSEG();			return E_OK;		}		if ( ehe->tid == 0 ) {			free = ehe;		}	}	if ( errhdr == NULL ) {		err = E_NOEXS;		goto err_ret;	}	if ( free   == NULL ) {		err = E_LIMIT;		goto err_ret;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -