/* * Sets a callback function to be used to output * trace statements. */ void DTrace_SetOutputCallback(DTRACE_OUTPUT_CALLBACK pfn) { DASSERT(pfn != NULL); DMutex_Enter(DTraceMutex); PfnTraceCallback = pfn; DMutex_Exit(DTraceMutex); }
static void DTrace_JavaPrint(const char * msg) { #if defined(DEBUG) DMutex_Enter(DTraceMutex); DTrace_ClientPrint(msg); DMutex_Exit(DTraceMutex); #else DTrace_PrintStdErr(msg); #endif }
/* * Enable tracing for a specific line in a specific module. * See comments above regarding filename argument. */ void DTrace_EnableLine(const char * file, int line, dbool_t enabled) { dtrace_id tid; p_dtrace_info info; DASSERT(file != NULL && (line > 0 && line < MAX_LINE)); DMutex_Enter(DTraceMutex); tid = DTrace_GetTraceId(file, line, DTRACE_LINE); info = DTrace_GetInfo(tid); info->enabled = enabled; DMutex_Exit(DTraceMutex); }
/* * Enable tracing for a specific module. Filename may * be fully or partially qualified. * e.g. awt_Component.cpp * or * src\win32\native\sun\windows\awt_Component.cpp */ void DTrace_EnableFile(const char * file, dbool_t enabled) { dtrace_id tid; p_dtrace_info info; DASSERT(file != NULL); DMutex_Enter(DTraceMutex); tid = DTrace_GetTraceId(file, -1, DTRACE_FILE); info = DTrace_GetInfo(tid); info->enabled = enabled; DMutex_Exit(DTraceMutex); }
/* * Should be called before any other DMem_XXX function */ void DMem_Initialize() { DMemMutex = DMutex_Create(); DMutex_Enter(DMemMutex); DMemGlobalState.pfnAlloc = NULL; DMemGlobalState.pfnFree = NULL; DMemGlobalState.pfnCheckPtr = NULL; DMemGlobalState.biggestBlock = 0; DMemGlobalState.maxHeap = INT_MAX; DMemGlobalState.totalHeapUsed = 0; DMemGlobalState.failNextAlloc = FALSE; DMemGlobalState.totalAllocs = 0; DMutex_Exit(DMemMutex); }
/* * Allocates a block of memory, reserving extra space at the start and end of the * block to store debug info on where the block was allocated, it's size, and * 'guard' areas to catch overwrite/underwrite bugs */ void * DMem_AllocateBlock(size_t size, const char * filename, int linenumber) { MemoryBlockHeader * header; MemoryBlockTail * tail; size_t debugBlockSize; byte_t * memptr = NULL; DMutex_Enter(DMemMutex); if (DMemGlobalState.failNextAlloc) { /* force an allocation failure if so ordered */ DMemGlobalState.failNextAlloc = FALSE; /* reset flag */ goto Exit; } /* allocate a block large enough to hold extra debug info */ debugBlockSize = sizeof(MemoryBlockHeader) + size + sizeof(MemoryBlockTail); header = (MemoryBlockHeader *)DMem_ClientAllocate(debugBlockSize); if (header == NULL) { goto Exit; } /* add block to list of allocated memory */ header->listEnter = DMem_TrackBlock(header); if ( header->listEnter == NULL ) { goto Exit; } /* store size of requested block */ header->size = size; /* update maximum block size */ DMemGlobalState.biggestBlock = DMEM_MAX(header->size, DMemGlobalState.biggestBlock); /* update used memory total */ DMemGlobalState.totalHeapUsed += header->size; /* store filename and linenumber where allocation routine was called */ strncpy(header->filename, filename, FILENAME_MAX); header->linenumber = linenumber; /* store the order the block was allocated in */ header->order = DMemGlobalState.totalAllocs++; /* initialize memory to a recognizable 'inited' value */ memptr = (byte_t *)header + sizeof(MemoryBlockHeader); memset(memptr, ByteInited, size); /* put guard area before block */ memset(header->guard, ByteGuard, MAX_GUARD_BYTES); /* put guard area after block */ tail = (MemoryBlockTail *)(memptr + size); memset(tail->guard, ByteGuard, MAX_GUARD_BYTES); Exit: DMutex_Exit(DMemMutex); return memptr; }
/* * Called via DTRACE_ macros. If tracing is enabled at the given location, it enters * the trace mutex and invokes the callback function to output the trace. */ void DTrace_PrintFunction( DTRACE_PRINT_CALLBACK pfn, dtrace_id * pFileTraceId, dtrace_id * pLineTraceId, const char * file, int line, int argc, const char * fmt, ... ) { va_list arglist; DASSERT(file != NULL); DASSERT(line > 0 && line < MAX_LINE); DASSERT(argc <= MAX_ARGC); DASSERT(fmt != NULL); DMutex_Enter(DTraceMutex); if ( DTrace_IsEnabledAt(pFileTraceId, pLineTraceId, file, line) ) { va_start(arglist, fmt); (*pfn)(file, line, argc, fmt, arglist); va_end(arglist); } DMutex_Exit(DTraceMutex); }
/* * Frees block of memory allocated with DMem_AllocateBlock */ void DMem_FreeBlock(void * memptr) { MemoryBlockHeader * header; DMutex_Enter(DMemMutex); if ( memptr == NULL) { goto Exit; } /* get the debug block header preceding the allocated memory */ header = DMem_GetHeader(memptr); /* fill memory with recognizable 'freed' value */ memset(memptr, ByteFreed, header->size); /* mark block as freed */ header->listEnter->freed = TRUE; /* update used memory total */ DMemGlobalState.totalHeapUsed -= header->size; Exit: DMutex_Exit(DMemMutex); }
/* * Call this function at shutdown time to report any leaked blocks */ void DMem_ReportLeaks() { MemoryListLink * link; DMutex_Enter(DMemMutex); /* Force memory leaks to be output regardless of trace settings */ DTrace_EnableFile(THIS_FILE, TRUE); DTRACE_PRINTLN("--------------------------"); DTRACE_PRINTLN("Debug Memory Manager Leaks"); DTRACE_PRINTLN("--------------------------"); /* walk through allocated list and dump any blocks not marked as freed */ link = MemoryList.next; while (link != NULL) { if ( !link->freed ) { DMem_DumpHeader(link->header); } link = link->next; } DMutex_Exit(DMemMutex); }
/* * Enable tracing for all modules. */ void DTrace_EnableAll(dbool_t enabled) { DMutex_Enter(DTraceMutex); GlobalTracingEnabled = enabled; DMutex_Exit(DTraceMutex); }
void DMem_SetCheckPtrCallback( DMEM_CHECKPTRFN pfn ) { DMutex_Enter(DMemMutex); DMemGlobalState.pfnCheckPtr = pfn; DMutex_Exit(DMemMutex); }
void DMem_SetFreeCallback( DMEM_FREEFN pfn ) { DMutex_Enter(DMemMutex); DMemGlobalState.pfnFree = pfn; DMutex_Exit(DMemMutex); }
void DMem_SetAllocCallback( DMEM_ALLOCFN pfn ) { DMutex_Enter(DMemMutex); DMemGlobalState.pfnAlloc = pfn; DMutex_Exit(DMemMutex); }