📄 smmemlib.c
字号:
) { SM_BLOCK_HDR volatile * pHdrStart; SM_BLOCK_HDR volatile * pHdrMid; SM_BLOCK_HDR volatile * pHdrEnd; char * pTmp; int 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); } /* insure that the pool starts on an even byte boundry */ pTmp = (char *) SM_MEM_ROUND_UP (pPool); /* get actual start */ poolSize = SM_MEM_ROUND_DOWN (poolSize - (pTmp - pPool)); /* adj length */ pPool = (char *) GLOB_TO_LOC_ADRS (pTmp); /* get local adrs */ /* * initialize three blocks one at each end of the pool * for end cases and real initial free block */ pHdrStart = (SM_BLOCK_HDR volatile *) pPool; pHdrStart->pPrevHdr = NULL; pHdrStart->free = htonl (FALSE); pHdrStart->nWords = htonl (sizeof (SM_BLOCK_HDR) >> 1); pHdrMid = (SM_BLOCK_HDR volatile *) SM_NEXT_HDR (pHdrStart); pHdrMid->pPrevHdr = (SM_BLOCK_HDR *)htonl (LOC_TO_GLOB_ADRS (pHdrStart)); pHdrMid->free = htonl (TRUE); pHdrMid->nWords = htonl ((poolSize - 2 * sizeof (SM_BLOCK_HDR)) >> 1); pHdrEnd = (SM_BLOCK_HDR volatile *) SM_NEXT_HDR (pHdrMid); pHdrEnd->pPrevHdr = (SM_BLOCK_HDR *) htonl (LOC_TO_GLOB_ADRS (pHdrMid)); pHdrEnd->free = htonl (FALSE); pHdrEnd->nWords = htonl (sizeof (SM_BLOCK_HDR) >> 1); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->options; /* BRIDGE FLUSH [SPR 68334] */ if (smMemPartAccessGet (partId) != OK) { return (ERROR); } smDllInsert(&partId->freeList, (SM_DL_NODE *)NULL, SM_HDR_TO_NODE(pHdrMid)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->totalWords; /* PCI bug [SPR 68844] */ partId->totalWords = htonl (ntohl (partId->totalWords) + (poolSize >> 1)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->options; /* BRIDGE FLUSH [SPR 68334] */ if (smMemPartAccessRelease (partId) != OK) { return (ERROR); } return (OK); }/******************************************************************************** smMemPartOptionsSet - set the debug options for a shared memory partition** This routine sets the debug options for a specified shared memory partition.* Two kinds of errors are detected: attempts to allocate more memory than* is available, and bad blocks found when memory is freed. In both cases,* the following options can be selected for actions to be taken when the error* is detected: (1) return the error status, (2) log an error message and* return the error status, or (3) log an error message and suspend the* calling task. These options are discussed in detail in the library manual* entry for smMemLib.** This routine is not user callable, it is called by the generic memory* partition routine memPartOptionsSet().** RETURNS: OK or ERROR.** ERRNO:* S_objLib_OBJ_ID_ERROR* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/STATUS smMemPartOptionsSet ( SM_PART_ID volatile partId, /* partition for which to set option */ unsigned options /* memory management options */ ) { int 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); } partId->options = htonl (options); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->options; /* BRIDGE FLUSH [SPR 68334] */ if (smMemPartAccessRelease (partId) != OK) { return (ERROR); } return (OK); }/******************************************************************************** smMemPartAlignedAlloc - allocate aligned memory from a partition** This routine allocates a buffer of size nBytes from the given * shared partition. Additionally, it will insure the allocated buffer * begins on a memory address that is evenly divisable by the given * alignment parameter. 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.** NOMANUAL*/void * smMemPartAlignedAlloc ( SM_PART_ID volatile partId, /* memory partition to allocate from */ unsigned nBytes, /* number of bytes to allocate */ unsigned alignment /* boundry to align to */ ) { unsigned nWords; unsigned nWordsExtra; SM_DL_NODE volatile * pNode; SM_BLOCK_HDR volatile * pHdr; SM_BLOCK_HDR volatile * pNewHdr; SM_BLOCK_HDR origpHdr; 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 (NULL); } /* get actual size to allocate; add overhead, check for minimum */ nWords = (SM_MEM_ROUND_UP (nBytes) + sizeof (SM_BLOCK_HDR)) >> 1; tmp = partId->minBlockWords; /* PCI bug [SPR 68844] */ if (nWords < ntohl (partId->minBlockWords)) { nWords = ntohl (partId->minBlockWords); } /* get exclusive access to the partition */ if (smMemPartAccessGet (partId) != OK) { return (NULL); } /* first fit */ pNode = (SM_DL_NODE volatile *) SM_DL_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 != LOC_NULL) { /* * fits if: * - blocksize > requested size + extra room for alignment or, * - block is already aligned and exactly the right size */ if ((ntohl (SM_NODE_TO_HDR (pNode)->nWords) > nWordsExtra) || ((((UINT) SM_HDR_TO_BLOCK (SM_NODE_TO_HDR (pNode)) % alignment) == 0) && (ntohl (SM_NODE_TO_HDR (pNode)->nWords) == nWords))) { break; } pNode = (SM_DL_NODE volatile *) SM_DL_NEXT (pNode); } if (pNode == LOC_NULL) { if (smMemPartAccessRelease (partId) != OK) { return (NULL); } smMemPartAllocError (partId, nBytes); return (NULL); } pHdr = (SM_BLOCK_HDR volatile *) SM_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 smMemAlignedBlockSplit 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 = smMemAlignedBlockSplit (partId, pHdr, nWords, ntohl (partId->minBlockWords), alignment); if (pNewHdr != NULL) { pHdr = pNewHdr; /* give split off block */ break; } pNode = (SM_DL_NODE volatile *) SM_DL_NEXT (pNode); } /* mark the block we're giving as not free */ pHdr->free = htonl (FALSE); /* update allocation statistics */ partId->curBlocksAllocated = htonl (ntohl (partId->curBlocksAllocated) +1); partId->cumBlocksAllocated = htonl (ntohl (partId->cumBlocksAllocated) +1); partId->curWordsAllocated = htonl (ntohl (partId->curWordsAllocated) + ntohl (pHdr->nWords)); partId->cumWordsAllocated = htonl (ntohl (partId->cumWordsAllocated) + ntohl (pHdr->nWords)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = partId->options; /* BRIDGE FLUSH [SPR 68334] */ if (smMemPartAccessRelease (partId) != OK) { return (NULL); } return ((void *) SM_HDR_TO_BLOCK (pHdr)); }/******************************************************************************** smMemPartAlloc - allocate a block of memory from a specified shared partition** From a specified shared partition, this routine allocates a block of memory* whose size is equal to or greater than <nBytes>. The shared partition * must have been previously created with memPartSmCreate().** This routine is not user callable, it is called by the generic memory* partition routine memPartAlloc.** RETURNS:* A pointer to a block, or* NULL if the call fails.** ERRNO:* S_objLib_OBJ_ID_ERROR* S_memLib_NOT_ENOUGH_MEMORY* S_smObjLib_LOCK_TIMEOUT** SEE ALSO: smMemPartInit()** NOMANUAL*/void * smMemPartAlloc ( SM_PART_ID partId, /* partition to allocate from */ unsigned nBytes /* number of bytes to allocate */ ) { return (smMemPartAlignedAlloc (partId, nBytes, SM_ALIGN_BOUNDARY)); }/******************************************************************************** smMemPartRealloc - reallocate a block of memory in specified shared partition** This routine changes the size of a specified block and returns a pointer to* the new block of memory. The contents that fit inside the new size (or old* size if smaller) remain unchanged.** This routine is not user callable, it is called by the generic memory* partition routine memPartRealloc.** RETURNS:* A pointer to the new block of memory, or NULL if the call fails.** ERRNO:* S_objLib_OBJ_ID_ERROR* S_memLib_NOT_ENOUGH_MEMORY* S_memLib_BLOCK_ERROR* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/void * smMemPartRealloc ( SM_PART_ID volatile partId, /* partition to reallocate from */ char * pBlock, /* block to be reallocated */ unsigned nBytes /* new block size in bytes */ ) { SM_BLOCK_HDR volatile * pHdr = SM_BLOCK_TO_HDR (pBlock); SM_BLOCK_HDR volatile * pNextHdr; unsigned nWords; void * pNewBlock; 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 (NULL); } /* get exclusive access to the partition */ if (smMemPartAccessGet (partId) != OK) { return (NULL); } /* get actual new size; round-up, add overhead, check for minimum */ nWords = (SM_MEM_ROUND_UP (nBytes) + sizeof (SM_BLOCK_HDR)) >> 1; tmp = partId->minBlockWords; /* PCI bug [SPR 68844] */ if (nWords < ntohl (partId->minBlockWords)) { nWords = ntohl (partId->minBlockWords); } /* optional check for validity of block */ partOptions = ntohl (partId->options); if ((partOptions & MEM_BLOCK_CHECK) && !smMemPartBlockIsValid (partId, pHdr, FALSE)) { smMemPartAccessRelease (partId); /* release access */ smMemPartBlockError (partId, pBlock, "smMemPartRealloc"); return (NULL); } /* test if we are trying to increase size of block */ tmp = pHdr->nWords; /* PCI bug [SPR 68844] */ if (nWords > ntohl (pHdr->nWords)) { /* * increase size of block - * check if next block is free and is big enough to satisfy request */ pNextHdr = (SM_BLOCK_HDR volatile *) SM_NEXT_HDR (pHdr); if (!(ntohl (pNextHdr->free)) || ((ntohl (pHdr->nWords) + ntohl (pNextHdr->nWords)) < nWords)) { /* * can't use adjacent free block - * allocate an entirely new block and copy data */ if (smMemPartAccessRelease (partId) != OK) { return (NULL); } if ((pNewBlock = smMemPartAlloc (partId, nBytes)) == NULL) { return (NULL); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* PCI bug [SPR 68844] */ bcopy (pBlock, (char *) pNewBlock, (int) (2 * ntohl (pHdr->nWords) - sizeof (SM_BLOCK_HDR))); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pHdr->nWords; /* BRIDGE FLUSH [SPR 68334] */ (void) smMemPartFree (partId, pBlock); return (pNewBlock); /* RETURN, don't fall through */ } else { /* * append next block to this one - * - delete next block from freelist, * - add its size to this block, * - update allocation statistics, * - fix prev info in new "next" block header */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -