usermode/library/malloc-original/src/persistentheap.cpp

00001 #include <mnemosyne.h>
00002 #include <stdint.h>
00003 #include <sys/mman.h>
00004 #include "config.h"
00005 #include "threadheap.h"
00006 #include "persistentheap.h"
00007 #include "persistentsuperblock.h"
00008 
00009 MNEMOSYNE_PERSISTENT void *psegmentheader = 0;
00010 MNEMOSYNE_PERSISTENT void *psegment = 0;
00011 
00012 persistentHeap::persistentHeap (void)
00013   : _buffer (NULL),
00014     _bufferCount (0)
00015 {
00016         int                  i;
00017         persistentSuperblock *psb;
00018 
00019         // Format persistent heap; this happens only the first time 
00020         // the heap is ever incarnated.
00021         format();
00022         scavenge();
00023         
00024         // Initialize some logically non-persistent information 
00025         // FIXME: This should really be implemented as a volatile index to avoid writing PCM
00026         for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00027                 psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00028                 psb->volatileInit();
00029         }       
00030 }
00031 
00032 
00033 void persistentHeap::format()
00034 {
00035         int   i;
00036         void  *b;
00037         void  *buf;
00038 
00039         assert((!psegmentheader && !psegment) || (psegmentheader && psegment));
00040 
00041         if (!psegmentheader) {
00042                 psegmentheader = m_pmap((void *) PERSISTENTHEAP_HEADER_BASE, PERSISTENTSUPERBLOCK_NUM*sizeof(persistentSuperblock), PROT_READ|PROT_WRITE, 0);
00043                 psegment = m_pmap((void *)PERSISTENTHEAP_BASE, persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE * PERSISTENTSUPERBLOCK_NUM, PROT_READ|PROT_WRITE, 0);
00044                 for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00045                         b = (void *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00046                         buf = (void *) ((uintptr_t) psegment + i*persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE);
00047                         new(b) persistentSuperblock((char *)buf);
00048                 }
00049                 _psegmentBase = psegment;
00050         }
00051 }
00052 
00053 
00054 // For every persistent superblock create a superblock that higher layers can use
00055 void persistentHeap::scavenge()
00056 {
00057         int                  i;
00058         int                  sizeclass;
00059         int                  blksize;
00060         persistentSuperblock *psb;
00061         superblock           *sb;
00062 
00063         for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00064                 psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00065                 blksize = psb->getBlockSize();
00066                 sizeclass = sizeClass(blksize);
00067                 sb = superblock::makeSuperblock (psb);
00068                 insertSuperblock (sizeclass, sb, (persistentHeap *) NULL);
00069 #if 0
00070                 std::cout << "psb: " << psb << std::endl;
00071                 std::cout << "  ->fullness : " << psb->getFullness() << std::endl;
00072                 std::cout << "  ->isFree   : " << psb->isFree() << std::endl;
00073                 std::cout << "  ->sizeClass: " << sizeclass << std::endl;
00074                 std::cout << "  ->blksize: " << blksize << std::endl;
00075                 std::cout << "sb: " << sb << std::endl;
00076                 std::cout << "  ->numBlocks: " << sb->getNumBlocks() << std::endl;
00077                 std::cout << "  ->numAvailable: " << sb->getNumAvailable() << std::endl;
00078                 std::cout << "  ->getFullness: " << sb->getFullness() << std::endl;
00079 #endif          
00080         }       
00081 }
00082 
00083 
00084 // Print out statistics information.
00085 void persistentHeap::stats (void) {
00086 }
00087 
00088 
00089 
00090 // free (ptr, pheap):
00091 //   inputs: a pointer to an object allocated by malloc().
00092 //   side effects: returns the block to the object's superblock;
00093 //                 updates the thread heap's statistics;
00094 //                 may release the superblock to the process heap.
00095 
00096 void persistentHeap::free (void * ptr)
00097 {
00098         // Return if ptr is 0.
00099         // This is the behavior prescribed by the standard.
00100         if (ptr == 0) {
00101                 return;
00102         }
00103 
00104         // Find the block and superblock corresponding to this ptr.
00105 
00106         uintptr_t psb_index = ((uintptr_t) ptr - (uintptr_t) psegment) / persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE;
00107         persistentSuperblock *psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + psb_index * sizeof(persistentSuperblock));
00108         int blksize = psb->getBlockSize();
00109         uintptr_t block_index = (((uintptr_t) ptr - (uintptr_t) psegment) % persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE) / blksize;
00110         superblock *sb = psb->getSuperblock();
00111         assert (sb);
00112         assert (sb->isValid());
00113         block *b = sb->getBlock(block_index);
00114         //std::cout << "block_index = " << block_index << std::endl;
00115         //std::cout << "psb = " << psb << std::endl;
00116         //std::cout << "1.sb = " << sb << std::endl;
00117 
00118         // Check to see if this block came from a memalign() call.
00119         // TODO: Currently we don't support memalign()
00120 
00121         b->markFree();
00122 
00123         assert (sb == b->getSuperblock());
00124         assert (sb);
00125         assert (sb->isValid());
00126 
00127         const int sizeclass = sb->getBlockSizeClass();
00128 
00129         //
00130         // Return the block to the superblock,
00131         // find the heap that owns this superblock
00132         // and update its statistics.
00133         //
00134 
00135         hoardHeap * owner;
00136 
00137         // By acquiring the up lock on the superblock,
00138         // we prevent it from moving to the global heap.
00139         // This eventually pins it down in one heap,
00140         // so this loop is guaranteed to terminate.
00141         // (It should generally take no more than two iterations.)
00142         sb->upLock();
00143         for (;;) {
00144                 owner = sb->getOwner();
00145                 owner->lock();
00146                 if (owner == sb->getOwner()) {
00147                         break;
00148                 } else {
00149                         owner->unlock();
00150                 }
00151                 // Suspend to allow ownership to quiesce.
00152                 hoardYield();
00153         }
00154 
00155 #if HEAP_LOG
00156         MemoryRequest m;
00157         m.free (ptr);
00158         getLog (owner->getIndex()).append(m);
00159 #endif
00160 #if HEAP_FRAG_STATS
00161         setDeallocated (b->getRequestedSize(), 0);
00162 #endif
00163 
00164         int sbUnmapped = owner->freeBlock (b, sb, sizeclass, this);
00165 
00166         owner->unlock();
00167         if (!sbUnmapped) {
00168                 sb->upUnlock();
00169         }
00170 }

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7