178 lines
3.4 KiB
C
178 lines
3.4 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
xprofile.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
XAPI profiling support functions
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
We access the kernel's profiling data buffer directly.
|
||
|
If the kernel's data structure changes, be sure to
|
||
|
update the CAP_Start_Profiling and CAP_End_Profiling
|
||
|
functions accordingly.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "basedll.h"
|
||
|
|
||
|
#ifdef _XBOX_ENABLE_PROFILING
|
||
|
|
||
|
#include "xprofp.h"
|
||
|
|
||
|
//
|
||
|
// Pointer to the kernel's global profiling data structure
|
||
|
//
|
||
|
XProfpGlobals* XapipProfileData;
|
||
|
|
||
|
VOID XapipInitProfiling() {
|
||
|
XapipProfileData = XProfpGetData();
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID __declspec(naked) __stdcall
|
||
|
_CAP_Start_Profiling(
|
||
|
VOID* caller,
|
||
|
VOID* callee
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Just before a function is about to be called
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
caller - Specifies the caller function
|
||
|
callee - Specifies the called function
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NONE
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
All registers are preserved.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
/*
|
||
|
ULONG* buf;
|
||
|
|
||
|
loop:
|
||
|
buf = XProfpData.bufnext
|
||
|
if buf >= XProfpData.bufend, return
|
||
|
Atomical incremnt XProfpData.bufnext by 4 ULONGs
|
||
|
if failed, goto loop
|
||
|
|
||
|
buf[0] = timestamp-high
|
||
|
buf[1] = timestamp-low
|
||
|
buf[2] = caller
|
||
|
buf[3] = callee
|
||
|
|
||
|
*/
|
||
|
|
||
|
__asm {
|
||
|
push ecx
|
||
|
mov ecx, XapipProfileData
|
||
|
test ecx, ecx
|
||
|
jz ret2
|
||
|
|
||
|
push eax
|
||
|
push edx
|
||
|
mov eax, [ecx] ; eax = XProfpData.bufnext
|
||
|
loop1:
|
||
|
cmp eax, [ecx+4] ; XProfpData.bufnext >= XProfpData.bufend?
|
||
|
jae ret1
|
||
|
lea edx, [eax+16] ; XProfpData.bufnext += 4
|
||
|
cmpxchg [ecx], edx
|
||
|
jnz loop1
|
||
|
|
||
|
mov ecx, eax
|
||
|
rdtsc
|
||
|
mov [ecx], edx ; timestamp-high
|
||
|
mov [ecx+4], eax ; timestamp-low
|
||
|
mov eax, [esp+16] ; caller - 3 pushes + return address
|
||
|
mov [ecx+8], eax
|
||
|
mov eax, [esp+20] ; callee
|
||
|
mov [ecx+12], eax
|
||
|
|
||
|
ret1:
|
||
|
pop edx
|
||
|
pop eax
|
||
|
ret2:
|
||
|
pop ecx
|
||
|
ret 8
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID __declspec(naked) __stdcall
|
||
|
_CAP_End_Profiling(
|
||
|
VOID* caller
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Just after a function call is made
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
caller - Specifies the caller function
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NONE
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
All registers are preserved.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
// Same logic as above, except the record is smaller by 1 ULONG
|
||
|
|
||
|
__asm {
|
||
|
push ecx
|
||
|
mov ecx, XapipProfileData
|
||
|
test ecx, ecx
|
||
|
jz ret2
|
||
|
|
||
|
push eax
|
||
|
push edx
|
||
|
mov eax, [ecx] ; eax = XProfpData.bufnext
|
||
|
loop1:
|
||
|
cmp eax, [ecx+4] ; XProfpData.bufnext >= XProfpData.bufend?
|
||
|
jae ret1
|
||
|
lea edx, [eax+12] ; XProfpData.bufnext += 3
|
||
|
cmpxchg [ecx], edx
|
||
|
jnz loop1
|
||
|
|
||
|
mov ecx, eax
|
||
|
rdtsc
|
||
|
bts edx, 29 ; timestamp-high | XPROFREC_CALL_END
|
||
|
mov [ecx], edx
|
||
|
mov [ecx+4], eax ; timestamp-low
|
||
|
mov eax, [esp+16] ; caller
|
||
|
mov [ecx+8], eax
|
||
|
|
||
|
ret1:
|
||
|
pop edx
|
||
|
pop eax
|
||
|
ret2:
|
||
|
pop ecx
|
||
|
ret 4
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // _XBOX_ENABLE_PROFILING
|