From 575379e2646e15cb76bfc79c5e263056dc7a11a6 Mon Sep 17 00:00:00 2001 From: Patedam Date: Sun, 18 Oct 2026 23:41:43 -0400 Subject: [PATCH] added thread naming --- Juliet/core/core.h | 3 ++ Juliet/core/core_string.c | 54 +++++++++++++++++++++++++++-- Juliet/core/core_string.h | 6 +++- Juliet/core/core_thread_context.c | 2 +- Juliet/core/core_threads.c | 16 +++++++-- Juliet/win32/core/win32_core.c | 56 ++++++++++++++++++++++++++++++- 6 files changed, 129 insertions(+), 8 deletions(-) diff --git a/Juliet/core/core.h b/Juliet/core/core.h index ff36a45..751aaa9 100644 --- a/Juliet/core/core.h +++ b/Juliet/core/core.h @@ -116,6 +116,9 @@ #define AlignPow2(x, align) (((x) + (align) - 1) & (~((align) - 1))) +#define Stringify_(S) #S +#define Stringify(S) Stringify_(S) + #define GLUE_(A, B) A##B #define GLUE(A, B) GLUE_(A, B) diff --git a/Juliet/core/core_string.c b/Juliet/core/core_string.c index 080d9b2..b8c7dc4 100644 --- a/Juliet/core/core_string.c +++ b/Juliet/core/core_string.c @@ -55,6 +55,18 @@ internal String8 str8_zero() return result; } +internal String16 str16(uint16* str, uint64 size) +{ + String16 result = { str, size }; + return result; +} + +internal String16 str16_zero() +{ + String16 result = { 0 }; + return result; +} + internal String8 str8_cstring(const char* cstring) { String8 result = { (uint8*)cstring, cstring8_length((uint8*)cstring) }; @@ -86,6 +98,19 @@ internal String8 str8_copy(Arena* arena, String8 in) return str; } +internal String8 str8fv(Arena* arena, char* fmt, va_list args) +{ + va_list args2; + va_copy(args2, args); + uint32 needed_bytes = juliet_vsnprintf(0, 0, fmt, args) + 1; + String8 result = { 0 }; + result.str = push_array_no_zero(arena, uint8, needed_bytes); + result.size = juliet_vsnprintf((char*)result.str, needed_bytes, fmt, args2); + result.str[result.size] = '\0'; + va_end(args2); + return result; +} + // ============================================================================= // Unicode String Encode/Decode @@ -236,12 +261,12 @@ internal String8 str8_from_16(Arena* arena, String16 in) uint64 capacity = in.size * 3; uint8* str = push_array_no_zero(arena, uint8, capacity + 1); uint16* ptr = in.str; - uint16* op1 = ptr + in.size; + uint16* opl = ptr + in.size; uint64 size = 0; UnicodeDecode consume; - for (; ptr < op1; ptr += consume.increment) + for (; ptr < opl; ptr += consume.increment) { - consume = utf16_decode(ptr, op1 - ptr); + consume = utf16_decode(ptr, opl - ptr); size += utf8_encode(str + size, consume.codepoint); } str[size] = '\0'; @@ -250,3 +275,26 @@ internal String8 str8_from_16(Arena* arena, String16 in) } return result; } + +internal String16 str16_from_8(Arena* arena, String8 in) +{ + String16 result = str16_zero(); + if (in.size) + { + uint64 capacity = in.size * 2; + uint16* str = push_array_no_zero(arena, uint16, capacity + 1); + uint8* ptr = in.str; + uint8* opl = ptr + in.size; + uint64 size = 0; + UnicodeDecode consume; + for (; ptr < opl; ptr += consume.increment) + { + consume = utf8_decode(ptr, opl - ptr); + size += utf16_encode(str + size, consume.codepoint); + } + str[size] = '\0'; + arena_pop(arena, (capacity - size) * 2); + result = str16(str, size); + } + return result; +} diff --git a/Juliet/core/core_string.h b/Juliet/core/core_string.h index d2b1ec6..48e52ad 100644 --- a/Juliet/core/core_string.h +++ b/Juliet/core/core_string.h @@ -45,6 +45,8 @@ internal uint64 cstring32_length(uint32* cstring); internal String8 str8(uint8* str, uint64 size); internal String8 str8_zero(); +internal String16 str16(uint16* str, uint64 size); +internal String16 str16_zero(); internal String8 str8_cstring(const char* cstring); internal String16 str16_cstring(uint16* cstring); internal String32 str32_cstring(uint32* cstring); @@ -53,6 +55,7 @@ internal String32 str32_cstring(uint32* cstring); // String Formatting & Copying internal String8 str8_copy(Arena* arena, String8 in); +internal String8 str8fv(Arena* arena, char* fmt, va_list args); // ========================================================================== // // Unicode String Encode/Decode @@ -65,4 +68,5 @@ internal uint32 utf16_encode(uint16* str, uint32 codepoint); // ========================================================================== // // Unicode String Conversions -internal String8 str8_from_16(Arena* arena, String16 in); +internal String8 str8_from_16(Arena* arena, String16 in); +internal String16 str16_from_8(Arena* arena, String8 in); diff --git a/Juliet/core/core_thread_context.c b/Juliet/core/core_thread_context.c index b9910c3..acbb134 100644 --- a/Juliet/core/core_thread_context.c +++ b/Juliet/core/core_thread_context.c @@ -27,8 +27,8 @@ internal TCTX* tctx_alloc() internal void tctx_release(TCTX* tctx) { - arena_release(tctx->arenas[0]); arena_release(tctx->arenas[1]); + arena_release(tctx->arenas[0]); } internal void tctx_select(TCTX* tctx) diff --git a/Juliet/core/core_threads.c b/Juliet/core/core_threads.c index fac7de8..a836b0e 100644 --- a/Juliet/core/core_threads.c +++ b/Juliet/core/core_threads.c @@ -1,6 +1,18 @@ // ============================================================================= // Thread Info Helpers -internal void set_thread_name(String8 name) {} +internal void set_thread_name(String8 name) +{ + set_platform_thread_name(name); +} -internal void set_thread_namef(char* fmt, ...) {} +internal void set_thread_namef(char* fmt, ...) +{ + TempArena scratch = scratch_begin(0, 0); + va_list args; + va_start(args, fmt); + String8 string = str8fv(scratch.arena, fmt, args); + set_thread_name(string); + va_end(args); + scratch_end(scratch); +} diff --git a/Juliet/win32/core/win32_core.c b/Juliet/win32/core/win32_core.c index 3e48ee6..fd67f1b 100644 --- a/Juliet/win32/core/win32_core.c +++ b/Juliet/win32/core/win32_core.c @@ -1,7 +1,14 @@ +typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); + +#define W32_KERNEL32_EXT_X_LIST X(SetThreadDescription) + +#define X(x) global W32_##x##_Type* w32_##x##_func; +W32_KERNEL32_EXT_X_LIST +#undef X + // ============================================================================= // System -#include "core/core_thread_context.h" internal SystemInfo* get_system_info() { return &w32_state.system_info; @@ -20,6 +27,42 @@ internal void set_platform_thread_name(String8 name) { TempArena scratch = scratch_begin(0, 0); + // Win10 and + + if (w32_SetThreadDescription_func) + { + String16 name16 = str16_from_8(scratch.arena, name); + HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str); + } + + // Old way by raising exception + { + String8 name_copy = str8_copy(scratch.arena, name); +#pragma pack(push, 8) + typedef struct THREADNAME_INFO THREADNAME_INFO; + struct THREADNAME_INFO + { + uint32 dwType; // Must be 0x1000. + char* szName; // Pointer to name (in user addr space). + uint32 dwThreadID; // Thread ID (-1=caller thread). + uint32 dwFlags; // Reserved for future use, must be zero. + }; +#pragma pack(pop) + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = (char*)name_copy.str; + info.dwThreadID = tid(); + info.dwFlags = 0; +#pragma warning(push) +#pragma warning(disable : 6320 6322) + __try + { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void*), (const ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } +#pragma warning(pop) + } scratch_end(scratch); } @@ -76,6 +119,17 @@ internal void abort_self(uint64 exit_code) internal void w32_entry_point(int argc, WCHAR** wargv) { + // Dynamically load some windows function that are not guaranteed in all sdk + { +#define X(x) w32_##x##_func = (void*)GetProcAddress(module, Stringify(x)); + HMODULE module; + + module = LoadLibraryA("kernek32.dll"); + W32_KERNEL32_EXT_X_LIST + FreeLibrary(module); +#undef X + } + SYSTEM_INFO sys_info = { 0 }; GetSystemInfo(&sys_info);