PikeAero::CMemHeap Class Reference

#include <cmemheap.h>


Data Structures

struct  FreeListBlock

Static Public Member Functions

static CMachine::ubit32 available ()
static CMachine::ubit8bottom ()
static void compress ()
static void free (void *ptr)
static void initialize ()
static void * malloc (CMachine::bit32 size)
static void * realloc (void *ptr, CMachine::bit32 size)
static CMachine::ubit8top ()
static CMachine::ubit32 used ()

Static Private Member Functions

static CMachine::ubit32 mFreeCount __attribute__ ((aligned))
static CMachine::bit32
mFreeListSize 
__attribute__ ((aligned))
static CMachine::ubit8 mHeap[] __attribute__ ((aligned(4)))
static FreeListBlock_freelist (CMachine::bit32 i)
static FreeListBlock_freelist_alloc (CMachine::bit32 size)
static FreeListBlock_freelist_append (FreeListBlock *f)
static void _freelist_compress (void)
static void _freelist_defragment (void)
static FreeListBlock_freelist_find (CMachine::bit32 size)
static FreeListBlock_freelist_findfriend (FreeListBlock *f)
static void _freelist_free (CMachine::bit32 i)
static CMachine::bit32 _freelist_locate (void *ptr)
static bool _freelist_remove (CMachine::bit32 index)


Detailed Description

Implements a memory heap.

Author:
Michael Sharkey <mike@pikeaero.com>

Definition at line 32 of file cmemheap.h.


Member Function Documentation

static CMachine::ubit32 mFreeCount PikeAero::CMemHeap::__attribute__ ( (aligned)   )  [static, private]

static CMachine::bit32 mFreeListSize PikeAero::CMemHeap::__attribute__ ( (aligned)   )  [static, private]

static CMachine::ubit8 mHeap [] PikeAero::CMemHeap::__attribute__ ( (aligned(4))   )  [static, private]

CMemHeap::FreeListBlock * PikeAero::CMemHeap::_freelist ( CMachine::bit32  i  )  [static, private]

Return a pointer to the FreeListBlock corresponding to freelist offset i.

_freelist() - return a pointer to a freelist entry from an index number.

Definition at line 65 of file cmemheap.cpp.

Referenced by _freelist_free().

00066 {
00067     FreeListBlock* f = (FreeListBlock*)NULL;
00068     if ( i < mFreeListSize && mFreeListSize > 0 )
00069     {
00070         f = (FreeListBlock*)&mHeap[i*sizeof(FreeListBlock)];
00071     }
00072     return f;
00073 }

Here is the caller graph for this function:

CMemHeap::FreeListBlock * PikeAero::CMemHeap::_freelist_alloc ( CMachine::bit32  size  )  [static, private]

Allocate a FreeListBlock of size and return a pointer to the FreeListBlock or NULL if failed.

_freelist_alloc - attempt to find a chunk, and if found, create a FreeListBlock, adjust the freelist, and return a pointer to the FreeListBlock struct. Allocates from top of heap downward toward freelist.

first, attemp to find a chunk that will fit....

The simple case, we found a chuck that fits exactly...

Create a new free list entry and take some memory from the free block that we found, then append to freelist.

fetch the pointer to the newly allocated freelist entry.

The heap is probably full to the point that we can't allocate a new freelist entry, so let's undo and return an error...

Definition at line 316 of file cmemheap.cpp.

References _freelist_append(), and _freelist_find().

Referenced by malloc().

00317 {
00318     /**
00319     ** first, attemp to find a chunk that will fit....
00320     */
00321     FreeListBlock* f = _freelist_find(size);
00322     if ( f != (FreeListBlock*)NULL )
00323     {
00324         FreeListBlock f_new;
00325         FreeListBlock* ff;
00326         /**
00327         ** The simple case, we found a chuck that fits exactly...
00328         */
00329         if ( f->size == size )
00330         {
00331             f->free = false;
00332             return f;
00333         }
00334         /**
00335         ** Create a new free list entry and take some memory from
00336         ** the free block that we found, then append to freelist.
00337         */
00338         f_new.free = false;
00339         f_new.p = &f->p[f->size-size];
00340         f_new.size = size;
00341         f->size -= size;
00342         ff = _freelist_append(&f_new);
00343         if ( ff != (FreeListBlock*)NULL )
00344         {
00345             /** fetch the pointer to the newly allocated freelist entry. */
00346             f = ff;
00347         } else {
00348             /**
00349             ** The heap is probably full to the point that we can't allocate
00350             ** a new freelist entry, so let's undo and return an error...
00351             */
00352             f->size += size;
00353             return (FreeListBlock*)NULL;
00354         }
00355     }
00356     return f;
00357 }

