示例#1
0
/*
 * Memory map
 *	When paddr is NULL, allocate len bytes of memory having contiguous physical address,
 *	and returns the logical address to *laddr.
 *	When paddr is not NULL, map len bytes of physical memory from paddr and returns 
 *	the logical address to *laddr.
 *
 *	N.B. Access to *laddr may cause page fault.
 */
LOCAL ER _MapMemory( CONST void *paddr, INT len, UINT attr, void **laddr )
{
	ER	ercd;
	UINT	a;

	if ( len <= 0 ) {
		ercd = E_PAR;
		goto err_ret;
	}

	a = ( (attr & MM_USER) != 0 )? TA_RNG3: TA_RNG0;
	if ( (attr & MM_CDIS) != 0 ) {
		a |= TA_NOCACHE;
	}

	if ( paddr == NULL ) {
		/* Allocate memory automatically */
		*laddr = GetSysMemBlk((INT)smPageCount((UW)len), a);
		if ( *laddr == NULL ) {
			ercd = E_NOMEM;
			goto err_ret;
		}

		/* Set memory access privilege */
		ercd = _SetMemoryAccess(*laddr, len, (attr & (MM_READ|MM_WRITE|MM_EXECUTE)));
		if ( ercd < E_OK ) {
			RelSysMemBlk(*laddr);
			*laddr = NULL;
			goto err_ret;
		}

	} else {
		/* Logical address conversion */
		*laddr = toLogicalAddress(paddr);

		/* Flush cache */
		FlushCache(*laddr, len);

		if ( (attr & MM_CDIS) != 0 ) {
			/* Allocate logical addresses for cache off area */
			*laddr = toNoCacheLogicalAddress(*laddr);
		}
	}

	return E_OK;

err_ret:
#ifdef DEBUG
	TM_DEBUG_PRINT(("_MapMemory ercd = %d\n", ercd));
#endif
	return ercd;
}
示例#2
0
文件: imalloc.c 项目: kidasan/tkernel
/*
 * 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);
}
示例#3
0
文件: segmgr.c 项目: kidasan/tkernel
/*
 * Memory unmap 
 */
LOCAL ER _UnmapMemory( VP laddr )
{
	ER	ercd;

	/* Memory release when memory is allocated automatically by MapMemory()
	 *	If the memory is not automatically allocated, RelSysMemBlk() 
	 *	returns E_PAR.
	 */
	ercd = RelSysMemBlk(laddr);
	if ( ercd < E_OK && ercd != E_PAR ) {
		goto err_ret;
	}

	return E_OK;

err_ret:
	DEBUG_PRINT(("_UnmapMemory ercd = %d\n", ercd));
	return ercd;
}