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
bbs_MemSeg_init(struct bbs_Context * cpA,struct bbs_MemSeg * ptrA)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
bbs_MemSeg_exit(struct bbs_Context * cpA,struct bbs_MemSeg * ptrA)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
bbs_MemSeg_availableSize(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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
bbs_MemSeg_allocatedSize(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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
bbs_MemSeg_usedSize(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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
bbs_MemSeg_blocks(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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
bbs_MemSeg_usedBlocks(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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
bbs_MemSeg_create(struct bbs_Context * cpA,void * memPtrA,uint32 sizeA)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
bbs_MemSeg_createShared(struct bbs_Context * cpA,void * memPtrA,uint32 sizeA)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
bbs_MemSeg_alloc(struct bbs_Context * cpA,struct bbs_MemSeg * ptrA,uint32 sizeA)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
bbs_MemSeg_free(struct bbs_Context * cpA,struct bbs_MemSeg * ptrA,void * memPtrA)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
bbs_MemSeg_checkConsistency(struct bbs_Context * cpA,const struct bbs_MemSeg * ptrA)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 /* ========================================================================= */
416