Here is the call graph for this function:

Here is the caller graph for this function:

CMemHeap::FreeListBlock * PikeAero::CMemHeap::_freelist_append ( FreeListBlock f  )  [static, private]

Append a FreeListBlock to the freelist and return a pointer to it.

_freelist_append - append a FreeListBlock to the freelist the contents of the input FreeListBlock struct are copied , so the caller maintains pointer ownership of the input pointer.

Get the target destination for the new freelist entry as well as the new target destination for the new free heap base..

Resize the free pointer that's pointi to the base of the heap area..

we found it, now just resize it and point to the new heap base...

this is an already allocated block. this means the heap is very full and we are having freelist allocation problems. Let's not push it....sorry...

We've sucessfully made room, so now copy the new freelist entry in the freed up heap slot and increment the freelist size.

Definition at line 97 of file cmemheap.cpp.

References _fast_freelist, and memcpy.

Referenced by _freelist_alloc(), and initialize().

00098 {
00099     /**
00100      ** Get the target destination for the new freelist entry as well
00101      ** as the new target destination for the new free heap base..
00102      */
00103     CMachine::ubit8* dst = &mHeap[mFreeListSize*sizeof(FreeListBlock)];
00104     CMachine::ubit8* hbase = &mHeap[(mFreeListSize+1)*sizeof(FreeListBlock)];
00105 
00106     /**
00107      ** Resize the free pointer that's pointi to the base of the heap
00108      ** area..
00109      */
00110     CMachine::bit32 i;
00111     for( i=mFreeListSize-1; i >=0; i-- )
00112     {
00113         FreeListBlock* f = _fast_freelist(i);
00114         if ( f->p == dst )
00115         {
00116             if ( f->free )
00117             {
00118                 /**  we found it, now just resize it and point to the new heap base... */
00119                 f->p = hbase;
00120                 f->size -= sizeof(FreeListBlock);
00121             }
00122             else
00123             {
00124                 /**
00125                 ** this is an already allocated block.
00126                 ** this means the heap is very full and
00127                 ** we are having freelist allocation
00128                 ** problems. Let's not push it....sorry...
00129                 */
00130                 return (FreeListBlock*)NULL;
00131             }
00132         }
00133     }
00134     /**
00135     ** We've sucessfully made room, so now copy the new freelist
00136     ** entry in the freed up heap slot and increment the freelist size.
00137     */
00138     memcpy(dst,f,sizeof(FreeListBlock));
00139     ++mFreeListSize;
00140     return (FreeListBlock*)dst;
00141 }

Here is the caller graph for this function:

void PikeAero::CMemHeap::_freelist_compress ( void   )  [static, private]

Remove FreeListBlocks from the freelist which have no size

_freelist_compress - remove 0 size blocks

Definition at line 188 of file cmemheap.cpp.

References _fast_freelist, and _freelist_remove().

Referenced by _freelist_defragment().

00189 {
00190     CMachine::bit32     i;
00191     bool    clean;
00192     do {
00193         clean=true;
00194         for( i=0; i < mFreeListSize; i++ )
00195         {
00196             FreeListBlock* f = _fast_freelist(i);
00197             if ( f->size == 0 )
00198             {
00199                 _freelist_remove(i);
00200                 clean=false;
00201                 break;
00202             }
00203         }
00204     } while (!clean);
00205 }

Here is the call graph for this function:

Here is the caller graph for this function:

void PikeAero::CMemHeap::_freelist_defragment ( void   )  [static, private]

Attempt to re-integrate previously split blocks.

_freelist_defragment - attempt to re-integrate previously split blocks.

Definition at line 212 of file cmemheap.cpp.

References _fast_freelist, _freelist_compress(), and _freelist_findfriend().

Referenced by _freelist_free(), and compress().

00213 {
00214     CMachine::bit32     i;
00215     bool    clean;
00216     mFreeCount=0;
00217     do
00218     {
00219         clean=true;
00220         for( i=0; i < mFreeListSize; i++ )
00221         {
00222             FreeListBlock* f = _fast_freelist(i);
00223             if ( f != (FreeListBlock*)NULL && f->free == true && f->size != 0 )
00224             {
00225                 FreeListBlock* ff = _freelist_findfriend(f);
00226                 if (  ff != (FreeListBlock*)NULL && ff->size != 0 )
00227                 {
00228                     if ( f->p == &(ff->p[ff->size]) )
00229                     {
00230                         ff->size += f->size;
00231                         f->size=0;
00232                     }
00233                     else if ( ff->p == &(f->p[f->size]) )
00234                     {
00235                         f->size += ff->size;
00236                         ff->size=0;
00237                     }
00238                     clean=false;
00239                     break;
00240                 }
00241             }
00242         }
00243     } while(!clean);
00244     _freelist_compress();
00245 }

