Home | History | Annotate | Download | only in utils
      1 /** \file bufferPool.c
      2  *  \brief This file include buffer pool module implementation
      3  *  \author Ronen Kalish
      4  *  \date 05-December-2005
      5  */
      6 
      7 /****************************************************************************
      8 **+-----------------------------------------------------------------------+**
      9 **|                                                                       |**
     10 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved.      |**
     11 **| All rights reserved.                                                  |**
     12 **|                                                                       |**
     13 **| Redistribution and use in source and binary forms, with or without    |**
     14 **| modification, are permitted provided that the following conditions    |**
     15 **| are met:                                                              |**
     16 **|                                                                       |**
     17 **|  * Redistributions of source code must retain the above copyright     |**
     18 **|    notice, this list of conditions and the following disclaimer.      |**
     19 **|  * Redistributions in binary form must reproduce the above copyright  |**
     20 **|    notice, this list of conditions and the following disclaimer in    |**
     21 **|    the documentation and/or other materials provided with the         |**
     22 **|    distribution.                                                      |**
     23 **|  * Neither the name Texas Instruments nor the names of its            |**
     24 **|    contributors may be used to endorse or promote products derived    |**
     25 **|    from this software without specific prior written permission.      |**
     26 **|                                                                       |**
     27 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |**
     28 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |**
     29 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
     30 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |**
     31 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
     32 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |**
     33 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
     34 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
     35 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |**
     36 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
     37 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |**
     38 **|                                                                       |**
     39 **+-----------------------------------------------------------------------+**
     40 ****************************************************************************/
     41 
     42 #include "bufferPool.h"
     43 #include "osApi.h"
     44 #include "report.h"
     45 
     46 /**
     47  * \author Ronen Kalish\n
     48  * \date 05-December-2005\n
     49  * \brief Creates a buffer pool object
     50  *
     51  * Function Scope \e Public.\n
     52  * \param hOS - handle to the OS object.\n
     53  * \param numOfBuffers - the number of buffers to allocate for this pool.\n
     54  * \param bufferSize - the size of each buffer in this pool.\n
     55  * \return a handle to a buffer pool object, NULL if an error occurred.\n
     56  */
     57 TI_HANDLE bufferPool_create( TI_HANDLE hOS, UINT32 numOfBuffers, UINT32 bufferSize )
     58 {
     59     /* allocate the buffer pool object */
     60     bufferPool_t *pBufferPool = os_memoryAlloc( hOS, sizeof(bufferPool_t) );
     61     if ( NULL == pBufferPool )
     62     {
     63         WLAN_OS_REPORT( ("ERROR: Failed to create buffer pool object") );
     64         return NULL;
     65     }
     66 
     67     /*
     68      * adjust buffer size if necessary - the buffer must at least store the pointer to the
     69      * next free buffer when it is free.
     70      */
     71     if ( sizeof( bufferPool_buffer_t ) > bufferSize )
     72     {
     73         bufferSize = sizeof( bufferPool_buffer_t );
     74     }
     75 
     76     /* nullify the buffer pool object */
     77     os_memoryZero( hOS, pBufferPool, sizeof( bufferPool_t ) );
     78 
     79     /* allocate the buffers */
     80     pBufferPool->firstBuffer = pBufferPool->firstFreeBuffer = os_memoryAlloc( hOS, numOfBuffers * bufferSize );
     81     if ( NULL == pBufferPool->firstBuffer )
     82     {
     83         WLAN_OS_REPORT( ("ERROR: Failed to allocate buffer storage space") );
     84         bufferPool_destroy( (TI_HANDLE)pBufferPool );
     85         return NULL;
     86     }
     87 
     88     /* store the OS handle */
     89     pBufferPool->hOS = hOS;
     90 
     91     /* store buffer pool information */
     92     pBufferPool->bufferSize = bufferSize;
     93     pBufferPool->numberOfBuffers = numOfBuffers;
     94 
     95     /* initialize the free buffers list */
     96     bufferPool_reinit( (TI_HANDLE)pBufferPool );
     97 
     98 #ifdef TI_DBG
     99 	/* initialize debug information */
    100 	os_memoryZero( pBufferPool->hOS, &(pBufferPool->bufferPoolDbg), sizeof( bufferPoolDbg_t ) );
    101 #endif /* TI_DBG */
    102 
    103     return pBufferPool;
    104 }
    105 
    106 /**
    107  * \author Ronen Kalish\n
    108  * \date 05-December-2005\n
    109  * \brief Configures a buffer pool object.\n
    110  *
    111  * Function Scope \e Public.\n
    112  * \param hbufferPool - handle to a buffer pool object.\n
    113  * \param hReport - handle to the report module.\n
    114  */
    115 void bufferPool_config( TI_HANDLE hBufferPool, TI_HANDLE hReport )
    116 {
    117     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    118 
    119     /* keep the report handle */
    120     pBufferPool->hReport = hReport;
    121 }
    122 
    123 /**
    124  * \author Ronen Kalish\n
    125  * \date 05-December-2005\n
    126  * \brief releasing a buffer pool object.\n
    127  *
    128  * Function Scope \e Public.\n
    129  * \param hbufferPool - handle to a buffer pool object.\n
    130  */
    131 void bufferPool_destroy( TI_HANDLE hBufferPool )
    132 {
    133     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    134 
    135     /* release the buffers storage space */
    136     os_memoryFree( pBufferPool->hOS, pBufferPool->firstBuffer,
    137                    pBufferPool->bufferSize * pBufferPool->numberOfBuffers );
    138 
    139     /* release the buffer pool object */
    140     os_memoryFree( pBufferPool->hOS, pBufferPool, sizeof(bufferPool_t) );
    141 }
    142 
    143 /**
    144  * \author Ronen Kalish\n
    145  * \date 05-December-2005\n
    146  * \brief Reinitializes the buffer pool object, by marking all buffers
    147  * \brief as unallocated.\n
    148  *
    149  * Function Scope \e Public.\n
    150  * \param hbufferPool - handle to a buffer pool object.\n
    151  */
    152 void bufferPool_reinit( TI_HANDLE hBufferPool )
    153 {
    154     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    155     UINT32 i;
    156 
    157     /* make the first free buffer point to the first buffer */
    158     pBufferPool->firstFreeBuffer = pBufferPool->firstBuffer;
    159 
    160     /* insert all buffers to free list - last buffer must point to NULL */
    161     for ( i = 0; i < pBufferPool->numberOfBuffers - 1; i++ )
    162     {
    163         /* make the i'th buffer point to the next buffer */
    164         *(bufferPool_buffer_t*)((char*)pBufferPool->firstBuffer + (pBufferPool->bufferSize * i)) =
    165             (bufferPool_buffer_t)((char*)pBufferPool->firstBuffer + (pBufferPool->bufferSize * (i+1)));
    166     }
    167 
    168     /* make the last buffer point to NULL */
    169     *(bufferPool_buffer_t*)((char*)pBufferPool->firstBuffer +
    170         (pBufferPool->bufferSize * (pBufferPool->numberOfBuffers - 1))) =
    171             BUFFER_POOL_NO_BUFFER;
    172 
    173 #ifdef TI_DBG
    174 	/* mark that no buffers are allocated */
    175 	pBufferPool->bufferPoolDbg.numberOfUsedBuffers = 0;
    176 
    177 	/* mark all buffers as unallocated in the debug information */
    178 	for ( i = 0; i < BUFFER_POOL_MAX_NUM_OF_BUFFERS_FOR_DBG; i++ )
    179 	{
    180 		pBufferPool->bufferPoolDbg.bAllocated[ i ] = FALSE;
    181 	}
    182 #endif /* TI_DBG */
    183 }
    184 
    185 /**
    186  * \author Ronen Kalish\n
    187  * \date 05-December-2005\n
    188  * \brief Allocates a buffer.\n
    189  *
    190  * Function Scope \e Public.\n
    191  * \param hbufferPool - handle to a buffer pool object.\n
    192  * \return a buffer object, BUFFER_POOL_NO_BUFFER indication if non is available.\n
    193  */
    194 bufferPool_buffer_t bufferPool_allocateBuffer( TI_HANDLE hBufferPool )
    195 {
    196     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    197     bufferPool_buffer_t buffer;
    198 #ifdef TI_DBG
    199 	UINT32 bufferIndex;
    200 #endif
    201 
    202     /* check if a buffer is available */
    203     if ( BUFFER_POOL_NO_BUFFER == pBufferPool->firstFreeBuffer )
    204     {
    205 #ifdef TI_DBG
    206 		pBufferPool->bufferPoolDbg.NumberOfDeclinedAllocations++;
    207 #endif /* TI_DBG */
    208 		return BUFFER_POOL_NO_BUFFER;
    209     }
    210 
    211     /* temporarily keep the first free buffer */
    212     buffer = pBufferPool->firstFreeBuffer;
    213 
    214     /* advance the first free buffer to point to the next buffer in the list */
    215     pBufferPool->firstFreeBuffer = *(bufferPool_buffer_t*)((pBufferPool->firstFreeBuffer));
    216 
    217 #ifdef TI_DBG
    218 	/* increase the buffer in use count */
    219 	pBufferPool->bufferPoolDbg.numberOfUsedBuffers++;
    220 
    221 	/* count the successful allocation */
    222 	pBufferPool->bufferPoolDbg.NumberOfSuccessfulAllocations++;
    223 
    224 	/* mark the specific buffer as used */
    225 	bufferIndex = ((UINT8*)buffer - (UINT8*)pBufferPool->firstBuffer) / pBufferPool->bufferSize;
    226 	if ( bufferIndex < BUFFER_POOL_MAX_NUM_OF_BUFFERS_FOR_DBG )
    227 	{
    228 		pBufferPool->bufferPoolDbg.bAllocated[ bufferIndex ] = TRUE;
    229 	}
    230 #endif /* TI_DBG */
    231 
    232     return buffer;
    233 }
    234 
    235 /**
    236  * \author Ronen Kalish\n
    237  * \date 05-December-2005\n
    238  * \brief Returns a buffer to the pool.\n
    239  *
    240  * Function Scope \e Public.\n
    241  * \param hbufferPool - handle to a buffer pool object.\n
    242  * \param buffer - the buffer object to return to the pool.\n
    243  */
    244 void bufferPool_releaseBuffer( TI_HANDLE hBufferPool, bufferPool_buffer_t buffer )
    245 {
    246     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    247 #ifdef TI_DBG
    248 	UINT32 bufferIndex;
    249 
    250 	/* check if the buffer is currently allocated */
    251 	bufferIndex = ((UINT8*)buffer - (UINT8*)pBufferPool->firstBuffer) / pBufferPool->bufferSize;
    252 
    253 	if ( (bufferIndex < BUFFER_POOL_MAX_NUM_OF_BUFFERS_FOR_DBG) &&
    254 		 (FALSE == pBufferPool->bufferPoolDbg.bAllocated[ bufferIndex ]) )
    255 	{
    256 		/* count number of free attempts for already free buffers */
    257 		pBufferPool->bufferPoolDbg.NumberOfFreeBufferRefreed++;
    258 
    259 		WLAN_OS_REPORT(("%s: Trying to re-free Buffer %d\n", __FUNCTION__, bufferIndex));
    260 		return;
    261 	}
    262 	else
    263 	{
    264 		/* decrease the buffers in use count */
    265 		pBufferPool->bufferPoolDbg.numberOfUsedBuffers--;
    266 
    267 		/* mark that the specific buffer is not in use */
    268 		pBufferPool->bufferPoolDbg.bAllocated[ bufferIndex ] = FALSE;
    269 	}
    270 #endif /* TI_DBG */
    271 
    272     /* make the newly released buffer point to the current first free buffer */
    273     *((bufferPool_buffer_t*)buffer) = pBufferPool->firstFreeBuffer;
    274 
    275     /* make the newly release buffer the first free buffer */
    276     pBufferPool->firstFreeBuffer = buffer;
    277 }
    278 
    279 #ifdef TI_DBG
    280 /**
    281  * \author Ronen Kalish\n
    282  * \date 29-December-2005\n
    283  * \brief Returns the buffer pool debug structure.\n
    284  *
    285  * Function Scope \e Public.\n
    286  * \param hbufferPool - handle to a buffer pool object.\n
    287  */
    288 bufferPoolDbg_t *bufferPool_getDebugInformation( TI_HANDLE hBufferPool )
    289 {
    290     bufferPool_t* pBufferPool = (bufferPool_t*)hBufferPool;
    291 
    292 	return &(pBufferPool->bufferPoolDbg);
    293 }
    294 #endif
    295 
    296