Mercurial > ecos
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 |
