Beispiel #1
0
/*
 * Registration of free area on FreeQue
 *	FreeQue is composed of 2 types: Queue that links the
 *	different size of areas by size and queue that links the
 *	same size of areas.
 *
 *	freeque
 *	|
 *	|   +-----------------------+	    +-----------------------+
 *	|   | AreaQue		    |	    | AreaQue		    |
 *	|   +-----------------------+	    +-----------------------+
 *	*---> FreeQue Size order    |	    | EmptyQue		    |
 *	|   | FreeQue Same size   --------->| FreeQue Same size   ----->
 *	|   |			    |	    |			    |
 *	|   |			    |	    |			    |
 *	|   +-----------------------+	    +-----------------------+
 *	|   | AreaQue		    |	    | AreaQue		    |
 *	v   +-----------------------+	    +-----------------------+
 */
EXPORT void knl_appendFreeArea( IMACB *imacb, QUEUE *aq )
{
	QUEUE	*fq;
	W	size = AreaSize(aq);

	/* Registration position search */
	/*  Search the free area whose size is equal to 'blksz',
	 *  or larger than 'blksz' but closest.
	 *  If it does not exist, return '&imacb->freeque'.
	 */
	fq = knl_searchFreeArea(imacb, size);

	/* Register */
	clrAreaFlag(aq, AREA_USE);
	if ( fq != &imacb->freeque && FreeSize(fq) == size ) {
		/* FreeQue Same size */
		(aq + 2)->next = (fq + 1)->next;
		(fq + 1)->next = aq + 2;
		(aq + 2)->prev = fq + 1;
		if( (aq + 2)->next != NULL ) {
			(aq + 2)->next->prev = aq + 2;
		}
		(aq + 1)->next = NULL;
	} else {
		/* FreeQue Size order */
		QueInsert(aq + 1, fq);
		(aq + 2)->next = NULL;
		(aq + 2)->prev = (QUEUE*)size;
	}
}
Beispiel #2
0
/*
 * Free memory block
 */
LOCAL ER rel_blk( MPLCB *mplcb, void *blk )
{
	QUEUE	*aq;

	aq = (QUEUE*)blk - 1;

#if CHK_PAR
	if ( !chkAreaFlag(aq, AREA_USE) ) {
		return E_PAR;
	}
#endif
	clrAreaFlag(aq, AREA_USE);

	if ( !chkAreaFlag(aq->next, AREA_USE) ) {
		/* Merge to the next area */
		removeFreeQue(aq->next + 1);
		removeAreaQue(aq->next);
	}
	if ( !chkAreaFlag(aq->prev, AREA_USE) ) {
		/* Merge to the previous area */
		aq = aq->prev;
		removeFreeQue(aq + 1);
		removeAreaQue(aq->next);
	}

	/* Register free area onto FreeQue */
	appendFreeArea(mplcb, aq);

	return E_OK;
}
Beispiel #3
0
/*
 * Free memory
 *	It may be called during interrupt disable. In this case, need to wait
 *	 until interrupt is enabled and until free.
 */
EXPORT void  knl_Ifree( void *ptr )
{
	QUEUE	*aq;
	UINT	imask;

	DI(imask);  /* Exclusive control by interrupt disable */

	aq = (QUEUE*)ptr - 1;
	clrAreaFlag(aq, AREA_USE);

	if ( !chkAreaFlag(aq->next, AREA_USE) ) {
		/* Merge with free area in after location */
		knl_removeFreeQue(aq->next + 1);
		knl_removeAreaQue(aq->next);
	}

	if ( !chkAreaFlag(aq->prev, AREA_USE) ) {
		/* Merge with free area in front location */
		aq = aq->prev;
		knl_removeFreeQue(aq + 1);
		knl_removeAreaQue(aq->next);
	}

	knl_appendFreeArea(knl_imacb, aq);

	EI(imask);
}
Beispiel #4
0
/*
 * Free memory
 *	It may be called during interrupt disable. In this case, need to wait
 *	 until interrupt is enabled and until free.
 */
LOCAL void ifree( void *ptr, IMACB *imacb )
{
	QUEUE	*aq;
	UW	imask;

	DI(imask);  /* Exclusive control by interrupt disable */
	SpinLock(&MemLockObj);

	aq = (QUEUE*)ptr - 1;
	clrAreaFlag(aq, AREA_USE);

	if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
		/* Merge with free area in after location */
		removeFreeQue(aq->next + 1);
		removeAreaQue(aq->next);
	}

	if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->prev, AREA_USE) ) {
		/* Merge with free area in front location */
		aq = aq->prev;
		removeFreeQue(aq + 1);
		removeAreaQue(aq->next);
	}

	/* If the whole page is free, then free the page.
	 * However, do not free the page if it is called during
	 * interrupt disabled.
	 */
	if ( !isDI(imask) && chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) {
		/* Free pages */
		removeAreaQue(aq->next);
		removeAreaQue(aq);
		SpinUnlock(&MemLockObj);
		EI(imask);
		RelSysMemBlk(aq);
		DI(imask);
		SpinLock(&MemLockObj);
	} else {
		/* Register free area to FreeQue */
		appendFreeArea(aq, imacb);
	}

	SpinUnlock(&MemLockObj);
	EI(imask);
}
Beispiel #5
0
/*
 * Free memory
 */
