Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

PsnThreadMemoryManager.cxx

Go to the documentation of this file.
00001 #include "PsnThreadMemoryManager.h"
00002 
00003 #include "PsnMemoryElementDescriptor.h"
00004 #include <assert.h>
00005 #include <iostream>
00006 #include "PsnSharedMemoryManager.h"
00007 
00008 #include "PsnDescriptorMemoryManager.h"
00009 //#define _DEBUGMEMORYMANAGEMENT
00010 
00011 list <void *> & PsnThreadMemoryManager::getListOfDetachedMemoryBlocks () 
00012 {
00013    static list <void  *> designPattern ; 
00014    return  designPattern ;
00015 }
00016 
00017 list <pair <void *, PsnThreadMemoryManager *> > & PsnThreadMemoryManager::getListOfLeakedMemoryBlocks () 
00018 {
00019    static list <pair <void *, PsnThreadMemoryManager *> > designPattern ; 
00020    return  designPattern ;
00021 }
00022 
00023 PsnMutexLock & PsnThreadMemoryManager::getFreedMemoryBlocksMutex() 
00024 {
00025    static PsnMutexLock toto ;
00026    return toto ;
00027 }
00028 PsnMutexLock & PsnThreadMemoryManager::getLeakedMemoryBlocksMutex() 
00029 {
00030    static PsnMutexLock toto ;
00031    return toto ;
00032 }
00033 
00034 void PsnThreadMemoryManager::freeLeakedMemoryBlocks ()
00035 {
00036    getFreedMemoryBlocksMutex().protect() ;
00037    list <void *> & mylist ( getListOfDetachedMemoryBlocks () ) ;
00038    for ( list <void *>::iterator i = mylist.begin() ;
00039          i != mylist.end() ;
00040          i = mylist.erase (i) )
00041       {
00042          PsnMemoryManager * correctMemoryManager = PsnMemoryManager::whichMemoryManager ( *i ) ;
00043          correctMemoryManager->freeSizeRemembered ( *i ) ;
00044       }
00045    getFreedMemoryBlocksMutex().unprotect() ;
00046    getLeakedMemoryBlocksMutex().protect() ;
00047    list <pair <void *, PsnThreadMemoryManager *> > & alist ( getListOfLeakedMemoryBlocks () ) ;
00048    for ( list <pair <void *, PsnThreadMemoryManager *> >::iterator i = alist.begin() ;
00049          i != alist.end() ;
00050          i = alist.erase (i) )
00051       {
00052          (*i).second->mfreeSizeRememberedOtherThread ( (*i).first ) ;
00053       }
00054    getLeakedMemoryBlocksMutex().unprotect() ;
00055 } 
00056 
00057 
00058 
00059 PsnThreadMemoryManager::~PsnThreadMemoryManager() 
00060 {
00061 }
00062 
00063 
00064 PsnThreadMemoryManager::PsnThreadMemoryManager ( void *startDsm, 
00065                                                  size_t sizeDsm, 
00066                                                  PsnMemoryManager & rawMemoryProvider,
00067                                                  PsnMemoryManager & descriptorMemoryProvider ) :
00068    PsnMemoryManager(),
00069    _memoryManaged ( sizeDsm ),
00070    _rawMemoryProvider ( rawMemoryProvider ),
00071    _descriptorMemoryProvider ( descriptorMemoryProvider ),
00072    _freeMemoryZones ( new(&descriptorMemoryProvider) PsnMemoryElementDescriptor ( ) ),
00073    _managedMemoryZones ( new(&descriptorMemoryProvider) PsnMemoryElementDescriptor ( ) ),
00074    _user ( pthread_self() )
00075 {
00076    // the getFromFree member function relies on that
00077    assert ( startDsm != 0 ) ;
00078 
00079    _managedMemoryZones->base = (unsigned int) startDsm ;
00080    _managedMemoryZones->size = sizeDsm ;
00081    _managedMemoryZones->next = 0 ;
00082 
00083    _freeMemoryZones->base = (unsigned int) startDsm ;
00084    _freeMemoryZones->size = sizeDsm ;
00085    _freeMemoryZones->next = 0 ;
00086 }
00087 
00088 
00089 
00090 void * PsnThreadMemoryManager::allocateSizeRemembered (size_t size) 
00091 {
00092 #ifdef _DEBUGMEMORYMANAGEMENT
00093    assert ( _user == pthread_self() ) ;
00094 #endif
00095    size_t sizeNeeded =  sizeof(size_t) + size ;
00096    void * result = getFromFree ( sizeNeeded  ) ;
00097    //cerr<<"PsnThreadMemoryManager::allocateSizeRemembered "<<result<<endl;
00098    if ( result == NULL )
00099       {
00100          PsnMemoryElementDescriptor * iNew ;
00101          
00102          //allocate more memory
00103          result = _rawMemoryProvider.allocateSizeRemembered ( _memoryManaged ) ;
00104          if ( result != NULL)
00105             {
00106                iNew = new (& _descriptorMemoryProvider) PsnMemoryElementDescriptor();
00107                iNew->base = (unsigned int)result ;
00108                iNew->size = _memoryManaged ;
00109                iNew->next = 0 ;
00110                _managedMemoryZones->next = (unsigned int) iNew ;
00111 
00112                addInFree (result, _memoryManaged ) ;
00113                _memoryManaged += _memoryManaged ;
00114 
00115                //retry
00116                result = allocateSizeRemembered ( sizeNeeded ) ;
00117             }
00118          else
00119             {//allocation has failed, try minimum allocation
00120                result = _rawMemoryProvider.allocateSizeRemembered ( sizeNeeded ) ;
00121                if ( result != NULL)
00122                   {
00123                      iNew = new (& _descriptorMemoryProvider) PsnMemoryElementDescriptor();
00124                      iNew->base = (unsigned int)result ;
00125                      iNew->size = sizeNeeded;
00126                      iNew->next = 0 ;
00127                      _managedMemoryZones->next = (unsigned int) iNew ;
00128 
00129                      addInFree (result, sizeNeeded ) ;
00130                      _memoryManaged += sizeNeeded ;
00131                      
00132                      //retry
00133                      result = allocateSizeRemembered ( sizeNeeded ) ;
00134                   }
00135             }
00136       }
00137    if (result != NULL) 
00138       {
00139          *((size_t *)result) = size;
00140          
00141          result = (void *) ((unsigned int)result + sizeof (size_t ) ) ;
00142       }
00143    return result ;
00144 }
00145 
00146 
00147 
00148 void PsnThreadMemoryManager::mfreeSizeRememberedOtherThread ( void * ptr ) 
00149 {
00150 #ifdef _DEBUGMEMORYALLOCATION
00151    inAdressSpace ( ptr) ;
00152 #endif
00153    size_t * addressOfSize = (size_t *) ((unsigned int)ptr - sizeof ( size_t ) ) ;
00154    addInFree ( (void *)addressOfSize, *addressOfSize + sizeof ( size_t ) ) ;
00155 }
00156 
00157 
00158 
00159 void PsnThreadMemoryManager::freeSizeRemembered ( void * ptr ) 
00160 {
00161    //cerr<<"PsnThreadMemoryManager::freeSizeRemembered "<<pthread_self()<<endl;
00162    if ( _user == pthread_self() ) 
00163       {
00164          if (inAdressSpace ( ptr) )
00165             {
00166                size_t * addressOfSize = (size_t *) ((unsigned int)ptr - sizeof ( size_t ) ) ;
00167                addInFree ( (void *)addressOfSize, *addressOfSize + sizeof ( size_t ) ) ;
00168             }
00169          else
00170             {
00171                if ( _descriptorMemoryProvider.inAdressSpace ( ptr ) )
00172                   {
00173                      _descriptorMemoryProvider.freeSizeRemembered( ptr ) ;
00174                   }
00175                else
00176                   {
00177                      getFreedMemoryBlocksMutex().protect() ;
00178                      getListOfDetachedMemoryBlocks().push_back ( ptr ) ;
00179                      getFreedMemoryBlocksMutex().unprotect() ;
00180                   }
00181             }
00182       }
00183    else
00184    {
00185       getLeakedMemoryBlocksMutex().protect() ;
00186       getListOfLeakedMemoryBlocks().push_back ( make_pair ( ptr, this) ) ;
00187       getLeakedMemoryBlocksMutex().unprotect() ;
00188    }
00189 }
00190 
00191 void * PsnThreadMemoryManager::getFromFree ( size_t size )
00192 {
00193 #ifdef _DEBUGMEMORYMANAGEMENT
00194    assert ( _user == pthread_self() ) ;
00195    //integrity check
00196    PsnMemoryElementDescriptor * test = _freeMemoryZones ;
00197    while (test != 0)
00198       {
00199          assert (inAdressSpace ( ( PsnMemoryElementDescriptor *)test->base ) ) ;
00200          assert ( test != ( PsnMemoryElementDescriptor *)test->next ) ;
00201          if ( test->next != 0)
00202             {
00203                assert ( ((PsnMemoryElementDescriptor *)test->next)->base > test->base + test->size ) ;
00204             }
00205          test = ( PsnMemoryElementDescriptor *)test->next ;
00206       }
00207 #endif
00208    PsnMemoryElementDescriptor *i , *pred ;
00209    
00210    unsigned int addr ;
00211    
00212    
00213    i = _freeMemoryZones ;
00214 
00215    pred = NULL ;
00216    
00217    addr = 0 ;
00218    
00219    while ( i != NULL )
00220     {
00221        if ( i->size >= size )   /* First fit strategy */
00222           {
00223              addr = i->base ;
00224              if ( i->size == size )
00225                 {
00226                    if ( pred == NULL ) 
00227                       {
00228                          PsnMemoryElementDescriptor * newStartFreeList = (PsnMemoryElementDescriptor *) i -> next ;
00229                          delete _freeMemoryZones ;
00230                          _freeMemoryZones = newStartFreeList ; 
00231                       }
00232                    else 
00233                       {
00234                          pred->next = i->next ;
00235                          delete ( i ) ;
00236                       }     
00237                 }
00238              else
00239                 {
00240                    i->base = i->base + size ;
00241                    i->size = i->size - size ;
00242                 }
00243              i = NULL ;
00244           }
00245        else
00246           {
00247              pred = i ;
00248              i = (PsnMemoryElementDescriptor *) i->next ;
00249           }
00250     }
00251 #ifdef _DEBUGMEMORYMANAGEMENT
00252    //integrity check
00253    test = _freeMemoryZones ;
00254    while (test != 0)
00255       {
00256          assert (inAdressSpace ( ( PsnMemoryElementDescriptor *)test->base ) ) ;
00257          assert ( test != ( PsnMemoryElementDescriptor *)test->next ) ;
00258          if ( test->next != 0)
00259             {
00260                assert ( ((PsnMemoryElementDescriptor *)test->next)->base > test->base + test->size ) ;
00261             }
00262          test = ( PsnMemoryElementDescriptor *)test->next ;
00263       }
00264 #endif
00265   if (addr == 0 ) //no correct memory zone was found
00266      {
00267         return NULL ;
00268      }
00269   else 
00270      {
00271         return (void *)addr ;
00272      }
00273 #ifdef _DEBUGMEMORYMANAGEMENT
00274    cerr<<"PsnThreadMemoryManager:"<<this<<":addInFree: ("<<(void *)addr<<","<<size<<")"<<endl;
00275 #endif
00276 }
00277 
00278 
00279 
00280 void PsnThreadMemoryManager::addInFree(void * ptr, size_t size)
00281 {
00282 #ifdef _DEBUGMEMORYMANAGEMENT
00283    assert ( _user == pthread_self() ) ;
00284    //integrity check
00285    PsnMemoryElementDescriptor * test = _freeMemoryZones ;
00286    while (test != 0)
00287       {
00288          assert (inAdressSpace ( ( PsnMemoryElementDescriptor *)test->base ) ) ;
00289          assert ( test != ( PsnMemoryElementDescriptor *)test->next ) ;
00290          if ( test->next != 0)
00291             {
00292                assert ( ((PsnMemoryElementDescriptor *)test->next)->base > test->base + test->size ) ;
00293             }
00294          test = ( PsnMemoryElementDescriptor *)test->next ;
00295       }
00296 #endif
00297 #ifdef _DEBUGMEMORYMANAGEMENT
00298    cerr<<"PsnThreadMemoryManager:"<<this<<":addInFree: ("<<ptr<<","<<size<<")"<<endl;
00299 #endif
00300    PsnMemoryElementDescriptor *l, *iNew, *tmp ;
00301 
00302    iNew = new(& _descriptorMemoryProvider) PsnMemoryElementDescriptor();
00303    iNew->base = (unsigned int)ptr ;
00304    iNew->size = size;
00305    
00306    if ( _freeMemoryZones  == NULL) 
00307       { /* No free memory in the memory manager */
00308          iNew->next = (unsigned int) NULL ;
00309          _freeMemoryZones = iNew ;
00310       }    
00311    else 
00312       {
00313          l = _freeMemoryZones ;
00314          if ( l->base > iNew->base ) 
00315             {
00316                /* iNew is the lowest interval */
00317                iNew->next = (unsigned int) _freeMemoryZones ;
00318                _freeMemoryZones = iNew ;
00319                //reorder so that l->next == iNew for merge test
00320                l = iNew ;
00321                iNew = (PsnMemoryElementDescriptor *) l->next ;
00322             }    
00323          else 
00324             { 
00325                /* Search the immediate lower interval */
00326                tmp = (PsnMemoryElementDescriptor * ) l -> next ;
00327                bool onBoucle = ( tmp != NULL ) ;
00328                if (onBoucle )
00329                   {
00330                      onBoucle = ( iNew->base > tmp->base ) ;
00331                   } 
00332                while ( onBoucle ) 
00333                   {
00334                      l = tmp ;
00335                      tmp = (PsnMemoryElementDescriptor * ) l->next ;
00336                      if (tmp != NULL) 
00337                         {
00338                            onBoucle = iNew->base > tmp->base ;
00339                         }       
00340                      else 
00341                         {
00342                            onBoucle = false ;
00343                         }
00344                   }
00345                
00346                iNew->next = (unsigned int) tmp ;
00347                l->next = (unsigned int) iNew ;
00348                if ( tmp != NULL ) 
00349                   {
00350                      //try to merge the the new free zone with the following free zonee
00351                      if (iNew->base + iNew->size == tmp -> base) 
00352                         {
00353 #ifdef _DEBUGMEMORYMANAGEMENT
00354                            cerr<<"Merging new free zone ("<<ptr<<") with following"<<endl;
00355 #endif
00356                            iNew->size += tmp->size ;
00357                            iNew->next = tmp->next ;
00358                            delete tmp ;
00359                         }
00360                   }
00361             }
00362          if ( l->base + l->size == iNew->base ) 
00363             {
00364                //try and merger the preceeding free memory block with the freed one
00365 #ifdef _DEBUGMEMORYMANAGEMENT
00366                cerr<<"Merging new free zone ("<<ptr<<") with preceeding"<<endl;
00367 #endif
00368                l->size += iNew->size ;
00369                l->next = iNew->next ;
00370                if (_freeMemoryZones == iNew) 
00371                   {
00372                      _freeMemoryZones = l;
00373                   }
00374                delete iNew ;
00375             }     
00376       }
00377 #ifdef _DEBUGMEMORYMANAGEMENT
00378    //integrity check
00379    test = _freeMemoryZones ;
00380    while (test != 0)
00381       {
00382          assert (inAdressSpace ( ( PsnMemoryElementDescriptor *)test->base ) ) ;
00383          assert ( test != ( PsnMemoryElementDescriptor *)test->next ) ;
00384          if ( test->next != 0)
00385             {
00386                assert ( ((PsnMemoryElementDescriptor *)test->next)->base > test->base + test->size ) ;
00387             }
00388          test = ( PsnMemoryElementDescriptor *)test->next ;
00389       }
00390 #endif
00391 }
00392 
00393 
00394 bool PsnThreadMemoryManager::inAdressSpace ( void * ptr ) const
00395 {
00396    bool result = false ;
00397    unsigned int adress = (unsigned int ) ptr ;
00398    PsnMemoryElementDescriptor * current = _managedMemoryZones ;
00399    while ( (! result) && ( current != NULL ) )
00400    {
00401       result = current->inAdressSpace ( adress ) ;
00402       current = (PsnMemoryElementDescriptor *) current->next ;
00403    }
00404    return result ;
00405 }
00406 
00407 

logo OpenMask

Documentation generated on Mon Nov 25 15:25:01 2002

Generated with doxygen 1.2.12 by Dimitri van Heesch ,   1997-2001