comparison packages/kernel/current/include/mvarimpl.inl @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children 443894e2e912
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 #ifndef CYGONCE_KERNEL_MVARIMPL_INL
2 #define CYGONCE_KERNEL_MVARIMPL_INL
3
4 //==========================================================================
5 //
6 // mvarimpl.inl
7 //
8 // Memory pool with variable block class declarations
9 //
10 //==========================================================================
11 //####COPYRIGHTBEGIN####
12 //
13 // -------------------------------------------
14 // The contents of this file are subject to the Cygnus eCos Public License
15 // Version 1.0 (the "License"); you may not use this file except in
16 // compliance with the License. You may obtain a copy of the License at
17 // http://sourceware.cygnus.com/ecos
18 //
19 // Software distributed under the License is distributed on an "AS IS"
20 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
21 // License for the specific language governing rights and limitations under
22 // the License.
23 //
24 // The Original Code is eCos - Embedded Cygnus Operating System, released
25 // September 30, 1998.
26 //
27 // The Initial Developer of the Original Code is Cygnus. Portions created
28 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved.
29 // -------------------------------------------
30 //
31 //####COPYRIGHTEND####
32 //==========================================================================
33 //#####DESCRIPTIONBEGIN####
34 //
35 // Author(s): hmt
36 // Contributors: hmt
37 // Date: 1998-03-23
38 // Purpose: Define Mvarimpl class interface
39 // Description: Inline class for constructing a variable block allocator
40 // Usage: #include <cyg/kernel/mvarimpl.hxx>
41 // #include <cyg/kernel/mvarimpl.inl>
42 //
43 //####DESCRIPTIONEND####
44 //
45 //==========================================================================
46
47 // Simple non-coalescing allocator
48
49 // The free list is stored on a doubly linked list, each member of
50 // which is stored in the body of the free memory. The head of the
51 // list has the same structure but its size field is zero. This
52 // resides in the memory pool structure. Always having at least one
53 // item on the list simplifies the alloc and free code.
54
55 //
56 inline cyg_int32
57 Cyg_Mempool_Variable_Implementation::roundup( cyg_int32 size )
58 {
59
60 size += sizeof(struct memdq);
61 size = (size + alignment - 1) & -alignment;
62 return size;
63 }
64
65 Cyg_Mempool_Variable_Implementation::Cyg_Mempool_Variable_Implementation(
66 cyg_uint8 *base,
67 cyg_int32 size,
68 CYG_ADDRWORD align )
69 {
70 CYG_ASSERT( align > 0, "Bad alignment" );
71 CYG_ASSERT( size > 0, "Bad size" );
72 CYG_ASSERT(0!=align ,"align is zero");
73 CYG_ASSERT(0==(align & align-1),"align not a power of 2");
74
75 obase=base;
76 osize=size;
77 oalign=align;
78
79 alignment = align;
80 while(alignment < (cyg_int32)sizeof(struct memdq))
81 alignment += alignment;
82 CYG_ASSERT(0==(alignment & alignment-1),"alignment not a power of 2");
83
84 bottom = (cyg_uint8 *)roundup((cyg_int32)base);
85 top = (cyg_uint8 *)((cyg_int32)(base+size) & -alignment);
86
87 CYG_ASSERT( top > bottom , "heap too small" );
88 CYG_ASSERT( ((cyg_int32)bottom & alignment-1)==0, "bottom badly aligned" );
89 CYG_ASSERT( ((cyg_int32)top & alignment-1)==0, "top badly aligned" );
90
91 struct memdq *hdq = &head, *dq = (struct memdq *)bottom;
92
93 hdq->prev = hdq->next = dq;
94 hdq->size = 0;
95 dq->prev = dq->next = hdq;
96
97 freemem = dq->size = top-bottom;
98 }
99
100 Cyg_Mempool_Variable_Implementation::~Cyg_Mempool_Variable_Implementation()
101 {
102 }
103
104 // allocation is simple
105 // First we look down the free list for a large enough block
106 // If we find a block the right size, we unlink the block from
107 // the free list and return a pointer to it.
108 // If we find a larger block, we chop a piece off the end
109 // and return that
110 // Otherwise we will eventually get back to the head of the list
111 // and return NULL
112 inline cyg_uint8 *
113 Cyg_Mempool_Variable_Implementation::alloc( cyg_int32 size )
114 {
115 struct memdq *dq = &head;
116 cyg_uint8 *alloced;
117
118 size = roundup(size);
119
120 do {
121 CYG_ASSERT( dq->next->prev==dq, "Bad link in dq");
122 dq = dq->next;
123 if(0 == dq->size) {
124 CYG_ASSERT(dq == &head, "bad free block");
125 return NULL;
126 }
127 } while(dq->size < size);
128
129 if( size == dq->size ) {
130 // exact fit -- unlink from free list
131 dq->prev->next = dq->next;
132 dq->next->prev = dq->prev;
133 alloced = (cyg_uint8 *)dq;
134 } else {
135
136 CYG_ASSERT( dq->size > size, "block found is too small");
137
138 // allocate portion of memory from end of block
139
140 dq->size -=size;
141
142 // The portion left over has to be large enough to store a
143 // struct memdq. This is guaranteed because the alignment is
144 // larger than the size of this structure.
145
146 CYG_ASSERT( (cyg_int32)sizeof(struct memdq)<=dq->size ,
147 "not enough space for list item" );
148
149 alloced = (cyg_uint8 *)dq + dq->size;
150 }
151
152 CYG_ASSERT( bottom<=alloced && alloced<=top, "alloced outside pool" );
153
154 // Set size on allocated block
155
156 dq = (struct memdq *)alloced;
157 dq->size = size;
158 dq->next = dq->prev = (struct memdq *)0xd530d53; // magic number
159
160 freemem -=size;
161 return alloced + sizeof(struct memdq);
162 }
163
164 // As no coalescing is done, free is simply a matter of using the
165 // freed memory as an element of the free list linking it in at the
166 // start.
167
168 inline cyg_bool
169 Cyg_Mempool_Variable_Implementation::free( cyg_uint8 *p, cyg_int32 size )
170 {
171 if(!(bottom<=p&&p<=top))
172 return false;
173
174 struct memdq *hdq=&head,*dq=(struct memdq *)(p-sizeof(struct memdq));
175
176 // check magic number in block to be freed
177 if(dq->next != dq->prev || dq->next != (struct memdq *)0xd530d53)
178 return false;
179
180 if(0==size) {
181 size = dq->size;
182 } else {
183 size = roundup(size);
184 }
185
186 if(dq->size != size)
187 return false;
188
189 CYG_ASSERT( (cyg_int32)sizeof(struct memdq)<=size ,
190 "not enough space for list item" );
191
192 #ifdef CYGSEM_KERNEL_MEMORY_COALESCE
193 // For simple coalescing have the free list be sorted by memory base address
194 struct memdq *idq;
195
196 for (idq = hdq->next; idq != hdq; idq = idq->next) {
197 if (idq < dq)
198 break;
199 }
200 dq->size = size;
201 if (idq != hdq) {
202 dq->prev = idq;
203 dq->next = idq->next;
204 idq->next = dq;
205 dq->next->prev = dq;
206 } else {
207 dq->next = idq;
208 dq->prev = idq->prev;
209 idq->prev = dq;
210 dq->prev->next = dq;
211 }
212 // Now do coalescing
213 if ((char *)dq + dq->size == (char *)dq->next) {
214 dq->size += dq->next->size;
215 dq->next = dq->next->next;
216 dq->next->prev = dq;
217 }
218 if ((char *)dq->prev + dq->prev->size == (char *)dq) {
219 dq->prev->size += dq->size;
220 dq->prev->next = dq->next;
221 dq->next->prev = dq->prev;
222 dq = dq->prev;
223 }
224 #else
225 dq->prev = hdq;
226 dq->next = hdq->next;
227 dq->size = size;
228 hdq->next = dq;
229 dq->next->prev=dq;
230 #endif
231
232 freemem +=size;
233 return true;
234 }
235
236
237 inline void
238 Cyg_Mempool_Variable_Implementation::get_arena(
239 cyg_uint8 * &base,
240 cyg_int32 &size,
241 CYG_ADDRWORD &maxfree)
242 {
243 struct memdq *dq = &head;
244 cyg_int32 mf = 0;
245
246 do {
247 CYG_ASSERT( dq->next->prev==dq, "Bad link in dq");
248 dq = dq->next;
249 if(0 == dq->size) {
250 CYG_ASSERT(dq == &head, "bad free block");
251 break;
252 }
253 if(dq->size > mf)
254 mf = dq->size;
255 } while(1);
256
257 base = obase;
258 size = osize;
259 maxfree = mf;
260 }
261
262
263 inline cyg_int32
264 Cyg_Mempool_Variable_Implementation::get_allocation_size( cyg_uint8 *ptr )
265 {
266 CYG_CHECK_DATA_PTR(ptr, "Requested allocation size of bad data pointer!");
267
268 if(!(bottom<=ptr && ptr<=top))
269 return -1;
270
271 struct memdq *dq=(struct memdq *)(ptr-sizeof(struct memdq));
272
273 // check magic number in block to be freed
274 if(dq->next != dq->prev || dq->next != (struct memdq *)0xd530d53)
275 return -1;
276
277 return dq->size;
278
279 } // get_allocation_size()
280
281 // -------------------------------------------------------------------------
282 #endif // ifndef CYGONCE_KERNEL_MVARIMPL_INL
283 // EOF mvarimpl.inl