Here is the call graph for this function:

Here is the caller graph for this function:

CMemHeap::FreeListBlock * PikeAero::CMemHeap::_freelist_find ( CMachine::bit32  size  )  [static, private]

Attempt to find a FreeListBlock with enough memory to fit size

_freelist_find - find a free block with enough space to fit requested size.

First, try to find a chuck that fits exactly....

Second, try to find a chuck that fits pretty good.... This assumes that much of the time we will be aloocating objects of the same size, so we look for a block which is at no more than twice the size of what we need so that the remaining free block will at least be able to allocate another of the same object size.

Third, try to find a chuck that fits at all....

Forth, no matching chunk was found...return NULL..

Definition at line 266 of file cmemheap.cpp.

References _fast_freelist.

Referenced by _freelist_alloc().

00267 {
00268     /**
00269     ** First, try to find a chuck that fits exactly....
00270     */
00271     for( CMachine::bit32 i=mFreeListSize-1; i >= 0; i-- )
00272     {
00273         FreeListBlock* f = _fast_freelist(i);
00274         if ( f->free && f->size == size )
00275         {
00276             return f;
00277         }
00278     }
00279     /**
00280     ** Second, try to find a chuck that fits pretty good....
00281     ** This assumes that much of the time we will be aloocating
00282     ** objects of the same size, so we look for a block which is at no more than
00283     ** twice the size of what we need so that the remaining free block will
00284     ** at least be able to allocate another of the same object size.
00285      */
00286     for( CMachine::bit32 i=mFreeListSize-1; i >= 0; i--  )
00287     {
00288         FreeListBlock* f = _fast_freelist(i);
00289         if ( f->free && f->size > size && f->size <= (size*2) )
00290         {
00291             return f;
00292         }
00293     }
00294     /**
00295     ** Third, try to find a chuck that fits at all....
00296     */
00297     for( CMachine::bit32 i=0; i < mFreeListSize; i++ )
00298     {
00299         FreeListBlock* f = _fast_freelist(i);
00300         if ( f->free && f->size >= size )
00301         {
00302             return f;
00303         }
00304     }
00305     /**
00306     ** Forth, no matching chunk was found...return NULL..
00307     */
00308     return (FreeListBlock*)NULL;
00309 }

Here is the caller graph for this function:

CMemHeap::FreeListBlock * PikeAero::CMemHeap::_freelist_findfriend ( FreeListBlock f  )  [static, private]

Attempt to find another free block which is contiguous with respect to the input block. Return NULL if not found

_freelist_findfriend - find another free block which is contiguous with respect to the input block.

Definition at line 165 of file cmemheap.cpp.

References _fast_freelist.

Referenced by _freelist_defragment().

00166 {
00167     if ( f->free )
00168     {
00169         CMachine::bit32 i;
00170         for( i=0; i < mFreeListSize; i++ )
00171         {
00172             FreeListBlock* ff = _fast_freelist(i);
00173             if ( ff->free && ff->size > 0)
00174             {
00175                 if ( f->p == &(ff->p[ff->size]) || ff->p == &(f->p[f->size]) )
00176                 {
00177                     return ff;
00178                 }
00179             }
00180         }
00181     }
00182     return (FreeListBlock*)NULL;
00183 }

Here is the caller graph for this function:

void PikeAero::CMemHeap::_freelist_free ( CMachine::bit32  i  )  [static, private]

Free a FreeListBlock from the freelist. The data pointer is assumed to have been already freed

_freelist_free - free a block

Definition at line 250 of file cmemheap.cpp.

References _freelist(), _freelist_defragment(), and DEFRAG_THRESHOLD.

Referenced by free(), and realloc().

00251 {
00252     FreeListBlock* f = _freelist(i);
00253     if ( f != NULL )
00254     {
00255         f->free = true;
00256         if ( ++mFreeCount > DEFRAG_THRESHOLD )
00257         {
00258             _freelist_defragment();
00259         }
00260     }
00261 }

Here is the call graph for this function:

Here is the caller graph for this function:

CMachine::bit32 PikeAero::CMemHeap::_freelist_locate ( void *  ptr  )  [static, private]

