aboutsummaryrefslogtreecommitdiff
path: root/core/thread
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2026-01-30 10:49:55 +0000
committerGitHub <noreply@github.com>2026-01-30 10:49:55 +0000
commit19b545e7cb0b09a7c8b3424ca8276b9e37f8de80 (patch)
tree974b844bf082c526f6a12396c4a80adfc73b9a60 /core/thread
parent8b745c3909a3482aebe27998d8b870286e448e35 (diff)
parent5a21213fa5e2c74d5021adb2a87f0cc441a38eab (diff)
Merge branch 'master' into bill/feature-using-stmt
Diffstat (limited to 'core/thread')
-rw-r--r--core/thread/thread.odin45
-rw-r--r--core/thread/thread_pool.odin33
-rw-r--r--core/thread/thread_unix.odin6
3 files changed, 61 insertions, 23 deletions
diff --git a/core/thread/thread.odin b/core/thread/thread.odin
index 26c1a3e27..a07801b98 100644
--- a/core/thread/thread.odin
+++ b/core/thread/thread.odin
@@ -5,7 +5,10 @@ import "base:runtime"
import "core:mem"
import "base:intrinsics"
-_ :: intrinsics
+@(private)
+unall :: intrinsics.unaligned_load
+@(private)
+unals :: intrinsics.unaligned_store
/*
Value, specifying whether `core:thread` functionality is available on the
@@ -347,7 +350,9 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(T))t.data
assert(t.user_index >= 1)
- data := (^T)(&t.user_args[0])^
+
+ data := unall((^T)(&t.user_args))
+
fn(data)
}
if t = create(thread_proc, priority); t == nil {
@@ -356,9 +361,7 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex
t.data = rawptr(fn)
t.user_index = 1
- data := data
-
- mem.copy(&t.user_args[0], &data, size_of(T))
+ unals((^T)(&t.user_args), data)
if self_cleanup {
intrinsics.atomic_or(&t.flags, {.Self_Cleanup})
@@ -393,9 +396,10 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2),
fn := cast(proc(T1, T2))t.data
assert(t.user_index >= 2)
- user_args := mem.slice_to_bytes(t.user_args[:])
- arg1 := (^T1)(raw_data(user_args))^
- arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^
+ ptr := uintptr(&t.user_args)
+
+ arg1 := unall((^T1)(rawptr(ptr)))
+ arg2 := unall((^T2)(rawptr(ptr + size_of(T1))))
fn(arg1, arg2)
}
@@ -405,11 +409,10 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2),
t.data = rawptr(fn)
t.user_index = 2
- arg1, arg2 := arg1, arg2
- user_args := mem.slice_to_bytes(t.user_args[:])
+ ptr := uintptr(&t.user_args)
- n := copy(user_args, mem.ptr_to_bytes(&arg1))
- _ = copy(user_args[n:], mem.ptr_to_bytes(&arg2))
+ unals((^T1)(rawptr(ptr)), arg1)
+ unals((^T2)(rawptr(ptr + size_of(T1))), arg2)
if self_cleanup {
intrinsics.atomic_or(&t.flags, {.Self_Cleanup})
@@ -444,10 +447,11 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr
fn := cast(proc(T1, T2, T3))t.data
assert(t.user_index >= 3)
- user_args := mem.slice_to_bytes(t.user_args[:])
- arg1 := (^T1)(raw_data(user_args))^
- arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^
- arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^
+ ptr := uintptr(&t.user_args)
+
+ arg1 := unall((^T1)(rawptr(ptr)))
+ arg2 := unall((^T2)(rawptr(ptr + size_of(T1))))
+ arg3 := unall((^T3)(rawptr(ptr + size_of(T1) + size_of(T2))))
fn(arg1, arg2, arg3)
}
@@ -457,12 +461,11 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr
t.data = rawptr(fn)
t.user_index = 3
- arg1, arg2, arg3 := arg1, arg2, arg3
- user_args := mem.slice_to_bytes(t.user_args[:])
+ ptr := uintptr(&t.user_args)
- n := copy(user_args, mem.ptr_to_bytes(&arg1))
- n += copy(user_args[n:], mem.ptr_to_bytes(&arg2))
- _ = copy(user_args[n:], mem.ptr_to_bytes(&arg3))
+ unals((^T1)(rawptr(ptr)), arg1)
+ unals((^T2)(rawptr(ptr + size_of(T1))), arg2)
+ unals((^T3)(rawptr(ptr + size_of(T1) + size_of(T2))), arg3)
if self_cleanup {
intrinsics.atomic_or(&t.flags, {.Self_Cleanup})
diff --git a/core/thread/thread_pool.odin b/core/thread/thread_pool.odin
index d7a03d04c..10f1438d7 100644
--- a/core/thread/thread_pool.odin
+++ b/core/thread/thread_pool.odin
@@ -20,6 +20,9 @@ Task :: struct {
allocator: mem.Allocator,
}
+Thread_Init_Proc :: #type proc(thread: ^Thread, user_data: rawptr)
+Thread_Fini_Proc :: #type proc(thread: ^Thread, user_data: rawptr)
+
// Do not access the pool's members directly while the pool threads are running,
// since they use different kinds of locking and mutual exclusion devices.
// Careless access can and will lead to nasty bugs. Once initialized, the
@@ -36,6 +39,13 @@ Pool :: struct {
num_done: int,
// end of atomics
+ // called once per thread at startup
+ thread_init_proc: Thread_Init_Proc,
+ thread_init_data: rawptr,
+ // called once per thread at shutdown
+ thread_fini_proc: Thread_Fini_Proc,
+ thread_fini_data: rawptr,
+
is_running: bool,
threads: []^Thread,
@@ -55,6 +65,10 @@ pool_thread_runner :: proc(t: ^Thread) {
data := cast(^Pool_Thread_Data)t.data
pool := data.pool
+ if pool.thread_init_proc != nil {
+ pool.thread_init_proc(t, pool.thread_init_data)
+ }
+
for intrinsics.atomic_load(&pool.is_running) {
sync.wait(&pool.sem_available)
@@ -66,6 +80,10 @@ pool_thread_runner :: proc(t: ^Thread) {
}
}
+ if pool.thread_fini_proc != nil {
+ pool.thread_fini_proc(t, pool.thread_fini_data)
+ }
+
sync.post(&pool.sem_available, 1)
}
@@ -73,13 +91,26 @@ pool_thread_runner :: proc(t: ^Thread) {
// it is destroyed.
//
// The thread pool requires an allocator which it either owns, or which is thread safe.
-pool_init :: proc(pool: ^Pool, allocator: mem.Allocator, thread_count: int) {
+pool_init :: proc(
+ pool: ^Pool,
+ allocator: mem.Allocator,
+ thread_count: int,
+ init_proc: Thread_Init_Proc = nil,
+ init_data: rawptr = nil,
+ fini_proc: Thread_Init_Proc = nil,
+ fini_data: rawptr = nil,
+){
context.allocator = allocator
pool.allocator = allocator
queue.init(&pool.tasks)
pool.tasks_done = make([dynamic]Task)
pool.threads = make([]^Thread, max(thread_count, 1))
+ pool.thread_init_proc = init_proc
+ pool.thread_fini_proc = fini_proc
+ pool.thread_init_data = init_data
+ pool.thread_fini_data = fini_data
+
pool.is_running = true
for _, i in pool.threads {
diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin
index e18ea593d..af2a4a3c1 100644
--- a/core/thread/thread_unix.odin
+++ b/core/thread/thread_unix.odin
@@ -107,7 +107,11 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
high := posix.sched_get_priority_max(policy)
switch priority {
case .Normal: // Okay
- case .Low: params.sched_priority = low + 1
+ case .Low:
+ params.sched_priority = low + 1
+ if params.sched_priority >= high {
+ params.sched_priority = low
+ }
case .High: params.sched_priority = high
}
res = posix.pthread_attr_setschedparam(&attrs, &params)