From 46da53ba151b410efb8f4646008e1ebdcfa6ad40 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Sun, 23 Apr 2023 22:08:12 -0400 Subject: [PATCH 1/4] Add the waits that support I/O completion routines in kernel32.odin --- core/sys/windows/kernel32.odin | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index a6897f164..c7bd7d7b0 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -156,6 +156,7 @@ foreign kernel32 { TolerableDelay: ULONG, ) -> BOOL --- WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- + WaitForSingleObjectEx :: proc(hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD --- Sleep :: proc(dwMilliseconds: DWORD) --- GetProcessId :: proc(handle: HANDLE) -> DWORD --- CopyFileExW :: proc( @@ -299,6 +300,13 @@ foreign kernel32 { bWaitAll: BOOL, dwMilliseconds: DWORD, ) -> DWORD --- + WaitForMultipleObjectsEx :: proc( + nCount: DWORD, + lpHandles: ^HANDLE, + bWaitAll: BOOL, + dwMilliseconds: DWORD, + bAlertable: BOOL, + ) -> DWORD --- CreateNamedPipeW :: proc( lpName: LPCWSTR, dwOpenMode: DWORD, From 57c14f6a9bfcf57ee598dcf8dedcc3f753535726 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Tue, 9 May 2023 00:03:58 -0400 Subject: [PATCH 2/4] Allow custom sleep on tsc fallback. This gives the user more control over the spectrum of precision vs. load time on Windows. Spall's output with much lower sleep times is still useful in my experience. NOTE: A better API might be to allow the user to pass the freq as a param to "create_context" in case they already paid for it beforehand, but this seems fine for now. --- core/prof/spall/spall.odin | 4 ++-- core/time/perf.odin | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index 6a78c466e..5c00d16a1 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -67,14 +67,14 @@ Buffer :: struct { BUFFER_DEFAULT_SIZE :: 0x10_0000 -context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok { +context_create :: proc(filename: string, freq_fallback_sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok { fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600) if err != os.ERROR_NONE { return } ctx.fd = fd - freq, freq_ok := time.tsc_frequency() + freq, freq_ok := time.tsc_frequency(freq_fallback_sleep) ctx.precise_time = freq_ok ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1 diff --git a/core/time/perf.odin b/core/time/perf.odin index 69f7eceaa..87192093a 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -70,7 +70,7 @@ has_invariant_tsc :: proc "contextless" () -> bool { return false } -tsc_frequency :: proc "contextless" () -> (u64, bool) { +tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) { if !has_invariant_tsc() { return 0, false } @@ -81,7 +81,7 @@ tsc_frequency :: proc "contextless" () -> (u64, bool) { tsc_begin := intrinsics.read_cycle_counter() tick_begin := tick_now() - sleep(2 * Second) + sleep(fallback_sleep) tsc_end := intrinsics.read_cycle_counter() tick_end := tick_now() From 9867037aa2a9adc93b2954f6bfab03b6db352a70 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Tue, 9 May 2023 00:16:17 -0400 Subject: [PATCH 3/4] Revert "Add the waits that support I/O completion routines in kernel32.odin" This reverts commit 46da53ba151b410efb8f4646008e1ebdcfa6ad40. --- core/sys/windows/kernel32.odin | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index c7bd7d7b0..a6897f164 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -156,7 +156,6 @@ foreign kernel32 { TolerableDelay: ULONG, ) -> BOOL --- WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- - WaitForSingleObjectEx :: proc(hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD --- Sleep :: proc(dwMilliseconds: DWORD) --- GetProcessId :: proc(handle: HANDLE) -> DWORD --- CopyFileExW :: proc( @@ -300,13 +299,6 @@ foreign kernel32 { bWaitAll: BOOL, dwMilliseconds: DWORD, ) -> DWORD --- - WaitForMultipleObjectsEx :: proc( - nCount: DWORD, - lpHandles: ^HANDLE, - bWaitAll: BOOL, - dwMilliseconds: DWORD, - bAlertable: BOOL, - ) -> DWORD --- CreateNamedPipeW :: proc( lpName: LPCWSTR, dwOpenMode: DWORD, From 4e146a75b60a76482fc3e1d6c2d83476a7b23776 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Tue, 9 May 2023 16:43:26 -0400 Subject: [PATCH 4/4] Allow user to pass in scale directly in spall.context_create --- core/prof/spall/spall.odin | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index 5c00d16a1..19a05d70a 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -67,16 +67,15 @@ Buffer :: struct { BUFFER_DEFAULT_SIZE :: 0x10_0000 -context_create :: proc(filename: string, freq_fallback_sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok { +context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok { fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600) if err != os.ERROR_NONE { return } - ctx.fd = fd - freq, freq_ok := time.tsc_frequency(freq_fallback_sleep) - ctx.precise_time = freq_ok - ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1 + ctx.fd = fd + ctx.precise_time = precise_time + ctx.timestamp_scale = timestamp_scale temp := [size_of(Manual_Header)]u8{} _build_header(temp[:], ctx.timestamp_scale) @@ -85,6 +84,14 @@ context_create :: proc(filename: string, freq_fallback_sleep := 2 * time.Second) return } +context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok { + freq, freq_ok := time.tsc_frequency(sleep) + timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1 + return context_create_with_scale(filename, freq_ok, timestamp_scale) +} + +context_create :: proc{context_create_with_scale, context_create_with_sleep} + context_destroy :: proc(ctx: ^Context) { if ctx == nil { return