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