mirror of
https://github.com/8damon/Blackbird-Platform
synced 2026-06-21 13:41:12 +00:00
117 lines
3.3 KiB
C
117 lines
3.3 KiB
C
#include "tempus_debug.h"
|
|
|
|
#ifdef BK_TEMPUS_DEBUG
|
|
|
|
typedef struct _BK_TEMPUS_BUCKET_STATE
|
|
{
|
|
volatile LONG64 SampleCount;
|
|
volatile LONG64 TotalQpc;
|
|
volatile LONG64 MaxQpc;
|
|
volatile LONG64 LastQpc;
|
|
} BK_TEMPUS_BUCKET_STATE;
|
|
|
|
static volatile LONG g_BlackbirdTempusEnabled = 0;
|
|
static UINT64 g_BlackbirdTempusQpcFrequency = 0;
|
|
static BK_TEMPUS_BUCKET_STATE g_BlackbirdTempusBuckets[BK_TEMPUS_SUBSYSTEM_COUNT];
|
|
|
|
static VOID BktmpUpdateMax(_Inout_ volatile LONG64 *Target, _In_ LONG64 Candidate)
|
|
{
|
|
LONG64 observed;
|
|
|
|
do
|
|
{
|
|
observed = InterlockedCompareExchange64(Target, 0, 0);
|
|
if (Candidate <= observed)
|
|
{
|
|
return;
|
|
}
|
|
} while (InterlockedCompareExchange64(Target, Candidate, observed) != observed);
|
|
}
|
|
|
|
NTSTATUS BktmpInitialize(VOID)
|
|
{
|
|
LARGE_INTEGER counter;
|
|
|
|
counter = KeQueryPerformanceCounter(NULL);
|
|
g_BlackbirdTempusQpcFrequency = (counter.QuadPart > 0) ? (UINT64)counter.QuadPart : 1ULL;
|
|
RtlZeroMemory(g_BlackbirdTempusBuckets, sizeof(g_BlackbirdTempusBuckets));
|
|
InterlockedExchange(&g_BlackbirdTempusEnabled, 1);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID BktmpUninitialize(VOID)
|
|
{
|
|
InterlockedExchange(&g_BlackbirdTempusEnabled, 0);
|
|
}
|
|
|
|
BOOLEAN BktmpIsEnabled(VOID)
|
|
{
|
|
return (InterlockedCompareExchange(&g_BlackbirdTempusEnabled, 0, 0) != 0);
|
|
}
|
|
|
|
UINT64 BktmpGetQpcFrequency(VOID)
|
|
{
|
|
return g_BlackbirdTempusQpcFrequency;
|
|
}
|
|
|
|
ULONGLONG BktmpEnter(_In_ UINT32 SubsystemId)
|
|
{
|
|
UNREFERENCED_PARAMETER(SubsystemId);
|
|
|
|
if (!BktmpIsEnabled())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart;
|
|
}
|
|
|
|
VOID BktmpLeave(_In_ UINT32 SubsystemId, _In_ ULONGLONG StartQpc)
|
|
{
|
|
ULONGLONG endQpc;
|
|
ULONGLONG elapsedQpc;
|
|
|
|
if (!BktmpIsEnabled() || StartQpc == 0 || SubsystemId >= BK_TEMPUS_SUBSYSTEM_COUNT)
|
|
{
|
|
return;
|
|
}
|
|
|
|
endQpc = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart;
|
|
elapsedQpc = (endQpc >= StartQpc) ? (endQpc - StartQpc) : 0ULL;
|
|
|
|
InterlockedIncrement64(&g_BlackbirdTempusBuckets[SubsystemId].SampleCount);
|
|
InterlockedAdd64(&g_BlackbirdTempusBuckets[SubsystemId].TotalQpc, (LONG64)elapsedQpc);
|
|
InterlockedExchange64(&g_BlackbirdTempusBuckets[SubsystemId].LastQpc, (LONG64)elapsedQpc);
|
|
BktmpUpdateMax(&g_BlackbirdTempusBuckets[SubsystemId].MaxQpc, (LONG64)elapsedQpc);
|
|
}
|
|
|
|
VOID BktmpQueryStats(_Out_writes_(BucketCount) PBK_TEMPUS_BUCKET Buckets, _In_ UINT32 BucketCount,
|
|
_Out_opt_ UINT64 *QpcFrequency)
|
|
{
|
|
UINT32 i;
|
|
UINT32 safeCount;
|
|
|
|
if (Buckets == NULL || BucketCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
safeCount = (BucketCount < BK_TEMPUS_SUBSYSTEM_COUNT) ? BucketCount : BK_TEMPUS_SUBSYSTEM_COUNT;
|
|
RtlZeroMemory(Buckets, sizeof(*Buckets) * BucketCount);
|
|
|
|
for (i = 0; i < safeCount; ++i)
|
|
{
|
|
Buckets[i].SampleCount = (UINT64)InterlockedCompareExchange64(&g_BlackbirdTempusBuckets[i].SampleCount, 0, 0);
|
|
Buckets[i].TotalQpc = (UINT64)InterlockedCompareExchange64(&g_BlackbirdTempusBuckets[i].TotalQpc, 0, 0);
|
|
Buckets[i].MaxQpc = (UINT64)InterlockedCompareExchange64(&g_BlackbirdTempusBuckets[i].MaxQpc, 0, 0);
|
|
Buckets[i].LastQpc = (UINT64)InterlockedCompareExchange64(&g_BlackbirdTempusBuckets[i].LastQpc, 0, 0);
|
|
}
|
|
|
|
if (QpcFrequency != NULL)
|
|
{
|
|
*QpcFrequency = g_BlackbirdTempusQpcFrequency;
|
|
}
|
|
}
|
|
|
|
#endif
|