| author | |
| committer | |
| log | 3d35188fe8c423e7afed863def0fa9ac347230f2 |
| tree | 1f173c2a5163ff865432506264be9464ca3d431d |
| parent | 9d27b6289b592d312618d87819d533dc6e140ccd |
| parent | fae25d72a94f09500cd15c7ff09caf939e7af1ab |
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 { |
| 829 | 829 | /// Always released when `Status.cancelation` is set to `.parked`. |
| 830 | 830 | futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn, |
| 831 | 831 | unpark_flag: UnparkFlag, |
| 832 | park_tid: if (ParkTid == std.Thread.Id) void else ParkTid, | |
| 832 | 833 | |
| 833 | 834 | csprng: Csprng, |
| 834 | 835 | |
| ... | ... | @@ -1220,7 +1221,7 @@ const Thread = struct { |
| 1220 | 1221 | parking_futex.removeCanceledWaiter(futex_waiter); |
| 1221 | 1222 | } |
| 1222 | 1223 | 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); | |
| 1224 | 1225 | return false; |
| 1225 | 1226 | }, |
| 1226 | 1227 | |
| ... | ... | @@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void { |
| 1749 | 1750 | .cancel_protection = .unblocked, |
| 1750 | 1751 | .futex_waiter = undefined, |
| 1751 | 1752 | .unpark_flag = unpark_flag_init, |
| 1753 | .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(), | |
| 1752 | 1754 | .csprng = .uninitialized, |
| 1753 | 1755 | }; |
| 1754 | 1756 | Thread.current = &thread; |
| ... | ... | @@ -17431,6 +17433,7 @@ const use_parking_futex = switch (native_os) { |
| 17431 | 17433 | .windows => true, // RtlWaitOnAddress is a userland implementation anyway |
| 17432 | 17434 | .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now. |
| 17433 | 17435 | .illumos => true, // Illumos has no futex mechanism |
| 17436 | .haiku => true, // Haiku has no futex mechanism | |
| 17434 | 17437 | else => false, |
| 17435 | 17438 | }; |
| 17436 | 17439 | const use_parking_sleep = switch (native_os) { |
| ... | ... | @@ -17476,7 +17479,7 @@ const parking_futex = struct { |
| 17476 | 17479 | const Waiter = struct { |
| 17477 | 17480 | node: std.DoublyLinkedList.Node, |
| 17478 | 17481 | address: usize, |
| 17479 | tid: std.Thread.Id, | |
| 17482 | tid: ParkTid, | |
| 17480 | 17483 | /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread |
| 17481 | 17484 | /// which atomically updates it (to `.none` or `.canceling`) is responsible for: |
| 17482 | 17485 | /// |
| ... | ... | @@ -17517,7 +17520,7 @@ const parking_futex = struct { |
| 17517 | 17520 | |
| 17518 | 17521 | // Put the threadlocal access outside of the critical section. |
| 17519 | 17522 | const opt_thread = Thread.current; |
| 17520 | const self_tid = if (opt_thread) |thread| thread.id else std.Thread.getCurrentId(); | |
| 17523 | const self_tid = getParkTid(); | |
| 17521 | 17524 | |
| 17522 | 17525 | var waiter: Waiter = .{ |
| 17523 | 17526 | .node = undefined, // populated by list append |
| ... | ... | @@ -17765,7 +17768,12 @@ const parking_sleep = struct { |
| 17765 | 17768 | }, |
| 17766 | 17769 | } |
| 17767 | 17770 | } |
| 17771 | ||
| 17768 | 17772 | // 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(); | |
| 17769 | 17777 | var dummy_flag: UnparkFlag = unpark_flag_init; |
| 17770 | 17778 | if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) { |
| 17771 | 17779 | unreachable; // unexpected unpark |
| ... | ... | @@ -17804,7 +17812,7 @@ const ParkingMutex = struct { |
| 17804 | 17812 | /// Never modified once the `Waiter` is in the linked list. |
| 17805 | 17813 | next: ?*Waiter, |
| 17806 | 17814 | /// Never modified once the `Waiter` is in the linked list. |
| 17807 | tid: std.Thread.Id, | |
| 17815 | tid: ParkTid, | |
| 17808 | 17816 | }; |
| 17809 | 17817 | fn lock(m: *ParkingMutex) void { |
| 17810 | 17818 | state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case |
| ... | ... | @@ -17820,7 +17828,7 @@ const ParkingMutex = struct { |
| 17820 | 17828 | |
| 17821 | 17829 | .locked_once, _ => |last_state| { |
| 17822 | 17830 | 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(); | |
| 17824 | 17832 | var waiter: Waiter = .{ |
| 17825 | 17833 | .next = old_waiter, |
| 17826 | 17834 | .unpark_flag = unpark_flag_init, |
| ... | ... | @@ -17948,9 +17956,36 @@ fn setUnparkFlag(f: *UnparkFlag) void { |
| 17948 | 17956 | /// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be. |
| 17949 | 17957 | const UnparkTid = switch (native_os) { |
| 17950 | 17958 | .windows => usize, |
| 17959 | else => ParkTid, | |
| 17960 | }; | |
| 17961 | ||
| 17962 | const ParkTid = switch (native_os) { | |
| 17963 | .haiku => std.c.sem_id, | |
| 17951 | 17964 | else => std.Thread.Id, |
| 17952 | 17965 | }; |
| 17953 | 17966 | |
| 17967 | threadlocal var park_sem: std.c.sem_id = -1; | |
| 17968 | ||
| 17969 | fn 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 | ||
| 17985 | fn destroyParkSem(_: ?*anyopaque) callconv(.c) void { | |
| 17986 | _ = std.c._kern_delete_sem(park_sem); | |
| 17987 | } | |
| 17988 | ||
| 17954 | 17989 | fn park( |
| 17955 | 17990 | timeout: Io.Timeout, |
| 17956 | 17991 | /// This value has no semantic effect, but may allow the OS to optimize the operation. |
| ... | ... | @@ -18016,6 +18051,27 @@ fn park( |
| 18016 | 18051 | } |
| 18017 | 18052 | }, |
| 18018 | 18053 | .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 | }, | |
| 18019 | 18075 | else => comptime unreachable, |
| 18020 | 18076 | } |
| 18021 | 18077 | } |
| ... | ... | @@ -18058,6 +18114,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void { |
| 18058 | 18114 | } |
| 18059 | 18115 | }, |
| 18060 | 18116 | .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 | }, | |
| 18061 | 18125 | else => comptime unreachable, |
| 18062 | 18126 | } |
| 18063 | 18127 | } |
lib/std/Thread.zig+3-4| ... | ... | @@ -719,10 +719,9 @@ const PosixThreadImpl = struct { |
| 719 | 719 | }, |
| 720 | 720 | .haiku => { |
| 721 | 721 | 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, | |
| 726 | 725 | }; |
| 727 | 726 | }, |
| 728 | 727 | else => { |
lib/std/c.zig+11-11| ... | ... | @@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) { |
| 2991 | 2991 | pub const UNBLOCK = 2; |
| 2992 | 2992 | pub const SETMASK = 3; |
| 2993 | 2993 | |
| 2994 | pub const IO: SIG = .POLL; | |
| 2994 | 2995 | pub const IOT: SIG = .ABRT; |
| 2995 | 2996 | |
| 2996 | 2997 | HUP = 1, |
| ... | ... | @@ -11267,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo; |
| 11267 | 11268 | pub const taskid_t = illumos.taskid_t; |
| 11268 | 11269 | pub const zoneid_t = illumos.zoneid_t; |
| 11269 | 11270 | |
| 11271 | pub const B_ABSOLUTE_TIMEOUT = haiku.B_ABSOLUTE_TIMEOUT; | |
| 11272 | pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH; | |
| 11273 | pub const B_TIMEOUT_REAL_TIME_BASE = haiku.B_TIMEOUT_REAL_TIME_BASE; | |
| 11270 | 11274 | pub const DirEnt = haiku.DirEnt; |
| 11271 | pub const _get_next_area_info = haiku._get_next_area_info; | |
| 11272 | pub const _get_next_image_info = haiku._get_next_image_info; | |
| 11273 | pub const _get_team_info = haiku._get_team_info; | |
| 11274 | pub const _kern_get_current_team = haiku._kern_get_current_team; | |
| 11275 | pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc; | |
| 11276 | pub const _kern_create_sem = haiku._kern_create_sem; | |
| 11277 | pub const _kern_delete_sem = haiku._kern_delete_sem; | |
| 11275 | 11278 | pub const _kern_open_dir = haiku._kern_open_dir; |
| 11276 | 11279 | pub const _kern_read_dir = haiku._kern_read_dir; |
| 11277 | 11280 | pub const _kern_read_stat = haiku._kern_read_stat; |
| 11281 | pub const _kern_release_sem_etc = haiku._kern_release_sem_etc; | |
| 11278 | 11282 | pub const _kern_rewind_dir = haiku._kern_rewind_dir; |
| 11279 | pub const readv_pos = haiku.readv_pos; | |
| 11280 | pub const writev_pos = haiku.writev_pos; | |
| 11281 | 11283 | pub const area_id = haiku.area_id; |
| 11282 | pub const area_info = haiku.area_info; | |
| 11283 | pub const directory_which = haiku.directory_which; | |
| 11284 | pub const find_directory = haiku.find_directory; | |
| 11285 | 11284 | pub const find_thread = haiku.find_thread; |
| 11286 | 11285 | pub const get_system_info = haiku.get_system_info; |
| 11287 | pub const image_info = haiku.image_info; | |
| 11286 | pub const on_exit_thread = haiku.on_exit_thread; | |
| 11288 | 11287 | pub const port_id = haiku.port_id; |
| 11288 | pub const readv_pos = haiku.readv_pos; | |
| 11289 | 11289 | pub const sem_id = haiku.sem_id; |
| 11290 | 11290 | pub const status_t = haiku.status_t; |
| 11291 | 11291 | pub const system_info = haiku.system_info; |
| 11292 | 11292 | pub const team_id = haiku.team_id; |
| 11293 | pub const team_info = haiku.team_info; | |
| 11294 | 11293 | pub const thread_id = haiku.thread_id; |
| 11294 | pub const writev_pos = haiku.writev_pos; | |
| 11295 | 11295 | |
| 11296 | 11296 | pub const AUTH = openbsd.AUTH; |
| 11297 | 11297 | pub const BI = openbsd.BI; |
lib/std/c/haiku.zig+18-69| ... | ... | @@ -1,15 +1,8 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | |
| 3 | 2 | const builtin = @import("builtin"); |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | const iovec = std.posix.iovec; | |
| 6 | const iovec_const = std.posix.iovec_const; | |
| 7 | const socklen_t = std.c.socklen_t; | |
| 3 | const assert = std.debug.assert; | |
| 8 | 4 | const fd_t = std.c.fd_t; |
| 9 | 5 | const off_t = std.c.off_t; |
| 10 | const PATH_MAX = std.c.PATH_MAX; | |
| 11 | const uid_t = std.c.uid_t; | |
| 12 | const gid_t = std.c.gid_t; | |
| 13 | 6 | const dev_t = std.c.dev_t; |
| 14 | 7 | const ino_t = std.c.ino_t; |
| 15 | 8 | |
| ... | ... | @@ -17,52 +10,27 @@ comptime { |
| 17 | 10 | assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS. |
| 18 | 11 | } |
| 19 | 12 | |
| 20 | pub extern "root" fn _errnop() *i32; | |
| 21 | pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; | |
| 22 | pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32; | |
| 23 | pub extern "root" fn get_system_info(system_info: *system_info) usize; | |
| 24 | pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32; | |
| 25 | pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32; | |
| 26 | pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32; | |
| 27 | pub extern "root" fn _kern_get_current_team() team_id; | |
| 13 | pub const B_OS_NAME_LENGTH = 32; | |
| 14 | pub const B_ABSOLUTE_TIMEOUT = 0x10; | |
| 15 | pub const B_TIMEOUT_REAL_TIME_BASE = 0x40; | |
| 16 | ||
| 17 | pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id; | |
| 18 | pub extern "root" fn _kern_delete_sem(id: sem_id) status_t; | |
| 19 | pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t; | |
| 20 | pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t; | |
| 28 | 21 | pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t; |
| 29 | 22 | pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize; |
| 30 | 23 | pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t; |
| 31 | 24 | pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t; |
| 32 | pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize; | |
| 33 | pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize; | |
| 34 | 25 | |
| 35 | pub 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 | }; | |
| 26 | pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t; | |
| 27 | pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id; | |
| 28 | pub extern "root" fn get_system_info(info: *system_info) status_t; | |
| 48 | 29 | |
| 49 | pub 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 | }; | |
| 30 | pub extern "root" fn _errnop() *i32; | |
| 31 | ||
| 32 | pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize; | |
| 33 | pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize; | |
| 66 | 34 | |
| 67 | 35 | pub const system_info = extern struct { |
| 68 | 36 | boot_time: i64, |
| ... | ... | @@ -86,31 +54,12 @@ pub const system_info = extern struct { |
| 86 | 54 | max_teams: u32, |
| 87 | 55 | used_teams: u32, |
| 88 | 56 | 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, | |
| 91 | 59 | kernel_version: i64, |
| 92 | 60 | abi: u32, |
| 93 | 61 | }; |
| 94 | 62 | |
| 95 | pub 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 | ||
| 108 | pub const directory_which = enum(i32) { | |
| 109 | B_USER_SETTINGS_DIRECTORY = 0xbbe, | |
| 110 | ||
| 111 | _, | |
| 112 | }; | |
| 113 | ||
| 114 | 63 | pub const area_id = i32; |
| 115 | 64 | pub const port_id = i32; |
| 116 | 65 | pub const sem_id = i32; |
src/target.zig-4| ... | ... | @@ -118,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool { |
| 118 | 118 | .wasm32, .wasm64 => return true, |
| 119 | 119 | else => {}, |
| 120 | 120 | } |
| 121 | switch (target.os.tag) { | |
| 122 | .haiku => return true, | |
| 123 | else => {}, | |
| 124 | } | |
| 125 | 121 | return false; |
| 126 | 122 | } |
| 127 | 123 |