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