00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 static void memAbort(const char *err, void *ptr)
00018 {
00019 #if 1
00020
00021 CmiPrintf("[%d] memory-paranoid> FATAL HEAP ERROR! %s (block %p)\n",
00022 CmiMyPe(),err,ptr);
00023 CmiAbort("memory-paranoid> FATAL HEAP ERROR");
00024 #else
00025
00026 fprintf(stderr,"memory-paranoid> FATAL HEAP ERROR! %s (block %p)\n",
00027 err,ptr);
00028 fflush(stdout);fflush(stderr);
00029 abort();
00030 #endif
00031 }
00032
00033
00034 #define MAX_BLOCKSIZE (1024*1024*512)
00035 static size_t max_allocated = 0;
00036
00037
00038
00039
00040
00041 struct _Slot {
00042
00043 struct _Slot *next;
00044 struct _Slot *prev;
00045
00046
00047 int userSize;
00048
00049
00050 #define SLOTMAGIC 0x8402a5f5
00051 #define SLOTMAGIC_VALLOC 0x7402a5f5
00052 #define SLOTMAGIC_FREED 0xDEADBEEF
00053 int magic;
00054
00055
00056 #define STACK_LEN 4
00057 void *from[STACK_LEN];
00058
00059
00060 #define PADLEN 72
00061 char pad[PADLEN];
00062 };
00063 typedef struct _Slot Slot;
00064
00065
00066 #define PADFN(i) (char)(217+(i))
00067
00068 static void setPad(char *pad) {
00069 int i;
00070 for (i=0;i<PADLEN;i++)
00071 pad[i]=PADFN(i);
00072 }
00073
00074
00075 static int memory_fill=-1;
00076 static int memory_fillphase=0;
00077 static void fill_uninit(char *loc,int len)
00078 {
00079 int fill=memory_fill;
00080 int fillChar;
00081 if (fill==-1)
00082 fill=(memory_fillphase++)%2;
00083 if (fill!=0) fillChar=0xDE;
00084 else fillChar=0;
00085 memset(loc,fillChar,len);
00086 }
00087
00088
00089
00090 static char *Slot_toUser(Slot *s) {
00091 return ((char *)s)+sizeof(Slot);
00092 }
00093
00094
00095 static Slot slot_first={&slot_first,&slot_first};
00096
00097
00098
00099
00100 static int memory_checkfreq=100;
00101 static int memory_checkphase=0;
00102 static int memory_verbose=0;
00103
00104 static void slotAbort(const char *why,Slot *s) {
00105 memory_checkfreq=100000;
00106 CmiPrintf("[%d] Error in block of %d bytes at %p, allocated from:\n",
00107 CmiMyPe(), s->userSize, Slot_toUser(s));
00108 CmiBacktracePrint(s->from,STACK_LEN);
00109 memAbort(why,Slot_toUser(s));
00110 }
00111
00112
00113 static void checkPad(const char *pad, const char *errMsg, const void *ptr, Slot *s) {
00114 int i;
00115 for (i=0;i<PADLEN;i++)
00116 if (pad[i]!=PADFN(i)) {
00117 memory_checkfreq=100000;
00118 fprintf(stderr,"Corrupted data:");
00119 for (i=0;i<PADLEN;i++)
00120 if (pad[i]!=PADFN(i))
00121 fprintf(stderr," %02x",(unsigned
00122 int)(unsigned char)pad[i]);
00123 else fprintf(stderr," -");
00124 fprintf(stderr,"\n");
00125 slotAbort(errMsg,s);
00126 }
00127 }
00128
00129
00130 static int badPointer(Slot *p) {
00131 char *c=(char *)p;
00132 if ((c<(char *)0x1000) || (c+0x1000)<(char *)0x1000)
00133 return 1;
00134 return 0;
00135 }
00136
00137
00138 static void checkSlot(Slot *s) {
00139 char *user=Slot_toUser(s);
00140 if (badPointer(s))
00141 slotAbort("Non-heap pointer passed to checkSlot",s);
00142 if (s->magic!=SLOTMAGIC && s->magic!=SLOTMAGIC_VALLOC)
00143 slotAbort("Corrupted slot magic number",s);
00144 if (s->userSize<0)
00145 slotAbort("Corrupted (negative) user size field",s);
00146 if (s->userSize>max_allocated)
00147 slotAbort("Corrupted (huge) user size field",s);
00148 if (badPointer(s->prev) || (s->prev->next!=s))
00149 slotAbort("Corrupted back link",s);
00150 if (badPointer(s->next) || (s->next->prev!=s))
00151 slotAbort("Corrupted forward link",s);
00152
00153 checkPad(s->pad,"Corruption before start of block",user,s);
00154 checkPad(user+s->userSize,"Corruption after block",user,s);
00155 }
00156
00157
00158 void memory_check(void)
00159 {
00160 Slot *cur=slot_first.next;
00161 int nBlocks=0, nBytes=0;
00162 memory_checkphase=0;
00163 while (cur!=&slot_first) {
00164 checkSlot(cur);
00165 nBlocks++;
00166 nBytes+=cur->userSize;
00167 cur=cur->next;
00168 }
00169 if (memory_verbose)
00170 {
00171 int nMegs=nBytes/(1024*1024);
00172 int nKb=(nBytes-(nMegs*1024*1024))/1024;
00173 CmiPrintf("[%d] Heap checked-- clean. %d blocks / %d.%03d megs\n",
00174 CmiMyPe(),nBlocks,nMegs,(int)(nKb*1000.0/1024.0));
00175 }
00176 }
00177
00178 #define CMI_MEMORY_ROUTINES 1
00179
00180
00181 void CmiMemoryMark(void) { }
00182 void CmiMemoryMarkBlock(void *blk) { }
00183 void CmiMemorySweep(const char *where) { }
00184
00185 void CmiMemoryCheck(void)
00186 {
00187 memory_check();
00188 }
00189
00190
00191
00192 static int memoryTraceDisabled = 0;
00193
00194
00195 static void *setSlot(Slot *s,int userSize) {
00196 char *user=Slot_toUser(s);
00197
00198
00199 if ((++memory_checkphase)>=memory_checkfreq) memory_check();
00200
00201
00202 s->next=slot_first.next;
00203 s->prev=&slot_first;
00204 s->next->prev=s;
00205 s->prev->next=s;
00206
00207 s->magic=SLOTMAGIC;
00208 {
00209 int n=STACK_LEN;
00210 if (memoryTraceDisabled==0) {
00211 memoryTraceDisabled = 1;
00212 CmiBacktraceRecord(s->from,3,&n);
00213 memoryTraceDisabled = 0;
00214 } else {
00215 s->from[0] = (void*)10;
00216 s->from[1] = (void*)9;
00217 s->from[2] = (void*)8;
00218 }
00219 }
00220 s->userSize=userSize;
00221 if (userSize > max_allocated) max_allocated = userSize;
00222 setPad(s->pad);
00223 fill_uninit(user,s->userSize);
00224 setPad(user+s->userSize);
00225 return (void *)user;
00226 }
00227
00228
00229 static void freeSlot(Slot *s) {
00230 checkSlot(s);
00231
00232
00233 s->next->prev=s->prev;
00234 s->prev->next=s->next;
00235 s->prev=s->next=(Slot *)0x0F0;
00236
00237 s->magic=SLOTMAGIC_FREED;
00238 fill_uninit(Slot_toUser(s),s->userSize);
00239 s->userSize=-1;
00240
00241
00242 if ((++memory_checkphase)>=memory_checkfreq) memory_check();
00243 }
00244
00245
00246 static Slot *Slot_fmUser(void *user) {
00247 char *cu=(char *)user;
00248 Slot *s=(Slot *)(cu-sizeof(Slot));
00249 checkSlot(s);
00250 return s;
00251 }
00252
00253
00254
00255
00256 #if ! CMK_MEMORY_BUILD_OS
00257
00258 #include "memory-gnu.C"
00259 #endif
00260
00261
00262 static void status(const char *msg) {
00263 if (CmiMyPe()==0 && !CmiArgGivingUsage()) {
00264 CmiPrintf("%s",msg);
00265 }
00266 }
00267 static void meta_init(char **argv)
00268 {
00269 if (CmiMyRank()==0) CmiMemoryIs_flag|=CMI_MEMORY_IS_PARANOID;
00270 CmiArgGroup("Converse","memory-paranoid");
00271 status("Converse -memory mode: paranoid");
00272
00273 int memory_fill_value;
00274 if (CmiGetArgIntDesc(argv,"+memory_fill",&memory_fill_value, "Overwrite new and deleted memory")) {
00275 if (CmiMyRank()==0) {
00276 memory_fill = memory_fill_value;
00277 }
00278 status(" fill");
00279 }
00280 if (CmiGetArgFlagDesc(argv,"+memory_fillphase", "Invert memory overwrite pattern")) {
00281 if (CmiMyRank()==0) {
00282 memory_fillphase=1;
00283 }
00284 status(" phaseflip");
00285 }
00286
00287 int memory_checkfreq_value;
00288 if (CmiGetArgIntDesc(argv,"+memory_checkfreq",&memory_checkfreq_value, "Check heap this many mallocs")) {
00289 if (CmiMyRank()==0) {
00290 memory_checkfreq = memory_checkfreq_value;
00291 }
00292 status(" checkfreq");
00293 }
00294 if (CmiGetArgFlagDesc(argv,"+memory_verbose", "Give a printout at each heap check")) {
00295 if (CmiMyRank()==0) {
00296 memory_verbose=1;
00297 }
00298 status(" verbose");
00299 }
00300 status("\n");
00301 }
00302
00303 static void *meta_malloc(size_t size)
00304 {
00305 Slot *s=(Slot *)mm_malloc(sizeof(Slot)+size+PADLEN);
00306 if (s==NULL) return s;
00307 return setSlot(s,size);
00308 }
00309
00310 static void meta_free(void *mem)
00311 {
00312 Slot *s;
00313 if (mem==NULL) return;
00314 if (badPointer((Slot *)mem))
00315 memAbort("Free'd near-NULL block",mem);
00316
00317 s=((Slot *)mem)-1;
00318 if (s->magic==SLOTMAGIC_VALLOC)
00319 {
00320 freeSlot(s);
00321 mm_free(((char *)mem)-CmiGetPageSize());
00322 }
00323 else if (s->magic==SLOTMAGIC)
00324 {
00325 freeSlot(s);
00326 mm_free(s);
00327 }
00328 else if (s->magic==SLOTMAGIC_FREED)
00329 memAbort("Free'd block twice",mem);
00330 else
00331 memAbort("Free'd non-malloc'd block",mem);
00332 }
00333
00334 static void *meta_calloc(size_t nelem, size_t size)
00335 {
00336 void *area=meta_malloc(nelem*size);
00337 if (area != NULL) memset(area,0,nelem*size);
00338 return area;
00339 }
00340
00341 static void meta_cfree(void *mem)
00342 {
00343 meta_free(mem);
00344 }
00345
00346 static void *meta_realloc(void *oldBuffer, size_t newSize)
00347 {
00348 void *newBuffer = meta_malloc(newSize);
00349 if ( newBuffer && oldBuffer ) {
00350
00351 Slot *o=Slot_fmUser(oldBuffer);
00352 size_t size=o->userSize;
00353 if (size>newSize) size=newSize;
00354 if (size > 0)
00355 memcpy(newBuffer, oldBuffer, size);
00356 }
00357 if (oldBuffer)
00358 meta_free(oldBuffer);
00359 return newBuffer;
00360 }
00361
00362 static void *meta_memalign(size_t align, size_t size)
00363 {
00364
00365 char *alloc=(char *)mm_memalign(align,CmiGetPageSize()+size+PADLEN);
00366 Slot *s=(Slot *)(alloc+CmiGetPageSize()-sizeof(Slot));
00367 void *user=setSlot(s,size);
00368 s->magic=SLOTMAGIC_VALLOC;
00369 return user;
00370 }
00371
00372 static int meta_posix_memalign(void **outptr, size_t align, size_t size)
00373 {
00374
00375 int ret = mm_posix_memalign(outptr,align,CmiGetPageSize()+size+PADLEN);
00376 if (ret != 0)
00377 return ret;
00378 char *alloc=(char *)*outptr;
00379 Slot *s=(Slot *)(alloc+CmiGetPageSize()-sizeof(Slot));
00380 void *user=setSlot(s,size);
00381 s->magic=SLOTMAGIC_VALLOC;
00382 *outptr = user;
00383 return 0;
00384 }
00385
00386 static void *meta_aligned_alloc(size_t align, size_t size)
00387 {
00388
00389 char *alloc=(char *)mm_aligned_alloc(align,CmiGetPageSize()+size+PADLEN);
00390 Slot *s=(Slot *)(alloc+CmiGetPageSize()-sizeof(Slot));
00391 void *user=setSlot(s,size);
00392 s->magic=SLOTMAGIC_VALLOC;
00393 return user;
00394 }
00395
00396 static void *meta_valloc(size_t size)
00397 {
00398 return meta_memalign(CmiGetPageSize(),size);
00399 }
00400
00401 static void *meta_pvalloc(size_t size)
00402 {
00403 const size_t pagesize = CmiGetPageSize();
00404 return meta_memalign(pagesize, (size + pagesize - 1) & ~(pagesize - 1));
00405 }