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

📄 space.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			la = NextPage(la);	/* Next page */			if ( --np <= 0 ) {				break;			}		}		if ( pfe->dbn_no == 0 ) {			/* When a page table becomes empty,			   delete the page table itself. */			pde->w = PDE_NONE;			/* Release page frames for page tables. */			DiscardPageFrame(pfe);		}	}	if ( error < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("__UnmakeSpace err = %d\n", error));	return error;}EXPORT ER _UnmakeSpace( VP laddr, W npage, UW lsid ){	ER	err;	LockSEG();	err = __UnmakeSpace(laddr, npage, lsid);	UnlockSEG();	return err;}/* * Change logical space attribute *	In lsid logical space, change attributes of virtual memory allocated to npage of area *	(starting from a page that includes a logical address laddr) into chg_pte. *	Change attributes related to specification of access mode and copy-on-write only. *	The other attributes of page table are not changed. *	If the logical space does not have a process unique space, specify "lsid = 0". */EXPORT ER __ChangeSpace( VP laddr, W npage, UW lsid, UW chg_pte ){const	UW	CHG_MSK = (PT_Writable|PT_User|PT_CopyOnWrite);	VP	la  = laddr;	W	np  = npage;	VP	uatb;	PDE	*pde;	PTE	*pte;	W	i;	ER	err, error = E_OK;	/* For a shared space, specify "lsid = 0". */	if ( !isLocalSpace(laddr) ) {		lsid = 0;	}	chg_pte &= CHG_MSK;	uatb = GetUATB_lsid(lsid);	while ( np > 0 ) {		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( pde == NULL ) {			error = err;		}		if ( (pde == NULL) || (pde->c.p == 0) ) {			/* No page table */			i = (W)(N_PTE - PTBL_NUM(la));			la = (VP)((VB*)la + (PAGESIZE * i));			np -= i;			continue;		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			/* Change attribute of page table. */			pte[i].w = (pte[i].w & ~CHG_MSK) | chg_pte;			PurgePageTLB(la, lsid);			la = NextPage(la);	/* Next page */			if ( --np <= 0 ) {				break;			}		}	}	if ( error < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("__ChangeSpace err = %d\n", error));	return error;}EXPORT ER _ChangeSpace( VP laddr, W npage, UW lsid, UW chg_pte ){	ER	err;	LockSEG();	err = __ChangeSpace(laddr, npage, lsid, chg_pte);	UnlockSEG();	return err;}/* * Lock logical space *	Allocate real memory to len bytes of area (starting from a logical address laddr) *	to make the area resident (lock the area). */EXPORT ER __LockSpace( VP laddr, W len ){	T_TSKSPC	tskspc;	VB		*la, *end;	PDE		*pde;	PTE		*pte;	PFE		*pfe;	W		i, limit_new, limit_exs;	BOOL		newpg;	ER		err;	if ( len <= 0 ) {		err = E_PAR;		goto err_ret1;	}	/* Non-logical spaces are always made resident. */	if ( !isLogicalSpace(laddr) ) {		return E_OK;	}	if ( isLocalSpace(laddr) != 0 ) {		tskspc = GetTSKSPC_tid(TSK_SELF);	} else {		tskspc = GetTSKSPC_lsid(0);	}	end = (VB*)laddr + len;	la  = PageAlignL(laddr);	/* getting the number of pages to enable to resident	 *	limit_new : the number of new pages to enable to resident	 *	limit_exs : the number of existing pages to enable to resident	 */	limit_new = LockablePages(&limit_exs);	while ( la < end ) {		/* Obtain page directory entry */		pde = GetPDE(la, tskspc.uatb, &err);		if ( pde == NULL ) {			goto err_ret2;		}		if ( pde->c.p == 0 ) {			goto err_adr; /* No page table */		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < N_PTE; ++i ) {			if ( pte[i].w == (UW)PTE_NONE ) {				goto err_adr; /* Invalid PTE */			}			newpg = ( (pte[i].c.p == 0) && (pte[i].c.va == 0) );			if ( pte[i].c.p == 0 ) {				/* Page in. */				err = PageIn(la, tskspc.lsid);				if ( err < E_OK ) {					goto err_ret2;				}			}			if ( pte[i].c.cow != 0 ) {				/* Perform copy-on-write. */				err = CopyOnWrite(la, tskspc.lsid);				if ( err < E_OK ) {					goto err_ret2;				}			}			pfe = PFAtoPFE(pte[i].c.pfa);			/* Count the number of locking. */			err = LockCount(pfe, la, tskspc.lsid, (+1));			if ( err < E_OK ) {				goto err_ret2;			}			if ( err == 1 ) {				/* the case of first residentation */				if ( (!newpg) && (limit_exs > 0) ) {					--limit_exs;									} else if ( --limit_new < 0 ) {					LockCount(pfe, la, tskspc.lsid, TSD_ULS_VAL_M1);					err = E_NOMEM;					goto err_ret2;				}			}			pte[i].c.va = 0;  /* Indicate that page frames are locked. */			/* Set frames locks at locked state. */			LockPageFrame(pfe);			la += PAGESIZE;			if ( la >= end ) {				break;			}		}	}	return E_OK;err_adr:	err = E_MACV;err_ret2:	(void)__UnlockSpace(laddr, la - (VB*)laddr);err_ret1:	DEBUG_PRINT(("__LockSpace err = %d\n", err));	return err;}EXPORT ER _LockSpace( VP laddr, W len ){	ER	err;	LockSEG();	err = __LockSpace(laddr, len);	UnlockSEG();	return err;}/* * Unlock logcal space *	Make len bytes of area (starting from a logical address laddr) non-resident (unlock the area). */EXPORT ER __UnlockSpace( VP laddr, W len ){	T_TSKSPC	tskspc;	VB		*la, *end;	PDE		*pde;	PTE		*pte;	PFE		*pfe;	W		i;	ER		err, error = E_OK;	if ( len <= 0 ) {		error = E_PAR;		goto err_ret;	}	/* Non-logical spaces are always made resident. */	if ( !isLogicalSpace(laddr) ) {		return E_OK;	}	if ( isLocalSpace(laddr) != 0 ) {		tskspc = GetTSKSPC_tid(TSK_SELF);	} else {		tskspc = GetTSKSPC_lsid(0);	}	end = (VB*)laddr + len;	la  = PageAlignL(laddr);	while ( la < end ) {		/* Obtain page directory entry */		pde = GetPDE(la, tskspc.uatb, &err);		if ( (pde == NULL) || (pde->c.p == 0) ) {			/* No page table */			error = ( pde == NULL )? err: E_MACV;			i = (W)(N_PTE - PTBL_NUM(la));			la += PAGESIZE * i;			continue;		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			if ( (pte[i].c.p != 0) && (pte[i].c.va == 0) ) {				pfe = PFAtoPFE(pte[i].c.pfa);				/* Count the number of locking. */				err = LockCount(pfe, la, (UW)tskspc.lsid, TSD_ULS_VAL_M1);				if ( err < E_OK ) {					error = err;				}				/* When the number of locking becomes 0, unlock page frames. */				if ( err == 0 ) {					pte[i].c.va = 1; /* Indicate that page frames are unlocked. */					/* Reset the locked state of page frames. */					UnlockPageFrame(pfe);					/* Enable the cache. */					pte[i].w |= (UW)PT_Cachable;					PurgePageTLB(la, (UW)tskspc.lsid);				}			} else {				error = E_MACV;			}			la += PAGESIZE;			if ( la >= end ) {				break;			}		}	}err_ret:#ifdef DEBUG	if ( error < E_OK ) {		DEBUG_PRINT(("__UnlockSpace err = %d\n", error));	}#endif	return error;}EXPORT ER _UnlockSpace( VP laddr, W len ){	ER	err;	LockSEG();	err = __UnlockSpace(laddr, len);	UnlockSEG();	return err;}/* * Obtain physical address *	In a logical space of the task, determine the physical address of logical address *	laddr and return it as *paddr. As a return value, return the number of bytes of *	consecutive physical memory in len bytes of area starting from laddr. *	In the returned bytes of area starting from laddr, the cache is disabled. *	The disabled cache is reset by UnlockSpace(). *	It is necessary to lock it in advance by LockSpace(). * *	(*) Do not execute LockSEG(). *	   It causes deadlock when called from the disk driver. *	(*) Note that page fault may occur when access is made to *paddr. */EXPORT W _CnvPhysicalAddr( VP laddr, W len, VP *paddr ){	VP	la;	VP	uatb;	UW	lsid;	PDE	*pde;	PTE	*pte;	W	i;	UW	next_pfa = 0;	W	plen;	UW	imask;	ER	err;	/* Non-logical spaces are handled in the same manner as physical addresses. */	if ( !isLogicalSpace(laddr) ) {		/* For the time being, do not include P1 area (except for ROM area)		   where the cache cannot be controlled on a page basis. */		if ( isP1(laddr) && !isROM(laddr) ) {			return E_PAR;		}		*paddr = (VP)toPhysicalAddress(laddr);		return len;	}	/* Obtain uatb of the current space from TTB register. */	uatb = CurrentUATB();	lsid = GetLSID_uatb(uatb);	la = laddr;	plen = 0;	do {		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( (pde == NULL) || (pde->c.p == 0) ) {			return E_MACV;	/* No page table */		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			if ( pte[i].c.p == 0 ) {				break; /* Page is absent. */			}			if ( plen == 0 ) {				/* First page */				*paddr = (VB*)PFAtoPADR(pte[i].c.pfa)							+ POFS_NUM(la);				plen = PAGESIZE - (W)POFS_NUM(la);				next_pfa = pte[i].c.pfa + 1U;			} else {				if ( pte[i].c.pfa != next_pfa ) {					break; /* Non-consecutive */				}				plen += PAGESIZE;				next_pfa++;			}			DI(imask);			/* In DMA transfer, an update flag is not set for the page table.			 * Set an update flag based on the assumption that physical			 * address are used for DMA transfer.			 * However, this is not the case if writing is disabled.			 */			if ( pte[i].c.w != 0 ) {				pte[i].c.d = 1;			}			/* Disable the cache. */			ExtFlushCache(la, lsid, pte[i].w);			pte[i].w &= ~(UW)PT_Cachable;			PurgePageTLB(la, lsid);			EI(imask);			la = (VB*)laddr + plen;			if ( plen >= len ) {				break;			}		}	} while ( i == (W)N_PTE );	if ( plen > len ) {		plen = len;	}	return plen;}/* * Check access attribute of logical space *	In a logical space of the task, check if it is possible to make access to len bytes *	of area (starting from a logical address laddr) from env environment in mode. *	If it is possible, return E_OK; if not possible, return E_MACV. * *	(*) Do not execute LockSEG(). *	   It causes deadlock when called from the disk driver. */EXPORT ER _ChkSpace( VP laddr, W len, UW mode, UW env ){	VP	la;	VP	uatb;	PDE	*pde;	PTE	*pte;	UW	chk_u, chk_w;	UW	imask;	W	i;	W	plen = 0;	ER	err;	/* Obtain uatb of the current space from TTB register. */	uatb = CurrentUATB();	/* Attributes necessary for access */	chk_u = ( (env & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3) )? 1U: 0U;	chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U;	/* Check non-logical spaces in a fixed manner. */	if ( !isLogicalSpace(laddr) ) {		if ( (chk_u > 0U) && !isP0(laddr) ) {			goto ret;		}		return E_OK;	}	do {		la = (VB*)laddr + plen;		/* Disable interruption to prevent deletion of the page table		   while it is checked. */		DI(imask);		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( (pde == NULL) || (pde->c.p == 0) ) {			/* No page table */			EI(imask);			break;		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			if ( pte[i].w == (UW)PTE_NONE ) {				break; /* Invalid PTE */			}			/* Check access right.				Enable writing for CopyOnWrite. */			if ( pte[i].c.u < chk_u ) {				break;			}			if ( (pte[i].c.w < chk_w) && (pte[i].c.cow == 0) ) {				break;			}			if ( plen == 0 ) {				/* First page */				plen = PAGESIZE - (W)POFS_NUM(la);			} else {				plen += PAGESIZE;			}			if ( plen >= len ) {				break;			}		}		EI(imask);	} while ( i == (W)N_PTE );ret:#ifdef DEBUG	if ( plen < len ) {		DEBUG_PRINT(("_ChkSpace(%#x, %d, %d, %#x) = E_MACV\n",						laddr, len, mode, env));	}#endif	return ( plen >= len )? E_OK: E_MACV;}/* * Check access attribute of logical space(TC character string) *	In a logical space of the task, check if it is possible to make access to an area *	(starting from a logical address str to TNULL or to the max-th character) from *	env environment in mode. When set at "max = 0", ignore the number (max) of characters. *	If it is possible, return the number of characters or the value of max (when "max > 0" *	and TNULL is not found before the max-th character); if not possible, return E_MACV. * *	(*) It is assumed that str is an even-number address. *	(*) Do not execute LockSEG(). *	   It causes deadlock when called from the disk driver. */EXPORT W _ChkSpaceTstr( TC *str, W max, UW mode, UW env ){	TC	*tp = str;	VP	uatb;	PDE	*pde;	PTE	*pte;	UW	chk_u, chk_w;	UW	imask;	W	n;#ifdef DEBUG	W	_max = max;#endif	ER	err;	/* Obtain uatb of the current space from TTB register. */	uatb = CurrentUATB();	/* Attributes necessary for access */	chk_u = ( (env & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3) )? 1U: 0U;	chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U;	/* Check non-logical spaces in a fixed manner. */	if ( !isLogicalSpace(str) ) {		if ( (chk_u > 0U) && !isP0(str) ) {			goto err_ret;		}		while ( *tp != TNULL ) {			tp++;			if ( --max == 0 ) {				break;			}		}		return tp - str;	}	for ( ;; ) {		/* Disable interruption to prevent deletion of the page table		   while it is checked. */		DI(imask);		/* Obtain page directory entry */		pde = GetPDE(tp, uatb, &err);		if ( (pde == NULL) || (pde->c.p == 0) ) {			break;  /* No page table */		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		/* Page table entry */		pte += PTBL_NUM(tp);		if ( pte->w == (UW)PTE_NONE ) {			break; /* Invalid PTE */		}		/* Check access right.			Enable writing for CopyOnWrite. */		if ( pte->c.u < chk_u ) {			break;		}		if ( (pte->c.w < chk_w) && (pte->c.cow == 0) ) {			break;		}		EI(imask);		/* Number of characters within this page */		n = (PAGESIZE - (W)POFS_NUM(tp)) / (W)sizeof(TC);		/* TNULL checking (Page-in may occur.) */		while ( --n >= 0 ) {			if ( *tp == TNULL ) {				return tp - str;			}			tp++;			if ( --max == 0 ) {				return tp - str;			}		}	}	EI(imask);err_ret:	DEBUG_PRINT(("_ChkSpaceTstr(%#x, %d, %d, %#x) = E_MACV\n",						str, _max, mode, env));	return E_MACV;}/* * Check access attribute of logical space(B character string) *	In a logical space of the task, check if it is possible to make access to an area *	(starting from a logical address str to '\0' or to the max-th byte) from *	env environment in mode. When set at "max = 0", ignore the number (max) of bytes. *	If it is possible, return the number of bytes or the value of max (when "max > 0" *	and '\0' is not found before the max-th byte); if not possible, return E_MACV. * *	(*) Do not execute LockSEG(). *	   It causes deadlock when called from the disk driver. */EXPORT W _ChkSpaceBstr( UB *str, W max, UW mode, UW env ){	UB	*p = str;	VP	uatb;	PDE	*pde;	PTE	*pte;	UW	chk_u, chk_w;	UW	imask;	W	n;#ifdef DEBUG	W	_max = max;#endif	ER	err;	/* Obtain uatb of the current space from TTB register. */	uatb = CurrentUATB();	/* Attributes necessary for access */	chk_u = ( (env & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3) )? 1: 0;	chk_w = ( (mode & MA_WRITE) != 0U )? 1: 0;	/* Check non-logical spaces in a fixed manner. */	if ( !isLogicalSpace(str) ) {		if ( (chk_u > 0U) && !isP0(str) ) {			goto err_ret;		}		while ( *p != '\0' ) {			p++;			if ( --max == 0 ) {				break;			}		}		return p - str;	}	for ( ;; ) {		/* Disable interruption to prevent deletion of the page table		   while it is checked. */		DI(imask);		/* Obtain page directory entry */		pde = GetPDE(p, uatb, &err);		if ( (pde == NULL) || (pde->c.p == 0) ) {			break;  /* No page table */		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		/* Page table entry */		pte += PTBL_NUM(p);		if ( pte->w == (UW)PTE_NONE ) {			break; /* Invalid PTE */		}		/* Check access right.			Enable writing for CopyOnWrite. */		if ( pte->c.u < chk_u ) {			break;		}		if ( (pte->c.w < chk_w) && (pte->c.cow == 0) ) {			break;		}		EI(imask);		/* Number of characters within this page */		n = PAGESIZE - (W)POFS_NUM(p);		/* '\0' checking (Page-in may occur.) */

⌨️ 快捷键说明

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