static void  _mem_free( void *ptr, MACB *macb )
{
	LIST	*aq;

	if ( ptr == 0 ) {
		return;
	}

	if ( macb->testmode > 0 ) {
		if ( !chkalloc(ptr, 0, macb) ) {
			return;
		}
	}

	aq = (LIST *)ptr - 1;
	clrAreaFlag(aq, AREA_USE);

	if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
		/* Merge with just next free area */
		removeFreeQue(aq->next + 1);
		removeAreaQue(aq->next);
	}

	if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->previous, AREA_USE) ) {
		/* Merge with just previous free area */
		aq = aq->previous;
		removeFreeQue(aq + 1);
		removeAreaQue(aq->next);
	}

	/* If whole page is empty, then release the page itself */
	if ( chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) {
		/* Page release */
		removeAreaQue(aq->next);
		removeAreaQue(aq);
		(*macb->relblk)(aq);
	} else {
		/* Register free area in free queue */
		appendFreeArea(aq, macb);
	}
}
Beispiel #6
0
/*
 * Registration in free space free queue
 *	Free queue comprises a two-tier structure: a queue linking
 *	areas of differing size in order of size, and a queue
 *	linking areas that are the same size.
 *
 *     macb->freeque
 *      |
 *	|   +-----------------------+		+-----------------------+
 *	|   | AreaQue		    |		| AreaQue		|
 *	|   +-----------------------+		+-----------------------+
 *	+----> FreeQue size order   |	 +--------> FreeQue same size ----->
 *	|   |  FreeQue same size --------+      |   EmptyQue		|
 *	|   |			    |		|			|
 *	|   |			    |		|			|
 *	|   +-----------------------+		+-----------------------+
 *	|   | AreaQue		    |		| AreaQue		|
 *	|   +-----------------------+		+-----------------------+
 */
void appendFreeArea( LIST *aq, MACB *macb )
{
	LIST	*fq;
	RAW_U32	size = (RAW_U32)AreaSize(aq);

	/* Search registration position */
	/*  Searches for a free space with the same size as 'size' or
	 *  the next largest.
	 *  If none is found, returns &freeque.
	 */
	fq = searchFreeArea(size, macb);

	/* Registration */
	clrAreaFlag(aq, AREA_USE);
	if ( fq != &macb->freeque && (RAW_U32)FreeSize(fq) == size ) {
		list_insert(fq + 1, aq + 1);
	} else {
		list_insert(fq, aq + 1);
	}
	list_init(aq + 2);
}
Beispiel #7
0
/*
 * Registration of free area on FreeQue
 *	FreeQue is composed of 2 types: Queue that links the
 *	different size of areas by size and queue that links the
 *	same size of areas.
 *
 *	freeque
 *	|
 *	|   +-----------------------+	    +-----------------------+
 *	|   | AreaQue		    |	    | AreaQue		    |
 *	|   +-----------------------+	    +-----------------------+
 *	*---> FreeQue Size order    |  *----> FreeQue Same size   ----->
 *	|   | FreeQue Same size   -----*    | EmptyQue		    |
 *	|   |			    |	    |			    |
 *	|   |			    |	    |			    |
 *	|   +-----------------------+	    +-----------------------+
 *	|   | AreaQue		    |	    | AreaQue		    |
 *	v   +-----------------------+	    +-----------------------+
 */
LOCAL void appendFreeArea( MPLCB *mplcb, QUEUE *aq )
{
	QUEUE	*fq;
	INT	size = AreaSize(aq);

	/* Registration position search */
	/*  Search the free area whose size is equal to 'blksz',
	 *  or larger than 'blksz' but closest.
	 *  If it does not exist, return '&mplcb->freeque'.
	 */
	fq = searchFreeArea(mplcb, size);

	/* Register */
	clrAreaFlag(aq, AREA_USE);
	if ( fq != &mplcb->freeque && FreeSize(fq) == size ) {
		QueInsert(aq + 1, fq + 1);
	} else {
		QueInsert(aq + 1, fq);
	}
	QueInit(aq + 2);
}
Beispiel #8
0
/*
 * Registration of free area on FreeQue
 *	FreeQue is composed of 2 types: Queue that links the different
 *	size of areas by size 
 *	and queue that links the same size areas.
 *
 *	imacb->freeque
 *	|
 *	|  +-----------------------+	  +-----------------------+
 *	|  | AreaQue		   |	  | AreaQue		  |
 *	|  +-----------------------+	  +-----------------------+
 *	*---> FreeQue by size	   |  *----> FreeQue same size   ---->
 *	|  | FreeQue same size    ----*   | EmptyQue		  |
 *	|  |			   |	  |			  |
 *	|  |			   |	  |			  |
 *	|  +-----------------------+	  +-----------------------+
 *	|  | AreaQue		   |	  | AreaQue		  |
 *	v  +-----------------------+	  +-----------------------+
 */
LOCAL void appendFreeArea( QUEUE *aq, IMACB *imacb )
{
	QUEUE	*fq;
	size_t	size = AreaSize(aq);

	/* Registration position search */
	/*  Search free area whose size is equal to 'blksz',
	 *  or closest and larger than 'blksz'.
	 *  If it can not be found, return '&imacb->freeque'.
	 */
	fq = searchFreeArea(size, imacb);

	/* Registration */
	clrAreaFlag(aq, AREA_USE);
	if ( (fq != &imacb->freeque) && (FreeSize(fq) == size) ) {
		QueInsert(aq + 1, fq + 1);
	} else {
		QueInsert(aq + 1, fq);
	}
	QueInit(aq + 2);
}