/*++ Copyright (c) 1997 Microsoft Corporation Module Name: tracelog.c Abstract: This module implements a trace log. A trace log is a fast, in-memory, thread safe activity log useful for debugging certain classes of problems. They are especially useful when debugging reference count bugs. Author: Keith Moore (keithmo) 30-Apr-1997 Revision History: --*/ #include #include #include #include #include #include #define ALLOC_MEM(cb) (PVOID)LocalAlloc( LPTR, (cb) ) #define FREE_MEM(ptr) (VOID)LocalFree( (HLOCAL)(ptr) ) PTRACE_LOG CreateTraceLog( IN LONG LogSize, IN LONG ExtraBytesInHeader, IN LONG EntrySize ) /*++ Routine Description: Creates a new (empty) trace log buffer. Arguments: LogSize - The number of entries in the log. ExtraBytesInHeader - The number of extra bytes to include in the log header. This is useful for adding application-specific data to the log. EntrySize - The size (in bytes) of each entry. Return Value: PTRACE_LOG - Pointer to the newly created log if successful, NULL otherwise. --*/ { LONG totalSize; PTRACE_LOG log; // // Sanity check the parameters. // DBG_ASSERT( LogSize > 0 ); DBG_ASSERT( EntrySize > 0 ); DBG_ASSERT( ( EntrySize & 3 ) == 0 ); // // Allocate & initialize the log structure. // totalSize = sizeof(*log) + ( LogSize * EntrySize ) + ExtraBytesInHeader; DBG_ASSERT( totalSize > 0 ); log = (PTRACE_LOG)ALLOC_MEM( totalSize ); // // Initialize it. // if( log != NULL ) { RtlZeroMemory( log, totalSize ); log->Signature = TRACE_LOG_SIGNATURE; log->LogSize = LogSize; log->NextEntry = -1; log->EntrySize = EntrySize; log->LogBuffer = (PUCHAR)( log + 1 ) + ExtraBytesInHeader; } return log; } // CreateTraceLog VOID DestroyTraceLog( IN PTRACE_LOG Log ) /*++ Routine Description: Destroys a trace log buffer created with CreateTraceLog(). Arguments: Log - The trace log buffer to destroy. Return Value: None. --*/ { if ( Log != NULL ) { DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); Log->Signature = TRACE_LOG_SIGNATURE_X; FREE_MEM( Log ); } } // DestroyTraceLog LONG WriteTraceLog( IN PTRACE_LOG Log, IN PVOID Entry ) /*++ Routine Description: Writes a new entry to the specified trace log. Arguments: Log - The log to write to. Entry - Pointer to the data to write. This buffer is assumed to be Log->EntrySize bytes long. Return Value: Index of entry in log. This is useful for correlating the output of !inetdbg.ref to a particular point in the output debug stream --*/ { PUCHAR target; LONG index; DBG_ASSERT( Log != NULL ); DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); DBG_ASSERT( Entry != NULL ); // // Find the next slot, copy the entry to the slot. // index = InterlockedIncrement( &Log->NextEntry ) % Log->LogSize; target = Log->LogBuffer + ( index * Log->EntrySize ); RtlCopyMemory( target, Entry, Log->EntrySize ); return index; } // WriteTraceLog VOID ResetTraceLog( IN PTRACE_LOG Log ) { DBG_ASSERT( Log != NULL ); DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); RtlZeroMemory( ( Log + 1 ), Log->LogSize * Log->EntrySize ); Log->NextEntry = -1; } // ResetTraceLog