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
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_DEBUG_PRINT (CL_DEBUG_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_DEBUG_PRINT (CL_DEBUG_TRACE,
            ("Adding extended pool %p to free list\n",
             (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;
}