2273480e423dca72b1251438587f1fb53cf38e6c galt Thu Jun 6 23:28:44 2013 -0700 adding mutex to make careful alloc, free, etc work with multiple pthreads, which customFactory now uses. The careful mem handler is being used in many cgis now although not hgTracks at this time. Because of the saved-session support going into cart.c, that means that practically anything that uses the cart now can be calling the multi-threaded customtrack loader. diff --git src/lib/memalloc.c src/lib/memalloc.c index 45d8567..f233819 100644 --- src/lib/memalloc.c +++ src/lib/memalloc.c @@ -1,25 +1,26 @@ /* memalloc.c - Routines to allocate and deallocate dynamic memory. * This lets you have a stack of memory handlers. The default * memory handler is a thin shell around malloc/free. You can * substitute routines that do more integrety checking with * pushCarefulMem(), or routines of your own devising with * pushMemHandler(). * * This file is copyright 2002 Jim Kent, but license is hereby * granted for all use - public, private or commercial. */ +#include <pthread.h> #include "common.h" #include "obscure.h" #include "memalloc.h" #include "dlist.h" static void *defaultAlloc(size_t size) /* Default allocator. */ { return malloc(size); } static void defaultFree(void *vpt) /* Default deallocator. */ { @@ -211,30 +212,32 @@ { if (pt != NULL) mhStack->free(pt); } void freez(void *vpt) /* Pass address of pointer. Will free pointer and set it * to NULL. */ { void **ppt = (void **)vpt; void *pt = *ppt; *ppt = NULL; freeMem(pt); } +static pthread_mutex_t carefulMutex = PTHREAD_MUTEX_INITIALIZER; + static int carefulAlignSize; /* Alignment size for machine - 8 bytes for DEC alpha, 4 for Sparc. */ static int carefulAlignAdd; /* Do aliSize = *(unaliSize+carefulAlignAdd)&carefulAlignMask); */ #if __WORDSIZE == 64 static bits64 carefulAlignMask; /* to make sure requests are aligned. */ #elif __WORDSIZE == 32 static bits32 carefulAlignMask; /* to make sure requests are aligned. */ #else static bits32 carefulAlignMask; /* to make sure requests are aligned. */ #endif static struct memHandler *carefulParent; static size_t carefulMaxToAlloc; static size_t carefulAlloced; @@ -265,129 +268,148 @@ if (sizeof(long) > carefulAlignSize) carefulAlignSize = sizeof(long); if (sizeof(off_t) > carefulAlignSize) carefulAlignSize = sizeof(off_t); if (sizeof(long long) > carefulAlignSize) carefulAlignSize = sizeof(long long); carefulAlignAdd = carefulAlignSize-1; carefulAlignMask = ~carefulAlignAdd; } static void *carefulAlloc(size_t size) /* Allocate extra memory for cookies and list node, and then * return memory block. */ { +pthread_mutex_lock( &carefulMutex ); struct carefulMemBlock *cmb; char *pEndCookie; size_t newAlloced = size + carefulAlloced; size_t aliSize; if (newAlloced > carefulMaxToAlloc) { char maxAlloc[32]; char allocRequest[32]; sprintLongWithCommas(maxAlloc, (long long)carefulMaxToAlloc); sprintLongWithCommas(allocRequest, (long long)newAlloced); + pthread_mutex_unlock( &carefulMutex ); errAbort("carefulAlloc: Allocated too much memory - more than %s bytes (%s)", maxAlloc, allocRequest); } carefulAlloced = newAlloced; aliSize = ((size + sizeof(*cmb) + 4 + carefulAlignAdd)&carefulAlignMask); cmb = carefulParent->alloc(aliSize); cmb->size = size; cmb->startCookie = cmbStartCookie; pEndCookie = (char *)(cmb+1); pEndCookie += size; memcpy(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)); dlAddHead(cmbAllocedList, (struct dlNode *)cmb); +pthread_mutex_unlock( &carefulMutex ); return (void *)(cmb+1); } static void carefulFree(void *vpt) /* Check cookies and free. */ { +pthread_mutex_lock( &carefulMutex ); struct carefulMemBlock *cmb = ((struct carefulMemBlock *)vpt)-1; size_t size = cmb->size; char *pEndCookie; carefulAlloced -= size; pEndCookie = (((char *)(cmb+1)) + size); if (cmb->startCookie != cmbStartCookie) + { + pthread_mutex_unlock( &carefulMutex ); errAbort("Bad start cookie %x freeing %llx\n", cmb->startCookie, ptrToLL(vpt)); + } if (memcmp(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)) != 0) + { + pthread_mutex_unlock( &carefulMutex ); errAbort("Bad end cookie %x%x%x%x freeing %llx\n", pEndCookie[0], pEndCookie[1], pEndCookie[2], pEndCookie[3], ptrToLL(vpt)); + } dlRemove((struct dlNode *)cmb); carefulParent->free(cmb); +pthread_mutex_unlock( &carefulMutex ); } static void *carefulRealloc(void *vpt, size_t size) /* realloc a careful memblock block. */ { unsigned char* newBlk = carefulAlloc(size); if (vpt != NULL) { struct carefulMemBlock *cmb = ((struct carefulMemBlock *)vpt)-1; memcpy(newBlk, vpt, cmb->size); carefulFree(vpt); } return newBlk; } void carefulCheckHeap() /* Walk through allocated memory and make sure that all cookies are * in place. */ { +pthread_mutex_lock( &carefulMutex ); int maxPieces = 10000000; /* Assume no more than this many pieces allocated. */ struct carefulMemBlock *cmb; char *pEndCookie; size_t size; if (carefulParent == NULL) return; for (cmb = (struct carefulMemBlock *)(cmbAllocedList->head); cmb->next != NULL; cmb = cmb->next) { size = cmb->size; pEndCookie = (((char *)(cmb+1)) + size); if (cmb->startCookie != cmbStartCookie) errAbort("Bad start cookie %x checking %llx\n", cmb->startCookie, ptrToLL(cmb+1)); if (memcmp(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)) != 0) errAbort("Bad end cookie %x%x%x%x checking %llx\n", pEndCookie[0], pEndCookie[1], pEndCookie[2], pEndCookie[3], ptrToLL(cmb+1)); if (--maxPieces == 0) errAbort("Loop or more than 10000000 pieces in memory list"); } +pthread_mutex_unlock( &carefulMutex ); } int carefulCountBlocksAllocated() /* How many memory items are allocated? */ { -return dlCount(cmbAllocedList); +pthread_mutex_lock( &carefulMutex ); +int result = dlCount(cmbAllocedList); +pthread_mutex_unlock( &carefulMutex ); +return result; } -long carefulTotalAllocated() +size_t carefulTotalAllocated() /* Return total bases allocated */ { -return carefulAlloced; +pthread_mutex_lock( &carefulMutex ); +size_t result = carefulAlloced; +pthread_mutex_unlock( &carefulMutex ); +return result; } static struct memHandler carefulMemHandler = /* Default memory handler. */ { NULL, carefulAlloc, carefulFree, carefulRealloc, }; void pushCarefulMemHandler(size_t maxAlloc) /* Push the careful (paranoid, conservative, checks everything) * memory handler top of the memHandler stack and use it. */ {