Get/Set Thread names

This commit is contained in:
PePerRoNii
2025-07-14 17:23:36 +07:00
parent 843c39189e
commit 0a3f73077e
10 changed files with 181 additions and 2 deletions

View File

@@ -5,7 +5,7 @@ import "core:c"
when ODIN_OS == .Darwin {
foreign import lib "system:System.framework"
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux {
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux || ODIN_OS == .OpenBSD {
foreign import lib "system:pthread"
} else {
foreign import lib "system:c"

View File

@@ -155,6 +155,28 @@ yield :: proc() {
_yield()
}
/*
Get thread's name/description.
If thread is nil the procedure will get the name of the calling thread.
allocates memory for the returned string using provided allocator.
*/
get_name :: proc(thread: ^Thread, allocator := context.allocator, loc := #caller_location) -> (string, runtime.Allocator_Error) #optional_allocator_error {
return _get_name(thread, allocator, loc)
}
/*
Set thread's name/description.
If thread is nil the procedure will set the name of the calling thread.
MacOS: only support changing the name of the calling thread.
if thread is not nil the procedure will do nothing.
*/
set_name :: proc(thread: ^Thread, name: string) {
_set_name(thread, name)
}
/*
Run a procedure on a different thread.

View File

@@ -0,0 +1,13 @@
#+build darwin
#+private
package thread
import "core:sys/posix"
import "core:c"
foreign import pthread "system:System.framework"
foreign pthread {
pthread_getname_np :: proc(thread: posix.pthread_t, name: [^]u8, len: c.size_t) -> posix.Errno ---
pthread_setname_np :: proc(name: [^]u8) -> posix.Errno ---
}

View File

@@ -0,0 +1,13 @@
#+build freebsd
#+private
package thread
import "core:sys/posix"
import "core:c"
foreign import pthread "system:pthread"
foreign pthread {
pthread_getname_np :: proc(thread: posix.pthread_t, name: [^]u8, len: c.size_t) -> posix.Errno ---
pthread_setname_np :: proc(thread: posix.pthread_t, name: [^]u8) -> posix.Errno ---
}

View File

@@ -0,0 +1,13 @@
#+build linux
#+private
package thread
import "core:sys/posix"
import "core:c"
foreign import pthread "system:pthread"
foreign pthread {
pthread_getname_np :: proc(thread: posix.pthread_t, name: [^]u8, len: c.size_t) -> posix.Errno ---
pthread_setname_np :: proc(thread: posix.pthread_t, name: [^]u8) -> posix.Errno ---
}

View File

@@ -0,0 +1,13 @@
#+build netbsd
#+private
package thread
import "core:sys/posix"
import "core:c"
foreign import pthread "system:pthread"
foreign pthread {
pthread_getname_np :: proc(thread: posix.pthread_t, name: [^]u8, len: c.size_t) -> posix.Errno ---
pthread_setname_np :: proc(thread: posix.pthread_t, name: [^]u8, arg: rawptr) -> posix.Errno ---
}

View File

@@ -0,0 +1,13 @@
#+build openbsd
#+private
package thread
import "core:sys/posix"
import "core:c"
foreign import pthread "system:pthread"
foreign pthread {
pthread_get_name_np :: proc(thread: posix.pthread_t, name: [^]u8, len: c.size_t) ---
pthread_set_name_np :: proc(thread: posix.pthread_t, name: [^]u8) ---
}

View File

@@ -2,6 +2,7 @@
package thread
import "base:intrinsics"
import "base:runtime"
_IS_SUPPORTED :: false
@@ -45,3 +46,7 @@ _yield :: proc() {
unimplemented("core:thread procedure not supported on target")
}
_get_name :: proc(thread: Thread, allocator : runtime.Allocator, loc : runtime.Source_Code_Location) -> (string, runtime.Allocator_Error) {
unimplemented("core:thread procedure not supported on target")
}

View File

@@ -7,7 +7,7 @@ import "core:sync"
import "core:sys/posix"
_IS_SUPPORTED :: true
_MAX_PTHREAD_NAME_LENGTH :: 16
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
// Also see core/sys/darwin/mach_darwin.odin/semaphore_t.
Thread_Os_Specific :: struct #align(16) {
@@ -182,3 +182,57 @@ _terminate :: proc(t: ^Thread, exit_code: int) {
_yield :: proc() {
posix.sched_yield()
}
_get_name :: proc(thread: ^Thread, allocator: runtime.Allocator, loc: runtime.Source_Code_Location) -> (name:string, err:runtime.Allocator_Error) {
// Haiku doesn't have pthread_getname yet
when ODIN_OS == .Haiku {
unimplemented("core:thread get_name for haiku is not yet supported")
}
tid : posix.pthread_t
if thread == nil do tid = transmute(posix.pthread_t)sync.current_thread_id()
else do tid = thread.unix_thread
buf := make([]u8, _MAX_PTHREAD_NAME_LENGTH, allocator, loc) or_return
when ODIN_OS == .Darwin || ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
pthread_getname_np(tid, raw_data(buf), len(buf))
} else when ODIN_OS == .OpenBSD {
pthread_get_name_np(tid, raw_data(buf), len(buf))
}
name = transmute(string)buf
return
}
_set_name :: proc(thread: ^Thread, name:string) {
// Haiku doesn't have pthread_getname yet
when ODIN_OS == .Haiku {
unimplemented("core:thread set_name for haiku is not yet supported")
} else when ODIN_OS == .Darwin {
if thread != nil do return
} else {
tid: posix.pthread_t
if thread == nil do tid = transmute(posix.pthread_t)sync.current_thread_id
else do tid = t.unix_thread
}
buf : [_MAX_PTHREAD_NAME_LENGTH]u8
copy_from_string(buf[:], name)
// _MAX_PTHREAD_NAME_LENGTH includes terminating null
buf[len(buf) - 1] = 0
when ODIN_OS == .Darwin {
pthread_setname_np(raw_data(buf[:]))
} else when ODIN_OS == .OpenBSD {
pthread_set_name_np(tid, raw_data(buf[:]))
} else when ODIN_OS == .NetBSD {
format := []u8{'%','s', 0}
pthread_setname_np(tid, raw_data(format), raw_data(buf[:]))
} else {
pthread_setname_np(tid, raw_data(buf[:]))
}
}

View File

@@ -6,8 +6,11 @@ import "base:intrinsics"
import "base:runtime"
import "core:sync"
import win32 "core:sys/windows"
import "core:unicode/utf16"
_IS_SUPPORTED :: true
//NOTE(peperronii): not sure about the exact length but there must be a limit
_THREAD_DESCRIPTION_LENGTH :: 64
Thread_Os_Specific :: struct {
win32_thread: win32.HANDLE,
@@ -152,3 +155,33 @@ _yield :: proc() {
win32.SwitchToThread()
}
_get_name :: proc(thread: ^Thread, allocator: runtime.Allocator, loc : runtime.Source_Code_Location) -> (name:string, err:runtime.Allocator_Error) {
t_handle : win32.HANDLE
if thread == nil do t_handle = win32.GetCurrentThread()
else do t_handle = t.win32_thread
buf_8 : [_THREAD_DESCRIPTION_LENGTH * 2]u8
buf_16 : [_THREAD_DESCRIPTION_LENGTH]u16
win32.GetThreadDescription(t_handle, raw_data(buf_16[:]))
n := utf16.decode_to_utf(buf_8[:], buf_16[:])
buf := make([]u8, n, allocator, loc)
copy(buf, buf_8[:])
name = transmute(string)buf
return
}
_set_name :: proc(thread: ^Thread, name: string) {
t_handle : win32.HANDLE
if thread == nil do t_handle = win32.GetCurrentThread()
else do t_handle = t.win32_thread
buf : [_THREAD_DESCRIPTION_LENGTH]u16
utf16.encode_string(buf_16[:], name)
// _THREAD_DESCRIPTION_LENGTH includes terminating null
buf[len(buf) - 1] = 0
win32.SetThreadDescription(t_handle, raw_data(buf[:]))
}