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

📄 memmgr.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. * *---------------------------------------------------------------------- *//* *	memmgr.c (memory) * *	Memory management (Virtual storage version) */#include "segmgr.h"#include <extension/sys/tkse_ssid.h>#include <extension/sys/svc/ifmemory.h>/* * Minimum size of memory to be reserved for system (number of pages) *	In the case of local memory, if the remaining memory is smaller than SysReserve, *	return E_NOMEM. In other cases, continue to reserve memory until the remaining size *	becomes 0. */LOCAL W		SysReserve;/* * Exclusive control lock for memory management *	At OS startup, Lock() is called before CreateLock(). *	In this case, set initial values to prevent wait sate. * *	Memory management may be called during LockPinfo. *	Do not execute LockPinfo during LockMEM. */LOCAL FastLock	MemLock = { -1, -1 };#define	LockMEM()	Lock(&MemLock)#define	UnlockMEM()	Unlock(&MemLock)/* * Page */typedef struct {	VB	mem[PAGESIZE];} PAGE;typedef UW	PN;	/* Page numbers (1-) *//* * Page management queue */typedef struct {	unsigned int	cont:1;		/* Two or more consecutive pages: 1 */	unsigned int	use:1;		/* When the current page is in use: 1 */	unsigned int	wall:2;		/* Wall flag */	unsigned int	next:28;	unsigned int	atr:4;		/* Memory block attribute */	unsigned int	prev:28;} PAGEQUE;#define	USE	1		/* In use */#define	FREE	0		/* Free */#define	CONT	1		/* Consecutive (two or more blocks in a row) */#define	ONE	0		/* Single */#define	TWALL	1U		/* Wall on the side of lower address */#define	EWALL	2U		/* Wall on the side of upper address */static const PAGEQUE	_clrPageQue = { ONE, FREE, 0, 0, 0, 0 };#define	clrPageQue(q)	( (q) = (_clrPageQue) )#define	NumOfPages(q)	( ( (q)->cont != 0 )? ((q)+1)->next: 1 )  /* Number of consecutive pages *//* * Memory block attribute */#define	MB_LOCAL	0x1U	/* Local memory */#define	MB_DELETE	0x2U	/* Delete at process termination */#define	MB_SHARE	0x4U	/* Shared memory *//* * Page management table *	Start of pageque is used for freeque. *	freeque is sorted in increasing order of number of consecutive free pages. */typedef struct {	UW	maxpage;	/* Total number of pages */	UW	freepage;	/* Number of free pages */	PAGE	*toppage;	/* Address of first page */	PAGEQUE	pageque[1];	/* Array of management information for all pages */} PAGETBL;#define	freeque		pageque[0]	/* Queue of free pages */#define	_PageAdr(pt, pn)	( (VP)((pt)->toppage + ((pn) - 1)) )#define	_PageNo(pt, adr)	( (PN)(((PAGE*)(adr) - (pt)->toppage) + 1) )LOCAL PAGETBL	*SystemPageTable;	/* System memory space management table */Inline VP PageAdr( PAGETBL *pt, PN pn );Inline PN PageNo( PAGETBL *pt, VP adr );Inline void setPageQue( PAGEQUE *q, BOOL u, BOOL c, PN n, PN p, UW a );Inline void initPageQue( PAGETBL *pt, PN pn );Inline void insertPageQue( PAGETBL *pt, PN que, PN ent );Inline void removePageQue( PAGETBL *pt, PN ent );Inline BOOL isEmptyPageQue( PAGETBL *pt, PN que );Inline void setUsePages( PAGETBL *pt, PN pn, W n, UW atr );LOCAL PN searchFreeQue( PAGETBL *pt, W n );LOCAL void appendFreePages( PAGETBL *pt, PN pn, W n );LOCAL void initFreePages( PAGETBL *pt, PN pn, W n );LOCAL VP getPages( PAGETBL *pt, VP *p_grp, W npage, UW atr );LOCAL W relPage1( PAGETBL *pt, PN pn );LOCAL W relPages( PAGETBL *pt, VP laddr, VP *p_grp );LOCAL W initPageTable( VP top, VP end, UW lsid );LOCAL PAGETBL* checkAddr( VP adr );LOCAL ER _tkse_get_mbk( VP *adr_p, INT nblk, UINT atr );LOCAL ER _tkse_rel_mbk( VP adr );LOCAL ER _tkse_mbk_sts( M_STATE *sts );LOCAL ER relMemGrpPiece( PAGETBL *pt, PN pn, UW lsid );LOCAL ER relMemGrp( PAGETBL *pt, VP *p_grp, UW lsid );LOCAL void MemCleanUp( ID resid, W pid );LOCAL WER MemSVCentry( VP para, W fn );#define TSD_AFP_VAL_2		2#define TSD_SUP_VAL_2		2#define TSD_DMT_DIV_1024	1024/* * Interconversion between page number and address */Inline VP PageAdr( PAGETBL *pt, PN pn ){#if USERLEVEL_ADDRESS_MASK	/* Processing to be performed when access right is determined based on address. */	VP adr = _PageAdr(pt, pn);	if ( (pt->pageque[pn].atr & MB_SHARE) != 0U ) {		adr = (VP)((UW)adr & (UW)USERLEVEL_ADDRESS_MASK);	}	return adr;#else	return _PageAdr(pt, pn);#endif}Inline PN PageNo( PAGETBL *pt, VP adr ){#if USERLEVEL_ADDRESS_MASK	if ( pt == SystemPageTable ) {		adr = (VP)((UW)adr | ~(UW)USERLEVEL_ADDRESS_MASK);	}#endif	return _PageNo(pt, adr);}/* ------------------------------------------------------------------------ *//* * Set page queue */Inline void setPageQue( PAGEQUE *q, BOOL u, BOOL c, PN n, PN p, UW a ){	q->use  = u;	q->cont = c;	q->next = n;	q->prev = p;	q->atr  = a;}/* * Initialize page queue */Inline void initPageQue( PAGETBL *pt, PN pn ){	pt->pageque[pn].next = pt->pageque[pn].prev = pn;}/* * Insert page queue *	Insert ent immediately anterior to que */Inline void insertPageQue( PAGETBL *pt, PN que, PN ent ){	pt->pageque[ent].prev = pt->pageque[que].prev;	pt->pageque[ent].next = que;	pt->pageque[pt->pageque[que].prev].next = ent;	pt->pageque[que].prev = ent;}/* * Separate page queue *	Separate ent from queue */Inline void removePageQue( PAGETBL *pt, PN ent ){	if ( pt->pageque[ent].next != ent ) {		pt->pageque[pt->pageque[ent].prev].next				= pt->pageque[ent].next;		pt->pageque[pt->pageque[ent].next].prev				= pt->pageque[ent].prev;	}}/* * The page queue is empty: TRUE */Inline BOOL isEmptyPageQue( PAGETBL *pt, PN que ){	return ( pt->pageque[que].next == que );}/* * Search for free page queue *	Search for a queue whose number of free pages is equal to "n", *	or greater but closest to "n". If not found, return 0 (freeque). */LOCAL PN searchFreeQue( PAGETBL *pt, W n ){	PN	pn = 0;	while ( (pn = pt->pageque[pn].next) > 0U ) {		if ( NumOfPages(&pt->pageque[pn]) >= n ) {			return pn;		}	}	return 0;}/* * Register free page additionally *	As additional free pages, register n consecutive pages starting from page pn. */LOCAL void appendFreePages( PAGETBL *pt, PN pn, W n ){	PN	ins;	/* Set queue */	pt->pageque[pn].use  = FREE;	pt->pageque[pn].cont = ( n > 1 )? CONT: ONE;	pt->pageque[pn].atr  = 0;	if ( n > 1 ) {		setPageQue(&pt->pageque[pn + 1U],   FREE, CONT, (UW)n, 0U, 0U);	}	if ( n > TSD_AFP_VAL_2 ) {		setPageQue(&pt->pageque[pn + (UW)n - 1U], FREE, CONT, (UW)n, 0U, 0U);	}	/* Find position for addition of free page */	ins = searchFreeQue(pt, n);	/* Register free page */	insertPageQue(pt, ins, pn);}/* * Register free page newly *	Newly register n consecutive pages starting from page pn. */LOCAL void initFreePages( PAGETBL *pt, PN pn, W n ){	appendFreePages(pt, pn, n);	if ( n > 1 ) {		pt->pageque[pn    ].wall = TWALL;		pt->pageque[pn + (UW)n - 1U].wall = EWALL;	} else {		pt->pageque[pn    ].wall = TWALL|EWALL;	}}/* * Set page to be used */Inline void setUsePages( PAGETBL *pt, PN pn, W n, UW atr ){	/* Set queue */	pt->pageque[pn].use  = USE;	pt->pageque[pn].cont = ( n > 1 )? CONT: ONE;	pt->pageque[pn].atr  = atr;	if ( n > 1 ) {		setPageQue(&pt->pageque[pn + 1U],   USE, CONT, (PN)n, 0U, 0U);	}	if ( n > TSD_SUP_VAL_2 ) {		setPageQue(&pt->pageque[pn + (UW)n - 1U], USE, CONT, (PN)n, 0U, 0U);	}	initPageQue(pt, pn);}/* * Obtain page */LOCAL VP getPages( PAGETBL *pt, VP *p_grp, W npage, UW atr ){	PN	pn;	W	free;	/* Search for free page */	pn = searchFreeQue(pt, npage);	if ( pn == 0U ) {		return NULL;	}	free = NumOfPages(&pt->pageque[pn]);	/* Temporarily remove all of pn consecutive free pages from the free queue. */	removePageQue(pt, pn);	/* Separate the necessary number of pages. */	free -= npage;	setUsePages(pt, pn, npage, atr);	if ( free > 0 ) {		/* Return the remaining pages to free the queue. */		appendFreePages(pt, pn + (UW)npage, free);		/* PAGEQUE is not initialized until it is used for the first time.		 * When PAGEQUE is used anew due to division of an area,		 * it is necessary to initialize PAGEQUE. Here, initialize		 * wall only because the others are initialized setUsePages()		 * and appendFreePages().		 */		if ( npage > 1 ) {			pt->pageque[pn + (UW)npage - 1U].wall = 0;		}		if ( free  > 1 ) {			pt->pageque[pn + (UW)npage    ].wall = 0;		}	}	if ( p_grp != NULL ) {		/* Register obtained pages in a group. */		if ( *p_grp != NULL ) {			insertPageQue(pt, PageNo(pt, *p_grp), pn);		}		*p_grp = PageAdr(pt, pn);	}	pt->freepage -= (UW)npage;	return PageAdr(pt, pn);}/* * Release a series of consecutive areas. *	Return the number of released pages. */LOCAL W relPage1( PAGETBL *pt, PN pn ){	W	npage, free;	ER	err;	if ( pt->pageque[pn].use == FREE ) {		err = E_PAR;		goto err_ret;	}	/* Separate pages to be released from the group. */	removePageQue(pt, pn);	/* Number of pages to be released */	free = npage = NumOfPages(&pt->pageque[pn]);	/* Check if there are free pages located posterior to the released pages. */	if (( (pt->pageque[pn + (UW)npage - 1U].wall & EWALL) == 0U )	  &&( pt->pageque[pn + (UW)npage].use == FREE )) {		/* Temporarily remove free pages located posterior from the free queue. */		removePageQue(pt, pn + (UW)npage);		/* Merge free and released pages. */		npage += NumOfPages(&pt->pageque[pn + (UW)npage]);	}	/* Check if there are free pages located anterior to the released pages. */	if (( (pt->pageque[pn].wall & TWALL) == 0U )	  &&( pt->pageque[pn - 1U].use == FREE )) {		/* Number of free pages located anterior */		W n = ( pt->pageque[pn - 1U].cont != 0 )? pt->pageque[pn - 1U].next: 1;		/* Temporarily remove free pages located anterior from the free queue. */		removePageQue(pt, pn - (UW)n);		/* Merge free and released pages. */		pn -= (UW)n;		npage += n;	}	/* Register released pages in free queue. */	appendFreePages(pt, pn, npage);	pt->freepage += (UW)free;	return free;err_ret:	DEBUG_PRINT(("relPage1 err = %d\n", err));	return err;}/* * Release page *	Return the total number of released pages */LOCAL W relPages( PAGETBL *pt, VP laddr, VP *p_grp ){	PN	pn;	VP	grp = NULL;	ER	err;	pn = PageNo(pt, laddr);	if ( p_grp != NULL ) {		grp = ( isEmptyPageQue(pt, pn) != 0 )?				NULL: PageAdr(pt, pt->pageque[pn].next);	}	err = relPage1(pt, pn);	if ( err < E_OK ) {		goto err_ret;	}	if ( p_grp != NULL ) {		*p_grp = grp;	}	return err;err_ret:	DEBUG_PRINT(("relPages err = %d\n", err));	return err;}/* * Initialize memory management table on a page basis. *	Manage areas located between top and end. *	top and end must be located on page boundaries. *	The management table will be at the top position. *	Return the size of management table (number of pages). * *	(*) An area between top and end must be the current logical space. */LOCAL W initPageTable( VP top, VP end, UW lsid ){	PAGETBL	*pt;	UW	memsz, maxpage, tblpage;	ER	err;	/* Memory size */	memsz = (UW)end - (UW)top;	/* Number of pages except for management table */	maxpage = (memsz - sizeof(PAGETBL)) / ((UW)PAGESIZE + sizeof(PAGEQUE));	/* Size of management table (number of pages) */	tblpage = PageCount(sizeof(PAGETBL) + (sizeof(PAGEQUE) * maxpage));	/* Allocate logical space to management table. */	err = _MakeSpace(top, (W)tblpage, lsid, (UW)PTE_SMEM_NC);	if ( err < E_OK ) {		goto err_ret;	}	/* Initialize management table. */	pt = (PAGETBL*)top;	pt->maxpage  = maxpage;	pt->freepage = maxpage;	pt->toppage  = (PAGE*)top + tblpage;	clrPageQue(pt->freeque);	initFreePages(pt, 1U, (W)maxpage);	return (W)tblpage;err_ret:	DEBUG_PRINT(("initPageTbl err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* * Check size of memory to be reserved. *	Reserve memory for npage; if the remaining memory becomes smaller than *	the minimum size to be reserved for system, return E_NOMEM. */EXPORT ER ChkSysRsvMem( W npage ){	return ( (AvailablePages() - npage) < SysReserve )? E_NOMEM: E_OK;}/* * Address check */LOCAL PAGETBL* checkAddr( VP adr ){	PAGETBL	*pt;	if ( isLocalSpace(adr) != 0 ) {		/* Local memory */		PINFO *pinfo = GetPinfo(TSK_SELF);		if ( pinfo == NULL ) {			return NULL;		}		pt = pinfo->lpgtbl;	} else {		/* System memory */		pt = SystemPageTable;#if USERLEVEL_ADDRESS_MASK		adr = (VP)((UW)adr | ~(UW)USERLEVEL_ADDRESS_MASK);#endif	}	return (   (adr >= (VP)pt->toppage)		&& (adr < (VP)(pt->toppage + pt->maxpage))		&& (((UW)adr & ((UW)PAGESIZE - 1U)) == 0U)		)? pt: NULL;}/* * Obtain memory block */LOCAL ER _tkse_get_mbk( VP *adr_p, INT nblk, UINT atr ){#define	ATR_MASK	(M_SYSTEM|M_RESIDENT|TA_DELEXIT)	PAGETBL	*pt;	PINFO	*pinfo = NULL;	UW	lsid   = GetLSID_tid(TSK_SELF);	UW	mb_atr;	VP	*memgrp, adr;	UW	pte;	ER	err;	/* Parameter check */	if (( nblk <= 0 )||( (atr & ~(UW)ATR_MASK) != 0U )) {		err = E_PAR;		goto err_ret1;	}	err = ChkSpaceRW(adr_p, sizeof(VP*));	if ( err < E_OK ) {		goto err_ret1;	}	LockMEM();	/* Check if the number of pages is allocatable. */	if ( (atr & M_SYSTEM) == M_SYSTEM ) {		if ( nblk > AvailablePages() ) {			err = E_NOMEM;			goto err_ret2;		}	} else {		err = ChkSysRsvMem(nblk);		if ( err < E_OK ) {			goto err_ret2;		}	}	/* Memory attribute */	mb_atr = 0;	if ( (atr & TA_DELEXIT)  != 0U ) {		mb_atr |= MB_DELETE;	}	switch ( atr & M_SYSTEM ) {	  case 0:		mb_atr |= MB_LOCAL;		break;	  case M_COMMON:		mb_atr |= MB_SHARE;		break;	  default:		/* nothing to do */		break;	}	if ( (mb_atr & (MB_LOCAL|MB_DELETE)) != 0U ) {		pinfo = GetPinfo(TSK_SELF);		if ( pinfo == NULL ) {			err = E_CTX;			goto err_ret2;		}	}	memgrp = ( (mb_atr & MB_LOCAL)  != 0U )? &pinfo->lmemgrp:		 (( (mb_atr & MB_DELETE) != 0U )? &pinfo->smemgrp:						NULL);	pt = ( (mb_atr & MB_LOCAL) != 0U )? pinfo->lpgtbl: SystemPageTable;	/* Obtain memory */	adr = getPages(pt, memgrp, nblk, mb_atr);	if ( adr == NULL ) {		err = E_NOMEM;		goto err_ret2;	}	/* Generate memory space */	pte = ( (atr & M_SYSTEM) == M_SYSTEM )? PTE_SMEM_NC: PTE_UMEM_NC;	err = MakeSpace(adr, nblk, (W)lsid, pte);	if ( err < E_OK ) {		goto err_ret3;	}	if ( (atr & M_RESIDENT) != 0U ) {		/* Resident */		err = LockSpace(adr, nblk * PAGESIZE);		if ( err < E_OK ) {			goto err_ret4;		}	} else {		/* Allocate physical memory to all pages so that it will be		   reflected in the amount of physical memory consumed. */		W	i;		for ( i = (nblk - 1) * PAGESIZE; i >= 0; i -= PAGESIZE ) {			((UB*)adr)[i] = 0U;		}	}	*adr_p = adr;	UnlockMEM();	return E_OK;err_ret4:	(void)UnmakeSpace(adr, nblk, (W)lsid);err_ret3:	(void)relPages(pt, adr, memgrp);err_ret2:	UnlockMEM();err_ret1:	DEBUG_PRINT(("_tkse_get_mbk err = %d\n", err));	return ERtoERR(err);}/* * Release memory block */LOCAL ER _tkse_rel_mbk( VP adr ){	PAGETBL	*pt;	PINFO	*pinfo = NULL;	UW	mb_atr;	VP	*memgrp;	W	nblk;	ER	err;	LockMEM();	/* Address check */	pt = checkAddr(adr);	if ( pt == NULL ) {		err = E_PAR;		goto err_ret1;	}	/* Memory attribute */	mb_atr = pt->pageque[PageNo(pt, adr)].atr;

⌨️ 快捷键说明

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