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

📄 zregion.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
字号:
/*
* File			:	ZRegion.c
*
* Description	:	This file contains functions to manage the region.
*
* Copyright 2004 ZiLOG Inc.  ALL RIGHTS RESERVED.
*
* This file contains unpublished confidential and proprietary information
* of ZiLOG, Inc.
* NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED 
* IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
* This is not a license and no use of any kind of this work is authorized
* in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's 
* sole discretion 
*/


#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZRegion.h"
#include "ZSemaphore.h"
#include "externvar.h"

#define pCurrentThread  ((RZK_TCB_t *) hCurrentThread)
#define pThread  ((RZK_TCB_t *) hThread)

#define ALIGN(V, SIZE) ((((V) + (SIZE) - 1) / (SIZE)) * (SIZE))
#define pRegion  ((RZK_REGION_t *) hRegion)

/** extern variables */
extern RZK_SEGMENT_CB_t nRegion_Tab[];  
extern RZK_THREADHANDLE_t hCurrentThread;
/****************************************************************************
*	Function		:	AddSegToOwnerQueue
*
*	Description		:	Adds the segment to the owned segments queue of the thread
* 
*	Inputs			:	hThread - Specifies the thread
*						pSeg - Pointer to Segment  
*						
*
*	Outputs			:	None
*
*	Dependencies	:	None.
*	
****************************************************************************/


/* Add to Owner Queue function */
void AddSegToOwnerQueue(RZK_HANDLE_t hThread,pRZK_SEGMENT_t pSeg)
{
	/* LOCAL VARIABLES*/
	pRZK_SEGMENT_t pTempObject,pTempObject2;

	if(pThread->pOwnedSegNext == NULL)
	{
		pThread->pOwnedSegNext = pSeg;
		pSeg->pOwnedSegNext = ( pRZK_SEGMENT_t ) NULL;
		return;
	}

	pTempObject = ( pRZK_SEGMENT_t ) pThread->pOwnedSegNext;
	while(pTempObject != NULL)
	{
		pTempObject2 = pTempObject;
		pTempObject = pTempObject->pOwnedSegNext;
	}
	pSeg->pOwnedSegNext = pTempObject2->pOwnedSegNext;
	pTempObject2->pOwnedSegNext = pSeg;
}/* end of AddSegToOwnerQueue */



/****************************************************************************
*	Function		:	RemoveSegFromOwnerQueue
*
*	Description		:	Removes the segment from the owned segments queue of the thread
* 
*	Inputs			:	hThread - Specifies the thread
*						pSeg - Pointer to Segment    
*						
*
*	Outputs			:	None
*
*	Dependencies	:	None
*	
****************************************************************************/


/* Remove From Owner Queue function */
void RemoveSegFromOwnerQueue(RZK_HANDLE_t hThread,pRZK_SEGMENT_t pSeg)
{
	/* LOCAL VARIABLES */
	pRZK_SEGMENT_t pTempObject,pTempObject2;
	
	#ifdef RZK_DEBUG
		if(pThread == NULL)
			return;
	#endif /* RZK_DEBUG*/
	if (pThread->pOwnedSegNext == pSeg)
	{
		/* if this is the first object in queue to be removed */
		pThread->pOwnedSegNext = pSeg-> pOwnedSegNext;
		return;
	}

	pTempObject = ( pRZK_SEGMENT_t ) pThread->pOwnedSegNext;
	while(pTempObject != pSeg)
	{
		pTempObject2 = pTempObject;
		pTempObject = pTempObject->pOwnedSegNext;
	}
	pTempObject2->pOwnedSegNext = pTempObject->pOwnedSegNext;
	
} /* end of RemoveSegFromOwnerQueue */





/****************************************************************************
*	Function		:	Is_Region_Valid
*
*	Description		:	This Function checks if the segment is valid or not
* 
*	Inputs			:	hRegion - Specifies the region
*						start - Specifies Segment entry.  
*						
*
*	Outputs			:	pRZK_SEGMENT_t - Pointer to Segment if valid, else NULL
*
*	Dependencies	:	All externs.
*	
****************************************************************************/


pRZK_SEGMENT_t Is_Segment_Valid(RZK_REGIONHANDLE_t	hRegion, void *start)
{
    pRZK_SEGMENT_t pSeg = ( pRZK_SEGMENT_t ) NULL;
	
    for (pSeg = ( pRZK_SEGMENT_t ) pRegion->Alloc_List; pSeg != NULL &&  pSeg->start != (UINT8 *) start; pSeg = pSeg->next);
    return pSeg;
}


/****************************************************************************
*	Function		:	Clear_Segment_Entry
*
*	Description		:	This Function clears the entry for a Segment
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						
*
*	Outputs			:	void
*
*	Dependencies	:	All externs.
*	
****************************************************************************/

void Clear_Segment_Entry(pRZK_SEGMENT_t pSeg)
{
    pSeg->prev = ( pRZK_SEGMENT_t ) NULL;
    pSeg->next = ( pRZK_SEGMENT_t ) NULL;
    pSeg->start = ( UINT8 * ) NULL ;
    pSeg->len = 0;
    pSeg->thread = ( RZK_TCB_t * ) NULL;
	pSeg->pOwnedSegNext = ( pRZK_SEGMENT_t ) NULL;
}


/****************************************************************************
*	Function		:	Segment_Insert_Before
*
*	Description		:	This Function inserts a Segment entry before pSegBefore
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						pSegBefore - Specifies the node before which insertion to be done
*						pSegHead - Specifies the head node of the list
*			
*	Outputs			:	void
*
*	Dependencies	:	All externs.
*	
****************************************************************************/


static void Segment_Insert_Before(pRZK_SEGMENT_t pSeg, pRZK_SEGMENT_t pSegBefore, pRZK_SEGMENT_t * pSegHead)
{
    pSeg->next = pSegBefore;
    if (*pSegHead == pSegBefore)
		*pSegHead = pSeg;
    else 
	{
		pSeg->prev = pSegBefore->prev;
		pSegBefore->prev->next = pSeg;
	}
    pSegBefore->prev = pSeg;
}


/****************************************************************************
*	Function		:	Segment_Insert_After
*
*	Description		:	This Function inserts a Segment entry after pSegAfter
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						pSegAfter - Specifies the node after which insertion to be done
*						pSegHead - Specifies the head node of the list
*			
*	Outputs			:	void
*
*	Dependencies	:	All externs.
*	
****************************************************************************/


static void Segment_Insert_After(pRZK_SEGMENT_t pSeg, pRZK_SEGMENT_t pSegAfter)
{
    pSeg->prev = pSegAfter;
    pSegAfter->next = pSeg;
}


/****************************************************************************
*	Function		:	Segment_Insert
*
*	Description		:	This Function inserts a Segment entry
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						pSegHead - Specifies the head node of the list
*			
*	Outputs			:	void
*
*	Dependencies	:	All externs.
*	
****************************************************************************/

void Segment_Insert(pRZK_SEGMENT_t pSeg, pRZK_SEGMENT_t * pSegHead)
{
    pRZK_SEGMENT_t pSegInsert;

    if (*pSegHead == NULL) 
	{
		*pSegHead = pSeg;
		return;
    }

    for (pSegInsert = *pSegHead;; pSegInsert = pSegInsert->next) 
	{
		if (pSegInsert->start > pSeg->start) 
		{
			Segment_Insert_Before(pSeg, pSegInsert, pSegHead);
			return;
		}
		if (pSegInsert->next == NULL) 
		{
			Segment_Insert_After(pSeg, pSegInsert);
			return;
		}
    }
}	


/****************************************************************************
*	Function		:	Segment_Remove
*
*	Description		:	This Function removes a Segment entry
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						pSegHead - Specifies the head node of the list
*			
*	Outputs			:	void
*
*	Dependencies	:	All externs.
*	
****************************************************************************/

void Segment_Remove(pRZK_SEGMENT_t pSeg, pRZK_SEGMENT_t * pSegHead)
{
    if (pSeg->next != NULL)
	pSeg->next->prev = pSeg->prev;
    if (pSeg->prev == NULL)
	*pSegHead = pSeg->next;
    else
	pSeg->prev->next = pSeg->next;
    pSeg->prev = ( pRZK_SEGMENT_t ) NULL;
    pSeg->next = ( pRZK_SEGMENT_t ) NULL;
}


/****************************************************************************
*	Function		:	Segment_Split
*
*	Description		:	This Function splits a segment
* 
*	Inputs			:	pSeg - Specifies Segment entry.  
*						size - Specifies size of first segment
*			
*	Outputs			:	void* - Specifies the start address of the split off segment
*
*	Dependencies	:	All externs.
*	
****************************************************************************/

void *Segment_Split(pRZK_SEGMENT_t pSeg, RZK_LENGTH_t size)	// IAR port - changed from COUNT_t RZK_LENGTH_t
{
    pRZK_SEGMENT_t pSegSplitOff;
    UINT i;	// IAR port - changed from int to UINT
     /* Search for a free region table entry to record the split off portion
        of the specified region*/
	
    for (i = 0; i < MAX_REGIONS_TAB && (pSegSplitOff = (pRZK_SEGMENT_t)&(nRegion_Tab[i]))->start != ( UINT8 * ) NULL; i++);	// IAR port
// IAR port    for (i = 0; i < MAX_REGIONS + MAX_REGIONS_TAB && (pSegSplitOff = (pRZK_SEGMENT_t)&(nRegion_Tab[i]))->start != 0; i++);

    if (i == MAX_REGIONS_TAB)
	return NULL;

    /* Record the split off portion */
    pSegSplitOff->start = pSeg->start + size;
    pSegSplitOff->len = pSeg->len - size;

    /* Reduce the size of the specified region */
    pSeg->len = size;

     
     /* Enter the split off region the same region list as that containing the
        specified region*/
     
    pSegSplitOff->prev = pSeg;
    pSegSplitOff->next = pSeg->next;
    if (pSeg->next != NULL)
	pSeg->next->prev = pSegSplitOff;
    pSeg->next = pSegSplitOff;

    /* Return a pointer to start of the split off region */
    return (void *) pSegSplitOff->start;
}



/****************************************************************************
*	Function		:	Mem_Alloc_Seg
*
*	Description		:	This Function allocates a segment of memory from
*						the region specified. The amount of memory to be
*						allocated should be greater than or equal to uUnit_Size
*						of the region.
* 
*	Inputs			:	hRegion - Specifies a handle to the Region.  
*						size -  Specifies the size of memory to allocate.
*						
*
*	Outputs			:	Void* - Pointer to memory allocated
*
*	Dependencies	:	All externs.
*	
****************************************************************************/
extern RZK_SEMAPHOREHANDLE_t hSem_Region;
void *Mem_Alloc_Seg(RZK_REGIONHANDLE_t	hRegion, RZK_LENGTH_t size)	// IAR port: changed from COUNT_t to RZK_LENGTH_t
{
    pRZK_SEGMENT_t pSeg;
	void *temp;

	RZKAcquireSemaphore(hSem_Region,INFINITE_SUSPEND);
    /* Increase size request to next multiple of page size */
    size = ALIGN(size, pRegion->uUnit_Size);

    /* First-fit search for free region */
	
    for (pSeg = pRegion->Free_List; pSeg != NULL && pSeg->len < size; pSeg = pSeg->next);

    if (pSeg == NULL)
	{
		pCurrentThread->errNum = RZKERR_OUT_OF_MEMORY;
		RZKReleaseSemaphore(hSem_Region);
		return NULL;
	}

    /* Split region into used and unused portions */
    if (pSeg->len > size)
	{
		/* RZKERR_SCB_UNAVAILABLE is returned, if the segment control
		block is not available for creating the split off memory entry
		in the free list of the region.*/
		temp = Segment_Split(pSeg, size);
		if(temp == NULL)
		{
			pCurrentThread->errNum = RZKERR_SCB_UNAVAILABLE;
			RZKReleaseSemaphore(hSem_Region);
			return NULL;
		}
	}
	/* could not split, check if this is the only free segment. If yes make the freelist empty*/
	else if((pRegion->Free_List)->next == NULL)
	{
		pRegion->Free_List = ( pRZK_SEGMENT_t ) NULL;
	}

    /* Move used portion from free to allocated list */
    Segment_Remove(pSeg, &(pRegion->Free_List));
    Segment_Insert(pSeg, &(pRegion->Alloc_List));

    /* Assign ownership of region to calling thread */
   
	pSeg->thread = ( RZK_TCB_t * ) hCurrentThread;
	/* Add the segment to the owned segments queue of the thread*/
//	AddSegToOwnerQueue(hCurrentThread,pSeg);

	RZKReleaseSemaphore(hSem_Region);
    return (void *) pSeg->start;
}

⌨️ 快捷键说明

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