NT4/private/ntos/nthals/halalpha/perfcntr.c
2020-09-30 17:12:29 +02:00

261 lines
5.0 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992, 1993 Digital Equipment Corporation
Module Name:
perfcntr.c
Abstract:
This module implements the interfaces that access the system
performance counter and the calibrated stall. The functions implemented
in this module are suitable for uniprocessor systems only.
Author:
Jeff McLeman (mcleman) 05-June-1992
Environment:
Kernel mode
Revision History:
Rod Gamache [DEC] 9-Mar-1993
Fix profile clock.
--*/
#include "halp.h"
#include "eisa.h"
//
// Define and initialize the 64-bit count of total system cycles used
// as the performance counter.
//
ULONGLONG HalpCycleCount = 0;
LARGE_INTEGER
KeQueryPerformanceCounter (
OUT PLARGE_INTEGER Frequency OPTIONAL
)
/*++
Routine Description:
This routine returns the current performance counter value and the
performance counter frequency.
Arguments:
Frequency - Supplies an optional pointer to a variable which receives
the performance counter frequency in Hertz.
Return Value:
The current performance counter value is returned as the function
value.
--*/
{
LARGE_INTEGER LocalRpccTime;
ULONG RpccValue;
//
// Obtain the current value of the processor cycle counter and adjust
// the upper 32 bits if a roll-over occurred since the last time the
// Rpcc value was checked (at least oncce per clock interrupt). This
// code may be interrupted so we must fetch HalpRpccTimec atomically.
//
*(PULONGLONG)&LocalRpccTime = HalpCycleCount;
RpccValue = HalpRpcc();
if (RpccValue < LocalRpccTime.LowPart) {
LocalRpccTime.HighPart += 1;
}
LocalRpccTime.LowPart = RpccValue;
//
// If the frequency parameter is specified, then return the performance
// counter frequency as the current system time frequency.
//
if (ARGUMENT_PRESENT(Frequency) != FALSE) {
Frequency->LowPart = HalpClockFrequency;
Frequency->HighPart = 0;
}
//
// Return the current processor cycle counter as the function value.
//
return LocalRpccTime;
}
VOID
HalCalibratePerformanceCounter (
IN volatile PLONG Number
)
/*++
Routine Description:
This routine resets the performance counter value for the current
processor to zero. The reset is done such that the resulting value
is closely synchronized with other processors in the configuration.
Arguments:
Number - Supplies a pointer to count of the number of processors in
the configuration.
Return Value:
None.
--*/
{
//
// ****** Warning ******
//
// This is a stub routine. It should clear the current value of the
// performance counter. It is really only needed in an MP system where,
// close, but not exact synchronization of the performance counters
// are needed. See MIPS code in halfxs\mips\j4prof.c for a method of
// synchronizing.
//
return;
}
VOID
HalpCheckPerformanceCounter(
VOID
)
/*++
Routine Description:
This function is called every system clock interrupt in order to
check for wrap of the performance counter. The function must handle
a wrap if it is detected.
N.B. - This function must be called at CLOCK_LEVEL.
Arguments:
None.
Return Value:
None.
--*/
{
LARGE_INTEGER LocalRpccTime;
ULONG RpccValue;
//
// Update the low part of the performance counter directly from the
// rpcc count. Check for wrap of the rpcc count, if wrap has occurred
// then increment the high part of the performance counter.
//
LocalRpccTime.QuadPart = HalpCycleCount;
RpccValue = HalpRpcc();
if (RpccValue < LocalRpccTime.LowPart) {
LocalRpccTime.HighPart += 1;
}
LocalRpccTime.LowPart = RpccValue;
HalpCycleCount = LocalRpccTime.QuadPart;
return;
}
VOID
KeStallExecutionProcessor (
IN ULONG Microseconds
)
/*++
Routine Description:
This function stalll execution of the current processor for the specified
number of microseconds.
Arguments:
Microseconds - Supplies the number of microseconds to stall.
Return Value:
None.
--*/
{
LONG StallCyclesRemaining; // signed value
ULONG PreviousRpcc, CurrentRpcc;
//
// Get the value of the RPCC as soon as we enter
//
PreviousRpcc = HalpRpcc();
//
// Compute the number of cycles to stall
//
StallCyclesRemaining = Microseconds * HalpClockMegaHertz;
//
// Wait while there are stall cycles remaining.
// The accuracy of this routine is limited by the
// length of this while loop.
//
while (StallCyclesRemaining > 0) {
CurrentRpcc = HalpRpcc();
//
// The subtraction always works because the Rpcc
// is a wrapping long-word. If it wraps, we still
// get the positive number we want.
//
StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
//
// remember this RPCC value
//
PreviousRpcc = CurrentRpcc;
}
}