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