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

📄 diskmap.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 */LOCAL ER unmapDiskSpace( ME *me, SyncOpt opt ){	VP	laddr = PageAlignL(me->mode.addr);	UW	lsid  = me->mode.space;	W	npage = (W)me->npage;	ER	err, error = E_OK;	/* Reset mapping to memory (lock state is also reset temporarily). */	err = __UnmakeSpace(laddr, npage, lsid);	if ( err < E_OK ) {		error = err;		goto err_ret;	}	me->mapped = FALSE;	/* Synchronize page frames and release unnecessary MapEntry */	err = syncMapEntry(me, opt);	if ( err < E_OK ) {		error = err;	}	if ( me->alloc != 0 ) {		/* Release address space for mapping */		UnlockSEG();		err = FreeMemorySpace(laddr, lsid);		LockSEG();		if ( err < E_OK ) {			error = err;		}		me->alloc = FALSE;	}	if ( !me->memmap ) {		if ( LimitMapRank(me->mode.rank) ) {			MapCount--;		}	}err_ret:#ifdef DEBUG	if ( error < E_OK ) {		DEBUG_PRINT(("unmapDiskSpace err = %d\n", error));	}#endif	return error;}/* ------------------------------------------------------------------------ *//* * Disk synchronization *	opt = FORCEDEL	Cancel page frames and then, if there are still MapEntry to which pages *			frames are mapped, release them forcefully. *	opt = DISCARD	Cancel page frames and then, if there are still MapEntry *			to which pages frames are mapped, abort processing and *			return E_BUSY. *	opt = SYNCONLY	Page frames remain valid and are used again *			when mapped next time. *	opt = NOSYNC,WRITEALL	Not available * *	When "de = NULL", map to the whole disk. * *	(*) When "opt != SYNCONLY", UnlockSEG may occur temporarily. *	   Therefore, call page frames in LockFS & LockSEG state. *	   When "opt == SYNCONLY", only LockSEG is necessary. */EXPORT ER SyncDisk( DE *de, VW info, SyncOpt opt ){	ID	did;	ME	*me;	W	i;	ER	err, error = E_OK;	did = ( de != NULL )? toDiskID(de): 0;	/* Perform synchronous processing in order of MapEntry. */	for ( i = 0; i < (W)MaxMapEntry; ++i ) {		/* Skip unused entries. */		if ( MapEntryTable[i].next != (VP)TSD_MET_VAL_M1 ) {			continue;		}		me = MapEntryTable[i].me;		/* Check if they are to be synchronized. */		if (( did != 0 )&&( me->did != did )) {			continue;		}		if ( info != 0 ) {			if ( !(( me->mode.info == info )			     ||( me->mode.info == 0 )) ) {				 continue;			}		}		if (( opt != SYNCONLY )&& me->mapped ) {			if ( opt == DISCARD ) {				error = E_BUSY;				goto err_ret;			}			/* Forced reset of maps and synchronous processing */			err = unmapDiskSpace(me, opt);			if ( err < E_OK ) {				error = err;			}		} else {			/* Synchronous processing */			err = syncMapEntry(me, opt);			if ( err < E_OK ) {				error = err;			}		}	}	if ( opt != SYNCONLY ) {		/* Cancel the remaining page frames. */		DiscardPageFrameDE(de);	}err_ret:#ifdef DEBUG	if ( error < E_OK ) {		DEBUG_PRINT(("SyncDisk err = %d\n", error));	}#endif	return error;}/* * Page in disk maps. */EXPORT ER PageInMapDisk( ID mid, VP laddr ){	ME	*me;	ER	err;	me = checkMapID(mid);	if ( me == NULL ) {		err = E_ID;		goto err_ret;	}	if ( !me->memmap ) {		err = pageinMapEntry(me, laddr);		if ( err < E_OK ) {			goto err_ret;		}	}	return E_OK;err_ret:	DEBUG_PRINT(("PageInMapDisk err = %d\n", err));	return err;}/* * Page out disk maps. *	Write pfe page frames to the disk, and separate all me  *	where pfe are mapped. *	Do not change page frame queues to which pfe are connected. *	pfe must not be PFS_lock. * *	When "nowrite = TRUE", return E_BUSY instead of  *	writing page frames to the disk (page-out). */EXPORT ER PageOutMapDisk( PFE *pfe, BOOL nowrite ){	ME	*me;	MEL	*mel;	PTE	pte;	VP	laddr;	ME	*maxme = NULL;	UW	maxpage = 0;	ER	err;	/* Set all mapped pages to absent. */	for ( mel = pfe->md.mel; mel != NULL; mel = mel->next_me ) {		me = mel->me;		if ( me->npage > maxpage ) {			maxme = me;			maxpage = me->npage;		}		laddr = mappingAddress(me, pfe);		if ( laddr == INVADR ) {			continue;  /* Already unmapped */		}		pte.w = GET_PTE(laddr, me->mode.space);		/* Not treated as disk map after copy-on-write processing. */		if ( CopyOnWriteP_done(pte.w) ) {			continue;		}		if ( !isValidP(pte.w) ) {			continue;  /* Pages are already absent. */		}		if ( isLocalSpace(laddr) != 0 ) {			/* Update process statistical information */			PINFO *pinfo = GetPINFO_lsid(me->mode.space);			if ( pinfo != NULL ) {				pinfo->allocpage--;				pinfo->poutcount++;			}		}		/* Set pages to absent. */		pte.w = 0;		pte.c.pfa = toMapID(me);		pte.w = CHG_PTE(laddr, me->mode.space, pte.w,		~(UW)(PT_Address|PT_Present|PT_Valid|PT_Update|PT_Accessed), TRUE);		/* If a write-protect page has been updated, 		 * return an error without writing it to the disk.		 *	Write-protect pages are sometimes updated by BMS.		 *	In such a case, do not write them to the disk. 		 *	Return an error so that such pages do not remain 		 *	on the disk cache. 		 */		if ( isUpdateP(pte.w) ) {			if ( isWritableP(pte.w) ) {				pfe->upd = TRUE;			} else {				pfe->err = TRUE;			}		}	}	/* Not necessary to write pages to the disk unless they have been updated. */	if ( pfe->upd != 0 ) {		if ( nowrite != 0 ) {			err = E_BUSY;			goto err_ret;		}		if ( maxme != NULL ) {			/* Write a map with the largest number of pages as a representative. */			(void)writeMapEntry(maxme, SYNCONLY);	/* Ignore errors. */		}	}	/* Separate pfe from map. */	while ( (mel = pfe->md.mel) != NULL ) {		deleteMapLink(mel);	}	return E_OK;err_ret:#ifdef DEBUG	if ( !(nowrite &&( err == E_BUSY)) ) {		DEBUG_PRINT(("PageOutMapDisk nowrite = %d err = %d\n",							nowrite, err));	}#endif	return err;}/* ------------------------------------------------------------------------ *//* * Disk map *	Map a group of physical blocks (block[]) on a disk specified with diskid to *	consecutive address spaces. *	If logical address spaces are not free, return error. If there is no free space *	in real memory (mode.real=1), wait until there is free space. *	Return mapid (> 0) as a function value. * *	(*) Note that page fault may occur when access is made *	   to block[] or *mode. *	(*) Note that during LockSEG(), it is not allowed to call Icalloc, Ifree, *	   AllocMemorySpace, or FreeMemorySpace. */EXPORT ER _MapDisk( ID diskid, PhyBlk block[], MapMode *mode ){	DE	*de;	ME	*me, *old_me = NULL;	ID	mid = 0;	VP	laddr;	W	n, npage, ofs;	UW	lsid;	ER	err;	lsid = mode->space;	if ( lsid >= MaxLSID ) {		err = E_PAR;		goto err_ret1;	}	LockFS();	if ( LimitMapRank(mode->rank) ) {		if ( MapCount >= MapLimit ) {			err = E_LIMIT;			goto err_ret2;		}	}	de = checkDiskID(diskid);	if ( de == NULL ) {		err = E_ID;		goto err_ret2;	}	/* Check block specification. */	n = checkBlockPara(de, block, &npage);	if ( n < E_OK ) {		err = n;		goto err_ret2;	}	/* Reserve memory for MapEntry. */	me = Icalloc(1U, MapEntrySize((UW)n));	if ( me == NULL ) {		err = E_NOMEM;		goto err_ret2;	}	me->mode   = *mode;	me->sync   = mode->real;	me->tid    = GetMyTid();	me->mapped = TRUE;	me->did    = diskid;	me->npage  = (UW)npage;	memcpy(me->pb, block, (size_t)(sizeof(PhyBlk) * (UW)n));#if RESIDENT_ONLY	/* If only resident blocks are specified, force them to be resident. */	me->mode.real = 1;#elif PT_Update == 0	/* When pages cannot be updated on the hardware, whether updated	 * or not is not known and therefore page-out cannot be performed	 * until unmapping (UnmapDisk). In such a case, force any writable	 * maps to be resident.	 */	if ( (me->mode.level & MapWrite) != 0 ) {		me->mode.real = 1;	}#endif	/* Offset address in a page located at the start of block */	ofs = BLKOFS(de, (W)block[0].blk) * de->info.blocksize;	if ( me->mode.addr == INVADR ) {		/* Obtain address space for mapping */		laddr = AllocMemorySpace(npage, lsid);		if ( laddr == NULL ) {			err = E_NOMEM;			goto err_ret3;		}#if USERLEVEL_ADDRESS_MASK		/* Processing to be performed when access right is determined based on address. */		if ( (me->mode.level & MapUser) != 0 ) {			laddr = (VP)((UW)laddr & (UW)USERLEVEL_ADDRESS_MASK);		}#endif		me->mode.addr = (VB*)laddr + ofs;		me->alloc = TRUE;	} else {		/* Check if user-specified addresses can be used for mapping. */		if ( PageOffset(me->mode.addr) != (UW)ofs ) {			err = E_PAR;			goto err_ret3;		}		laddr = (VB*)me->mode.addr - ofs;#if USERLEVEL_ADDRESS_MASK		/* Processing to be performed when access right is determined based on address. */		/* Do not place restrictions on addresses in the case of MapSystem. */		if ( (me->mode.level & MapUser) != 0 ) {			if (((UW)laddr & ~(UW)USERLEVEL_ADDRESS_MASK) != 0U ) {				err = E_NOSPT;				goto err_ret3;			}		}#endif	}	LockSEG();	/* Register MapEntry */	mid = registMapEntry(me, &old_me);	if ( mid < E_OK ) {		err = mid;		goto err_ret4;	}	if ( de->memadr == INVADR ) {		/* Normal disk map */		err = mapDiskSpace(de, me, laddr);		if ( err < E_OK ) {			goto err_ret5;		}	} else {		/* Direct mapping to memory disk */		me->memmap = TRUE;		err = mapDiskMemory(de, me, laddr);		if ( err < E_OK ) {			goto err_ret5;		}	}	UnlockSEG();	UnlockFS();	if ( old_me != NULL ) {		Ifree(old_me);	}	mode->addr = (VB*)laddr + ofs;	return mid;err_ret5:	(void)unmapDiskSpace(me, NOSYNC);err_ret4:	UnlockSEG();	if ( me->alloc != 0 ) {		(void)FreeMemorySpace(laddr, lsid);	}err_ret3:	if ( mid <= 0 ) {		Ifree(me);	}	if ( old_me != NULL ) {		Ifree(old_me);	}err_ret2:	UnlockFS();err_ret1:	DEBUG_PRINT(("_MapDisk err = %d\n", err));	return ERtoERR(err);}/* * Disk unmap *	Delete the address spaces mapped by mapid. *	Use flag to indicate whether writing has been performed at the addresses mapped by mapid. * *	(*) If writing is checked on a hardware basis, ignore the flag. *	(*) Note that during LockSEG(), it is not allowed to call Ifree. */EXPORT ER _UnmapDisk( ID mapid, UW flag ){	ME	*me;	SyncOpt	opt;	ER	err;	LockFS();	LockSEG();	me = checkMapID(mapid);	if ( me == NULL ) {		err = E_ID;		goto err_ret;	}#if PT_Update == 0	/* If updates cannot be checked on hardware: use flag. */	if ( (flag & MD_WRITE) != 0 ) {		opt = ( me->sync != 0 )? WRITEALL: MARKUPD;	} else {		opt = ( me->sync != 0 )? SYNCONLY: NOSYNC;	}#else	/* If updates can be checked on hardware: do not use flag. */	opt = ( me->sync != 0 )? SYNCONLY: NOSYNC;#endif	/* Reset mapping */	err = unmapDiskSpace(me, opt);	if ( err < E_OK ) {		goto err_ret;	}	me = checkFreeMapID(mapid);	UnlockSEG();	if ( me != NULL ) {		Ifree(me);	}	UnlockFS();	return E_OK;err_ret:	UnlockSEG();	UnlockFS();	DEBUG_PRINT(("_UnmapDisk err = %d\n", err));	return ERtoERR(err);}/* ------------------------------------------------------------------------ *//* * Disk map-related initialization *	(immediately after T-Kernel startup) */EXPORT ER InitDiskMap( void ){	W	val[TSD_IDM_ARR_5];	MET	*met;	ER	err;	/* Obtain definition information from SYSCONF. */	err = GetSysConf_bms((UB*)"MaxMapID", val, 1);	if ( err < E_OK ) {		goto err_ret;	}	MaxMapEntry = (UW)val[0];	MapLimit = (MaxMapEntry * TSD_IDM_VAL_7) / TSD_IDM_DIV_10; /* 70% */	MapCount = 0U;	/* Generate/initialize map management information table */	MapEntryTable = Imalloc(MaxMapEntry * sizeof(MET));	if ( MapEntryTable == NULL ) {		err = E_NOMEM;		goto err_ret;	}	FreeMapEntryTop = &MapEntryTable[MaxMapEntry - 1U];	FreeMapEntryEnd = &MapEntryTable[0];	for ( met = FreeMapEntryTop; met > FreeMapEntryEnd; --met ) {		met->next = met - 1;		met->me = NULL;	}	FreeMapEntryEnd->next = NULL;	FreeMapEntryEnd->me = NULL;	/* Initialize memory pool for map entry connection information */	InitFMB(&MapEntryLinkPool, sizeof(MEL));	return E_OK;err_ret:	BMS_DEBUG_PRINT(("InitDiskMap err = %d\n", err));	return err;}/* ======================================================================== *//* *	Debug support function */#if DEBUGFUNC_SUPPORT#define	M(v, c)		( ( (v) != 0 )? (c): '-' )/* * Indicate map ID information */EXPORT void DumpMap( void ){	ME	*me;	W	i;	PhyBlk	*pb;	printf("FILE MAP:\n");	DumpMore(0);	for ( i = 0; i < MaxMapEntry; ++i ) {		if ( MapEntryTable[i].next != (VP)TSD_MET_VAL_M1 ) {			continue;  /* Not used */		}		me = MapEntryTable[i].me;		printf( "  [%3d] addr:%08x npage:%-3d did:%-3d tid:%-3d info:%08x\n"			"    %c%c  rank:%d real:%d clear:%d level:%02x space:%-5d\n"			"        blk:",			me->mapid,		/* Map ID */			me->mode.addr,		/* Specify map address */			me->npage,		/* Total number of pages in map */			me->did,		/* Disk ID */			me->tid,		/* Mapped task */			me->mode.info,		/* Map information */			M(me->mapped, 'M'),	/* In the process of mapping */			M(me->memmap, 'R'),	/* Memory disk */			me->mode.rank,		/* Specify rank  */			me->mode.real,		/* Specify real/virtual IO */			me->mode.clear,		/* Specify clear */			me->mode.level,		/* Specify access level */			me->mode.space		/* Specify map space */		);		pb = me->pb;			/* Disk blocks to be used */		while ( pb->len > 0 ) {			printf(" %d#%d", pb->blk, pb->len);			pb++;		}		printf("\n");		if ( DumpMore(TSD_DPM_VAL_3) ) {			break;		}	}}#endif /* DEBUGFUNC_SUPPORT */

⌨️ 快捷键说明

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