ClRcT clPoolShrink( ClPoolT poolHandle, const ClPoolShrinkOptionsT* pShrinkOptions) { ClRcT rc = CL_OK; ClPoolHeaderT* pPoolHeader = (ClPoolHeaderT*)poolHandle; ClPoolShrinkOptionsT defaultShrinkOptions; defaultShrinkOptions.shrinkFlags = CL_POOL_SHRINK_DEFAULT; NULL_CHECK (pPoolHeader); if (pShrinkOptions == NULL) { pShrinkOptions = &defaultShrinkOptions; } CL_POOL_LOG(CL_LOG_TRACE, "Shrinking %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); CL_POOL_LOCK (pPoolHeader); rc = CL_POOL_SHRINK_FREELIST (pPoolHeader, pShrinkOptions); CL_POOL_UNLOCK(pPoolHeader); if(rc != CL_OK) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error in shrinking free list\n")); CL_POOL_LOG(CL_LOG_ERROR, "Error shrinking %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); } return rc; }
ClRcT clPoolFree( ClUint8T* pChunk, void* pCookie) { ClRcT rc = CL_OK; ClPoolHeaderT* pPoolHeader = NULL; ClExtendedPoolHeaderT* pExtendedPoolHeader = NULL; ClUint32T freeChunk = 0; ClUint32T chunkSize = 0; ClFreeListHeaderT* pCurrentFreeList = NULL; NULL_CHECK (pChunk); NULL_CHECK (pCookie); pExtendedPoolHeader = (ClExtendedPoolHeaderT*)pCookie; pPoolHeader = pExtendedPoolHeader->pPoolHeader; CL_POOL_LOG(CL_LOG_SEV_TRACE,"freeing chunk pChunk = %p,extended pool = %p\n", pChunk,(void*)pExtendedPoolHeader); CL_POOL_LOCK (pPoolHeader); chunkSize = pPoolHeader->poolConfig.chunkSize; CL_POOL_REVOKE_SIZE(pPoolHeader->flags,chunkSize); CL_POOL_FREE_LIST_GET (pChunk, pExtendedPoolHeader, pCurrentFreeList); pCurrentFreeList->pChunk = (ClUint8T*)pChunk; pCurrentFreeList->pNextFreeChunk = pExtendedPoolHeader->pFirstFreeChunk; pExtendedPoolHeader->pFirstFreeChunk = pCurrentFreeList; CL_POOL_STATS_UPDATE_FREES (pPoolHeader); freeChunk = ++pExtendedPoolHeader->numFreeChunks; if (freeChunk == 1) { /*Was full before. Move it to partial*/ CL_POOL_LOG(CL_LOG_SEV_TRACE,"Dequeuing extended pool %p from full list and moving the extended pool to partial list\n", (void*)pExtendedPoolHeader); CL_POOL_EXTENDED_FULLLIST_DEQUEUE (pPoolHeader, pExtendedPoolHeader); CL_POOL_EXTENDED_PARTIALLIST_QUEUE (pPoolHeader, pExtendedPoolHeader); } if (freeChunk == pExtendedPoolHeader->numChunks) { /* * Add to the free extended pool list after deleting from the partial * list */ CL_POOL_LOG(CL_LOG_SEV_TRACE, "Dequeuing extended pool %p from partial list and moving the extended pool to free list\n", (void*)pExtendedPoolHeader); CL_POOL_EXTENDED_PARTIALLIST_DEQUEUE(pPoolHeader,pExtendedPoolHeader); CL_POOL_EXTENDED_FREELIST_QUEUE(pPoolHeader,pExtendedPoolHeader); } CL_POOL_UNLOCK(pPoolHeader); rc = CL_OK; return rc; }
static ClRcT clPoolShrinkList( ClPoolHeaderT *pPoolHeader, ClExtendedListT *pList, const ClPoolShrinkOptionsT *pShrinkOptions) { ClExtendedPoolHeaderT *pExtendedPoolHeader = NULL; ClExtendedPoolHeaderT *pNext = NULL; ClUint32T numExtendedFreePools = 0; ClUint32T i; ClRcT rc = CL_OK; numExtendedFreePools = CL_POOL_EXTENDED_LIST_COUNT (pList); switch(pShrinkOptions->shrinkFlags) { case CL_POOL_SHRINK_DEFAULT: /*50 % of the free list*/ numExtendedFreePools /= 2; break; case CL_POOL_SHRINK_ONE: numExtendedFreePools = CL_MIN (1, numExtendedFreePools); break; default: case CL_POOL_SHRINK_ALL: ; break; } if (numExtendedFreePools == 0) { CL_POOL_LOG(CL_LOG_SEV_WARNING,"No free list to shrink"); goto out; } for(i = 0, pExtendedPoolHeader = pList->pHeadExtendedList; i < numExtendedFreePools && pExtendedPoolHeader; ++i) { pNext = pExtendedPoolHeader->pNext; CL_POOL_EXTENDED_LIST_DEQUEUE(pList, pExtendedPoolHeader); rc = clExtendedPoolDestroy (pPoolHeader, pExtendedPoolHeader); if(rc != CL_OK) { CL_POOL_LOG(CL_LOG_SEV_ERROR,"Error in destroying extended pool"); goto out; } pExtendedPoolHeader = pNext; } out: return rc; }
static ClRcT clPoolDestroyWithForce( ClPoolHeaderT *pPoolHeader, ClBoolT forceFlag) { ClPoolShrinkOptionsT shrinkOptions; ClRcT rc = CL_POOL_RC(CL_ERR_OP_NOT_PERMITTED); shrinkOptions.shrinkFlags = CL_POOL_SHRINK_ALL; if (forceFlag == CL_FALSE && (!CL_POOL_EXTENDED_PARTIALLIST_EMPTY (pPoolHeader) || !CL_POOL_EXTENDED_FULLLIST_EMPTY (pPoolHeader))) { CL_POOL_LOG(CL_LOG_SEV_WARNING, "Warning!!Destroy called when pool is being used. Chunk size:%d", pPoolHeader->poolConfig.chunkSize); goto out; } rc = CL_POOL_SHRINK_FREELIST (pPoolHeader, &shrinkOptions); if (rc != CL_OK) { CL_POOL_LOG(CL_LOG_SEV_ERROR, "Error shrinking pools free list for chunk size:%d", pPoolHeader->poolConfig.chunkSize); goto out; } if (!CL_POOL_EXTENDED_PARTIALLIST_EMPTY(pPoolHeader)) { CL_POOL_LOG(CL_LOG_SEV_WARNING, "Warning!!Partial list isnt empty for chunk size:%d Count :%d\n", pPoolHeader->poolConfig.chunkSize, CL_POOL_EXTENDED_PARTIALLIST_COUNT (pPoolHeader)); rc = CL_POOL_SHRINK_PARTIALLIST (pPoolHeader, &shrinkOptions); } if (!CL_POOL_EXTENDED_FULLLIST_EMPTY (pPoolHeader)) { CL_POOL_LOG(CL_LOG_SEV_WARNING, "Warning !!Full list isnt empty for chunk size:%d Count :%d\n", pPoolHeader->poolConfig.chunkSize, CL_POOL_EXTENDED_FULLLIST_COUNT (pPoolHeader)); rc = CL_POOL_SHRINK_FULLLIST (pPoolHeader, &shrinkOptions); } else { rc = CL_OK; } out: return rc; }
static ClRcT clPoolAllocateExtendedPool( ClPoolHeaderT* pPoolHeader, ClExtendedPoolHeaderT* pExtendedPoolHeader) { ClRcT rc = CL_OK; ClUint32T chunkSize = pPoolHeader->poolConfig.chunkSize; ClUint32T incrementPoolSize = pPoolHeader->poolConfig.incrementPoolSize; rc = CL_POOL_RC (CL_ERR_NO_MEMORY); if ((pExtendedPoolHeader->pExtendedPoolStart = (ClUint8T*)CL_POOL_ALLOC_EXT (incrementPoolSize)) == NULL) { CL_POOL_LOG(CL_LOG_SEV_ERROR,"Error allocating memory of size:%d\n", incrementPoolSize); goto out; } pExtendedPoolHeader->pPoolHeader = pPoolHeader; pExtendedPoolHeader->numChunks = incrementPoolSize/chunkSize; pExtendedPoolHeader->numFreeChunks = pExtendedPoolHeader->numChunks; rc = clPoolPartitionExtendedPool (pExtendedPoolHeader); if (rc != CL_OK) { goto out_free; } /*Add this extended pool to the free list*/ CL_POOL_LOG(CL_LOG_SEV_TRACE,"Adding extended pool %p to free list",(void*)pExtendedPoolHeader); CL_POOL_EXTENDED_FREELIST_QUEUE(pPoolHeader,pExtendedPoolHeader); goto out; out_free: CL_POOL_FREE_EXTERNAL (pPoolHeader->flags, pExtendedPoolHeader->pExtendedPoolStart, incrementPoolSize); out: return rc; }
ClRcT clPoolDestroy( ClPoolT poolHandle) { ClRcT rc = CL_OK; ClPoolHeaderT *pPoolHeader = (ClPoolHeaderT*)poolHandle; ClPoolFlagsT flags; NULL_CHECK (pPoolHeader); flags = pPoolHeader->flags; CL_POOL_LOG(CL_LOG_NOTICE, "Destroying %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize ); CL_POOL_LOCK (pPoolHeader); rc = clPoolDestroyWithForce (pPoolHeader, CL_FALSE); CL_POOL_UNLOCK (pPoolHeader); if (rc != CL_OK) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error destroying the pool\n")); CL_POOL_LOG(CL_LOG_ERROR, "Error destroying %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); goto out; } /* * This is pretty dangerous and hence any users of this pool * go for a toss. * But destroy shouldnt be used on pre-defined pools * with pools in use anyway. */ CL_POOL_LOCK_DESTROY (pPoolHeader); CL_POOL_FREE_EXTERNAL (flags, (void*)pPoolHeader, sizeof (*pPoolHeader)); out: return rc; }
ClRcT clPoolDestroyForce( ClPoolT poolHandle) { ClRcT rc = CL_OK; ClPoolHeaderT *pPoolHeader = (ClPoolHeaderT*)poolHandle; ClPoolFlagsT flags; NULL_CHECK (pPoolHeader); flags = pPoolHeader->flags; CL_POOL_LOG(CL_LOG_TRACE, "Force destroying %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize ); CL_POOL_LOCK (pPoolHeader); rc = clPoolDestroyWithForce (pPoolHeader, CL_TRUE); CL_POOL_UNLOCK (pPoolHeader); CL_POOL_LOCK_DESTROY (pPoolHeader); CL_POOL_FREE_EXTERNAL (flags, (void*)pPoolHeader, sizeof (*pPoolHeader)); return rc; }
static ClRcT clPoolPartitionExtendedPoolDebug( ClExtendedPoolHeaderT *pExtendedPoolHeader) { register ClUint32T i; ClFreeListHeaderT *pFreeList; ClFreeListHeaderT *pCurrentFreeList; ClUint8T *pCurrentChunkStart; ClUint32T chunkSize = pExtendedPoolHeader->pPoolHeader->poolConfig.chunkSize; ClUint32T numChunks = pExtendedPoolHeader->numChunks; ClRcT rc = CL_POOL_RC(CL_ERR_NO_MEMORY); pFreeList = (ClFreeListHeaderT*)CL_POOL_ALLOC_EXTERNAL (pExtendedPoolHeader->pPoolHeader->flags, sizeof (*pFreeList) * numChunks); if (pFreeList == NULL) { CL_POOL_LOG(CL_LOG_SEV_ERROR,"Error allocating memory for freelist for chunk Size:%d",chunkSize); goto out; } pCurrentChunkStart = pExtendedPoolHeader->pExtendedPoolStart; pCurrentFreeList = pFreeList; pExtendedPoolHeader->pFreeListStart = pFreeList; pExtendedPoolHeader->pFirstFreeChunk = pCurrentFreeList; pCurrentFreeList->pChunk = pCurrentChunkStart; for(i = 0; i < numChunks - 1; ++i) { pCurrentChunkStart += chunkSize; pCurrentFreeList->pNextFreeChunk = pCurrentFreeList + 1; pCurrentFreeList->pNextFreeChunk->pChunk = pCurrentChunkStart; ++pCurrentFreeList; } pCurrentFreeList->pNextFreeChunk = NULL; rc = CL_OK; out: return rc; }
ClRcT clPoolAllocate( ClPoolT poolHandle, ClUint8T** ppChunk, void** ppCookie) { ClPoolHeaderT* pPoolHeader = NULL; ClRcT rc = CL_OK; ClFreeListHeaderT* pFreeChunk = NULL; ClExtendedPoolHeaderT* pExtendedPoolHeader = NULL; pPoolHeader = (ClPoolHeaderT*)poolHandle; NULL_CHECK (pPoolHeader); NULL_CHECK (ppChunk); NULL_CHECK (ppCookie); CL_POOL_LOCK (pPoolHeader); if(CL_POOL_GRANT_SIZE(pPoolHeader->flags, pPoolHeader->poolConfig.chunkSize) == CL_FALSE) { rc = CL_POOL_RC(CL_ERR_NO_MEMORY); CL_DEBUG_PRINT(CL_DEBUG_ERROR,("Request of %d bytes would exceed process upper limit\n",pPoolHeader->poolConfig.chunkSize)); goto out_unlock; } /*Check for a partially full queue*/ if (CL_POOL_EXTENDED_PARTIALLIST_EMPTY (pPoolHeader)) { /*Look for an extended pool in the free list*/ if (CL_POOL_EXTENDED_FREELIST_EMPTY (pPoolHeader)) { /*Grow the extended pool*/ rc = clPoolExtend(poolHandle); if(rc != CL_OK) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Pool extension error for chunksize:%d\n", pPoolHeader->poolConfig.chunkSize)); CL_POOL_LOG(CL_LOG_ERROR, "Pool allocate failed to extend %d byte pool of %d chunksize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); goto out_unlock; } } CL_POOL_EXTENDED_FREELIST_POP_DEQUEUE (pPoolHeader, pExtendedPoolHeader); CL_POOL_EXTENDED_PARTIALLIST_QUEUE (pPoolHeader ,pExtendedPoolHeader); } /* * We are here when we have a free chunk: * Point of no-return */ CL_POOL_EXTENDED_PARTIALLIST_POP (pPoolHeader, pExtendedPoolHeader); pFreeChunk = pExtendedPoolHeader->pFirstFreeChunk; pExtendedPoolHeader->pFirstFreeChunk = pFreeChunk->pNextFreeChunk; *ppChunk = (ClUint8T*)pFreeChunk->pChunk; *ppCookie = (void *)pExtendedPoolHeader; CL_POOL_STATS_UPDATE_ALLOCS (pPoolHeader); --pExtendedPoolHeader->numFreeChunks; CL_DEBUG_PRINT (CL_DEBUG_TRACE, ("pExtendedPoolHeader = %p pExtendedPoolHeader->numFreeChunks " "= %d pPoolHeader->poolConfig.chunkSize = %d from address = %p\n", (void*)pExtendedPoolHeader, pExtendedPoolHeader->numFreeChunks, pPoolHeader->poolConfig.chunkSize, (void*)pFreeChunk->pChunk)); /* * Was free partially but now full. * move it to full list. */ if (pExtendedPoolHeader->numFreeChunks == 0) { CL_DEBUG_PRINT (CL_DEBUG_TRACE, ("Dequeuing extended pool %p from partial list and queueing it to " "full list\n", (void*)pExtendedPoolHeader)); CL_POOL_EXTENDED_PARTIALLIST_DEQUEUE (pPoolHeader, pExtendedPoolHeader); CL_POOL_EXTENDED_FULLLIST_QUEUE (pPoolHeader, pExtendedPoolHeader); } out_unlock: CL_POOL_UNLOCK (pPoolHeader); return rc; }
ClRcT clPoolExtend( ClPoolT poolHandle) { ClRcT rc = CL_OK; ClPoolHeaderT* pPoolHeader = NULL; ClExtendedPoolHeaderT* pExtendedPoolHeader = NULL; pPoolHeader = (ClPoolHeaderT*)poolHandle; NULL_CHECK (pPoolHeader); CL_DEBUG_PRINT (CL_DEBUG_INFO, ("clPoolExtend() :: extendedPoolSize = %d, chunkSize = %d \n", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize)); rc = CL_POOL_RC (CL_ERR_NO_MEMORY); if (CL_POOL_MAX_EXTENDED_POOLS (pPoolHeader)) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("POOL extend of %d byte pool failed.Max pool size :%d, " "extended pools:%d\n", pPoolHeader->poolConfig.chunkSize, pPoolHeader->poolConfig.maxPoolSize, pPoolHeader->stats.numExtendedPools)); goto out; } if((pExtendedPoolHeader = (ClExtendedPoolHeaderT*)CL_POOL_ALLOC_EXTERNAL (pPoolHeader->flags, sizeof (ClExtendedPoolHeaderT))) == NULL) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error allocating memory for extended pool header, chunk " "size:%d extended pool number:%d\n", pPoolHeader->poolConfig.chunkSize, pPoolHeader->stats.numExtendedPools)); goto out; } memset (pExtendedPoolHeader, 0, sizeof (*pExtendedPoolHeader)); CL_POOL_LOG(CL_LOG_TRACE,"Extending %d byte pool of %d chunkSize", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); /*Initialise the extended pool*/ rc = clPoolAllocateExtendedPool (pPoolHeader, pExtendedPoolHeader); if (rc != CL_OK) { CL_POOL_LOG(CL_LOG_ERROR, "Extended pool allocation of %d byte pool of %d chunksize failed", pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize ); CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error allocating extended pool, chunk size:%d extended " "pool number:%d\n", pPoolHeader->poolConfig.chunkSize, pPoolHeader->stats.numExtendedPools)); goto out_free; } CL_POOL_STATS_UPDATE_EXTENDED_POOLS_INCR(pPoolHeader); rc = CL_OK; goto out; out_free: CL_POOL_FREE_EXTERNAL (pPoolHeader->flags, pExtendedPoolHeader, sizeof (*pExtendedPoolHeader)); out: return rc; }
ClRcT clPoolCreate( ClPoolT *pHandle, ClPoolFlagsT flags, const ClPoolConfigT *pPoolConfig) { ClRcT rc = CL_OK; ClPoolHeaderT* pPoolHeader = NULL; ClUint32T chunkSize = 0; ClUint32T incrementPoolSize = 0; ClUint32T extendedPools = 0; ClUint32T i = 0; NULL_CHECK (pPoolConfig); NULL_CHECK (pHandle); *pHandle = 0; /* Validate the chunk config*/ rc = clPoolValidateConfig (pPoolConfig); if(rc != CL_OK) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Invalid param\n")); goto out; } chunkSize = pPoolConfig->chunkSize; incrementPoolSize = pPoolConfig->incrementPoolSize; extendedPools = pPoolConfig->initialPoolSize/incrementPoolSize; rc = CL_POOL_RC (CL_ERR_NO_MEMORY); if ((pPoolHeader = (ClPoolHeaderT*)CL_POOL_ALLOC_EXTERNAL (flags, sizeof (*pPoolHeader))) == NULL) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error in allocating memory for pool header, chunk size:%d\n", chunkSize)); goto out; } memset (pPoolHeader, 0, sizeof (*pPoolHeader)); memcpy (&(pPoolHeader->poolConfig), pPoolConfig, sizeof (pPoolHeader->poolConfig)); pPoolHeader->flags = (ClPoolFlagsT) (pPoolHeader->flags | flags); rc = CL_POOL_LOCK_INIT (pPoolHeader); if(CL_OK != rc) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("CL_POOL_LOCK_INIT failed, rc=[%#X]\n", rc)); goto out; } /*Initialise the extended pool free,partial and full list*/ CL_POOL_EXTENDED_FREELIST_INIT (pPoolHeader); CL_POOL_EXTENDED_PARTIALLIST_INIT (pPoolHeader); CL_POOL_EXTENDED_FULLLIST_INIT (pPoolHeader); if (extendedPools == 0) { rc = CL_OK; goto out; } /*Create the initial extended pools*/ for (i = 0; i < extendedPools; ++i) { ClExtendedPoolHeaderT *pExtendedPoolHeader = NULL; if ((pExtendedPoolHeader = (ClExtendedPoolHeaderT*)CL_POOL_ALLOC_EXTERNAL (flags, sizeof (*pExtendedPoolHeader))) == NULL) { CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error allocating memory for extended pool header, chunk " "size:%d extended pool number:%d\n", chunkSize, i)); goto out_free; } memset (pExtendedPoolHeader, 0, sizeof (*pExtendedPoolHeader)); /*Initialize the extended pool*/ rc = clPoolAllocateExtendedPool (pPoolHeader, pExtendedPoolHeader); if(rc != CL_OK) { CL_POOL_FREE_EXTERNAL (flags, pExtendedPoolHeader, sizeof (*pExtendedPoolHeader)); CL_DEBUG_PRINT (CL_DEBUG_ERROR, ("Error allocating extended pool, chunk size:%d extended " "pool number:%d\n", chunkSize, i)); goto out_free; } CL_POOL_STATS_UPDATE_EXTENDED_POOLS_INCR(pPoolHeader); } *pHandle = (ClPoolT)pPoolHeader; CL_POOL_LOG(CL_LOG_TRACE, "%d extended pools created for %d byte pool with chunksize:%d", extendedPools, pPoolHeader->poolConfig.incrementPoolSize, pPoolHeader->poolConfig.chunkSize); rc = CL_OK; goto out; out_free: if(pPoolHeader) { clPoolDestroy((ClPoolT)pPoolHeader); } out: return rc; }