feat: std.thread — Thread, Mutex/Cond, bounded worker Pool (PLAN-HTTPZ S6)
pthread bindings with darwin opaque sizes (mutex 64B, cond 48B; glibc divergence is a C3 per-OS item). Mutex/Cond initialize IN PLACE and Pool lives behind Pool.create's heap pointer — POSIX sync objects are address-sensitive, so nothing here moves after setup. Thread.spawn takes the C2 re-entry contract entry (callconv(.c), fabricates its own Context); Pool workers do exactly that with a per-worker malloc-backed GPA, then run default-conv tasks inside it. submit returns false on a full backlog (httpz thread_pool backpressure); shutdown finishes queued work and joins every worker. examples/1637 pins: 4 raw threads x 1000 locked increments, 100 pool tasks summing exactly once across 4 workers, a held worker + full backlog refusing the next submit, clean shutdown. JIT + AOT (AOT run three times). The std.sx barrel carries thread; .ir snapshot regen is the usual renumbering.
This commit is contained in:
116
examples/1637-std-thread.sx
Normal file
116
examples/1637-std-thread.sx
Normal file
@@ -0,0 +1,116 @@
|
||||
// std.thread (PLAN-HTTPZ S6): raw threads contend correctly on a Mutex,
|
||||
// the Pool runs every submitted task exactly once across its workers,
|
||||
// a full backlog applies backpressure (submit returns false), and
|
||||
// shutdown joins cleanly with queued work finished.
|
||||
#import "modules/std.sx";
|
||||
|
||||
Shared :: struct {
|
||||
mu: thread.Mutex = .{};
|
||||
counter: i64 = 0;
|
||||
gate: i64 = 0;
|
||||
}
|
||||
|
||||
// Raw-thread entry: C->sx boundary, own fabricated context.
|
||||
bump_entry :: (arg: *void) -> *void callconv(.c) {
|
||||
sh : *Shared = xx arg;
|
||||
gpa := GPA.init();
|
||||
push Context.{ allocator = xx gpa } {
|
||||
i := 0;
|
||||
while i < 1000 {
|
||||
sh.mu.lock();
|
||||
sh.counter += 1;
|
||||
sh.mu.unlock();
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Pool tasks are default-conv: they run inside a worker's context.
|
||||
AddArg :: struct {
|
||||
sh: *Shared;
|
||||
v: i64;
|
||||
}
|
||||
|
||||
add_task :: (arg: usize) {
|
||||
a : *AddArg = xx arg;
|
||||
a.sh.mu.lock();
|
||||
a.sh.counter += a.v;
|
||||
a.sh.mu.unlock();
|
||||
}
|
||||
|
||||
// Holds its worker hostage until the gate opens (backpressure case).
|
||||
gate_task :: (arg: usize) {
|
||||
sh : *Shared = xx arg;
|
||||
while true {
|
||||
sh.mu.lock();
|
||||
g := sh.gate;
|
||||
sh.mu.unlock();
|
||||
if g != 0 { return; }
|
||||
}
|
||||
}
|
||||
|
||||
main :: () -> i32 {
|
||||
sh : Shared = .{};
|
||||
if !sh.mu.setup() { print("mutex setup failed\n"); return 1; }
|
||||
|
||||
// ── 4 raw threads, 1000 locked increments each ────────────────────
|
||||
ths : [4]thread.Thread = ---;
|
||||
i := 0;
|
||||
while i < 4 {
|
||||
t, te := thread.Thread.spawn(bump_entry, xx @sh);
|
||||
if te { print("spawn failed\n"); return 1; }
|
||||
ths[i] = t;
|
||||
i += 1;
|
||||
}
|
||||
i = 0;
|
||||
while i < 4 {
|
||||
ths[i].join();
|
||||
i += 1;
|
||||
}
|
||||
if sh.counter != 4000 { print("raw threads: expected 4000, got {}\n", sh.counter); return 1; }
|
||||
print("raw threads: 4 x 1000 locked increments = {}\n", sh.counter);
|
||||
|
||||
// ── pool: 100 tasks, each adds its index+1; sum = 5050 ───────────
|
||||
sh.counter = 0;
|
||||
pool, pe := thread.Pool.create(4, 128);
|
||||
if pe { print("pool create failed\n"); return 1; }
|
||||
args : [*]AddArg = xx context.allocator.alloc_bytes(100 * size_of(AddArg));
|
||||
n := 0;
|
||||
while n < 100 {
|
||||
args[n] = AddArg.{ sh = @sh, v = xx (n + 1) };
|
||||
if !pool.submit(add_task, xx @args[n]) { print("submit unexpectedly refused\n"); return 1; }
|
||||
n += 1;
|
||||
}
|
||||
pool.shutdown(); // queued tasks finish before workers exit
|
||||
if sh.counter != 5050 { print("pool: expected 5050, got {}\n", sh.counter); return 1; }
|
||||
print("pool: 100 tasks across 4 workers summed to {}\n", sh.counter);
|
||||
|
||||
// ── backpressure: 1 worker held at the gate, backlog 2 fills ─────
|
||||
sh.gate = 0;
|
||||
p2, pe2 := thread.Pool.create(1, 2);
|
||||
if pe2 { print("pool2 create failed\n"); return 1; }
|
||||
if !p2.submit(gate_task, xx @sh) { print("gate submit refused\n"); return 1; }
|
||||
// give the worker a beat to take the gate task off the queue
|
||||
spins := 0;
|
||||
taken := false;
|
||||
while !taken and spins < 100000000 {
|
||||
p2.mu.lock();
|
||||
taken = p2.len == 0;
|
||||
p2.mu.unlock();
|
||||
spins += 1;
|
||||
}
|
||||
if !taken { print("worker never took the gate task\n"); return 1; }
|
||||
if !p2.submit(gate_task_noop, 0) { print("backlog slot 1 refused\n"); return 1; }
|
||||
if !p2.submit(gate_task_noop, 0) { print("backlog slot 2 refused\n"); return 1; }
|
||||
if p2.submit(gate_task_noop, 0) { print("full backlog must refuse\n"); return 1; }
|
||||
print("backpressure: full backlog refuses\n");
|
||||
sh.mu.lock();
|
||||
sh.gate = 1;
|
||||
sh.mu.unlock();
|
||||
p2.shutdown();
|
||||
print("std.thread ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gate_task_noop :: (arg: usize) {}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -938,6 +938,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i64 @accept_c(ptr %0) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1430,6 +1430,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @BuildOptions.add_link_flag.77(i64, ptr) #0
|
||||
|
||||
|
||||
@@ -1446,6 +1446,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @BuildOptions.add_link_flag.77(i64, ptr) #0
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @BuildOptions.add_link_flag.77(i64, ptr) #0
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1448,6 +1448,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @BuildOptions.add_link_flag.77(i64, ptr) #0
|
||||
|
||||
|
||||
@@ -1424,6 +1424,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i32 @read_int(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i64 @read_long(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal double @read_double(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i1 @read_bool(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal ptr @get_window(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal i32 @call_static_max(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -1422,6 +1422,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
|
||||
@@ -945,6 +945,90 @@ declare void @Server.write_more(ptr, ptr, i64) #0
|
||||
; Function Attrs: nounwind
|
||||
declare void @Server.respond_error_close(ptr, ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_create(ptr, ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_join(i64, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_detach(i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_lock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_unlock(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_mutex_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_init(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_wait(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_signal(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_broadcast(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @pthread_cond_destroy(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Mutex.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.lock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.unlock(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Mutex.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Cond.setup(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.wait(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.signal(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.broadcast(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Cond.destroy(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Thread.spawn(ptr, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.join(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Thread.detach(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare [2 x i64] @Pool.create(ptr, i64, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i1 @Pool.submit(ptr, ptr, ptr, i64) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @Pool.shutdown(ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare ptr @pool_worker(ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @BuildOptions.add_link_flag.77(i64, ptr) #0
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
1
examples/expected/1637-std-thread.exit
Normal file
1
examples/expected/1637-std-thread.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/1637-std-thread.stderr
Normal file
1
examples/expected/1637-std-thread.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
4
examples/expected/1637-std-thread.stdout
Normal file
4
examples/expected/1637-std-thread.stdout
Normal file
@@ -0,0 +1,4 @@
|
||||
raw threads: 4 x 1000 locked increments = 4000
|
||||
pool: 100 tasks across 4 workers summed to 5050
|
||||
backpressure: full backlog refuses
|
||||
std.thread ok
|
||||
@@ -100,3 +100,4 @@ test :: #import "modules/std/test.sx";
|
||||
time :: #import "modules/std/time.sx";
|
||||
event :: #import "modules/std/event.sx";
|
||||
http :: #import "modules/std/http.sx";
|
||||
thread :: #import "modules/std/thread.sx";
|
||||
|
||||
225
library/modules/std/thread.sx
Normal file
225
library/modules/std/thread.sx
Normal file
@@ -0,0 +1,225 @@
|
||||
// std.thread — OS threads, Mutex/Cond, and a bounded worker Pool over
|
||||
// pthreads (PLAN-HTTPZ S6).
|
||||
//
|
||||
// THE RE-ENTRY CONTRACT (pinned by examples/1636): a thread entry is a
|
||||
// `callconv(.c)` function — it has NO implicit context — and enters
|
||||
// the sx world by fabricating one: `push Context.{ allocator = xx gpa }`
|
||||
// around the default-conv code it runs. Pool workers do exactly that,
|
||||
// each with its own malloc-backed GPA, so tasks allocate freely and
|
||||
// never share allocator state across threads.
|
||||
//
|
||||
// ALLOCATOR DISCIPLINE: GPA is malloc/free — thread-safe. Arena and
|
||||
// every other context-flowing allocator is NOT; never share one across
|
||||
// threads. Pool buffers come from the creating context's allocator and
|
||||
// are touched only under the pool mutex.
|
||||
//
|
||||
// MOVE SEMANTICS: a pthread mutex/cond is address-sensitive once
|
||||
// initialized — POSIX leaves moving one undefined. Mutex/Cond therefore
|
||||
// initialize IN PLACE (`m.setup()`) and Pool lives behind a pointer
|
||||
// (`Pool.create`), never by-value copy.
|
||||
//
|
||||
// PER-OS: sizes below are darwin's (pthread_mutex_t 64 bytes,
|
||||
// pthread_cond_t 48, pthread_t a pointer). glibc differs (40/48);
|
||||
// PLAN-HTTPZ C3 selects per-OS when the linux target activates.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
tlib :: #library "c";
|
||||
|
||||
pthread_create :: (thread: *usize, attr: *void, start: (*void) -> *void callconv(.c), arg: *void) -> i32 #foreign tlib;
|
||||
pthread_join :: (thread: usize, retval: **void) -> i32 #foreign tlib;
|
||||
pthread_detach :: (thread: usize) -> i32 #foreign tlib;
|
||||
|
||||
pthread_mutex_init :: (m: *MutexBuf, attr: *void) -> i32 #foreign tlib;
|
||||
pthread_mutex_lock :: (m: *MutexBuf) -> i32 #foreign tlib;
|
||||
pthread_mutex_unlock :: (m: *MutexBuf) -> i32 #foreign tlib;
|
||||
pthread_mutex_destroy :: (m: *MutexBuf) -> i32 #foreign tlib;
|
||||
|
||||
pthread_cond_init :: (c: *CondBuf, attr: *void) -> i32 #foreign tlib;
|
||||
pthread_cond_wait :: (c: *CondBuf, m: *MutexBuf) -> i32 #foreign tlib;
|
||||
pthread_cond_signal :: (c: *CondBuf) -> i32 #foreign tlib;
|
||||
pthread_cond_broadcast :: (c: *CondBuf) -> i32 #foreign tlib;
|
||||
pthread_cond_destroy :: (c: *CondBuf) -> i32 #foreign tlib;
|
||||
|
||||
// darwin pthread_mutex_t: { long __sig; char __opaque[56]; } — 64 bytes.
|
||||
MutexBuf :: struct {
|
||||
sig: i64 = 0;
|
||||
o0: i64 = 0; o1: i64 = 0; o2: i64 = 0; o3: i64 = 0;
|
||||
o4: i64 = 0; o5: i64 = 0; o6: i64 = 0;
|
||||
}
|
||||
|
||||
// darwin pthread_cond_t: { long __sig; char __opaque[40]; } — 48 bytes.
|
||||
CondBuf :: struct {
|
||||
sig: i64 = 0;
|
||||
o0: i64 = 0; o1: i64 = 0; o2: i64 = 0; o3: i64 = 0; o4: i64 = 0;
|
||||
}
|
||||
|
||||
ThreadErr :: error {
|
||||
Spawn, // pthread_create refused
|
||||
Init, // mutex/cond/pool initialization failed
|
||||
}
|
||||
|
||||
// ── Mutex / Cond (in-place; see MOVE SEMANTICS above) ────────────────
|
||||
|
||||
Mutex :: struct {
|
||||
buf: MutexBuf = .{};
|
||||
|
||||
setup :: (self: *Mutex) -> bool {
|
||||
return pthread_mutex_init(@self.buf, null) == 0;
|
||||
}
|
||||
lock :: (self: *Mutex) {
|
||||
pthread_mutex_lock(@self.buf);
|
||||
}
|
||||
unlock :: (self: *Mutex) {
|
||||
pthread_mutex_unlock(@self.buf);
|
||||
}
|
||||
destroy :: (self: *Mutex) {
|
||||
pthread_mutex_destroy(@self.buf);
|
||||
}
|
||||
}
|
||||
|
||||
Cond :: struct {
|
||||
buf: CondBuf = .{};
|
||||
|
||||
setup :: (self: *Cond) -> bool {
|
||||
return pthread_cond_init(@self.buf, null) == 0;
|
||||
}
|
||||
// Atomically releases `m` and sleeps; reacquires `m` before returning.
|
||||
wait :: (self: *Cond, m: *Mutex) {
|
||||
pthread_cond_wait(@self.buf, @m.buf);
|
||||
}
|
||||
signal :: (self: *Cond) {
|
||||
pthread_cond_signal(@self.buf);
|
||||
}
|
||||
broadcast :: (self: *Cond) {
|
||||
pthread_cond_broadcast(@self.buf);
|
||||
}
|
||||
destroy :: (self: *Cond) {
|
||||
pthread_cond_destroy(@self.buf);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Thread ───────────────────────────────────────────────────────────
|
||||
|
||||
Thread :: struct {
|
||||
handle: usize = 0;
|
||||
|
||||
// `entry` is the C->sx boundary: callconv(.c), fabricates its own
|
||||
// Context before touching default-conv sx code (examples/1636).
|
||||
spawn :: (entry: (*void) -> *void callconv(.c), arg: *void) -> (Thread, !ThreadErr) {
|
||||
t : Thread = .{};
|
||||
if pthread_create(@t.handle, null, entry, arg) != 0 { raise error.Spawn; }
|
||||
return t;
|
||||
}
|
||||
join :: (self: *Thread) {
|
||||
pthread_join(self.handle, null);
|
||||
}
|
||||
detach :: (self: *Thread) {
|
||||
pthread_detach(self.handle);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Pool: fixed workers, bounded queue, backpressure ────────────────
|
||||
//
|
||||
// httpz's thread_pool shape: `submit` enqueues a task for the next free
|
||||
// worker and returns false when the backlog is full (the caller sheds —
|
||||
// reject, retry, or run inline). `shutdown` drains nothing: queued
|
||||
// tasks still run, then workers exit and join.
|
||||
|
||||
PoolTask :: struct {
|
||||
f: (usize) -> void; // default-conv: runs inside the worker's context
|
||||
arg: usize = 0;
|
||||
}
|
||||
|
||||
Pool :: struct {
|
||||
mu: Mutex = .{};
|
||||
nonempty: Cond = .{};
|
||||
tasks: [*]PoolTask = null;
|
||||
cap: i64 = 0;
|
||||
head: i64 = 0;
|
||||
len: i64 = 0;
|
||||
stop: bool = false;
|
||||
threads: [*]usize = null;
|
||||
count: i64 = 0;
|
||||
|
||||
// Heap-allocate (the pool must never move: workers hold its address,
|
||||
// and it embeds a live mutex), init in place, spawn the workers.
|
||||
create :: (workers: i64, backlog: i64) -> (*Pool, !ThreadErr) {
|
||||
alloc := context.allocator;
|
||||
p : *Pool = xx alloc.alloc_bytes(size_of(Pool));
|
||||
p.* = Pool.{};
|
||||
if !p.mu.setup() { raise error.Init; }
|
||||
if !p.nonempty.setup() { raise error.Init; }
|
||||
p.tasks = xx alloc.alloc_bytes(backlog * size_of(PoolTask));
|
||||
p.cap = backlog;
|
||||
p.threads = xx alloc.alloc_bytes(workers * size_of(usize));
|
||||
p.count = workers;
|
||||
i : i64 = 0;
|
||||
while i < workers {
|
||||
if pthread_create(@p.threads[i], null, pool_worker, xx p) != 0 {
|
||||
// join what started, then fail loudly
|
||||
p.count = i;
|
||||
p.shutdown();
|
||||
raise error.Spawn;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// False = backlog full (backpressure); the task did not enqueue.
|
||||
submit :: (self: *Pool, f: (usize) -> void, arg: usize) -> bool {
|
||||
self.mu.lock();
|
||||
if self.len == self.cap or self.stop {
|
||||
self.mu.unlock();
|
||||
return false;
|
||||
}
|
||||
slot := (self.head + self.len) % self.cap;
|
||||
self.tasks[slot] = PoolTask.{ f = f, arg = arg };
|
||||
self.len += 1;
|
||||
self.nonempty.signal();
|
||||
self.mu.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop accepting work, let queued tasks finish, join every worker.
|
||||
shutdown :: (self: *Pool) {
|
||||
self.mu.lock();
|
||||
self.stop = true;
|
||||
self.nonempty.broadcast();
|
||||
self.mu.unlock();
|
||||
i : i64 = 0;
|
||||
while i < self.count {
|
||||
pthread_join(self.threads[i], null);
|
||||
i += 1;
|
||||
}
|
||||
self.mu.destroy();
|
||||
self.nonempty.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// The worker loop: C entry, own fabricated Context, then
|
||||
// pop-task/run-task until stop with an empty queue.
|
||||
pool_worker :: (arg: *void) -> *void callconv(.c) {
|
||||
p : *Pool = xx arg;
|
||||
gpa := GPA.init();
|
||||
push Context.{ allocator = xx gpa } {
|
||||
while true {
|
||||
p.mu.lock();
|
||||
while !p.stop and p.len == 0 {
|
||||
p.nonempty.wait(@p.mu);
|
||||
}
|
||||
if p.len == 0 { // stop, and nothing queued
|
||||
p.mu.unlock();
|
||||
break;
|
||||
}
|
||||
t := p.tasks[p.head];
|
||||
p.head = (p.head + 1) % p.cap;
|
||||
p.len -= 1;
|
||||
p.mu.unlock();
|
||||
f := t.f;
|
||||
f(t.arg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user