392 lines
9.2 KiB
C
392 lines
9.2 KiB
C
/*++
|
|
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;
|
|
}
|
|
|