diff --git a/base/runtime/thread_management.odin b/base/runtime/threading.odin similarity index 68% rename from base/runtime/thread_management.odin rename to base/runtime/threading.odin index cabd4691c..778d7e900 100644 --- a/base/runtime/thread_management.odin +++ b/base/runtime/threading.odin @@ -5,6 +5,20 @@ Thread_Local_Cleaner :: #type proc "odin" () @(private="file") thread_local_cleaners: [8]Thread_Local_Cleaner +// The thread ID is cached here to save time from making syscalls with every +// call. +@(thread_local) local_thread_id: int + +// Return the current thread ID. +@(require_results) +get_current_thread_id :: proc "contextless" () -> int { + if local_thread_id == 0 { + local_thread_id = _get_current_thread_id() + assert_contextless(local_thread_id != 0, "_get_current_thread_id returned 0.") + } + return local_thread_id +} + // Add a procedure that will be run at the end of a thread for the purpose of // deallocating state marked as `thread_local`. // diff --git a/base/runtime/threading_darwin.odin b/base/runtime/threading_darwin.odin new file mode 100644 index 000000000..8dd76f155 --- /dev/null +++ b/base/runtime/threading_darwin.odin @@ -0,0 +1,17 @@ +#+private +package runtime + +foreign import lib "system:System.framework" + +foreign lib { + pthread_threadid_np :: proc "c" (rawptr, ^u64) -> i32 --- +} + +_get_current_thread_id :: proc "contextless" () -> int { + tid: u64 + result := pthread_threadid_np(nil, &tid) + if result != 0 { + panic_contextless("Failed to get current thread ID.") + } + return int(tid) +} diff --git a/base/runtime/threading_freebsd.odin b/base/runtime/threading_freebsd.odin new file mode 100644 index 000000000..053e63640 --- /dev/null +++ b/base/runtime/threading_freebsd.odin @@ -0,0 +1,19 @@ +#+private +package runtime + +import "base:intrinsics" + +SYS_thr_self :: uintptr(432) + +_get_current_thread_id :: proc "contextless" () -> int { + when size_of(rawptr) == 4 { + id: i32 + } else { + id: i64 + } + _, ok := intrinsics.syscall_bsd(SYS_thr_self, uintptr(&id)) + if !ok { + panic_contextless("Failed to get current thread ID.") + } + return int(id) +} diff --git a/base/runtime/threading_linux.odin b/base/runtime/threading_linux.odin new file mode 100644 index 000000000..3fc7aa993 --- /dev/null +++ b/base/runtime/threading_linux.odin @@ -0,0 +1,22 @@ +#+private +package runtime + +import "base:intrinsics" + +when ODIN_ARCH == .amd64 { + SYS_gettid :: uintptr(186) +} else when ODIN_ARCH == .arm32 { + SYS_gettid :: uintptr(224) +} else when ODIN_ARCH == .arm64 { + SYS_gettid :: uintptr(178) +} else when ODIN_ARCH == .i386 { + SYS_gettid :: uintptr(224) +} else when ODIN_ARCH == .riscv64 { + SYS_gettid :: uintptr(178) +} else { + #panic("Syscall numbers related to threading are missing for this Linux architecture.") +} + +_get_current_thread_id :: proc "contextless" () -> int { + return int(intrinsics.syscall(SYS_gettid)) +} diff --git a/base/runtime/threading_netbsd.odin b/base/runtime/threading_netbsd.odin new file mode 100644 index 000000000..0ba6fd0fd --- /dev/null +++ b/base/runtime/threading_netbsd.odin @@ -0,0 +1,11 @@ +#+private +package runtime + +import "base:intrinsics" + +SYS__lwp_self :: uintptr(311) + +_get_current_thread_id :: proc "contextless" () -> int { + result, _ := intrinsics.syscall_bsd(SYS__lwp_self) + return int(result) +} diff --git a/base/runtime/threading_openbsd.odin b/base/runtime/threading_openbsd.odin new file mode 100644 index 000000000..8bfb3de9b --- /dev/null +++ b/base/runtime/threading_openbsd.odin @@ -0,0 +1,11 @@ +#+private +package runtime + +import "base:intrinsics" + +SYS_getthrid :: uintptr(299) + +_get_current_thread_id :: proc "contextless" () -> int { + result, _ := intrinsics.syscall_bsd(SYS_getthrid) + return int(result) +} diff --git a/base/runtime/threading_other.odin b/base/runtime/threading_other.odin new file mode 100644 index 000000000..4bad1a242 --- /dev/null +++ b/base/runtime/threading_other.odin @@ -0,0 +1,12 @@ +#+private +#+build !darwin +#+build !freebsd +#+build !linux +#+build !netbsd +#+build !openbsd +#+build !windows +package runtime + +_get_current_thread_id :: proc "contextless" () -> int { + unimplemented_contextless("This platform does not support multithreading.") +} diff --git a/base/runtime/threading_windows.odin b/base/runtime/threading_windows.odin new file mode 100644 index 000000000..967135061 --- /dev/null +++ b/base/runtime/threading_windows.odin @@ -0,0 +1,13 @@ +#+private +package runtime + +foreign import Kernel32 "system:Kernel32.lib" + +@(default_calling_convention="system") +foreign Kernel32 { + GetCurrentThreadId :: proc() -> u32 --- +} + +_get_current_thread_id :: proc "contextless" () -> int { + return int(GetCurrentThreadId()) +}