struct dgNode *dgAddNode(struct diGraph *dg, char *name, void *val) /* Create new node in graph. It's legal (but not efficient) to add * a node with the same name and value twice. It's not legal to * add a node with the same name and a different value. * You can pass in NULL for the name in which case the * hexadecimal representation of val will become the name. */ { struct dgNode *node; struct hashEl *hel; struct hash *hash = dg->nodeHash; char nbuf[17]; if (name == NULL) { sprintf(nbuf, "%p", val); name = nbuf; } hel = hashLookup(hash, name); if (hel != NULL) { node = hel->val; if (node->val != val) { errAbort("Trying to add node %s with a new value (old 0x%"PRIxMAX" new 0x%"PRIxMAX")", name, ptrToLL(node->val), ptrToLL(val)); } return node; } AllocVar(node); hel = hashAdd(hash, name, node); node->name = hel->name; node->val = val; slAddHead(&dg->nodeList, node); return node; }
void carefulCheckHeap() /* Walk through allocated memory and make sure that all cookies are * in place. */ { 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"); } }
static struct perThreadAbortVars *getThreadVars() /* Return a pointer to the perThreadAbortVars for the current pthread. */ { pthread_t pid = pthread_self(); // can be a pointer or a number // Don't safef, theoretically that could abort. char pidStr[64]; snprintf(pidStr, sizeof(pidStr), "%lld", ptrToLL(pid)); pidStr[ArraySize(pidStr)-1] = '\0'; static char pidInUse[64] = ""; // use a string since there is no known unused value for pthread_t variable if (sameString(pidStr, pidInUse)) // avoid deadlock on self { // this only happens when it has aborted already due to out of memory // which should be a rare occurrence. char *errMsg = "errAbort re-entered due to out-of-memory condition. Exiting."; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(1); } static pthread_mutex_t ptavMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock( &ptavMutex ); snprintf(pidInUse, sizeof(pidInUse), "%lld", ptrToLL(pid)); pidInUse[ArraySize(pidInUse)-1] = '\0'; static struct hash *perThreadVars = NULL; if (perThreadVars == NULL) perThreadVars = hashNew(0); struct hashEl *hel = hashLookup(perThreadVars, pidStr); if (hel == NULL) { // if it is the first time, initialization the perThreadAbortVars struct perThreadAbortVars *ptav; AllocVar(ptav); ptav->debugPushPopErr = FALSE; ptav->errAbortInProgress = FALSE; ptav->warnIx = 0; ptav->warnArray[0] = defaultVaWarn; ptav->abortIx = 0; ptav->abortArray[0] = defaultAbort; hel = hashAdd(perThreadVars, pidStr, ptav); } pidInUse[0] = '\0'; pthread_mutex_unlock( &ptavMutex ); return (struct perThreadAbortVars *)(hel->val); }
static void carefulFree(void *vpt) /* Check cookies and free. */ { 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) errAbort("Bad start cookie %x freeing %llx\n", cmb->startCookie, ptrToLL(vpt)); if (memcmp(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)) != 0) 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); }