📄 mempartlib.c
字号:
) { errno = S_memLib_NO_PARTITION_DESTROY; return (ERROR); }/********************************************************************************* memPartAddToPool - add memory to a memory partition** This routine adds memory to a specified memory partition already created* with memPartCreate(). The memory added need not be contiguous with* memory previously assigned to the partition.** RETURNS: OK or ERROR.** ERRNO: S_smObjLib_NOT_INITIALIZED, S_memLib_INVALID_NBYTES** SEE ALSO: smMemLib, memPartCreate()*/STATUS memPartAddToPool ( FAST PART_ID partId, /* partition to initialize */ FAST char *pPool, /* pointer to memory block */ FAST unsigned poolSize /* block size in bytes */ ) { FAST BLOCK_HDR *pHdrStart; FAST BLOCK_HDR *pHdrMid; FAST BLOCK_HDR *pHdrEnd; char * tmp; int reducePool; /* reduce size of pool by this amount*/ if (ID_IS_SHARED (partId)) /* partition is shared? */ { if (smMemPartAddToPoolRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (ERROR); } return ((*smMemPartAddToPoolRtn) (SM_OBJ_ID_TO_ADRS (partId), pPool, poolSize)); } /* partition is local */ if (OBJ_VERIFY (partId, memPartClassId) != OK) return (ERROR); /* insure that the pool starts on an even byte boundary */ tmp = (char *) MEM_ROUND_UP (pPool); /* get actual start */ reducePool = tmp - pPool; if (poolSize >= reducePool) /* adjust length */ poolSize -= reducePool; else poolSize = 0; pPool = tmp; /* * Make sure poolSize is an even multiple of the memory alignment size * and is large enough to include at least one valid free block and * three header blocks. */ poolSize = MEM_ROUND_DOWN (poolSize); if (poolSize < ((sizeof (BLOCK_HDR) * 3) + (partId->minBlockWords * 2))) { errno = S_memLib_INVALID_NBYTES; return (ERROR); } /* initialize three blocks - * one at each end of the pool for end cases and real initial free block */ pHdrStart = (BLOCK_HDR *) pPool; pHdrStart->pPrevHdr = NULL; pHdrStart->free = FALSE; pHdrStart->nWords = sizeof (BLOCK_HDR) >> 1; pHdrMid = NEXT_HDR (pHdrStart); pHdrMid->pPrevHdr = pHdrStart; pHdrMid->free = TRUE; pHdrMid->nWords = (poolSize - 2 * sizeof (BLOCK_HDR)) >> 1; pHdrEnd = NEXT_HDR (pHdrMid); pHdrEnd->pPrevHdr = pHdrMid; pHdrEnd->free = FALSE; pHdrEnd->nWords = sizeof (BLOCK_HDR) >> 1; semTake (&partId->sem, WAIT_FOREVER);#ifdef WV_INSTRUMENTATION EVT_OBJ_2 (OBJ, partId, memPartClassId, EVENT_MEMADDTOPOOL, partId, poolSize);#endif dllInsert (&partId->freeList, (DL_NODE *) NULL, HDR_TO_NODE (pHdrMid)); partId->totalWords += (poolSize >> 1); semGive (&partId->sem); return (OK); }/********************************************************************************* memPartAlignedAlloc - allocate aligned memory from a partition** This routine allocates a buffer of size <nBytes> from a specified* partition. Additionally, it insures that the allocated buffer begins on a* memory address evenly divisible by <alignment>. The <alignment> parameter* must be a power of 2.** RETURNS:* A pointer to the newly allocated block, or NULL if the buffer could not be* allocated.*/void *memPartAlignedAlloc ( FAST PART_ID partId, /* memory partition to allocate from */ unsigned nBytes, /* number of bytes to allocate */ unsigned alignment /* boundary to align to */ ) { FAST unsigned nWords; FAST unsigned nWordsExtra; FAST DL_NODE * pNode; FAST BLOCK_HDR * pHdr; BLOCK_HDR * pNewHdr; BLOCK_HDR origpHdr; if (OBJ_VERIFY (partId, memPartClassId) != OK) return (NULL); /* get actual size to allocate; add overhead, check for minimum */ nWords = (MEM_ROUND_UP (nBytes) + sizeof (BLOCK_HDR)) >> 1; /* check if we have an overflow. if so, set errno and return NULL */ if ((nWords << 1) < nBytes) { if (memPartAllocErrorRtn != NULL) (* memPartAllocErrorRtn) (partId, nBytes); errnoSet (S_memLib_NOT_ENOUGH_MEMORY); if (partId->options & MEM_ALLOC_ERROR_SUSPEND_FLAG) { if ((taskIdCurrent->options & VX_UNBREAKABLE) == 0) taskSuspend (0); /* suspend ourselves */ } return (NULL); } if (nWords < partId->minBlockWords) nWords = partId->minBlockWords; /* get exclusive access to the partition */ semTake (&partId->sem, WAIT_FOREVER); /* first fit */ pNode = DLL_FIRST (&partId->freeList); /* We need a free block with extra room to do the alignment. * Worst case we'll need alignment extra bytes. */ nWordsExtra = nWords + alignment / 2; FOREVER { while (pNode != NULL) { /* fits if: * - blocksize > requested size + extra room for alignment or, * - block is already aligned and exactly the right size */ if ((NODE_TO_HDR (pNode)->nWords > nWordsExtra) || ((NODE_TO_HDR (pNode)->nWords == nWords) && (ALIGNED (HDR_TO_BLOCK(NODE_TO_HDR(pNode)), alignment)))) break; pNode = DLL_NEXT (pNode); } if (pNode == NULL) { semGive (&partId->sem); if (memPartAllocErrorRtn != NULL) (* memPartAllocErrorRtn) (partId, nBytes); errnoSet (S_memLib_NOT_ENOUGH_MEMORY); if (partId->options & MEM_ALLOC_ERROR_SUSPEND_FLAG) { if ((taskIdCurrent->options & VX_UNBREAKABLE) == 0) taskSuspend (0); /* suspend ourselves */ } return (NULL); } pHdr = NODE_TO_HDR (pNode); origpHdr = *pHdr; /* now we split off from this block, the amount required by the user; * note that the piece we are giving the user is at the end of the * block so that the remaining piece is still the piece that is * linked in the free list; if memAlignedBlockSplit returned NULL, * it couldn't split the block because the split would leave the * first block too small to be hung on the free list, so we continue * trying blocks. */ pNewHdr = memAlignedBlockSplit (partId, pHdr, nWords, partId->minBlockWords, alignment); if (pNewHdr != NULL) { pHdr = pNewHdr; /* give split off block */ break; } pNode = DLL_NEXT (pNode); } /* mark the block we're giving as not free */ pHdr->free = FALSE;#ifdef WV_INSTRUMENTATION EVT_OBJ_4 (OBJ, partId, memPartClassId, EVENT_MEMALLOC, partId, HDR_TO_BLOCK (pHdr), 2 * (pHdr->nWords), nBytes);#endif /* update allocation statistics */ partId->curBlocksAllocated++; partId->cumBlocksAllocated++; partId->curWordsAllocated += pHdr->nWords; partId->cumWordsAllocated += pHdr->nWords; semGive (&partId->sem); return ((void *) HDR_TO_BLOCK (pHdr)); }/********************************************************************************* memPartAlloc - allocate a block of memory from a partition** This routine allocates a block of memory from a specified partition. * The size of the block will be equal to or greater than <nBytes>. * The partition must already be created with memPartCreate().** RETURNS:* A pointer to a block, or NULL if the call fails.** ERRNO: S_smObjLib_NOT_INITIALIZED** SEE ALSO: smMemLib, memPartCreate()*/void *memPartAlloc ( FAST PART_ID partId, /* memory partition to allocate from */ unsigned nBytes /* number of bytes to allocate */ ) { if (ID_IS_SHARED (partId)) /* partition is shared? */ { if (smMemPartAllocRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (NULL); } return ((void *) (*smMemPartAllocRtn) (SM_OBJ_ID_TO_ADRS (partId), nBytes)); } /* partition is local */ return (memPartAlignedAlloc (partId, nBytes, memDefaultAlignment)); }/********************************************************************************* memPartFree - free a block of memory in a partition** This routine returns to a partition's free memory list a block of * memory previously allocated with memPartAlloc().** RETURNS: OK, or ERROR if the block is invalid.** ERRNO: S_smObjLib_NOT_INITIALIZED** SEE ALSO: smMemLib, memPartAlloc()*/STATUS memPartFree ( PART_ID partId, /* memory partition to add block to */ char *pBlock /* pointer to block of memory to free */ ) { FAST BLOCK_HDR *pHdr; FAST unsigned nWords; FAST BLOCK_HDR *pNextHdr; if (ID_IS_SHARED (partId)) /* partition is shared? */ { if (smMemPartFreeRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (ERROR); } return ((*smMemPartFreeRtn) (SM_OBJ_ID_TO_ADRS (partId), pBlock)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -