usermode/library/pmalloc/src/persistentheap.cpp

00001 /*
00002     Copyright (C) 2011 Computer Sciences Department, 
00003     University of Wisconsin -- Madison
00004 
00005     ----------------------------------------------------------------------
00006 
00007     This file is part of Mnemosyne: Lightweight Persistent Memory, 
00008     originally developed at the University of Wisconsin -- Madison.
00009 
00010     Mnemosyne was originally developed primarily by Haris Volos
00011     with contributions from Andres Jaan Tack.
00012 
00013     ----------------------------------------------------------------------
00014 
00015     Mnemosyne is free software; you can redistribute it and/or
00016     modify it under the terms of the GNU General Public License
00017     as published by the Free Software Foundation, version 2
00018     of the License.
00019  
00020     Mnemosyne is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU General Public License for more details.
00024 
00025     You should have received a copy of the GNU General Public License
00026     along with this program; if not, write to the Free Software
00027     Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00028     Boston, MA  02110-1301, USA.
00029 
00030 ### END HEADER ###
00031 */
00032 
00033 #include <sys/time.h>
00034 #include <mnemosyne.h>
00035 #include <stdint.h>
00036 #include <sys/mman.h>
00037 #include "config.h"
00038 #include "threadheap.h"
00039 #include "persistentheap.h"
00040 #include "persistentsuperblock.h"
00041 
00042 MNEMOSYNE_PERSISTENT void *psegmentheader = 0;
00043 MNEMOSYNE_PERSISTENT void *psegment = 0;
00044 
00045 persistentHeap::persistentHeap (void)
00046   : _buffer (NULL),
00047     _bufferCount (0)
00048 {
00049         int                  i;
00050         persistentSuperblock *psb;
00051 
00052         // Format persistent heap; this happens only the first time 
00053         // the heap is ever incarnated.
00054         format();
00055         scavenge();
00056         
00057         // Initialize some logically non-persistent information 
00058         // FIXME: This should really be implemented as a volatile index to avoid 
00059         // writing PCM cells
00060         for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00061                 psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00062                 psb->volatileInit();
00063         }       
00064 }
00065 
00066 
00067 void persistentHeap::format()
00068 {
00069         int   i;
00070         void  *b;
00071         void  *buf;
00072 
00073         assert((!psegmentheader && !psegment) || (psegmentheader && psegment));
00074 
00075         if (!psegmentheader) {
00076                 psegmentheader = m_pmap((void *) PERSISTENTHEAP_HEADER_BASE, PERSISTENTSUPERBLOCK_NUM*sizeof(persistentSuperblock), PROT_READ|PROT_WRITE, 0);
00077                 assert(psegmentheader != (void *) -1);
00078                 psegment = m_pmap((void *)PERSISTENTHEAP_BASE, (uint64_t) persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE * PERSISTENTSUPERBLOCK_NUM, PROT_READ|PROT_WRITE, 0);
00079                 assert(psegment != (void *) -1);
00080                 for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00081                         b = (void *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00082                         buf = (void *) ((uintptr_t) psegment + i*persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE);
00083                         new(b) persistentSuperblock((char *)buf);
00084                 }
00085                 _psegmentBase = psegment;
00086         }
00087 }
00088 
00089 
00090 // For every persistent superblock create a superblock that higher layers can use
00091 void persistentHeap::scavenge()
00092 {
00093 #ifdef _M_STATS_BUILD
00094         struct timeval     start_time;
00095         struct timeval     stop_time;
00096         unsigned long long op_time;
00097 #endif
00098 
00099         int                  i;
00100         int                  sizeclass;
00101         int                  blksize;
00102         persistentSuperblock *psb;
00103         superblock           *sb;
00104 
00105 #ifdef _M_STATS_BUILD
00106         gettimeofday(&start_time, NULL);
00107 #endif
00108         for(i=0; i<PERSISTENTSUPERBLOCK_NUM; i++) { 
00109                 psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + i*sizeof(persistentSuperblock));
00110                 blksize = psb->getBlockSize();
00111                 sizeclass = sizeClass(blksize);
00112                 sb = superblock::makeSuperblock (psb);
00113                 insertSuperblock (sizeclass, sb, (persistentHeap *) NULL);
00114 #if 0
00115                 std::cout << "psb: " << psb << std::endl;
00116                 std::cout << "  ->fullness : " << psb->getFullness() << std::endl;
00117                 std::cout << "  ->isFree   : " << psb->isFree() << std::endl;
00118                 std::cout << "  ->sizeClass: " << sizeclass << std::endl;
00119                 std::cout << "  ->blksize: " << blksize << std::endl;
00120                 std::cout << "sb: " << sb << std::endl;
00121                 std::cout << "  ->numBlocks: " << sb->getNumBlocks() << std::endl;
00122                 std::cout << "  ->numAvailable: " << sb->getNumAvailable() << std::endl;
00123                 std::cout << "  ->getFullness: " << sb->getFullness() << std::endl;
00124 #endif          
00125         }
00126 #ifdef _M_STATS_BUILD
00127         gettimeofday(&stop_time, NULL);
00128         op_time = 1000000 * (stop_time.tv_sec - start_time.tv_sec) +
00129                              stop_time.tv_usec - start_time.tv_usec;
00130         printf("persistent_heap_scavenge_latency = %llu (us)\n", op_time);
00131 #endif
00132 }
00133 
00134 
00135 // Print out statistics information.
00136 void persistentHeap::stats (void) {
00137 }
00138 
00139 
00140 
00141 // free (ptr, pheap):
00142 //   inputs: a pointer to an object allocated by malloc().
00143 //   side effects: returns the block to the object's superblock;
00144 //                 updates the thread heap's statistics;
00145 //                 may release the superblock to the process heap.
00146 
00147 void persistentHeap::free (void * ptr)
00148 {
00149         // Return if ptr is 0.
00150         // This is the behavior prescribed by the standard.
00151         if (ptr == 0) {
00152                 return;
00153         }
00154 
00155         // Find the block and superblock corresponding to this ptr.
00156 
00157         uintptr_t psb_index = ((uintptr_t) ptr - (uintptr_t) psegment) / persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE;
00158         persistentSuperblock *psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + psb_index * sizeof(persistentSuperblock));
00159         int blksize = psb->getBlockSize();
00160         uintptr_t block_index = (((uintptr_t) ptr - (uintptr_t) psegment) % persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE) / blksize;
00161         superblock *sb = psb->getSuperblock();
00162         assert (sb);
00163         assert (sb->isValid());
00164         block *b = sb->getBlock(block_index);
00165         //std::cout << "block_index = " << block_index << std::endl;
00166         //std::cout << "psb = " << psb << std::endl;
00167         //std::cout << "1.sb = " << sb << std::endl;
00168 
00169         // Check to see if this block came from a memalign() call.
00170         // TODO: Currently we don't support memalign()
00171 
00172         b->markFree();
00173 
00174         assert (sb == b->getSuperblock());
00175         assert (sb);
00176         assert (sb->isValid());
00177 
00178         const int sizeclass = sb->getBlockSizeClass();
00179 
00180         //
00181         // Return the block to the superblock,
00182         // find the heap that owns this superblock
00183         // and update its statistics.
00184         //
00185 
00186         hoardHeap * owner;
00187 
00188         // By acquiring the up lock on the superblock,
00189         // we prevent it from moving to the global heap.
00190         // This eventually pins it down in one heap,
00191         // so this loop is guaranteed to terminate.
00192         // (It should generally take no more than two iterations.)
00193         sb->upLock();
00194         for (;;) {
00195                 owner = sb->getOwner();
00196                 owner->lock();
00197                 if (owner == sb->getOwner()) {
00198                         break;
00199                 } else {
00200                         owner->unlock();
00201                 }
00202                 // Suspend to allow ownership to quiesce.
00203                 hoardYield();
00204         }
00205 
00206 #if HEAP_LOG
00207         MemoryRequest m;
00208         m.free (ptr);
00209         getLog (owner->getIndex()).append(m);
00210 #endif
00211 #if HEAP_FRAG_STATS
00212         setDeallocated (b->getRequestedSize(), 0);
00213 #endif
00214 
00215         int sbUnmapped = owner->freeBlock (b, sb, sizeclass, this);
00216 
00217         owner->unlock();
00218         if (!sbUnmapped) {
00219                 sb->upUnlock();
00220         }
00221 }
00222 
00223 size_t persistentHeap::objectSize (void * ptr) 
00224 {
00225         // Find the superblock pointer.
00226         uintptr_t psb_index = ((uintptr_t) ptr - (uintptr_t) psegment) / persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE;
00227         persistentSuperblock *psb = (persistentSuperblock *) ((uintptr_t) psegmentheader + psb_index * sizeof(persistentSuperblock));
00228         int blksize = psb->getBlockSize();
00229         uintptr_t block_index = (((uintptr_t) ptr - (uintptr_t) psegment) % persistentSuperblock::PERSISTENTSUPERBLOCK_SIZE) / blksize;
00230         superblock *sb = psb->getSuperblock();
00231         assert (sb);
00232         assert (sb->isValid());
00233   
00234   // Return the size.
00235   return sizeFromClass (sb->getBlockSizeClass());
00236 }
00237 
00238 

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