summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/util/p_debug_prof.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/util/p_debug_prof.c')
-rw-r--r--src/gallium/auxiliary/util/p_debug_prof.c269
1 files changed, 207 insertions, 62 deletions
diff --git a/src/gallium/auxiliary/util/p_debug_prof.c b/src/gallium/auxiliary/util/p_debug_prof.c
index 958f99c327..5f9772ef91 100644
--- a/src/gallium/auxiliary/util/p_debug_prof.c
+++ b/src/gallium/auxiliary/util/p_debug_prof.c
@@ -46,15 +46,86 @@
#include "util/u_string.h"
-#define PROFILE_FILE_SIZE 4*1024*1024
+#define PROFILE_TABLE_SIZE (1024*1024)
#define FILE_NAME_SIZE 256
-static WCHAR wFileName[FILE_NAME_SIZE];
+struct debug_profile_entry
+{
+ uintptr_t caller;
+ uintptr_t callee;
+ uint64_t samples;
+};
+
+static unsigned long enabled = 0;
+
+static WCHAR wFileName[FILE_NAME_SIZE] = L"\\??\\c:\\00000000.prof";
static ULONG_PTR iFile = 0;
-static void *pMap = NULL;
-static void *pMapEnd = NULL;
+
+static struct debug_profile_entry *table = NULL;
+static unsigned long free_table_entries = 0;
+static unsigned long max_table_entries = 0;
+
+uint64_t start_stamp = 0;
+uint64_t end_stamp = 0;
+
+
+static void
+debug_profile_entry(uintptr_t caller, uintptr_t callee, uint64_t samples)
+{
+ unsigned hash = ( caller + callee ) & PROFILE_TABLE_SIZE - 1;
+
+ while(1) {
+ if(table[hash].caller == 0 && table[hash].callee == 0) {
+ table[hash].caller = caller;
+ table[hash].callee = callee;
+ table[hash].samples = samples;
+ --free_table_entries;
+ break;
+ }
+ else if(table[hash].caller == caller && table[hash].callee == callee) {
+ table[hash].samples += samples;
+ break;
+ }
+ else {
+ ++hash;
+ }
+ }
+}
+
+
+static uintptr_t caller_stack[1024];
+static unsigned last_caller = 0;
+
+
+static int64_t delta(void) {
+ int64_t result = end_stamp - start_stamp;
+ if(result > UINT64_C(0xffffffff))
+ result = 0;
+ return result;
+}
+
+
+static void __cdecl
+debug_profile_enter(uintptr_t callee)
+{
+ uintptr_t caller = last_caller ? caller_stack[last_caller - 1] : 0;
+
+ if (caller)
+ debug_profile_entry(caller, 0, delta());
+ debug_profile_entry(caller, callee, 1);
+ caller_stack[last_caller++] = callee;
+}
+static void __cdecl
+debug_profile_exit(uintptr_t callee)
+{
+ debug_profile_entry(callee, 0, delta());
+ if(last_caller)
+ --last_caller;
+}
+
+
/**
* Called at the start of every method or function.
*
@@ -63,27 +134,49 @@ static void *pMapEnd = NULL;
void __declspec(naked) __cdecl
_penter(void) {
_asm {
- push ebx
- mov ebx, [pMap]
- test ebx, ebx
- jz done
- cmp ebx, [pMapEnd]
- je done
push eax
+ mov eax, [enabled]
+ test eax, eax
+ jz skip
+
push edx
- mov eax, [esp+12]
- and eax, 0xfffffffe
- mov [ebx], eax
- add ebx, 4
+
rdtsc
- mov [ebx], eax
- add ebx, 4
- mov [pMap], ebx
+ mov dword ptr [end_stamp], eax
+ mov dword ptr [end_stamp+4], edx
+
+ xor eax, eax
+ mov [enabled], eax
+
+ mov eax, [esp+8]
+
+ push ebx
+ push ecx
+ push ebp
+ push edi
+ push esi
+
+ push eax
+ call debug_profile_enter
+ add esp, 4
+
+ pop esi
+ pop edi
+ pop ebp
+ pop ecx
+ pop ebx
+
+ mov eax, 1
+ mov [enabled], eax
+
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
pop edx
+skip:
pop eax
-done:
- pop ebx
- ret
+ ret
}
}
@@ -96,46 +189,60 @@ done:
void __declspec(naked) __cdecl
_pexit(void) {
_asm {
- push ebx
- mov ebx, [pMap]
- test ebx, ebx
- jz done
- cmp ebx, [pMapEnd]
- je done
push eax
+ mov eax, [enabled]
+ test eax, eax
+ jz skip
+
push edx
- mov eax, [esp+12]
- or eax, 0x00000001
- mov [ebx], eax
- add ebx, 4
+
rdtsc
- mov [ebx], eax
- add ebx, 4
- mov [pMap], ebx
- pop edx
- pop eax
-done:
+ mov dword ptr [end_stamp], eax
+ mov dword ptr [end_stamp+4], edx
+
+ xor eax, eax
+ mov [enabled], eax
+
+ mov eax, [esp+8]
+
+ push ebx
+ push ecx
+ push ebp
+ push edi
+ push esi
+
+ push eax
+ call debug_profile_exit
+ add esp, 4
+
+ pop esi
+ pop edi
+ pop ebp
+ pop ecx
pop ebx
- ret
- }
-}
+ mov eax, 1
+ mov [enabled], eax
-void __declspec(naked)
-__debug_profile_reference1(void) {
- _asm {
- call _penter
- call _pexit
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
+ pop edx
+skip:
+ pop eax
ret
}
}
+/**
+ * Reference function for calibration.
+ */
void __declspec(naked)
-__debug_profile_reference2(void) {
+__debug_profile_reference(void) {
_asm {
call _penter
- call __debug_profile_reference1
call _pexit
ret
}
@@ -145,31 +252,69 @@ __debug_profile_reference2(void) {
void
debug_profile_start(void)
{
- static unsigned no = 0;
- char filename[FILE_NAME_SIZE];
- unsigned i;
+ WCHAR *p;
- util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u.prof", ++no);
- for(i = 0; i < FILE_NAME_SIZE; ++i)
- wFileName[i] = (WCHAR)filename[i];
-
- pMap = EngMapFile(wFileName, PROFILE_FILE_SIZE, &iFile);
- if(pMap) {
- pMapEnd = (unsigned char*)pMap + PROFILE_FILE_SIZE;
- /* reference functions for calibration purposes */
- __debug_profile_reference2();
+ // increment starting from the less significant digit
+ p = &wFileName[14];
+ while(1) {
+ if(*p == '9') {
+ *p-- = '0';
+ }
+ else {
+ *p += 1;
+ break;
+ }
+ }
+
+ table = EngMapFile(wFileName,
+ PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry),
+ &iFile);
+ if(table) {
+ unsigned i;
+
+ free_table_entries = max_table_entries = PROFILE_TABLE_SIZE;
+ memset(table, 0, PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry));
+
+ table[0].caller = (uintptr_t)&__debug_profile_reference;
+ table[0].callee = 0;
+ table[0].samples = 0;
+ --free_table_entries;
+
+ _asm {
+ push edx
+ push eax
+
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
+ pop edx
+ pop eax
+ }
+
+ last_caller = 0;
+
+ enabled = 1;
+
+ for(i = 0; i < 8; ++i) {
+ _asm {
+ call __debug_profile_reference
+ }
+ }
}
}
+
void
debug_profile_stop(void)
{
- if(iFile) {
+ enabled = 0;
+
+ if(iFile)
EngUnmapFile(iFile);
- /* TODO: truncate file */
- }
iFile = 0;
- pMapEnd = pMap = NULL;
+ table = NULL;
+ free_table_entries = max_table_entries = 0;
}
#endif /* PROFILE */