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;
}
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;
}