windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/i64perfc.c
2020-09-26 16:20:57 +08:00

192 lines
3.3 KiB
C
Raw Permalink 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) 1995 Intel Corporation
Module Name:
i64perfc.c copied from simperfc.c
Abstract:
This module implements the routines to support performance counters.
Author:
14-Apr-1995
Environment:
Kernel mode
Revision History:
--*/
#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;
BOOLEAN HalpITCCalibrate = TRUE; // XXTF
extern ULONGLONG HalpITCFrequency;
extern ULONGLONG HalpClockCount;
#if 0
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 was from the Alpha HAL.
This function must be called at CLOCK_LEVEL.
Arguments:
None.
Return Value:
None.
{
return;
} // HalpCheckPerformanceCounter()
#endif // 0
LARGE_INTEGER
KeQueryPerformanceCounter (
OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
)
/*++
Routine Description:
This routine returns current 64-bit performance counter and,
optionally, the Performance Frequency.
Arguments:
PerformanceFrequency - optionally, supplies the address
of a variable to receive the performance counter frequency.
Return Value:
Current value of the performance counter will be returned.
--*/
{
LARGE_INTEGER result;
#ifndef DISABLE_ITC_WORKAROUND
result.QuadPart = __getReg(CV_IA64_ApITC);
while ((result.QuadPart & 0xFFFFFFFF) == 0xFFFFFFFF) {
result.QuadPart = __getReg(CV_IA64_ApITC);
}
#else
result.QuadPart = __getReg(CV_IA64_ApITC);
#endif
if (ARGUMENT_PRESENT(PerformanceFrequency)) {
PerformanceFrequency->QuadPart = HalpITCFrequency;
}
return result;
} // KeQueryPerformanceCounter()
VOID
HalCalibratePerformanceCounter (
IN LONG volatile *Number,
IN ULONGLONG NewCount
)
/*++
Routine Description:
This routine sets the performance counter value for the current
processor to the specified valueo.
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.
--*/
{
KSPIN_LOCK Lock;
KIRQL OldIrql;
if ( HalpITCCalibrate ) {
//
// Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
// wait until the number is zero.
//
KeInitializeSpinLock(&Lock);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
PCR->HalReserved[CURRENT_ITM_VALUE_INDEX] = NewCount + HalpClockCount;
HalpWriteITM( PCR->HalReserved[CURRENT_ITM_VALUE_INDEX] );
if (ExInterlockedDecrementLong((PLONG)Number, &Lock) != RESULT_ZERO) {
do {
} while (*((LONG volatile *)Number) !=0);
}
//
// Write the compare register with defined current ITM value,
// and set the performance counter for the current processor
// with the passed count.
//
HalpWriteITC( NewCount );
//
// Restore IRQL to its previous value and return.
//
KeLowerIrql(OldIrql);
}
else {
*Number = 0;
}
return;
} // HalCalibratePerformanceCounter()