00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "common.h"
00012 #include "obscure.h"
00013 #include "memalloc.h"
00014 #include "dlist.h"
00015
00016 static char const rcsid[] = "$Id: memalloc.c,v 1.30 2007/03/07 01:46:43 angie Exp $";
00017
00018 static void *defaultAlloc(size_t size)
00019
00020 {
00021 return malloc(size);
00022 }
00023
00024 static void defaultFree(void *vpt)
00025
00026 {
00027 free(vpt);
00028 }
00029
00030 static void *defaultRealloc(void *vpt, size_t size)
00031
00032 {
00033 return realloc(vpt, size);
00034 }
00035
00036 static struct memHandler defaultMemHandler =
00037
00038 {
00039 NULL,
00040 defaultAlloc,
00041 defaultFree,
00042 defaultRealloc,
00043 };
00044
00045 static struct memHandler *mhStack = &defaultMemHandler;
00046
00047 struct memHandler *pushMemHandler(struct memHandler *newHandler)
00048
00049
00050 {
00051 struct memHandler *oldHandler = mhStack;
00052 slAddHead(&mhStack, newHandler);
00053 return oldHandler;
00054 }
00055
00056
00057 struct memHandler *popMemHandler()
00058
00059 {
00060 struct memHandler *oldHandler = mhStack;
00061 if (mhStack == &defaultMemHandler)
00062 errAbort("Too many popMemHandlers()");
00063 mhStack = mhStack->next;
00064 return oldHandler;
00065 }
00066
00067
00068 void setDefaultMemHandler()
00069
00070 {
00071 mhStack = &defaultMemHandler;
00072 }
00073
00074
00075
00076 static size_t maxAlloc = 128*8*1024*1024*(sizeof(size_t)/4)*(sizeof(size_t)/4);
00077
00078 void setMaxAlloc(size_t s)
00079
00080 {
00081 maxAlloc = s;
00082 }
00083
00084 void *needLargeMem(size_t size)
00085
00086
00087 {
00088 void *pt;
00089 if (size == 0 || size >= maxAlloc)
00090 errAbort("needLargeMem: trying to allocate %llu bytes (limit: %llu)",
00091 (unsigned long long)size, (unsigned long long)maxAlloc);
00092 if ((pt = mhStack->alloc(size)) == NULL)
00093 errAbort("needLargeMem: Out of memory - request size %llu bytes\n",
00094 (unsigned long long)size);
00095 return pt;
00096 }
00097
00098 void *needLargeZeroedMem(size_t size)
00099
00100 {
00101 void *v;
00102 v = needLargeMem(size);
00103 memset(v, 0, size);
00104 return v;
00105 }
00106
00107 void *needLargeMemResize(void* vp, size_t size)
00108
00109
00110 {
00111 void *pt;
00112 if (size == 0 || size >= maxAlloc)
00113 errAbort("needLargeMemResize: trying to allocate %llu bytes (limit: %llu)",
00114 (unsigned long long)size, (unsigned long long)maxAlloc);
00115 if ((pt = mhStack->realloc(vp, size)) == NULL)
00116 errAbort("needLargeMemResize: Out of memory - request size %llu bytes\n",
00117 (unsigned long long)size);
00118 return pt;
00119 }
00120
00121 void *needLargeZeroedMemResize(void* vp, size_t oldSize, size_t newSize)
00122
00123
00124 {
00125 void *v = needLargeMemResize(vp, newSize);
00126 if (newSize > oldSize)
00127 memset(((char*)v)+oldSize, 0, newSize-oldSize);
00128 return v;
00129 }
00130
00131 void *needHugeMem(size_t size)
00132
00133 {
00134 void *pt;
00135 if (size == 0)
00136 errAbort("needHugeMem: trying to allocate 0 bytes");
00137 if ((pt = mhStack->alloc(size)) == NULL)
00138 errAbort("needHugeMen: Out of huge memory - request size %llu bytes\n",
00139 (unsigned long long)size);
00140 return pt;
00141 }
00142
00143
00144 void *needHugeZeroedMem(size_t size)
00145
00146 {
00147 void *v;
00148 v = needHugeMem(size);
00149 memset(v, 0, size);
00150 return v;
00151 }
00152
00153 void *needHugeMemResize(void* vp, size_t size)
00154
00155
00156
00157 {
00158 void *pt;
00159 if ((pt = mhStack->realloc(vp, size)) == NULL)
00160 errAbort("needHugeMemResize: Out of memory - request resize %llu bytes\n",
00161 (unsigned long long)size);
00162 return pt;
00163 }
00164
00165
00166 void *needHugeZeroedMemResize(void* vp, size_t oldSize, size_t newSize)
00167
00168
00169
00170 {
00171 void *v;
00172 v = needHugeMemResize(vp, newSize);
00173 if (newSize > oldSize)
00174 memset(((char*)v)+oldSize, 0, newSize-oldSize);
00175 return v;
00176 }
00177
00178 #define NEEDMEM_LIMIT 500000000
00179
00180 void *needMem(size_t size)
00181
00182
00183 {
00184 void *pt;
00185 if (size == 0 || size > NEEDMEM_LIMIT)
00186 errAbort("needMem: trying to allocate %llu bytes (limit: %llu)",
00187 (unsigned long long)size, (unsigned long long)NEEDMEM_LIMIT);
00188 if ((pt = mhStack->alloc(size)) == NULL)
00189 errAbort("needMem: Out of memory - request size %llu bytes\n",
00190 (unsigned long long)size);
00191 memset(pt, 0, size);
00192 return pt;
00193 }
00194
00195 void *needMoreMem(void *old, size_t oldSize, size_t newSize)
00196
00197
00198
00199 {
00200 return needLargeZeroedMemResize(old, oldSize, newSize);
00201 }
00202
00203 void *wantMem(size_t size)
00204
00205
00206 {
00207 return mhStack->alloc(size);
00208 }
00209
00210 void freeMem(void *pt)
00211
00212 {
00213 if (pt != NULL)
00214 mhStack->free(pt);
00215 }
00216
00217 void freez(void *vpt)
00218
00219
00220 {
00221 void **ppt = (void **)vpt;
00222 void *pt = *ppt;
00223 *ppt = NULL;
00224 freeMem(pt);
00225 }
00226
00227 static int carefulAlignSize;
00228 static int carefulAlignAdd;
00229
00230 #if __WORDSIZE == 64
00231 static bits64 carefulAlignMask;
00232 #elif __WORDSIZE == 32
00233 static bits32 carefulAlignMask;
00234 #else
00235 static bits32 carefulAlignMask;
00236 #endif
00237
00238 static struct memHandler *carefulParent;
00239
00240 static size_t carefulMaxToAlloc;
00241 static size_t carefulAlloced;
00242
00243 struct carefulMemBlock
00244
00245 {
00246 struct carefulMemBlock *next;
00247 struct carefulMemBlock *prev;
00248 int size;
00249 int startCookie;
00250 };
00251
00252 int cmbStartCookie = 0x78753421;
00253
00254 char cmbEndCookie[4] = {0x44, 0x33, 0x7F, 0x42};
00255
00256 struct dlList *cmbAllocedList;
00257
00258 static void carefulMemInit(size_t maxToAlloc)
00259
00260 {
00261 carefulMaxToAlloc = maxToAlloc;
00262 cmbAllocedList = newDlList();
00263 carefulAlignSize = sizeof(double);
00264 if (sizeof(void *) > carefulAlignSize)
00265 carefulAlignSize = sizeof(void *);
00266 if (sizeof(long) > carefulAlignSize)
00267 carefulAlignSize = sizeof(long);
00268 if (sizeof(off_t) > carefulAlignSize)
00269 carefulAlignSize = sizeof(off_t);
00270 if (sizeof(long long) > carefulAlignSize)
00271 carefulAlignSize = sizeof(long long);
00272 carefulAlignAdd = carefulAlignSize-1;
00273 carefulAlignMask = ~carefulAlignAdd;
00274 }
00275
00276
00277 static void *carefulAlloc(size_t size)
00278
00279
00280 {
00281 struct carefulMemBlock *cmb;
00282 char *pEndCookie;
00283 size_t newAlloced = size + carefulAlloced;
00284 size_t aliSize;
00285
00286 if (newAlloced > carefulMaxToAlloc)
00287 {
00288 char maxAlloc[32];
00289 char allocRequest[32];
00290 sprintLongWithCommas(maxAlloc, (long long)carefulMaxToAlloc);
00291 sprintLongWithCommas(allocRequest, (long long)newAlloced);
00292 errAbort("Allocated too much memory - more than %s bytes (%s)",
00293 maxAlloc, allocRequest);
00294 }
00295 carefulAlloced = newAlloced;
00296 aliSize = ((size + sizeof(*cmb) + 4 + carefulAlignAdd)&carefulAlignMask);
00297 cmb = carefulParent->alloc(aliSize);
00298 cmb->size = size;
00299 cmb->startCookie = cmbStartCookie;
00300 pEndCookie = (char *)(cmb+1);
00301 pEndCookie += size;
00302 memcpy(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie));
00303 dlAddHead(cmbAllocedList, (struct dlNode *)cmb);
00304 return (void *)(cmb+1);
00305 }
00306
00307 static void carefulFree(void *vpt)
00308
00309 {
00310 struct carefulMemBlock *cmb = ((struct carefulMemBlock *)vpt)-1;
00311 size_t size = cmb->size;
00312 char *pEndCookie;
00313
00314 carefulAlloced -= size;
00315 pEndCookie = (((char *)(cmb+1)) + size);
00316 if (cmb->startCookie != cmbStartCookie)
00317 errAbort("Bad start cookie %x freeing %llx\n", cmb->startCookie,
00318 ptrToLL(vpt));
00319 if (memcmp(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)) != 0)
00320 errAbort("Bad end cookie %x%x%x%x freeing %llx\n",
00321 pEndCookie[0], pEndCookie[1], pEndCookie[2], pEndCookie[3],
00322 ptrToLL(vpt));
00323 dlRemove((struct dlNode *)cmb);
00324 carefulParent->free(cmb);
00325 }
00326
00327
00328 static void *carefulRealloc(void *vpt, size_t size)
00329
00330 {
00331 unsigned char* newBlk = carefulAlloc(size);
00332 if (vpt != NULL)
00333 {
00334 struct carefulMemBlock *cmb = ((struct carefulMemBlock *)vpt)-1;
00335 memcpy(newBlk, vpt, cmb->size);
00336 carefulFree(vpt);
00337 }
00338 return newBlk;
00339 }
00340
00341
00342 void carefulCheckHeap()
00343
00344
00345 {
00346 int maxPieces = 10000000;
00347 struct carefulMemBlock *cmb;
00348 char *pEndCookie;
00349 size_t size;
00350
00351 if (carefulParent == NULL)
00352 return;
00353
00354 for (cmb = (struct carefulMemBlock *)(cmbAllocedList->head); cmb->next != NULL; cmb = cmb->next)
00355 {
00356 size = cmb->size;
00357 pEndCookie = (((char *)(cmb+1)) + size);
00358 if (cmb->startCookie != cmbStartCookie)
00359 errAbort("Bad start cookie %x checking %llx\n", cmb->startCookie,
00360 ptrToLL(cmb+1));
00361 if (memcmp(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)) != 0)
00362 errAbort("Bad end cookie %x%x%x%x checking %llx\n",
00363 pEndCookie[0], pEndCookie[1], pEndCookie[2], pEndCookie[3],
00364 ptrToLL(cmb+1));
00365 if (--maxPieces == 0)
00366 errAbort("Loop or more than 10000000 pieces in memory list");
00367 }
00368 }
00369
00370 int carefulCountBlocksAllocated()
00371
00372 {
00373 return dlCount(cmbAllocedList);
00374 }
00375
00376 long carefulTotalAllocated()
00377
00378 {
00379 return carefulAlloced;
00380 }
00381
00382 static struct memHandler carefulMemHandler =
00383
00384 {
00385 NULL,
00386 carefulAlloc,
00387 carefulFree,
00388 carefulRealloc,
00389 };
00390
00391 void pushCarefulMemHandler(size_t maxAlloc)
00392
00393
00394 {
00395 carefulMemInit(maxAlloc);
00396 carefulParent = pushMemHandler(&carefulMemHandler);
00397 }
00398
00399 struct memTracker
00400
00401 {
00402 struct memTracker *next;
00403 struct dlList *list;
00404 struct memHandler *parent;
00405 struct memHandler *handler;
00406 };
00407
00408 static struct memTracker *memTracker = NULL;
00409
00410 static void *memTrackerAlloc(size_t size)
00411
00412
00413 {
00414 struct dlNode *node;
00415
00416 size += sizeof (*node);
00417 node = memTracker->parent->alloc(size);
00418 if (node == NULL)
00419 return node;
00420 dlAddTail(memTracker->list, node);
00421 return (void*)(node+1);
00422 }
00423
00424 static void memTrackerFree(void *vpt)
00425
00426 {
00427 struct dlNode *node = vpt;
00428 node -= 1;
00429 dlRemove(node);
00430 memTracker->parent->free(node);
00431 }
00432
00433 static void *memTrackerRealloc(void *vpt, size_t size)
00434
00435 {
00436 if (vpt == NULL)
00437 return memTrackerAlloc(size);
00438 else
00439 {
00440 struct dlNode *node = ((struct dlNode *)vpt)-1;
00441 size += sizeof(*node);
00442 dlRemove(node);
00443 node = memTracker->parent->realloc(node, size);
00444 if (node == NULL)
00445 return node;
00446 dlAddTail(memTracker->list, node);
00447 return (void*)(node+1);
00448 }
00449 }
00450
00451 void memTrackerStart()
00452
00453
00454
00455
00456 {
00457 struct memTracker *mt;
00458
00459 if (memTracker != NULL)
00460 errAbort("multiple memTrackerStart calls");
00461 AllocVar(mt);
00462 AllocVar(mt->handler);
00463 mt->handler->alloc = memTrackerAlloc;
00464 mt->handler->free = memTrackerFree;
00465 mt->handler->realloc = memTrackerRealloc;
00466 mt->list = dlListNew();
00467 mt->parent = pushMemHandler(mt->handler);
00468 memTracker = mt;
00469 }
00470
00471 void memTrackerEnd()
00472
00473 {
00474 struct memTracker *mt = memTracker;
00475 if (mt == NULL)
00476 errAbort("memTrackerEnd without memTrackerStart");
00477 memTracker = NULL;
00478 popMemHandler();
00479 dlListFree(&mt->list);
00480 freeMem(mt->handler);
00481 freeMem(mt);
00482 }