00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #if ! CMK_MEMORY_BUILD_OS
00019
00020 #include "memory-gnuold.c"
00021 #endif
00022
00023
00024 typedef struct Slot Slot;
00025
00026
00027
00028
00029 struct Slot {
00030
00031 Slot *next;
00032 Slot *prev;
00033
00034
00035 int userSize;
00036
00037
00038 #define SLOTMAGIC 0x8402a5f5
00039 #define SLOTMAGIC_VALLOC 0x7402a5f5
00040 #define SLOTMAGIC_FREED 0xDEADBEEF
00041 int magic;
00042
00043
00044 #define STACK_LEN 8
00045 void *from[STACK_LEN];
00046 };
00047
00048
00049 static char *Slot_toUser(Slot *s) {
00050 return ((char *)s)+sizeof(Slot);
00051 }
00052
00053
00054 static Slot *Slot_fmUser(void *user) {
00055 char *cu=(char *)user;
00056 Slot *s=(Slot *)(cu-sizeof(Slot));
00057 return s;
00058 }
00059
00060 static void printSlot(Slot *s) {
00061 CmiPrintf("[%d] Leaked block of %d bytes at %p:\n",
00062 CmiMyPe(), s->userSize, Slot_toUser(s));
00063 CmiBacktracePrint(s->from,STACK_LEN);
00064 }
00065
00066
00067
00068
00069 Slot slot_first_storage={&slot_first_storage,&slot_first_storage};
00070 Slot *slot_first=&slot_first_storage;
00071
00072 #define CMI_MEMORY_ROUTINES 1
00073
00074
00075 void CmiMemoryMark(void) {
00076 CmiMemLock();
00077
00078 slot_first=(Slot *)mm_malloc(sizeof(Slot));
00079 slot_first->next=slot_first->prev=slot_first;
00080 CmiMemUnlock();
00081 }
00082
00083
00084 void CmiMemoryMarkBlock(void *blk) {
00085 Slot *s=Slot_fmUser(blk);
00086 CmiMemLock();
00087 if (s->magic!=SLOTMAGIC) CmiAbort("CmiMemoryMarkBlock called on non-malloc'd block!\n");
00088
00089 s->next->prev=s->prev;
00090 s->prev->next=s->next;
00091 s->prev=s->next=s;
00092 CmiMemUnlock();
00093 }
00094
00095
00096 void CmiMemorySweep(const char *where)
00097 {
00098 Slot *cur;
00099 int nBlocks=0,nBytes=0;
00100 CmiMemLock();
00101 cur=slot_first->next;
00102 CmiPrintf("[%d] ------- LEAK CHECK: %s -----\n",CmiMyPe(), where);
00103 while (cur!=slot_first) {
00104 printSlot(cur);
00105 nBlocks++; nBytes+=cur->userSize;
00106 cur=cur->next;
00107 }
00108 if (nBlocks) {
00109 CmiPrintf("[%d] Total leaked memory: %d blocks, %d bytes\n",
00110 CmiMyPe(),nBlocks,nBytes);
00111
00112 }
00113 CmiMemUnlock();
00114 CmiMemoryMark();
00115 }
00116 void CmiMemoryCheck(void) {}
00117
00118
00119
00120 static int memoryTraceDisabled = 0;
00121
00122
00123 static void *setSlot(Slot *s,int userSize) {
00124 char *user=Slot_toUser(s);
00125
00126
00127 s->next=slot_first->next;
00128 s->prev=slot_first;
00129 s->next->prev=s;
00130 s->prev->next=s;
00131
00132 s->magic=SLOTMAGIC;
00133 s->userSize=userSize;
00134 {
00135 int n=STACK_LEN;
00136 if (memoryTraceDisabled==0) {
00137 memoryTraceDisabled = 1;
00138 CmiBacktraceRecord(s->from,3,&n);
00139 memoryTraceDisabled = 0;
00140 } else {
00141 s->from[0] = (void*)10;
00142 s->from[1] = (void*)9;
00143 s->from[2] = (void*)8;
00144 s->from[3] = (void*)7;
00145 }
00146 }
00147 return (void *)user;
00148 }
00149
00150
00151 static void freeSlot(Slot *s) {
00152
00153 s->next->prev=s->prev;
00154 s->prev->next=s->next;
00155 s->prev=s->next=(Slot *)0x0F00;
00156
00157 s->magic=SLOTMAGIC_FREED;
00158 s->userSize=-1;
00159 }
00160
00161
00162
00163
00164
00165 static int meta_getpagesize(void)
00166 {
00167 static int cache=0;
00168 #if defined(CMK_GETPAGESIZE_AVAILABLE)
00169 if (cache==0) cache=getpagesize();
00170 #else
00171 if (cache==0) cache=8192;
00172 #endif
00173 return cache;
00174 }
00175
00176
00177 static void status(char *msg) {
00178 if (CmiMyPe()==0 && !CmiArgGivingUsage()) {
00179 CmiPrintf("%s",msg);
00180 }
00181 }
00182 static void meta_init(char **argv)
00183 {
00184 status("Converse -memory mode: leak");
00185 status("\n");
00186 }
00187
00188 static void *meta_malloc(size_t size)
00189 {
00190 Slot *s=(Slot *)mm_malloc(sizeof(Slot)+size);
00191 if (s==NULL) return s;
00192 return setSlot(s,size);
00193 }
00194
00195 static void meta_free(void *mem)
00196 {
00197 Slot *s;
00198 if (mem==NULL) return;
00199
00200 s=((Slot *)mem)-1;
00201 if (s->magic==SLOTMAGIC_VALLOC)
00202 {
00203 freeSlot(s);
00204 mm_free(((char *)mem)-meta_getpagesize());
00205 }
00206 else if (s->magic==SLOTMAGIC)
00207 {
00208 freeSlot(s);
00209 mm_free(s);
00210 }
00211 else if (s->magic==SLOTMAGIC_FREED)
00212 CmiAbort("Free'd block twice");
00213 else
00214 CmiAbort("Free'd non-malloc'd block");
00215 }
00216
00217 static void *meta_calloc(size_t nelem, size_t size)
00218 {
00219 void *area=meta_malloc(nelem*size);
00220 if (area != NULL) memset(area,0,nelem*size);
00221 return area;
00222 }
00223
00224 static void meta_cfree(void *mem)
00225 {
00226 meta_free(mem);
00227 }
00228
00229 static void *meta_realloc(void *oldBuffer, size_t newSize)
00230 {
00231 void *newBuffer = meta_malloc(newSize);
00232 if ( newBuffer && oldBuffer ) {
00233
00234 Slot *o=Slot_fmUser(oldBuffer);
00235 size_t size=o->userSize;
00236 if (size>newSize) size=newSize;
00237 if (size > 0)
00238 memcpy(newBuffer, oldBuffer, size);
00239 }
00240 if (oldBuffer)
00241 meta_free(oldBuffer);
00242 return newBuffer;
00243 }
00244
00245 static void *meta_memalign(size_t align, size_t size)
00246 {
00247
00248 char *alloc=(char *)mm_memalign(align,meta_getpagesize()+size);
00249 Slot *s=(Slot *)(alloc+meta_getpagesize()-sizeof(Slot));
00250 void *user=setSlot(s,size);
00251 s->magic=SLOTMAGIC_VALLOC;
00252 return user;
00253 }
00254 static void *meta_valloc(size_t size)
00255 {
00256 return meta_memalign(meta_getpagesize(),size);
00257 }