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