📄 smmemlib.c
字号:
smDllRemove (&partId->freeList, SM_HDR_TO_NODE (pNextHdr)); /* fix size */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* PCI bug [SPR 68844] */ pHdr->nWords = htonl (ntohl (pHdr->nWords) + ntohl (pNextHdr->nWords)); /* fix stats */ partId->curWordsAllocated = htonl (ntohl (partId->curWordsAllocated) + ntohl (pNextHdr->nWords)); partId->cumWordsAllocated = htonl (ntohl (partId->cumWordsAllocated) + ntohl (pNextHdr->nWords)); /* fix next */ SM_NEXT_HDR (pHdr)->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pHdr)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ /* if this combined block is too big, it will get fixed below */ } } /* * split off any extra and give it back; * note that this covers both the case of a realloc for smaller space * and the case of a realloc for bigger space that caused a coalesce * with the next block that resulted in larger than required block */ pNextHdr = smMemBlockSplit (pHdr, ntohl (pHdr->nWords) - nWords, ntohl (partId->minBlockWords)); if (smMemPartAccessRelease (partId) != OK) { return (NULL); } if (pNextHdr != NULL) { (void) smMemPartFree (partId, SM_HDR_TO_BLOCK (pNextHdr)); /* adjust statistics */ partId->curBlocksAllocated = htonl(ntohl(partId->curBlocksAllocated)+1); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ } return ((void *) pBlock); }/******************************************************************************** smMemPartFree - free a block of memory in a specified shared partition** This routine takes a block of memory previously allocated with* smMemPartAlloc() and returns it to the shared partition's free memory list.** This routine is not user callable, it is called by the generic memory* partition routine memPartFree().** RETURNS: OK or ERROR if there is an invalid block.** ERRNO:* S_objLib_OBJ_ID_ERROR* S_memLib_BLOCK_ERROR* S_smObjLib_LOCK_TIMEOUT:** NOMANUAL*/STATUS smMemPartFree ( SM_PART_ID volatile partId, /* partition to use */ char * pBlock /* pointer to block of memory to be freed */ ) { SM_BLOCK_HDR volatile * pHdr; SM_BLOCK_HDR volatile * pNextHdr; unsigned nWords; int partOptions; /* partition options */ unsigned tmp; /* temp storage */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->verify; /* PCI bridge bug [SPR 68844] */ if (SM_OBJ_VERIFY (partId) != OK) { return (ERROR); } if (pBlock == NULL) { return (OK); /* ANSI C compatibility */ } pHdr = (SM_BLOCK_HDR volatile *) SM_BLOCK_TO_HDR (pBlock); nWords = ntohl (pHdr->nWords); /* get exclusive access to the partition */ if (smMemPartAccessGet (partId) != OK) { return (ERROR); } /* optional check for validity of block */ tmp = partId->options; /* PCI bug [SPR 68844] */ partOptions = ntohl (partId->options); if ((partOptions & MEM_BLOCK_CHECK) && !smMemPartBlockIsValid (partId, pHdr, FALSE)) { smMemPartAccessRelease (partId); /* release access */ smMemPartBlockError (partId, pBlock, "smMemPartFree"); return (ERROR); } /* * 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 (ntohl (SM_PREV_HDR (pHdr)->free)) { pHdr->free = htonl (FALSE); /* this isn't a free block */ pHdr = SM_PREV_HDR (pHdr); /* coalesce with prev block */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* PCI bug [SPR 68844] */ pHdr->nWords = htonl (ntohl (pHdr->nWords) + nWords); } else { pHdr->free = htonl (TRUE); /* add new free block */ smDllInsert (&partId->freeList, (SM_DL_NODE *) NULL, SM_HDR_TO_NODE (pHdr)); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ /* * Check if we can coalesce with next block; * if so, then we can extend our block delete next block from free list */ pNextHdr = (SM_BLOCK_HDR volatile *) SM_NEXT_HDR (pHdr); if (ntohl (pNextHdr->free)) { /* coalesce with next */ pHdr->nWords = htonl (ntohl (pHdr->nWords) + ntohl (pNextHdr->nWords)); smDllRemove (&partId->freeList, SM_HDR_TO_NODE (pNextHdr)); } /* fix up prev info of whatever block is now next */ SM_NEXT_HDR (pHdr)->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pHdr)); /* adjust allocation stats */ partId->curBlocksAllocated = htonl (ntohl (partId->curBlocksAllocated) - 1); partId->curWordsAllocated = htonl (ntohl (partId->curWordsAllocated) - nWords); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ if (smMemPartAccessRelease (partId) != OK) { return (ERROR); } return (OK); }/******************************************************************************** smMemPartFindMax - find the size of the largest available free block** This routine searches for the largest block in a shared memory partition free* list, and returns its size.** This routine is not user callable, it is called by the generic memory* partition routine memPartFindMax().** RETURNS: The size (in bytes) of the largest available block or ERROR if* <partId> is not a valid partition or if attempt to get access to the * partition fails.** ERRNO:* S_objLib_OBJ_ID_ERROR* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/int smMemPartFindMax ( SM_PART_ID volatile partId /* partition to use */ ) { SM_BLOCK_HDR volatile * pHdr; SM_DL_NODE volatile * pNode; unsigned biggestWords = 0; unsigned tmp; /* temp storage */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->verify; /* PCI bridge bug [SPR 68844] */ if (SM_OBJ_VERIFY (partId) != OK) { return (ERROR); } if (smMemPartAccessGet (partId) != OK) { return (ERROR); } /* go through free list and find largest free */ for (pNode = (SM_DL_NODE volatile *) SM_DL_FIRST (&partId->freeList); pNode != LOC_NULL; pNode = (SM_DL_NODE volatile *) SM_DL_NEXT (pNode)) { pHdr = (SM_BLOCK_HDR volatile *) SM_NODE_TO_HDR (pNode); if (ntohl (pHdr->nWords) > biggestWords) { biggestWords = ntohl (pHdr->nWords); } } if (smMemPartAccessRelease (partId) != OK) { return (ERROR); } /* convert words to bytes only if non-zero value [SPR 70280] */ if (biggestWords > 0) { biggestWords *= 2; biggestWords -= sizeof (SM_BLOCK_HDR); } return (biggestWords); }/******************************************************************************** smMemAlignedBlockSplit - split a block on the free list into two blocks** This routine is like smMemBlockSplit(), 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 ** NOMANUAL*/LOCAL SM_BLOCK_HDR volatile * smMemAlignedBlockSplit ( SM_PART_ID volatile partId, SM_BLOCK_HDR volatile * pHdr, unsigned nWords, /* number of words in second block */ unsigned minWords, /* min num of words allowed in a block */ unsigned alignment /* boundry to align to */ ) { SM_BLOCK_HDR volatile * pNewHdr; SM_BLOCK_HDR volatile * pNextHdr; char * endOfBlock; char * pNewBlock; int blockSize; unsigned tmp; /* temp storage */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* PCI bridge bug [SPR 68844] */ /* calculate end of pHdr block */ endOfBlock = (char *) pHdr + (ntohl (pHdr->nWords) * 2); /* calculate unaligned beginning of new block */ pNewBlock = (char *) ((unsigned) endOfBlock - ((nWords - sizeof (SM_BLOCK_HDR) / 2) * 2)); /* align the beginning of the block */ pNewBlock = (char *)((unsigned) pNewBlock & ~(alignment - 1)); pNewHdr = (SM_BLOCK_HDR volatile *) SM_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) { smDllRemove (&partId->freeList, SM_HDR_TO_NODE (pHdr)); } else { return (NULL); } } else { pNewHdr->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pHdr)); pHdr->nWords = htonl (blockSize); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pNewHdr->nWords; /* BRIDGE FLUSH [SPR 68844] */ /* * 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 = htonl ((endOfBlock - pNewBlock + sizeof (SM_BLOCK_HDR)) / 2); pNewHdr->free = htonl (TRUE); /* fix next block to point to newly allocated block */ SM_NEXT_HDR (pNewHdr)->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (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 = htonl (nWords); pNewHdr->free = htonl (TRUE); /* split off the memory after pNewHdr and add it to the free list */ pNextHdr = SM_NEXT_HDR (pHdr); pNextHdr->nWords = htonl (((UINT) endOfBlock - (UINT) pNextHdr) / 2); pNextHdr->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pHdr)); pNextHdr->free = htonl (TRUE); smDllAdd (&partId->freeList, SM_HDR_TO_NODE (pNextHdr)); /* fix next block to point to the new fragment on the free list */ SM_NEXT_HDR (pNextHdr)->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pNewHdr)); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pNewHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ return (pNewHdr); }/******************************************************************************** smMemBlockSplit - split a block into two blocks** This routine splits the block pointed to into two blocks. The second * block will have nWords words in it. A pointer is returned to this block.* If either resultant block would end up having less than minWords in it,* NULL is returned.** RETURNS: A pointer to the second block, or NULL.* * NOMANUAL*/LOCAL SM_BLOCK_HDR volatile * smMemBlockSplit ( SM_BLOCK_HDR volatile * pHdr, unsigned nWords, /* number of words in second block */ unsigned minWords /* min num of words allowed in a block */ ) { unsigned wordsLeft; SM_BLOCK_HDR volatile * pNewHdr; unsigned tmp; /* temp storage */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* PCI bug [SPR 68844] */ /* check if block can be split */ if ((nWords < minWords) || ((wordsLeft = (ntohl (pHdr->nWords) - nWords)) < minWords))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -