📄 zregion.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 + -