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 */
bufferPool_create(TI_HANDLE hOS,UINT32 numOfBuffers,UINT32 bufferSize)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 */
bufferPool_config(TI_HANDLE hBufferPool,TI_HANDLE hReport)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 */
bufferPool_destroy(TI_HANDLE hBufferPool)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 */
bufferPool_reinit(TI_HANDLE hBufferPool)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 */
bufferPool_allocateBuffer(TI_HANDLE hBufferPool)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 */
bufferPool_releaseBuffer(TI_HANDLE hBufferPool,bufferPool_buffer_t buffer)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 */
bufferPool_getDebugInformation(TI_HANDLE hBufferPool)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