Get the freelist offset from a FreeListBlock pointer

_freelist_locate - attempt to locate a freelist entry based on a heap memory pointer.

Definition at line 79 of file cmemheap.cpp.

References _fast_freelist.

Referenced by free(), and realloc().

00080 {
00081     for(CMachine::bit32 i=mFreeListSize-1; i >= 0; i-- )
00082     {
00083         FreeListBlock* f =  _fast_freelist(i);
00084         if ( f->p == (CMachine::ubit8*)ptr )
00085         {
00086             return i;
00087         }
00088     }
00089     return (-1);
00090 }

Here is the caller graph for this function:

bool PikeAero::CMemHeap::_freelist_remove ( CMachine::bit32  index  )  [static, private]

Remove a FreeListBlock from the freelist referenced by offset i

_freelist_remove - remove a FreeListBlock from the freelist based on an index reference.

Definition at line 147 of file cmemheap.cpp.

References memmove.

Referenced by _freelist_compress().

00148 {
00149     if ( index < mFreeListSize && mFreeListSize > 0 )
00150     {
00151         CMachine::bit32 dst = index*sizeof(FreeListBlock);
00152         CMachine::bit32 src = (index+1)*sizeof(FreeListBlock);
00153         CMachine::bit32 len = (mFreeListSize-index)*sizeof(FreeListBlock);
00154         memmove(&mHeap[dst],&mHeap[src],len);
00155         --mFreeListSize;
00156         return true;
00157     }
00158     return false;
00159 }

Here is the caller graph for this function:

CMachine::ubit32 PikeAero::CMemHeap::available (  )  [static]

available() Total up the amout of available memory on the heap.

Definition at line 464 of file cmemheap.cpp.

References _fast_freelist.

Referenced by PikeAero::CTaskConsolePacket::monitor(), and PikeAero::CTaskConsole::monitor().

00465 {
00466     CMachine::ubit32 size=0;
00467     for( CMachine::bit32 i=0; i < mFreeListSize; i++ )
00468     {
00469         FreeListBlock* f = _fast_freelist(i);
00470         if ( f->free )
00471         {
00472             size += f->size - sizeof( FreeListBlock );
00473         }
00474     }
00475     return size;
00476 }

Here is the caller graph for this function:

CMachine::ubit8 * PikeAero::CMemHeap::bottom (  )  [static]

bottom() - return the address of the byte at the bottom of the heap space

Definition at line 57 of file cmemheap.cpp.

Referenced by PikeAero::CTaskConsolePacket::monitor(), and PikeAero::CTaskConsole::monitor().

00058 {
00059     return &mHeap[0];
00060 }

Here is the caller graph for this function:

static void PikeAero::CMemHeap::compress (  )  [inline, static]

Definition at line 44 of file cmemheap.h.

References _freelist_defragment().

Referenced by PikeAero::CTaskQueue::initialize().

Here is the call graph for this function:

Here is the caller graph for this function:

void PikeAero::CMemHeap::free ( void *  ptr  )  [static]

free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no opera‐ tion is performed.

Definition at line 436 of file cmemheap.cpp.

References _freelist_free(), and _freelist_locate().

Referenced by PikeAero::CByteArray::clear(), PikeAero::CArray< T >::clear(), PikeAero::CConfiguration::createVolatileRecord(), PikeAero::CConfiguration::disposeVolatile1DMap(), PikeAero::CConfiguration::disposeVolatile2DMap(), PikeAero::CConfiguration::disposeVolatileRecord(), PikeAero::CObject::operator delete(), PikeAero::CObject::operator delete[](), realloc(), PikeAero::CMap::unload(), and PikeAero::CObject::~CObject().

00437 {
00438     CMachine::bit32 i = _freelist_locate(ptr);
00439     if ( i >= 0 ) {
00440         _freelist_free(i);
00441     }
00442 }

Here is the call graph for this function:

Here is the caller graph for this function:

void PikeAero::CMemHeap::initialize ( void   )  [static]

FIXME - Make this class thread-safe using CMutexLock when accessing the freelist table. FIXME - Emit a CEventTriggerSourceprogramFault on allocation/free errors TODO - Provide an interface for retrieving information about memory usage and fragmentation TODO - use const where applicable

initialize() - initialize memory.

Definition at line 38 of file cmemheap.cpp.

References _freelist_append().

00039 {
00040     FreeListBlock f;
00041 
00042     mFreeListSize=0;
00043     mFreeCount=0;
00044     f.free = true;
00045     f.p = &mHeap[sizeof(FreeListBlock)];
00046     f.size = sizeof(mHeap)-sizeof(FreeListBlock);
00047     _freelist_append(&f);
00048 }

