00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef MEMORY_TEMPORAL_H_
00025 #define MEMORY_TEMPORAL_H_
00026
00027 #include "pose_config.h"
00028 #include "memory_temporal.decl.h"
00029
00030
00031
00032 #define BLOCK_SIZE 8192 // size of SuperBlocks in bytes
00033 #define RECYCLE_BIN_CAPACITY 100
00034
00035 extern CkGroupID TempMemID;
00036
00038 class SuperBlock {
00039 int refCount;
00040 char *blk;
00041 char *pos;
00042 int percent_full;
00043 SuperBlock *nextBlock;
00044
00045 public:
00046 SuperBlock() : refCount(0), blk(NULL), pos(NULL) {};
00047 ~SuperBlock() { free(blk); }
00049 inline void initBlock() {
00050 refCount = 0;
00051 blk = (char *)malloc(BLOCK_SIZE);
00052 pos = blk;
00053 nextBlock = NULL;
00054 percent_full = 0;
00055 }
00056 inline void resetBlock() {
00057
00058 refCount = 0;
00059 pos = blk;
00060 nextBlock = NULL;
00061 percent_full = 0;
00062 }
00063 inline bool noLongerReferenced() { return(refCount == 0); }
00065 char *sb_alloc(int sz) {
00066 #ifdef VERBOSE_DEBUG
00067 CkPrintf("[sb_alloc:\n");
00068 #endif
00069 int remaining = BLOCK_SIZE - (pos - blk);
00070 #ifdef ALIGN16
00071 int actual_sz = (sz%16 == 0)? sz : (sz+16)/16 * 16;
00072 #else
00073 int actual_sz = sz;
00074 #endif
00075 char *ret = NULL;
00076 if (actual_sz <= remaining) {
00077 ret = pos;
00078 pos += actual_sz;
00079 refCount++;
00080 percent_full = (int)(((float)(pos-blk)/4096.0)*100.0);
00081 }
00082 #ifdef VERBOSE_DEBUG
00083 CkPrintf(".sb_alloc]\n");
00084 #endif
00085 return ret;
00086 }
00087
00088 bool sb_free(void *mem) {
00089 #ifdef VERBOSE_DEBUG
00090 CkPrintf("[sb_free:\n");
00091 #endif
00092 if ((mem >= blk) && (mem < pos)) {
00093 refCount--;
00094 #ifdef VERBOSE_DEBUG
00095 CkPrintf(".sb_free]\n");
00096 #endif
00097 return true;
00098 }
00099 else {
00100 #ifdef VERBOSE_DEBUG
00101 CkPrintf(".sb_free]\n");
00102 #endif
00103 return false;
00104 }
00105 }
00106 inline SuperBlock *getNextBlock() { return nextBlock; }
00107 inline void setNextBlock(SuperBlock *loc) { nextBlock = loc; }
00108 inline int getPercentFull() { return percent_full; }
00109 void sanity_check();
00110 };
00111
00113 class TimeBucket {
00114 POSE_TimeType start;
00115 POSE_TimeType range;
00116 int numSuperBlocks;
00117 SuperBlock *sBlocks;
00118 TimeBucket *nextBucket;
00119 TimeBucket *prevBucket;
00120 SuperBlock **pool;
00121 int *poolSz;
00122
00123 public:
00124 TimeBucket() : start(POSE_UnsetTS), range(POSE_UnsetTS), numSuperBlocks(0),
00125 sBlocks(NULL), nextBucket(NULL), prevBucket(NULL) {}
00126 ~TimeBucket() {}
00127
00128 void initBucket(POSE_TimeType start_t, POSE_TimeType range_t, SuperBlock **p, int *pSz) {
00129 pool = p;
00130 poolSz = pSz;
00131 start = start_t;
00132 range = range_t;
00133 if (!(*pool)) {
00134 sBlocks = new SuperBlock;
00135 sBlocks->initBlock();
00136 }
00137 else {
00138 sBlocks = (*pool);
00139 (*pool) = (*pool)->getNextBlock();
00140 sBlocks->resetBlock();
00141 (*poolSz)--;
00142 }
00143 numSuperBlocks = 1;
00144 }
00145 inline int getNumSuperBlocks() { return numSuperBlocks; }
00146 inline int getStart() { return start; }
00147 inline int getRange() { return range; }
00148 inline void setStart(int s) { start = s; }
00149 inline void setRange(int r) { range = r; }
00150 inline bool isVeryFull() {
00151 if (numSuperBlocks > 1) return true;
00152 else if (sBlocks->getPercentFull() > 90) return true;
00153 else return false;
00154 }
00155 inline SuperBlock *getFirstSuperBlock() { return sBlocks; }
00156 inline void setFirstSuperBlock(SuperBlock *sb) { sBlocks = sb; }
00157 inline void setPrevBucket(TimeBucket *p) { prevBucket = p; }
00158 inline void setNextBucket(TimeBucket *n) { nextBucket = n; }
00159 inline TimeBucket *getPrevBucket() { return prevBucket; }
00160 inline TimeBucket *getNextBucket() { return nextBucket; }
00161
00162 char *tb_alloc(int sz) {
00163 #ifdef VERBOSE_DEBUG
00164 CkPrintf("[tb_alloc:\n");
00165 #endif
00166 char *newblk = sBlocks->sb_alloc(sz);
00167 if (!newblk) {
00168 SuperBlock *tmp;
00169 if (!(*pool)) {
00170 tmp = new SuperBlock;
00171 tmp->initBlock();
00172 }
00173 else {
00174 tmp = (*pool);
00175 (*pool) = (*pool)->getNextBlock();
00176 tmp->resetBlock();
00177 (*poolSz)--;
00178 }
00179 tmp->setNextBlock(sBlocks);
00180 sBlocks = tmp;
00181 numSuperBlocks++;
00182 #ifdef VERBOSE_DEBUG
00183 if (numSuperBlocks > 3)
00184 CkPrintf("WARNING: # SuperBlocks in TimeBucket exceeds 3 at %d. SUGGESTION: Increase block size.\n", numSuperBlocks);
00185 #endif
00186 newblk = sBlocks->sb_alloc(sz);
00187 }
00188 #ifdef VERBOSE_DEBUG
00189 CkPrintf(".tb_alloc]\n");
00190 #endif
00191 return newblk;
00192 }
00193
00194 void tb_free(char *mem) {
00195 #ifdef VERBOSE_DEBUG
00196 CkPrintf("[tb_free:\n");
00197 #endif
00198 SuperBlock *tmp = sBlocks;
00199 bool done = false;
00200 while (tmp && !done) {
00201 done = tmp->sb_free(mem);
00202 if (done) {
00203 if (tmp->noLongerReferenced())
00204 numSuperBlocks--;
00205 }
00206 else {
00207 tmp = tmp->getNextBlock();
00208 }
00209 }
00210 if (!done) CkAbort("ERROR: block to deallocate not found in time range.\n");
00211 #ifdef VERBOSE_DEBUG
00212 CkPrintf(".tb_free]\n");
00213 #endif
00214 }
00215 POSE_TimeType sanity_check(POSE_TimeType last_time);
00216 };
00217
00218 class TimePool : public Group {
00219 TimeBucket *last_in_use;
00220 TimeBucket *first_in_use;
00221 SuperBlock *not_in_use;
00222 int not_in_use_sz;
00223
00224 POSE_TimeType min_time;
00225
00226
00227 int BLOCK_RANGE;
00228
00229
00230 void clean_up();
00231 public:
00232 TimePool() : min_time(POSE_UnsetTS), last_in_use(NULL), first_in_use(NULL),
00233 not_in_use(NULL), not_in_use_sz(0) {}
00234 TimePool(CkMigrateMessage *msg) : Group(msg) {}
00235 ~TimePool();
00236 void pup(PUP::er &p) {}
00237
00238 char *tmp_alloc(POSE_TimeType timestamp, int sz_in_bytes);
00239
00240 void tmp_free(POSE_TimeType timestamp, void *mem);
00241
00242 inline void set_min_time(POSE_TimeType min_t) { min_time = min_t; clean_up(); }
00243 void empty_recycle_bin() {
00244 SuperBlock *b = not_in_use;
00245 while (not_in_use) {
00246 not_in_use = not_in_use->getNextBlock();
00247 delete b;
00248 b = not_in_use;
00249 }
00250 }
00251 void sanity_check();
00252 };
00253
00254 #endif