authorgravatar for services@mlugg.co.ukmlugg <services@mlugg.co.uk> 2026-08-07 19:24:07+02:00
committergravatar for services@mlugg.co.ukmlugg <services@mlugg.co.uk> 2026-08-07 19:24:07+02:00
log3d35188fe8c423e7afed863def0fa9ac347230f2
tree1f173c2a5163ff865432506264be9464ca3d431d
parent9d27b6289b592d312618d87819d533dc6e140ccd
parentfae25d72a94f09500cd15c7ff09caf939e7af1ab

Merge pull request 'remove haiku from defaultSingleThreaded' (#32137) from ypsvlq/zig:master into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32137 Reviewed-by: mlugg <services@mlugg.co.uk>

5 files changed, 101 insertions(+), 93 deletions(-)

lib/std/Io/Threaded.zig+69-5
......@@ -829,6 +829,7 @@ const Thread = struct {
829829 /// Always released when `Status.cancelation` is set to `.parked`.
830830 futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
831831 unpark_flag: UnparkFlag,
832 park_tid: if (ParkTid == std.Thread.Id) void else ParkTid,
832833
833834 csprng: Csprng,
834835
......@@ -1220,7 +1221,7 @@ const Thread = struct {
12201221 parking_futex.removeCanceledWaiter(futex_waiter);
12211222 }
12221223 if (need_unpark_flag) setUnparkFlag(&thread.unpark_flag);
1223 unpark(&.{thread.id}, null);
1224 unpark(&.{if (ParkTid == std.Thread.Id) thread.id else thread.park_tid}, null);
12241225 return false;
12251226 },
12261227
......@@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void {
17491750 .cancel_protection = .unblocked,
17501751 .futex_waiter = undefined,
17511752 .unpark_flag = unpark_flag_init,
1753 .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(),
17521754 .csprng = .uninitialized,
17531755 };
17541756 Thread.current = &thread;
......@@ -17431,6 +17433,7 @@ const use_parking_futex = switch (native_os) {
1743117433 .windows => true, // RtlWaitOnAddress is a userland implementation anyway
1743217434 .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now.
1743317435 .illumos => true, // Illumos has no futex mechanism
17436 .haiku => true, // Haiku has no futex mechanism
1743417437 else => false,
1743517438};
1743617439const use_parking_sleep = switch (native_os) {
......@@ -17476,7 +17479,7 @@ const parking_futex = struct {
1747617479 const Waiter = struct {
1747717480 node: std.DoublyLinkedList.Node,
1747817481 address: usize,
17479 tid: std.Thread.Id,
17482 tid: ParkTid,
1748017483 /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread
1748117484 /// which atomically updates it (to `.none` or `.canceling`) is responsible for:
1748217485 ///
......@@ -17517,7 +17520,7 @@ const parking_futex = struct {
1751717520
1751817521 // Put the threadlocal access outside of the critical section.
1751917522 const opt_thread = Thread.current;
17520 const self_tid = if (opt_thread) |thread| thread.id else std.Thread.getCurrentId();
17523 const self_tid = getParkTid();
1752117524
1752217525 var waiter: Waiter = .{
1752317526 .node = undefined, // populated by list append
......@@ -17765,7 +17768,12 @@ const parking_sleep = struct {
1776517768 },
1776617769 }
1776717770 }
17771
1776817772 // Uncancelable sleep; we expect not to be manually unparked.
17773
17774 // On systems where parking the thread requires a one-time setup operation (e.g. creating a
17775 // semaphore), we need to ensure that setup is done before we call `park`.
17776 _ = getParkTid();
1776917777 var dummy_flag: UnparkFlag = unpark_flag_init;
1777017778 if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {
1777117779 unreachable; // unexpected unpark
......@@ -17804,7 +17812,7 @@ const ParkingMutex = struct {
1780417812 /// Never modified once the `Waiter` is in the linked list.
1780517813 next: ?*Waiter,
1780617814 /// Never modified once the `Waiter` is in the linked list.
17807 tid: std.Thread.Id,
17815 tid: ParkTid,
1780817816 };
1780917817 fn lock(m: *ParkingMutex) void {
1781017818 state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case
......@@ -17820,7 +17828,7 @@ const ParkingMutex = struct {
1782017828
1782117829 .locked_once, _ => |last_state| {
1782217830 const old_waiter = last_state.waiter();
17823 const self_tid = if (Thread.current) |t| t.id else std.Thread.getCurrentId();
17831 const self_tid = getParkTid();
1782417832 var waiter: Waiter = .{
1782517833 .next = old_waiter,
1782617834 .unpark_flag = unpark_flag_init,
......@@ -17948,9 +17956,36 @@ fn setUnparkFlag(f: *UnparkFlag) void {
1794817956/// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be.
1794917957const UnparkTid = switch (native_os) {
1795017958 .windows => usize,
17959 else => ParkTid,
17960};
17961
17962const ParkTid = switch (native_os) {
17963 .haiku => std.c.sem_id,
1795117964 else => std.Thread.Id,
1795217965};
1795317966
17967threadlocal var park_sem: std.c.sem_id = -1;
17968
17969fn getParkTid() ParkTid {
17970 switch (native_os) {
17971 .haiku => {
17972 if (park_sem == -1) {
17973 park_sem = std.c._kern_create_sem(0, null);
17974 if (park_sem < 0) @panic("_kern_create_sem failed");
17975 _ = std.c.on_exit_thread(destroyParkSem, null);
17976 }
17977 return park_sem;
17978 },
17979 else => {
17980 return if (Thread.current) |thread| thread.id else std.Thread.getCurrentId();
17981 },
17982 }
17983}
17984
17985fn destroyParkSem(_: ?*anyopaque) callconv(.c) void {
17986 _ = std.c._kern_delete_sem(park_sem);
17987}
17988
1795417989fn park(
1795517990 timeout: Io.Timeout,
1795617991 /// This value has no semantic effect, but may allow the OS to optimize the operation.
......@@ -18016,6 +18051,27 @@ fn park(
1801618051 }
1801718052 },
1801818053 .illumos => @panic("TODO: illumos lwp_park"),
18054 .haiku => {
18055 const timeout_flags: u32, const timeout_us = switch (timeout) {
18056 .none => .{ 0, 0 },
18057 .deadline => |deadline| .{
18058 if (deadline.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
18059 deadline.raw.toMicroseconds(),
18060 },
18061 .duration => |duration| .{
18062 if (duration.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
18063 nowPosix(duration.clock).addDuration(duration.raw).toMicroseconds(),
18064 },
18065 };
18066 while (true) {
18067 switch (std.c._kern_acquire_sem_etc(park_sem, 1, timeout_flags, timeout_us)) {
18068 0 => return,
18069 std.c.E.B_TIMED_OUT => return error.Timeout,
18070 std.c.E.B_INTERRUPTED => {},
18071 else => unreachable,
18072 }
18073 }
18074 },
1801918075 else => comptime unreachable,
1802018076 }
1802118077}
......@@ -18058,6 +18114,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void {
1805818114 }
1805918115 },
1806018116 .illumos => @panic("TODO: illumos lwp_unpark"),
18117 .haiku => {
18118 for (tids) |tid| {
18119 switch (std.c._kern_release_sem_etc(tid, 1, 0)) {
18120 0 => {},
18121 else => recoverableOsBugDetected(),
18122 }
18123 }
18124 },
1806118125 else => comptime unreachable,
1806218126 }
1806318127}
lib/std/Thread.zig+3-4
......@@ -719,10 +719,9 @@ const PosixThreadImpl = struct {
719719 },
720720 .haiku => {
721721 var system_info: std.c.system_info = undefined;
722 const rc = std.c.get_system_info(&system_info); // always returns B_OK
723 return switch (posix.errno(rc)) {
724 .SUCCESS => @as(usize, @intCast(system_info.cpu_count)),
725 else => |err| posix.unexpectedErrno(err),
722 return switch (std.c.get_system_info(&system_info)) {
723 0 => @as(usize, @intCast(system_info.cpu_count)),
724 else => error.Unexpected,
726725 };
727726 },
728727 else => {
lib/std/c.zig+11-11
......@@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) {
29912991 pub const UNBLOCK = 2;
29922992 pub const SETMASK = 3;
29932993
2994 pub const IO: SIG = .POLL;
29942995 pub const IOT: SIG = .ABRT;
29952996
29962997 HUP = 1,
......@@ -11267,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;
1126711268pub const taskid_t = illumos.taskid_t;
1126811269pub const zoneid_t = illumos.zoneid_t;
1126911270
11271pub const B_ABSOLUTE_TIMEOUT = haiku.B_ABSOLUTE_TIMEOUT;
11272pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH;
11273pub const B_TIMEOUT_REAL_TIME_BASE = haiku.B_TIMEOUT_REAL_TIME_BASE;
1127011274pub const DirEnt = haiku.DirEnt;
11271pub const _get_next_area_info = haiku._get_next_area_info;
11272pub const _get_next_image_info = haiku._get_next_image_info;
11273pub const _get_team_info = haiku._get_team_info;
11274pub const _kern_get_current_team = haiku._kern_get_current_team;
11275pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc;
11276pub const _kern_create_sem = haiku._kern_create_sem;
11277pub const _kern_delete_sem = haiku._kern_delete_sem;
1127511278pub const _kern_open_dir = haiku._kern_open_dir;
1127611279pub const _kern_read_dir = haiku._kern_read_dir;
1127711280pub const _kern_read_stat = haiku._kern_read_stat;
11281pub const _kern_release_sem_etc = haiku._kern_release_sem_etc;
1127811282pub const _kern_rewind_dir = haiku._kern_rewind_dir;
11279pub const readv_pos = haiku.readv_pos;
11280pub const writev_pos = haiku.writev_pos;
1128111283pub const area_id = haiku.area_id;
11282pub const area_info = haiku.area_info;
11283pub const directory_which = haiku.directory_which;
11284pub const find_directory = haiku.find_directory;
1128511284pub const find_thread = haiku.find_thread;
1128611285pub const get_system_info = haiku.get_system_info;
11287pub const image_info = haiku.image_info;
11286pub const on_exit_thread = haiku.on_exit_thread;
1128811287pub const port_id = haiku.port_id;
11288pub const readv_pos = haiku.readv_pos;
1128911289pub const sem_id = haiku.sem_id;
1129011290pub const status_t = haiku.status_t;
1129111291pub const system_info = haiku.system_info;
1129211292pub const team_id = haiku.team_id;
11293pub const team_info = haiku.team_info;
1129411293pub const thread_id = haiku.thread_id;
11294pub const writev_pos = haiku.writev_pos;
1129511295
1129611296pub const AUTH = openbsd.AUTH;
1129711297pub const BI = openbsd.BI;
lib/std/c/haiku.zig+18-69
......@@ -1,15 +1,8 @@
11const std = @import("../std.zig");
2const assert = std.debug.assert;
32const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;
7const socklen_t = std.c.socklen_t;
3const assert = std.debug.assert;
84const fd_t = std.c.fd_t;
95const off_t = std.c.off_t;
10const PATH_MAX = std.c.PATH_MAX;
11const uid_t = std.c.uid_t;
12const gid_t = std.c.gid_t;
136const dev_t = std.c.dev_t;
147const ino_t = std.c.ino_t;
158
......@@ -17,52 +10,27 @@ comptime {
1710 assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.
1811}
1912
20pub extern "root" fn _errnop() *i32;
21pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
22pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;
23pub extern "root" fn get_system_info(system_info: *system_info) usize;
24pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;
25pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;
26pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;
27pub extern "root" fn _kern_get_current_team() team_id;
13pub const B_OS_NAME_LENGTH = 32;
14pub const B_ABSOLUTE_TIMEOUT = 0x10;
15pub const B_TIMEOUT_REAL_TIME_BASE = 0x40;
16
17pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id;
18pub extern "root" fn _kern_delete_sem(id: sem_id) status_t;
19pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t;
20pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t;
2821pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
2922pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
3023pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
3124pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
32pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
33pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
3425
35pub const area_info = extern struct {
36 area: u32,
37 name: [32]u8,
38 size: usize,
39 lock: u32,
40 protection: u32,
41 team_id: i32,
42 ram_size: u32,
43 copy_count: u32,
44 in_count: u32,
45 out_count: u32,
46 address: *anyopaque,
47};
26pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t;
27pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id;
28pub extern "root" fn get_system_info(info: *system_info) status_t;
4829
49pub const image_info = extern struct {
50 id: u32,
51 image_type: u32,
52 sequence: i32,
53 init_order: i32,
54 init_routine: *anyopaque,
55 term_routine: *anyopaque,
56 device: i32,
57 node: i64,
58 name: [PATH_MAX]u8,
59 text: *anyopaque,
60 data: *anyopaque,
61 text_size: i32,
62 data_size: i32,
63 api_version: i32,
64 abi: i32,
65};
30pub extern "root" fn _errnop() *i32;
31
32pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
33pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
6634
6735pub const system_info = extern struct {
6836 boot_time: i64,
......@@ -86,31 +54,12 @@ pub const system_info = extern struct {
8654 max_teams: u32,
8755 used_teams: u32,
8856 kernel_name: [256]u8,
89 kernel_build_date: [32]u8,
90 kernel_build_time: [32]u8,
57 kernel_build_date: [B_OS_NAME_LENGTH]u8,
58 kernel_build_time: [B_OS_NAME_LENGTH]u8,
9159 kernel_version: i64,
9260 abi: u32,
9361};
9462
95pub const team_info = extern struct {
96 team_id: i32,
97 thread_count: i32,
98 image_count: i32,
99 area_count: i32,
100 debugger_nub_thread: i32,
101 debugger_nub_port: i32,
102 argc: i32,
103 args: [64]u8,
104 uid: uid_t,
105 gid: gid_t,
106};
107
108pub const directory_which = enum(i32) {
109 B_USER_SETTINGS_DIRECTORY = 0xbbe,
110
111 _,
112};
113
11463pub const area_id = i32;
11564pub const port_id = i32;
11665pub const sem_id = i32;
src/target.zig-4
......@@ -118,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {
118118 .wasm32, .wasm64 => return true,
119119 else => {},
120120 }
121 switch (target.os.tag) {
122 .haiku => return true,
123 else => {},
124 }
125121 return false;
126122}
127123