Here is the call graph for this function:

void * PikeAero::CMemHeap::malloc ( CMachine::bit32  size  )  [static]

malloc() allocates size bytes and returns a pointer to the allocated memory. The memory is not cleared. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

Adjust size to end up on 32 bit boundary...

Definition at line 363 of file cmemheap.cpp.

References _freelist_alloc().

Referenced by PikeAero::CConfiguration::createVolatile1DMap(), PikeAero::CConfiguration::createVolatile2DMap(), PikeAero::CConfiguration::createVolatileRecord(), PikeAero::CEventQueue::initialize(), PikeAero::CObject::installCallback(), PikeAero::CMap::load(), PikeAero::CObject::operator new(), PikeAero::CObject::operator new[](), and realloc().

00364 {
00365     /**
00366     ** Adjust size to end up on 32 bit boundary...
00367     */
00368     while ( (size & 0x03) != 0x00 )
00369     {
00370         ++size;
00371     }
00372     if ( size > 0 )
00373     {
00374         FreeListBlock* f = _freelist_alloc(size);
00375         if ( f != (FreeListBlock*)NULL )
00376         {
00377             return f->p;
00378         }
00379     }
00380     return (void*)NULL;
00381 }

Here is the call graph for this function:

Here is the caller graph for this function:

void * PikeAero::CMemHeap::realloc ( void *  ptr,
CMachine::bit32  size 
) [static]

realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, then the call is equivalent to mal‐ loc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.

Adjust size to end up on 32 bit boundary...

Definition at line 390 of file cmemheap.cpp.

References _fast_freelist, _freelist_free(), _freelist_locate(), free(), malloc(), and memmove.

Referenced by PikeAero::CObjectList::append(), PikeAero::CObjectList::insert(), PikeAero::CObject::installCallback(), PikeAero::CObjectList::remove(), PikeAero::CByteArray::resize(), and PikeAero::CArray< T >::resize().

00391 {
00392     /**
00393     ** Adjust size to end up on 32 bit boundary...
00394     */
00395     while ( (size & 0x03) != 0x00 )
00396     {
00397         ++size;
00398     }
00399     if ( ptr != (void*)NULL )
00400     {
00401         if ( size == 0 )
00402         {
00403             free( ptr );
00404         }
00405         else
00406         {
00407             CMachine::bit32 i = _freelist_locate(ptr);
00408             if ( i >= 0 )
00409             {
00410                 FreeListBlock* f = _fast_freelist(i);
00411                 CMachine::bit32 s = f->size;
00412                 CMachine::ubit8* p = (CMachine::ubit8*)f->p;
00413                 if ( f->size < size )
00414                 {
00415                     CMachine::ubit8* pp = (CMachine::ubit8*)malloc(size);
00416                     _freelist_free(i);
00417                     if ( pp != (CMachine::ubit8*)NULL )
00418                     {
00419                         memmove(pp,p,s);
00420                     }
00421                     return pp;
00422                 }
00423                 return f->p;
00424             }
00425         }
00426         return((void*)NULL);
00427     }
00428     return malloc(size);
00429 }

Here is the call graph for this function:

Here is the caller graph for this function:

CMachine::ubit8 * PikeAero::CMemHeap::top (  )  [static]

top() - return the address of the byte at the top of the heap space

Definition at line 51 of file cmemheap.cpp.

References HEAP_SIZE.

Referenced by PikeAero::CTaskConsolePacket::monitor(), and PikeAero::CTaskConsole::monitor().

00052 {
00053     return &mHeap[HEAP_SIZE-1];
00054 }

Here is the caller graph for this function:

CMachine::ubit32 PikeAero::CMemHeap::used (  )  [static]

used() Total up the amout of used memory on the heap.

Definition at line 447 of file cmemheap.cpp.

References _fast_freelist.

Referenced by PikeAero::CTaskConsolePacket::monitor(), and PikeAero::CTaskConsole::monitor().

00448 {
00449     CMachine::ubit32 size=0;
00450     for( CMachine::bit32 i=0; i < mFreeListSize; i++ )
00451     {
00452         FreeListBlock* f = _fast_freelist(i);
00453         if ( !f->free )
00454         {
00455             size += f->size + sizeof( FreeListBlock );
00456         }
00457     }
00458     return size;
00459 }

Here is the caller graph for this function:


The documentation for this class was generated from the following files:

Generated on Sun Oct 25 14:00:11 2009 for stingray3 by  doxygen 1.5.8