?? mempartlib.c
字號:
/* partition is local */ if (OBJ_VERIFY (partId, memPartClassId) != OK) return (ERROR); if (pBlock == NULL) return (OK); /* ANSI C compatibility */ pHdr = BLOCK_TO_HDR (pBlock); /* get exclusive access to the partition */ semTake (&partId->sem, WAIT_FOREVER); /* optional check for validity of block */ if ((partId->options & MEM_BLOCK_CHECK) && !memPartBlockIsValid (partId, pHdr, FALSE)) { semGive (&partId->sem); /* release mutual exclusion */ if (memPartBlockErrorRtn != NULL) (* memPartBlockErrorRtn) (partId, pBlock, "memPartFree"); if (partId->options & MEM_BLOCK_ERROR_SUSPEND_FLAG) { if ((taskIdCurrent->options & VX_UNBREAKABLE) == 0) taskSuspend (0); } errnoSet (S_memLib_BLOCK_ERROR); return (ERROR); }#ifdef WV_INSTRUMENTATION EVT_OBJ_3 (OBJ, partId, memPartClassId, EVENT_MEMFREE, partId, pBlock, 2 * (pHdr->nWords));#endif nWords = pHdr->nWords; /* check if we can coalesce with previous block; * if so, then we just extend the previous block, * otherwise we have to add this as a new free block */ if (PREV_HDR (pHdr)->free) { pHdr->free = FALSE; /* this isn't a free block */ pHdr = PREV_HDR (pHdr); /* coalesce with prev block */ pHdr->nWords += nWords; } else { pHdr->free = TRUE; /* add new free block */ dllInsert (&partId->freeList, (DL_NODE *) NULL, HDR_TO_NODE (pHdr)); } /* check if we can coalesce with next block; * if so, then we can extend our block delete next block from free list */ pNextHdr = NEXT_HDR (pHdr); if (pNextHdr->free) { pHdr->nWords += pNextHdr->nWords; /* coalesce with next */ dllRemove (&partId->freeList, HDR_TO_NODE (pNextHdr)); } /* fix up prev info of whatever block is now next */ NEXT_HDR (pHdr)->pPrevHdr = pHdr; /* adjust allocation stats */ partId->curBlocksAllocated--; partId->curWordsAllocated -= nWords; semGive (&partId->sem); return (OK); }/********************************************************************************* memPartBlockIsValid - check validity of block** This routine checks the validity of a block. If the pointer to the block* header is bogus we could run into bus errors and the calling task could take* the partId semaphore with it. To prvent this from happening we make the task* preemption proof and release the semaphore before doing the block validity * check. ** NOMANUAL*/BOOL memPartBlockIsValid ( PART_ID partId, FAST BLOCK_HDR *pHdr, BOOL isFree /* expected status */ ) { BOOL valid; TASK_LOCK (); /* LOCK PREEMPTION */ semGive (&partId->sem); /* release mutex */ valid = MEM_ALIGNED (pHdr) /* aligned */ && MEM_ALIGNED (2 * pHdr->nWords) /* size is round */ && (pHdr->nWords <= partId->totalWords) /* size <= total */ && (pHdr->free == isFree) /* right alloc-ness */#if (CPU_FAMILY == SH) && MEM_ALIGNED(NEXT_HDR (pHdr)) /* aligned(08aug95,sa)*/ && MEM_ALIGNED(PREV_HDR (pHdr)) /* aligned(08aug95,sa)*/#endif && (pHdr == PREV_HDR (NEXT_HDR (pHdr))) /* matches next block */ && (pHdr == NEXT_HDR (PREV_HDR (pHdr))); /* matches prev block */ semTake (&partId->sem, WAIT_FOREVER); /* reacquire mutex */ TASK_UNLOCK (); /* UNLOCK PREEMPTION */ return (valid); }/******************************************************************************* memAlignedBlockSplit - split a block on the free list into two blocks** This routine is like memBlockSplit, but also aligns the data block to the* given alignment. The block looks like this after it is split:** |----------------------------------------------------------------|* ^ ^ ^ ^* | | | space left over |* | |<------- nWords ------>| after alignment |* | | | |* block begin new aligned buffer begin end block end*** After the split, if the first block has less than minWords in it, the* block is rejected, and null is returned, since we can't place this first* block on the free list.* If the space succeeding the newly allocated aligned buffer is less than the* minimum block size, then the bytes are added to the newly allocated buffer.* If the space is greater than the minimum block size, then a new memory* fragment is created and added to the free list.* Care must be taken to insure that the orignal block passed in* to be split has at least (nWords + alignment/2) words in it. * If the block has exactly nWords and is already aligned to the given alignment,* it will be deleted from the free list and returned unsplit.* Otherwise, the second block will be returned.** RETURNS: A pointer to a BLOCK_HDR */LOCAL BLOCK_HDR *memAlignedBlockSplit ( PART_ID partId, FAST BLOCK_HDR *pHdr, FAST unsigned nWords, /* number of words in second block */ unsigned minWords, /* min num of words allowed in a block */ unsigned alignment /* boundary to align to */ ) { FAST BLOCK_HDR *pNewHdr; FAST BLOCK_HDR *pNextHdr; FAST char *endOfBlock; FAST char *pNewBlock; int blockSize; /* calculate end of pHdr block */ endOfBlock = (char *) pHdr + (pHdr->nWords * 2); /* caluclate unaligned beginning of new block */ pNewBlock = (char *) ((unsigned) endOfBlock - ((nWords - sizeof (BLOCK_HDR) / 2) * 2)); /* align the beginning of the block */ pNewBlock = (char *)((unsigned) pNewBlock & ~(alignment - 1)); pNewHdr = BLOCK_TO_HDR (pNewBlock); /* adjust original block's word count */ blockSize = ((char *) pNewHdr - (char *) pHdr) / 2; if (blockSize < minWords) { /* check to see if the new block is the same as the original block - * if so, delete if from the free list. If not, reject the newly * split block because it's too small to hang on the free list. */ if (pNewHdr == pHdr) dllRemove (&partId->freeList, HDR_TO_NODE (pHdr)); else return (NULL); } else { pNewHdr->pPrevHdr = pHdr; pHdr->nWords = blockSize; } /* check to see if space left over after we aligned the new buffer * is big enough to be a fragment on the free list. */ if (((UINT) endOfBlock - (UINT) pNewHdr - (nWords * 2)) < (minWords * 2)) { /* nope - give all the memory to the newly allocated block */ pNewHdr->nWords = (endOfBlock - pNewBlock + sizeof (BLOCK_HDR)) / 2; pNewHdr->free = TRUE; /* fix next block to point to newly allocated block */ NEXT_HDR (pNewHdr)->pPrevHdr = pNewHdr; } else { /* the extra bytes are big enough to be a fragment on the free list - * first, fix up the newly allocated block. */ pNewHdr->nWords = nWords; pNewHdr->free = TRUE; /* split off the memory after pNewHdr and add it to the free list */ pNextHdr = NEXT_HDR (pNewHdr); pNextHdr->nWords = ((UINT) endOfBlock - (UINT) pNextHdr) / 2; pNextHdr->pPrevHdr = pNewHdr; pNextHdr->free = TRUE; dllAdd (&partId->freeList, HDR_TO_NODE (pNextHdr)); /* fix next block to point to the new fragment on the free list */ NEXT_HDR (pNextHdr)->pPrevHdr = pNextHdr; } return (pNewHdr); }/******************************************************************************** memAddToPool - add memory to the system memory partition** This routine adds memory to the system memory partition, after the initial* allocation of memory to the system memory partition.** RETURNS: N/A** SEE ALSO: memPartAddToPool()*/void memAddToPool ( FAST char *pPool, /* pointer to memory block */ FAST unsigned poolSize /* block size in bytes */ ) { (void) memPartAddToPool (&memSysPartition, pPool, poolSize); }/********************************************************************************* malloc - allocate a block of memory from the system memory partition (ANSI)** This routine allocates a block of memory from the free list. The size of* the block will be equal to or greater than <nBytes>.** RETURNS: A pointer to the allocated block of memory, or a null pointer if* there is an error.** SEE ALSO: * .I "American National Standard for Information Systems -"* .I "Programming Language - C, ANSI X3.159-1989: General Utilities (stdlib.h)"*/void *malloc ( size_t nBytes /* number of bytes to allocate */ ) { return (memPartAlloc (&memSysPartition, (unsigned) nBytes)); }/********************************************************************************* free - free a block of memory (ANSI)** This routine returns to the free memory pool a block of memory previously* allocated with malloc() or calloc().** RETURNS: N/A** SEE ALSO: * malloc(), calloc(),* .I "American National Standard for Information Systems -"* .I "Programming Language - C, ANSI X3.159-1989: General Utilities (stdlib.h)"*/void free ( void *ptr /* pointer to block of memory to free */ ) { (void) memPartFree (&memSysPartition, (char *) ptr); }/********************************************************************************* memPartSemInit - initialize the partition semaphore as type binary** This routine initializes the partition semaphore as a binary semaphore.* This function is called indirectly from memPartInit(). This coupling* allows alternative semaphore types to serve as the basis for memory* partition interlocking.*/LOCAL void memPartSemInit ( PART_ID partId /* partition to initialize semaphore for */ ) { semBInit (&partId->sem, SEM_Q_PRIORITY, SEM_FULL); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -