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/Functions.h"
20 #include "b_BasicEm/DynMemManager.h"
21 #include "b_BasicEm/Context.h"
22 
23 /* ------------------------------------------------------------------------- */
24 
25 /* minimum block size dynamically allocated in function nextBlock (affects only shared memory) */
26 #define bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE 0
27 
28 /** Offset to actual memory area on allocated memory blocks (in 16-bit words).
29   * Value needs to be large enough to hold the pointer to the next memory block
30   * and the size value (32-bit) of the memory area.
31   */
32 #define bbs_MEM_OFFSET 6
33 
34 /* ========================================================================= */
35 /*                                                                           */
36 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
37 /*                                                                           */
38 /* ========================================================================= */
39 
40 /* ------------------------------------------------------------------------- */
41 
42 /* ========================================================================= */
43 /*                                                                           */
44 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
45 /*                                                                           */
46 /* ========================================================================= */
47 
48 /* ------------------------------------------------------------------------- */
49 
bbs_DynMemManager_init(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA)50 void bbs_DynMemManager_init( struct bbs_Context* cpA,
51 							 struct bbs_DynMemManager* ptrA )
52 {
53 	ptrA->memPtrE = NULL;
54 	ptrA->mallocFPtrE = NULL;
55 	ptrA->freeFPtrE = NULL;
56 }
57 
58 /* ------------------------------------------------------------------------- */
59 
bbs_DynMemManager_exit(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA)60 void bbs_DynMemManager_exit( struct bbs_Context* cpA,
61 							 struct bbs_DynMemManager* ptrA )
62 {
63 	ptrA->memPtrE = NULL;
64 	ptrA->mallocFPtrE = NULL;
65 	ptrA->freeFPtrE = NULL;
66 }
67 
68 /* ------------------------------------------------------------------------- */
69 
70 /* ========================================================================= */
71 /*                                                                           */
72 /* ---- \ghd{ operators } -------------------------------------------------- */
73 /*                                                                           */
74 /* ========================================================================= */
75 
76 /* ------------------------------------------------------------------------- */
77 
78 /* ========================================================================= */
79 /*                                                                           */
80 /* ---- \ghd{ query functions } -------------------------------------------- */
81 /*                                                                           */
82 /* ========================================================================= */
83 
84 /* ------------------------------------------------------------------------- */
85 
bbs_DynMemManager_allocatedSize(struct bbs_Context * cpA,const struct bbs_DynMemManager * ptrA)86 uint32 bbs_DynMemManager_allocatedSize( struct bbs_Context* cpA,
87 									    const struct bbs_DynMemManager* ptrA )
88 {
89 	uint32 sizeL = 0;
90 	uint16* pL = ( uint16* )ptrA->memPtrE;
91 	while( pL != NULL )
92 	{
93 		sizeL += ( ( uint32* )pL )[ 2 ];
94 		pL = *( uint16** )pL;
95 	}
96 	return sizeL;
97 }
98 
99 /* ------------------------------------------------------------------------- */
100 
101 /* ========================================================================= */
102 /*                                                                           */
103 /* ---- \ghd{ modify functions } ------------------------------------------- */
104 /*                                                                           */
105 /* ========================================================================= */
106 
107 /* ------------------------------------------------------------------------- */
108 
109 /* ========================================================================= */
110 /*                                                                           */
111 /* ---- \ghd{ I/O } -------------------------------------------------------- */
112 /*                                                                           */
113 /* ========================================================================= */
114 
115 /* ------------------------------------------------------------------------- */
116 
117 /* ========================================================================= */
118 /*                                                                           */
119 /* ---- \ghd{ exec functions } --------------------------------------------- */
120 /*                                                                           */
121 /* ========================================================================= */
122 
123 /* ------------------------------------------------------------------------- */
124 
bbs_DynMemManager_alloc(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA,const struct bbs_MemSeg * memSegPtrA,uint32 sizeA)125 uint16* bbs_DynMemManager_alloc( struct bbs_Context* cpA,
126 								 struct bbs_DynMemManager* ptrA,
127 								 const struct bbs_MemSeg* memSegPtrA,
128 								 uint32 sizeA )
129 {
130 	uint16* pL = NULL;
131 	bbs_DEF_fNameL( "uint16* bbs_DynMemManager_alloc( struct bbs_DynMemManager* ptrA, uint32 sizeA )" )
132 
133 
134 	if( ptrA->mallocFPtrE == NULL )
135 	{
136 		bbs_ERROR1( "%s:\n Malloc handler not defined.\n", fNameL );
137 		return NULL;
138 	}
139 
140 	if( ptrA->memPtrE == NULL )
141 	{
142 		ptrA->memPtrE = ptrA->mallocFPtrE( cpA, memSegPtrA, ( sizeA + bbs_MEM_OFFSET ) << 1 );
143 		pL = ptrA->memPtrE;
144 	}
145 	else
146 	{
147 		uint16** ppL = ( uint16** )ptrA->memPtrE;
148 		while( *ppL != NULL ) ppL = ( uint16** )*ppL;
149 		*ppL = ptrA->mallocFPtrE( cpA, memSegPtrA, ( sizeA + bbs_MEM_OFFSET ) << 1 );
150 		pL = *ppL;
151 	}
152 
153 	if( pL == NULL )
154 	{
155 		bbs_ERR1( bbs_ERR_OUT_OF_MEMORY, "%s:\n Allocation failed.\n", fNameL );
156 		return NULL;
157 	}
158 
159 	( ( uint32* )pL )[ 0 ] = 0;
160 	( ( uint32* )pL )[ 1 ] = 0;
161 	( ( uint32* )pL )[ 2 ] = sizeA + bbs_MEM_OFFSET;
162 
163 	return pL + bbs_MEM_OFFSET;
164 }
165 
166 /* ------------------------------------------------------------------------- */
167 
bbs_DynMemManager_free(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA,uint16 * memPtrA)168 void bbs_DynMemManager_free( struct bbs_Context* cpA,
169 							 struct bbs_DynMemManager* ptrA,
170 							 uint16* memPtrA )
171 {
172 	bbs_DEF_fNameL( "void bbs_DynMemManager_free( .... )" )
173 
174 	if( ptrA->memPtrE == NULL )
175 	{
176 		bbs_ERROR1( "%s:\n Memory was not allocated.\n", fNameL );
177 		return;
178 	}
179 	else if( ptrA->memPtrE + bbs_MEM_OFFSET == memPtrA )
180 	{
181 		uint16* memPtrL = ptrA->memPtrE;
182 		ptrA->memPtrE = *( uint16** )ptrA->memPtrE;
183 		ptrA->freeFPtrE( memPtrL );
184 	}
185 	else
186 	{
187 		uint16* p0L = NULL;
188 		uint16* pL = ( uint16* )ptrA->memPtrE;
189 
190 		while( pL != NULL )
191 		{
192 			if( pL + bbs_MEM_OFFSET == memPtrA ) break;
193 			p0L = pL;
194 			pL = *( uint16** )pL;
195 		}
196 
197 		if( pL != NULL )
198 		{
199 			if( ptrA->freeFPtrE == NULL )
200 			{
201 				bbs_ERROR1( "%s:\n Free handler not defined.\n", fNameL );
202 				return;
203 			}
204 
205 			if( p0L != NULL )
206 			{
207 				*( uint16** )p0L = *( uint16** )pL;
208 			}
209 			else
210 			{
211 				ptrA->memPtrE = *( uint16** )pL;
212 			}
213 
214 			ptrA->freeFPtrE( pL );
215 		}
216 		else
217 		{
218 			bbs_ERROR1( "%s:\n Attempt to free memory that was not allocated.\n", fNameL );
219 			return;
220 		}
221 	}
222 }
223 
224 /* ------------------------------------------------------------------------- */
225 
bbs_DynMemManager_nextBlock(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA,const struct bbs_MemSeg * memSegPtrA,uint16 * curBlockPtrA,uint32 minSizeA,uint32 * actualSizePtrA)226 uint16* bbs_DynMemManager_nextBlock( struct bbs_Context* cpA,
227 									 struct bbs_DynMemManager* ptrA,
228 									 const struct bbs_MemSeg* memSegPtrA,
229 									 uint16* curBlockPtrA,
230 									 uint32 minSizeA,
231 									 uint32* actualSizePtrA )
232 {
233 	uint16* pL = ( uint16* )ptrA->memPtrE;
234 	bbs_DEF_fNameL( "uint16* bbs_DynMemManager_nextBlock( .... )" )
235 
236 	if( curBlockPtrA != NULL )
237 	{
238 		/* find current block */
239 		while( pL != NULL )
240 		{
241 			if( pL + bbs_MEM_OFFSET == curBlockPtrA ) break;
242 			pL = *( uint16** )pL;
243 		}
244 
245 		if( pL == NULL )
246 		{
247 			bbs_ERROR1( "%s:\nCould not find current memory block.\n", fNameL );
248 			*actualSizePtrA = 0;
249 			return NULL;
250 		}
251 
252 		/* go to next block */
253 		pL = *( uint16** )pL;
254 	}
255 
256 	/* find next fitting block */
257 	while( pL != NULL )
258 	{
259 		if( ( ( uint32* )pL )[ 2 ] >= minSizeA + bbs_MEM_OFFSET ) break;
260 		pL = *( uint16** )pL;
261 	}
262 
263 	if( pL == NULL )
264 	{
265 		/* no proper block -> allocate new one */
266 		uint32 blockSizeL = minSizeA > bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE ? minSizeA : bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE;
267 		uint16* memPtrL = bbs_DynMemManager_alloc( cpA, ptrA, memSegPtrA, blockSizeL );
268 		if( memPtrL != NULL )
269 		{
270 			*actualSizePtrA = blockSizeL;
271 		}
272 		else
273 		{
274 			*actualSizePtrA = 0;
275 		}
276 		return memPtrL;
277 	}
278 	else
279 	{
280 		*actualSizePtrA = ( ( uint32* )pL )[ 2 ] - bbs_MEM_OFFSET;
281 		return pL + bbs_MEM_OFFSET;
282 	}
283 }
284 
285 /* ------------------------------------------------------------------------- */
286 
bbs_DynMemManager_freeAll(struct bbs_Context * cpA,struct bbs_DynMemManager * ptrA)287 void bbs_DynMemManager_freeAll( struct bbs_Context* cpA, struct bbs_DynMemManager* ptrA )
288 {
289 	uint16** ppL = ( uint16** )ptrA->memPtrE;
290 	while( ppL != NULL )
291 	{
292 		uint16* memPtrL = ( uint16* )ppL;
293 		ppL = ( uint16** )*ppL;
294 		ptrA->freeFPtrE( memPtrL );
295 	}
296 	ptrA->memPtrE = NULL;
297 }
298 
299 /* ------------------------------------------------------------------------- */
300 
301 /* ========================================================================= */
302