|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
schedt.c
Abstract: Psched Tracing support
Author: Rajesh Sundaram (rajeshsu) 01-Aug-1998.
Environment:
Kernel Mode
Revision History:
--*/ #include "psched.h"
#pragma hdrstop
//
// Globals
//
NDIS_SPIN_LOCK GlobalLoggingLock; ULONG SchedTraceIndex; ULONG SchedBufferSize; ULONG SchedTraced; UCHAR *SchedTraceBuffer; ULONG SchedBufferStart; ULONG SchedTraceBytesUnread; ULONG SchedTraceThreshold; PVOID SchedTraceThreshContext; SCHEDTRACE_THRESH_PROC SchedTraceThreshProc; BOOLEAN TraceBufferAllocated;
VOID SchedInitialize( ULONG BufferSize) {
SchedBufferSize = BufferSize;
TraceBufferAllocated = FALSE;
PsAllocatePool(SchedTraceBuffer, SchedBufferSize, PsMiscTag);
if(SchedTraceBuffer){
TraceBufferAllocated = TRUE; NdisAllocateSpinLock(&GlobalLoggingLock); } else { TraceBufferAllocated = FALSE; } }
VOID SchedDeInitialize( ) { if(TraceBufferAllocated) { PsFreePool(SchedTraceBuffer); TraceBufferAllocated = FALSE; } NdisFreeSpinLock(&GlobalLoggingLock); }
VOID DbugTraceSetThreshold( ULONG Threshold, PVOID Context, SCHEDTRACE_THRESH_PROC ThreshProc) { ULONG bytesToCopyAtEnd; ULONG bytesToCopyAtStart;
NdisAcquireSpinLock(&GlobalLoggingLock);
SchedTraceThreshProc = ThreshProc; SchedTraceThreshold = (Threshold <= SchedBufferSize) ? Threshold : SchedBufferSize; SchedTraceThreshContext = Context;
if ((SchedTraceThreshContext != NULL) && (SchedTraceBytesUnread >= SchedTraceThreshold)) { SchedTraceThreshContext = NULL; NdisReleaseSpinLock(&GlobalLoggingLock); (*ThreshProc)(Context); } else { NdisReleaseSpinLock(&GlobalLoggingLock); } }
VOID DbugReadTraceBuffer( PUCHAR Buffer, ULONG BytesToRead, PULONG BytesRead ) { ULONG bytesToCopyAtEnd; ULONG bytesToCopyAtStart; ULONG bytesToCopy; ULONG startIndex;
// Copy the most recently added bytes to the user buffer. If BytesToRead is less than
// the number of unread bytes in the trace buffer, the older bytes are lost. This
// ensures that the last record in the user buffer is complete (as long as the user
// buffer is big enough to accommodate at least that one record).
NdisAcquireSpinLock(&GlobalLoggingLock);
bytesToCopy = (SchedTraceBytesUnread <= BytesToRead) ? SchedTraceBytesUnread : BytesToRead; startIndex = (bytesToCopy > SchedTraceIndex) ? SchedTraceIndex + SchedBufferSize - bytesToCopy : SchedTraceIndex - bytesToCopy;
if ((startIndex + bytesToCopy) > SchedBufferSize) { bytesToCopyAtEnd = SchedBufferSize - startIndex; bytesToCopyAtStart = bytesToCopy - bytesToCopyAtEnd; RtlCopyMemory(Buffer, &SchedTraceBuffer[startIndex], bytesToCopyAtEnd); RtlCopyMemory(Buffer + bytesToCopyAtEnd, &SchedTraceBuffer[0], bytesToCopyAtStart); } else { bytesToCopyAtEnd = bytesToCopy; RtlCopyMemory(Buffer, &SchedTraceBuffer[startIndex], bytesToCopy); }
SchedTraceBytesUnread = 0; *BytesRead = bytesToCopy; NdisReleaseSpinLock(&GlobalLoggingLock);
}
NTSTATUS WriteRecord( UCHAR * Record, ULONG Bytes ) { ULONG bytesToCopyAtEnd; ULONG bytesToCopyAtStart; SCHEDTRACE_THRESH_PROC ThreshProc; PVOID Context;
if(!TraceBufferAllocated){
return(STATUS_UNSUCCESSFUL); }
NdisAcquireSpinLock(&GlobalLoggingLock);
if((SchedTraceIndex + Bytes) > SchedBufferSize){ bytesToCopyAtEnd = SchedBufferSize - SchedTraceIndex; bytesToCopyAtStart = Bytes - bytesToCopyAtEnd; RtlCopyMemory(&SchedTraceBuffer[SchedTraceIndex], Record, bytesToCopyAtEnd); RtlCopyMemory(&SchedTraceBuffer[0], (UCHAR *)Record + bytesToCopyAtEnd, bytesToCopyAtStart); SchedTraceIndex = bytesToCopyAtStart; SchedTraced += Bytes; } else{ bytesToCopyAtEnd = Bytes; RtlCopyMemory(&SchedTraceBuffer[SchedTraceIndex], Record, Bytes); SchedTraceIndex += Bytes; SchedTraced += Bytes; }
SchedTraceBytesUnread += Bytes; if (SchedTraceBytesUnread > SchedBufferSize) { SchedTraceBytesUnread = SchedBufferSize; }
if ((SchedTraceThreshContext != NULL) && (SchedTraceBytesUnread >= SchedTraceThreshold)) { ThreshProc = SchedTraceThreshProc; Context = SchedTraceThreshContext; SchedTraceThreshContext = NULL; NdisReleaseSpinLock(&GlobalLoggingLock); (*ThreshProc)(Context); } else { NdisReleaseSpinLock(&GlobalLoggingLock); } return(STATUS_SUCCESS); }
#define ClearRecord(x, y) \
RtlFillMemory(x, y, 0)
VOID DbugSchedString(char *format, ...) { TRACE_RECORD_STRING record; CHAR buffer[TRACE_STRING_LENGTH]; va_list va;
va_start(va, format); _vsnprintf(buffer, TRACE_STRING_LENGTH-1, format, va); va_end(va);
ClearRecord(&record, sizeof(TRACE_RECORD_STRING));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_TSTRING; PsGetCurrentTime(&record.Now); strncpy(record.StringStart, buffer, TRACE_STRING_LENGTH);
WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_STRING)); return; }
VOID DbugRecv( ULONG Event, ULONG Action, PVOID Adapter, PNDIS_PACKET Packet1, PNDIS_PACKET Packet2 ) { TRACE_RECORD_RECV record;
ClearRecord(&record, sizeof(TRACE_RECORD_RECV));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_RECV; PsGetCurrentTime(&record.Now); record.Event = Event; record.Action = Action; record.Adapter = Adapter; record.Packet1 = Packet1; record.Packet2 = Packet2;
WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_RECV)); }
VOID DbugSend( ULONG Event, ULONG Action, PVOID Adapter, PVOID Vc, PNDIS_PACKET Packet1, PNDIS_PACKET Packet2 ) { TRACE_RECORD_SEND record;
ClearRecord(&record, sizeof(TRACE_RECORD_SEND));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_SEND; PsGetCurrentTime(&record.Now); record.Event = Event; record.Action = Action; record.Adapter = Adapter; record.Vc = Vc; record.Packet1 = Packet1; record.Packet2 = Packet2;
WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_SEND)); }
VOID DbugOid( ULONG Action, ULONG Local, ULONG PTState, ULONG MPState, PVOID Adapter, ULONG Oid, ULONG Status ) { TRACE_RECORD_OID record;
ClearRecord(&record, sizeof(TRACE_RECORD_OID));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_OID; PsGetCurrentTime(&record.Now); record.Action = Action; record.Local = Local; record.Oid = Oid; record.PTState = PTState; record.MPState = MPState; record.Adapter = Adapter; record.Status = Status;
WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_OID)); }
VOID DbugSchedPkts( ULONG CallingFunction, PVOID VC, PNDIS_PACKET Packet, ULONG Action, ULONG PacketLength) { TRACE_RECORD_PKT record;
ClearRecord(&record, sizeof(TRACE_RECORD_PKT));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_PKT; record.CallingFunction = CallingFunction; PsGetCurrentTime(&record.Now); record.VC = VC; record.Packet = Packet; record.Action = Action; record.PacketLength = PacketLength; WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_PKT)); }
VOID DbugSched( ULONG SchedulerComponent, ULONG Action, PVOID VC, PNDIS_PACKET Packet, ULONG PacketLength, ULONG Priority, LONGLONG ArrivalTime, LONGLONG ConformanceTime, ULONG PacketsInComponent, ULONG BytesInComponent ) { TRACE_RECORD_SCHED record;
ClearRecord(&record, sizeof(TRACE_RECORD_SCHED));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_SCHED; record.SchedulerComponent = SchedulerComponent; PsGetCurrentTime(&record.Now); record.Action = Action; record.VC = VC; record.Packet = Packet; record.PacketLength = PacketLength; record.Priority = Priority; record.ArrivalTime = ArrivalTime, record.ConformanceTime = ConformanceTime; record.PacketsInComponent = PacketsInComponent; record.BytesInComponent = BytesInComponent; WriteRecord((UCHAR *)&record, sizeof(TRACE_RECORD_SCHED)); }
VOID DbugComponentSpecificRec( ULONG Component, PVOID Data, ULONG Length) { TRACE_RECORD_COMPONENT_SPECIFIC record;
ClearRecord(&record, sizeof(TRACE_RECORD_COMPONENT_SPECIFIC));
record.Preamble = TRACE_PREAMBLE; record.RecordType = RECORD_COMPONENT_SPECIFIC; record.SchedulerComponent = Component; PsGetCurrentTime(&record.Now); record.Length = (Length > MAX_RECORD_DATA) ? MAX_RECORD_DATA : Length; RtlCopyMemory(record.Data, Data, record.Length); WriteRecord((UCHAR *)&record, record.Length + FIELD_OFFSET(TRACE_RECORD_COMPONENT_SPECIFIC, Data)); }
ULONG SchedtGetBufferSize() { return SchedBufferSize; }
ULONG SchedtGetBytesUnread() { return SchedTraceBytesUnread; }
|