00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00053
00054 format();
00055 scavenge();
00056
00057
00058
00059
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
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
00136 void persistentHeap::stats (void) {
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 void persistentHeap::free (void * ptr)
00148 {
00149
00150
00151 if (ptr == 0) {
00152 return;
00153 }
00154
00155
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
00166
00167
00168
00169
00170
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
00182
00183
00184
00185
00186 hoardHeap * owner;
00187
00188
00189
00190
00191
00192
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
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
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
00235 return sizeFromClass (sb->getBlockSizeClass());
00236 }
00237
00238