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
50void 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
60void 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
86uint32 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
125uint16* 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
168void 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
226uint16* 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
287void 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