windows-nt/Source/XPSP1/NT/net/qos/psched/sys/schedt.c
2020-09-26 16:20:57 +08:00

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;
}