auto import from //depot/cupcake/@135843
[android/platform/external/neven.git] / Embedded / common / src / b_BasicEm / MemSeg.c
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* ---- includes ----------------------------------------------------------- */
18
19 #include "b_BasicEm/MemSeg.h"
20 #include "b_BasicEm/Functions.h"
21 #include "b_BasicEm/Context.h"
22
23 /* ------------------------------------------------------------------------- */
24
25 /* ========================================================================= */
26 /*                                                                           */
27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
28 /*                                                                           */
29 /* ========================================================================= */
30
31 /* ------------------------------------------------------------------------- */
32
33 /* ========================================================================= */
34 /*                                                                           */
35 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
36 /*                                                                           */
37 /* ========================================================================= */
38
39 /* ------------------------------------------------------------------------- */
40
41 void bbs_MemSeg_init( struct bbs_Context* cpA, 
42                                           struct bbs_MemSeg* ptrA )
43 {
44         ptrA->memPtrE = NULL;
45         ptrA->sizeE = 0;
46         ptrA->allocIndexE = 0;
47         ptrA->sharedE = FALSE;
48         ptrA->idE = 0;
49         ptrA->dynMemManagerPtrE = NULL;
50 }
51
52 /* ------------------------------------------------------------------------- */
53
54 void bbs_MemSeg_exit( struct bbs_Context* cpA, 
55                                           struct bbs_MemSeg* ptrA )
56 {
57         ptrA->memPtrE = NULL;
58         ptrA->sizeE = 0;
59         ptrA->allocIndexE = 0;
60         ptrA->sharedE = FALSE;
61         ptrA->idE = 0;
62         ptrA->dynMemManagerPtrE = NULL;
63 }
64
65 /* ------------------------------------------------------------------------- */
66
67 /* ========================================================================= */
68 /*                                                                           */
69 /* ---- \ghd{ operators } -------------------------------------------------- */
70 /*                                                                           */
71 /* ========================================================================= */
72
73 /* ------------------------------------------------------------------------- */
74
75 /* ========================================================================= */
76 /*                                                                           */
77 /* ---- \ghd{ query functions } -------------------------------------------- */
78 /*                                                                           */
79 /* ========================================================================= */
80
81 /* ------------------------------------------------------------------------- */
82
83 uint32 bbs_MemSeg_availableSize( struct bbs_Context* cpA, 
84                                                                  const struct bbs_MemSeg* ptrA )
85 {
86         if( ptrA->dynMemManagerPtrE == NULL )
87         {
88                 return ( ptrA->sizeE == ptrA->allocIndexE ) ? 0 : ptrA->sizeE - ptrA->allocIndexE - 2 * ptrA->sharedE;
89         }
90         else
91         {
92                 return 0xFFFFFFFF;
93         }
94 }
95
96 /* ------------------------------------------------------------------------- */
97
98 uint32 bbs_MemSeg_allocatedSize( struct bbs_Context* cpA, 
99                                                                  const struct bbs_MemSeg* ptrA )
100 {
101         if( ptrA->dynMemManagerPtrE == NULL )
102         {
103                 return ptrA->allocIndexE;
104         }
105         else
106         {
107                 return bbs_DynMemManager_allocatedSize( cpA, ptrA->dynMemManagerPtrE );
108         }
109 }
110
111 /* ------------------------------------------------------------------------- */
112
113 uint32 bbs_MemSeg_usedSize( struct bbs_Context* cpA, 
114                                                     const struct bbs_MemSeg* ptrA )
115 {
116         if( ptrA->dynMemManagerPtrE == NULL )
117         {
118                 if( ptrA->sharedE )
119                 {
120                         return ptrA->allocIndexE;
121                 }
122                 else
123                 {
124                         uint32 indexL = 0;
125                         uint32 countL = 0;
126                         while( indexL < ptrA->allocIndexE )
127                         {
128                                 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
129                                 indexL += ( sizeL & 0xFFFFFFFE );
130                                 if( ( sizeL & 1 ) == 0 )
131                                 {
132                                         countL += sizeL - 2;
133                                 }
134                         }
135                         return countL;
136                 }
137         }
138         else
139         {
140                 return bbs_MemSeg_allocatedSize( cpA, ptrA );
141         }
142 }
143
144 /* ------------------------------------------------------------------------- */
145
146 uint32 bbs_MemSeg_blocks( struct bbs_Context* cpA, 
147                                                   const struct bbs_MemSeg* ptrA )
148 {
149         uint32 indexL = 0;
150         uint32 countL = 0;
151
152         if( ptrA->sharedE ) return 0;
153
154         while( indexL < ptrA->allocIndexE )
155         {
156                 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
157                 indexL += ( sizeL & 0xFFFFFFFE );
158                 countL++;
159         }
160         return countL;
161 }
162
163 /* ------------------------------------------------------------------------- */
164
165 uint32 bbs_MemSeg_usedBlocks( struct bbs_Context* cpA, 
166                                                           const struct bbs_MemSeg* ptrA )
167 {
168         uint32 indexL = 0;
169         uint32 countL = 0;
170
171         if( ptrA->sharedE ) return 0;
172
173         while( indexL < ptrA->allocIndexE )
174         {
175                 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
176                 indexL += ( sizeL & 0xFFFFFFFE );
177                 countL += ( ( sizeL & 1 ) == 0 );
178         }
179         return countL;
180 }
181
182 /* ------------------------------------------------------------------------- */
183
184 /* ========================================================================= */
185 /*                                                                           */
186 /* ---- \ghd{ modify functions } ------------------------------------------- */
187 /*                                                                           */
188 /* ========================================================================= */
189
190 /* ------------------------------------------------------------------------- */
191
192 /* ========================================================================= */
193 /*                                                                           */
194 /* ---- \ghd{ I/O } -------------------------------------------------------- */
195 /*                                                                           */
196 /* ========================================================================= */
197
198 /* ------------------------------------------------------------------------- */
199
200 /* ========================================================================= */
201 /*                                                                           */
202 /* ---- \ghd{ exec functions } --------------------------------------------- */
203 /*                                                                           */
204 /* ========================================================================= */
205
206 /* ------------------------------------------------------------------------- */
207
208 struct bbs_MemSeg bbs_MemSeg_create( struct bbs_Context* cpA,
209                                                                          void* memPtrA, uint32 sizeA )
210 {
211         struct bbs_MemSeg memSegL;
212         memSegL.memPtrE     = ( uint16* )memPtrA;
213         memSegL.sizeE       = sizeA & 0xFFFFFFFE; /* enforce even size to avoid overflow problems */
214         memSegL.allocIndexE = 0;
215         memSegL.sharedE     = FALSE;
216         memSegL.idE         = 0;
217         memSegL.dynMemManagerPtrE = NULL;
218         return memSegL;
219 }
220
221 /* ------------------------------------------------------------------------- */
222
223 struct bbs_MemSeg bbs_MemSeg_createShared( struct bbs_Context* cpA,
224                                                                                    void* memPtrA, uint32 sizeA )
225 {
226         struct bbs_MemSeg memSegL;
227         memSegL.memPtrE     = ( uint16* )memPtrA;
228         memSegL.sizeE       = sizeA;
229         memSegL.allocIndexE = 0;
230         memSegL.sharedE     = TRUE;
231         memSegL.idE         = 0;
232         memSegL.dynMemManagerPtrE = NULL;
233         return memSegL;
234 }
235
236 /* ------------------------------------------------------------------------- */
237
238 void* bbs_MemSeg_alloc( struct bbs_Context* cpA, 
239                                             struct bbs_MemSeg* ptrA, 
240                                                 uint32 sizeA )
241 {
242         uint16* memPtrL = NULL;
243
244         if( bbs_Context_error( cpA ) ) return NULL;
245
246         if( !ptrA->sharedE )
247         {
248                 if( ptrA->dynMemManagerPtrE == NULL )
249                 {
250                         uint32 effSizeL = sizeA + ( sizeA & 1 ) + 2; /* effective block size */
251                         memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
252                         *( ( uint32* )memPtrL ) = effSizeL;
253                         memPtrL += 2;
254                         if( ptrA->allocIndexE + effSizeL > ptrA->sizeE )
255                         {
256                                 bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
257                                                   "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
258                                                   "Exclusive Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
259                                 return NULL;
260                         }
261                         ptrA->allocIndexE += effSizeL;
262                 }
263                 else
264                 {
265                         memPtrL = bbs_DynMemManager_alloc( cpA, ptrA->dynMemManagerPtrE, ptrA, sizeA );
266                 }
267         }
268         else
269         {
270                 uint32 effSizeL = sizeA + ( sizeA & 1 );  /* effective block size */
271
272                 if( ptrA->allocIndexE + effSizeL > ptrA->sizeE  + ( ptrA->sizeE & 1 ) )
273                 {
274                         if( ptrA->dynMemManagerPtrE == NULL )
275                         {
276                                 bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
277                                                   "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
278                                                   "Shared Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
279                                 return NULL;
280                         }
281                         else
282                         {
283                                 uint32 actualBlockSizeL = 0;
284                                 ptrA->memPtrE = bbs_DynMemManager_nextBlock( cpA, ptrA->dynMemManagerPtrE, ptrA, ptrA->memPtrE, effSizeL, &actualBlockSizeL );
285                                 ptrA->sizeE = actualBlockSizeL;
286                                 ptrA->allocIndexE = 0;
287                         }
288                 }
289
290                 memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
291                 ptrA->allocIndexE += effSizeL;
292         }
293
294         #if defined( HW_TMS320C5x )
295         #ifdef DEBUG2
296         {
297                 /* check if segment crosses page boundary */
298                 if( ( ( ( uint32 ) ptrA->memPtrE ) >> 16 ) !=
299                         ( ( ( uint32 ) ptrA->memPtrE + ( ptrA->sizeE - 1 ) ) >> 16 ) )
300                 {
301                         bbs_ERROR0( "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\nSegment crosses page boundary\n" );
302                         return NULL;
303                 }
304         }
305         #endif
306         #endif
307
308         return memPtrL;
309 }
310
311 /* ------------------------------------------------------------------------- */
312
313 void bbs_MemSeg_free( struct bbs_Context* cpA,
314                                           struct bbs_MemSeg* ptrA,
315                                           void* memPtrA )
316 {
317         bbs_DEF_fNameL( "void bbs_MemSeg_free( struct bbs_MemSeg* ptrA, void* memPtrA )" )
318
319         if( bbs_Context_error( cpA ) ) return;
320
321         /** only valid exclusive segments can be freed */
322         if( ptrA == NULL || memPtrA == NULL || ptrA->sharedE ) return;
323
324         if( ptrA->dynMemManagerPtrE != NULL )
325         {
326                 bbs_DynMemManager_free( cpA, ptrA->dynMemManagerPtrE, memPtrA );
327         }
328         else
329         {
330                 uint32 indexL, sizeL;
331                 uint16* memPtrL;
332
333                 if( ptrA == NULL || memPtrA == NULL ) return;
334                 if( ptrA->sharedE ) return;
335
336                 #ifdef HW_TMS320C5x
337                         indexL = ( uint32 ) memPtrA - ( uint32 ) ptrA->memPtrE - 2;
338                 #else
339                         indexL = ( uint16* )memPtrA - ptrA->memPtrE - 2;
340                 #endif
341
342                 memPtrL = ptrA->memPtrE + indexL;
343                 sizeL = *( ( int32* )memPtrL );
344
345                 /* checks */
346                 if( indexL > ptrA->allocIndexE || ( indexL & 1 ) != 0 )
347                 {
348                         bbs_ERROR4( "%s\n: Invalid memory.\n"
349                                                 "sizeE       = %i\n"
350                                                 "allocIndexE = %i\n"
351                                                 "indexL      = %i\n",
352                                                 fNameL,
353                                                 ptrA->sizeE,
354                                                 ptrA->allocIndexE,
355                                                 indexL );
356                         return;
357                 }
358
359                 if( ( sizeL & 1 ) != 0 )
360                 {
361                         bbs_ERROR1( "%s\n: Memory block was already freed once", fNameL );
362                         return;
363                 }
364
365                 *( ( uint32* )memPtrL ) += 1; /* odd size value indicates unused memory block */
366
367                 /* free last unused blocks if any */
368                 if( indexL + sizeL == ptrA->allocIndexE )
369                 {
370                         uint32 newAllocIndexL = 0;
371                         indexL = 0;
372                         while( indexL < ptrA->allocIndexE )
373                         {
374                                 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
375                                 indexL += ( sizeL & 0xFFFFFFFE );
376                                 if( ( sizeL & 1 ) == 0 )
377                                 {
378                                         newAllocIndexL = indexL;
379                                 }
380                         }
381
382                         ptrA->allocIndexE = newAllocIndexL;
383                 }
384
385         #ifdef DEBUG2
386                 bbs_MemSeg_checkConsistency( cpA, ptrA );
387         #endif
388
389         }
390 }
391
392 /* ------------------------------------------------------------------------- */
393
394 void bbs_MemSeg_checkConsistency( struct bbs_Context* cpA,
395                                                                   const struct bbs_MemSeg* ptrA )
396 {
397         uint32 indexL = 0;
398
399         if( ptrA->sharedE ) return;
400
401         while( indexL < ptrA->allocIndexE )
402         {
403                 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
404                 indexL += ( sizeL & 0xFFFFFFFE );
405         }
406
407         if( indexL != ptrA->allocIndexE )
408         {
409                 bbs_ERROR0( "Memory consistency check failed" );
410         }
411 }
412
413 /* ------------------------------------------------------------------------- */
414
415 /* ========================================================================= */