
00001 /* 00002 ** memory_temporal.C 00003 ** 00004 ** Made by Terry Wilmarth 00005 */ 00006 #include "charm++.h" 00007 #include "pose.h" 00008 #include "memory_temporal.def.h" 00009 00010 CkGroupID TempMemID; // global readonly to access pool anywhere 00011 00012 void SuperBlock::sanity_check() { 00013 // no obvious way to verify the sanity of a SuperBlock 00014 } 00015 00016 POSE_TimeType TimeBucket::sanity_check(POSE_TimeType last_time) { 00017 CkAssert(start > last_time); 00018 if (!sBlocks) CkAssert(numSuperBlocks == 0); 00019 if (sBlocks) { 00020 int count=0; 00021 SuperBlock *tmpblk = sBlocks; 00022 while (tmpblk) { 00023 if (!tmpblk->noLongerReferenced()) count++; 00024 tmpblk = tmpblk->getNextBlock(); 00025 } 00026 CkAssert(count == numSuperBlocks); 00027 tmpblk = sBlocks; 00028 while (tmpblk) { 00029 tmpblk->sanity_check(); 00030 tmpblk = tmpblk->getNextBlock(); 00031 } 00032 } 00033 return (start+range-1); 00034 } 00035 00036 void TimePool::clean_up() { 00037 #ifdef VERBOSE_DEBUG 00038 sanity_check(); 00039 #endif 00040 TimeBucket *tmpbkt = first_in_use; 00041 while (tmpbkt && (min_time >= (tmpbkt->getStart()+tmpbkt->getRange()))) { 00042 // move the blocks of this bucket to not_in_use 00043 SuperBlock *sb = tmpbkt->getFirstSuperBlock(); 00044 while (sb) { 00045 if (sb->noLongerReferenced()) { 00046 SuperBlock *next = sb->getNextBlock(); 00047 if (not_in_use_sz < RECYCLE_BIN_CAPACITY) { 00048 sb->setNextBlock(not_in_use); 00049 not_in_use = sb; 00050 not_in_use_sz++; 00051 } 00052 else { 00053 #ifdef VERBOSE_DEBUG 00054 CkPrintf("INFO: recycle bin at capacity; deleting blocks\n"); 00055 #endif 00056 delete sb; 00057 } 00058 sb = next; 00059 } 00060 else break; 00061 } 00062 if (!sb) { // bucket is totally empty, delete it 00063 // move the first_in_use ptr forward 00064 if (tmpbkt == first_in_use) { 00065 if (first_in_use == last_in_use) { 00066 first_in_use = last_in_use = NULL; 00067 } 00068 else { 00069 first_in_use = first_in_use->getPrevBucket(); 00070 first_in_use->setNextBucket(NULL); 00071 } 00072 delete tmpbkt; 00073 tmpbkt = first_in_use; 00074 } 00075 else if (tmpbkt == last_in_use) { 00076 last_in_use = last_in_use->getNextBucket(); 00077 last_in_use->setPrevBucket(NULL); 00078 delete tmpbkt; 00079 tmpbkt = NULL; 00080 } 00081 else { 00082 TimeBucket *tmp = tmpbkt->getPrevBucket(); 00083 tmp->setNextBucket(tmpbkt->getNextBucket()); 00084 tmpbkt->getNextBucket()->setPrevBucket(tmp); 00085 delete tmpbkt; 00086 tmpbkt = tmp; 00087 } 00088 } 00089 else { 00090 tmpbkt->setFirstSuperBlock(sb); 00091 tmpbkt = tmpbkt->getPrevBucket(); 00092 } 00093 } 00094 #ifdef VERBOSE_DEBUG 00095 sanity_check(); 00096 #endif 00097 } 00098 00099 TimePool::~TimePool() 00100 { 00101 TimeBucket *tmpbkt = last_in_use; 00102 while (tmpbkt) { 00103 last_in_use = last_in_use->getNextBucket(); 00104 delete tmpbkt; 00105 tmpbkt = last_in_use; 00106 } 00107 SuperBlock *tmpblk = not_in_use; 00108 while (tmpblk) { 00109 not_in_use = not_in_use->getNextBlock(); 00110 delete tmpblk; 00111 tmpblk = not_in_use; 00112 } 00113 } 00114 00115 // Return memory from a time range 00116 char *TimePool::tmp_alloc(POSE_TimeType timestamp, int sz_in_bytes) 00117 { // List looks like this: 00118 // last (newer, higher ts) .... first (older, lower ts) 00119 #ifdef VERBOSE_DEBUG 00120 sanity_check(); 00121 CkPrintf("[tmp_alloc:\n"); 00122 #endif 00123 TimeBucket *bkt = last_in_use; 00124 while (bkt && (timestamp < bkt->getStart())) { 00125 bkt = bkt->getNextBucket(); 00126 } 00127 if (!bkt) { // either empty, or ts is older than anything we have 00128 if (!first_in_use) { // empty 00129 first_in_use = new TimeBucket(); 00130 first_in_use->initBucket(timestamp, 1, ¬_in_use, ¬_in_use_sz); 00131 last_in_use = first_in_use; 00132 char *mem = last_in_use->tb_alloc(sz_in_bytes); 00133 #ifdef VERBOSE_DEBUG 00134 CkPrintf(".tmp_alloc]\n"); 00135 sanity_check(); 00136 #endif 00137 return mem; 00138 } 00139 else if (timestamp < first_in_use->getStart()) { //not empty, ts is oldest 00140 first_in_use->setStart(timestamp); 00141 char *mem = first_in_use->tb_alloc(sz_in_bytes); 00142 #ifdef VERBOSE_DEBUG 00143 CkPrintf(".tmp_alloc]\n"); 00144 sanity_check(); 00145 #endif 00146 return mem; 00147 } 00148 } 00149 else if (bkt == last_in_use) { // we have some options if the target is last 00150 if (bkt->isVeryFull() && (timestamp >= (bkt->getStart() + bkt->getRange()))) { // let's make a new bucket, timestamp is far out enough 00151 int start = bkt->getStart()+bkt->getRange(); 00152 int range = timestamp - start + 1; 00153 last_in_use = new TimeBucket(); 00154 last_in_use->initBucket(start, range, ¬_in_use, ¬_in_use_sz); 00155 bkt->setPrevBucket(last_in_use); 00156 last_in_use->setNextBucket(bkt); 00157 char *mem = last_in_use->tb_alloc(sz_in_bytes); 00158 #ifdef VERBOSE_DEBUG 00159 CkPrintf(".tmp_alloc]\n"); 00160 sanity_check(); 00161 #endif 00162 return mem; 00163 } 00164 else { // let's put it here, expanding the range if necessary 00165 if (timestamp >= (bkt->getStart() + bkt->getRange())) { 00166 bkt->setRange(timestamp - bkt->getStart() + 1); 00167 } 00168 char *mem = bkt->tb_alloc(sz_in_bytes); 00169 #ifdef VERBOSE_DEBUG 00170 CkPrintf(".tmp_alloc]\n"); 00171 sanity_check(); 00172 #endif 00173 return mem; 00174 } 00175 } 00176 else { // this is in the range of this bucket, must put it here 00177 char *mem = bkt->tb_alloc(sz_in_bytes); 00178 #ifdef VERBOSE_DEBUG 00179 CkPrintf(".tmp_alloc]\n"); 00180 sanity_check(); 00181 #endif 00182 return mem; 00183 } 00184 } 00185 00186 // "Free" up memory from a time range 00187 void TimePool::tmp_free(POSE_TimeType timestamp, void *mem) 00188 { 00189 #ifdef VERBOSE_DEBUG 00190 sanity_check(); 00191 CkPrintf("[tmp_free:\n"); 00192 #endif 00193 if (mem) { 00194 TimeBucket *tmpbkt = first_in_use; 00195 while (tmpbkt && (timestamp >= (tmpbkt->getStart()+tmpbkt->getRange()))) { 00196 tmpbkt = tmpbkt->getPrevBucket(); 00197 } 00198 if (tmpbkt) { 00199 tmpbkt->tb_free((char *)mem); 00200 } 00201 else CkAbort("ERROR: Memory in that time range not found for deallocation.\n"); 00202 #ifdef VERBOSE_DEBUG 00203 CkPrintf(".tmp_free]\n"); 00204 sanity_check(); 00205 #endif 00206 } 00207 } 00208 00209 void TimePool::sanity_check() { 00210 // first check the quality of the list of in-use buckets 00211 if (!last_in_use) CkAssert(!first_in_use); 00212 if (!first_in_use) CkAssert(!last_in_use); 00213 if (last_in_use) CkAssert(!(last_in_use->getPrevBucket())); 00214 if (first_in_use) CkAssert(!(first_in_use->getNextBucket())); 00215 TimeBucket *tmpbkt = last_in_use; 00216 if (tmpbkt) { 00217 while (tmpbkt->getNextBucket()) { 00218 CkAssert(tmpbkt->getNextBucket()->getPrevBucket() == tmpbkt); 00219 tmpbkt = tmpbkt->getNextBucket(); 00220 } 00221 CkAssert(tmpbkt == first_in_use); 00222 } 00223 tmpbkt = first_in_use; 00224 if (tmpbkt) { 00225 while (tmpbkt->getPrevBucket()) { 00226 CkAssert(tmpbkt->getPrevBucket()->getNextBucket() == tmpbkt); 00227 tmpbkt = tmpbkt->getPrevBucket(); 00228 } 00229 CkAssert(tmpbkt == last_in_use); 00230 } 00231 // ASSERT: Bucket structure of TimePool is fine at this point. 00232 // Now, we examine the bucket contents 00233 tmpbkt = first_in_use; 00234 if (tmpbkt) { 00235 POSE_TimeType lastTime = POSE_UnsetTS; 00236 while (tmpbkt) { 00237 lastTime = tmpbkt->sanity_check(lastTime); 00238 tmpbkt = tmpbkt->getPrevBucket(); 00239 } 00240 } 00241 }
1.5.5