mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 02:44:43 +01:00
Merge pull request 'bsd-futex' (#30626) from mikdusan/zig:bsd-futex into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30626 Reviewed-by: Andrew Kelley <andrewrk@noreply.codeberg.org>
This commit is contained in:
commit
1eb8fe7c61
6 changed files with 97 additions and 11 deletions
|
|
@ -66,13 +66,13 @@ pub fn main() void {
|
|||
}
|
||||
|
||||
if (listen) {
|
||||
return mainServer() catch @panic("internal test runner failure");
|
||||
return mainServer(args) catch @panic("internal test runner failure");
|
||||
} else {
|
||||
return mainTerminal();
|
||||
return mainTerminal(args);
|
||||
}
|
||||
}
|
||||
|
||||
fn mainServer() !void {
|
||||
fn mainServer(args: []const [:0]const u8) !void {
|
||||
@disableInstrumentation();
|
||||
var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io, &stdin_buffer);
|
||||
var stdout_writer = Io.File.stdout().writerStreaming(runner_threaded_io, &stdout_buffer);
|
||||
|
|
@ -131,7 +131,9 @@ fn mainServer() !void {
|
|||
|
||||
.run_test => {
|
||||
testing.allocator_instance = .{};
|
||||
testing.io_instance = .init(testing.allocator, .{});
|
||||
testing.io_instance = .init(testing.allocator, .{
|
||||
.argv0 = if (@hasField(Io.Threaded.Argv0, "value")) .{ .value = args[0] } else .{},
|
||||
});
|
||||
log_err_count = 0;
|
||||
const index = try server.receiveBody_u32();
|
||||
const test_fn = builtin.test_functions[index];
|
||||
|
|
@ -215,7 +217,7 @@ fn mainServer() !void {
|
|||
}
|
||||
}
|
||||
|
||||
fn mainTerminal() void {
|
||||
fn mainTerminal(args: []const [:0]const u8) void {
|
||||
@disableInstrumentation();
|
||||
if (builtin.fuzz) @panic("fuzz test requires server");
|
||||
|
||||
|
|
@ -233,7 +235,9 @@ fn mainTerminal() void {
|
|||
var leaks: usize = 0;
|
||||
for (test_fn_list, 0..) |test_fn, i| {
|
||||
testing.allocator_instance = .{};
|
||||
testing.io_instance = .init(testing.allocator, .{});
|
||||
testing.io_instance = .init(testing.allocator, .{
|
||||
.argv0 = if (@hasField(Io.Threaded.Argv0, "value")) .{ .value = args[0] } else .{},
|
||||
});
|
||||
defer {
|
||||
testing.io_instance.deinit();
|
||||
if (testing.allocator_instance.deinit() == .leak) leaks += 1;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ pub const Reader = struct {
|
|||
},
|
||||
.wasi => @sizeOf(std.os.wasi.dirent_t) +
|
||||
std.mem.alignForward(usize, max_name_bytes, @alignOf(std.os.wasi.dirent_t)),
|
||||
.openbsd => std.c.S.BLKSIZE,
|
||||
else => if (builtin.link_libc) @sizeOf(std.c.dirent) else std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -390,6 +390,52 @@ const Thread = struct {
|
|||
else => unreachable,
|
||||
};
|
||||
},
|
||||
.openbsd => {
|
||||
var tm: std.c.timespec = undefined;
|
||||
var tm_ptr: ?*const std.c.timespec = null;
|
||||
if (timeout_ns) |ns| {
|
||||
tm_ptr = &tm;
|
||||
tm = timestampToPosix(ns);
|
||||
}
|
||||
if (thread) |t| try t.beginSyscall();
|
||||
const rc = std.c.futex(
|
||||
ptr,
|
||||
std.c.FUTEX.WAIT | std.c.FUTEX.PRIVATE_FLAG,
|
||||
@as(c_int, @bitCast(expect)),
|
||||
tm_ptr,
|
||||
null, // uaddr2 is ignored
|
||||
);
|
||||
if (thread) |t| t.endSyscall();
|
||||
if (is_debug) switch (posix.errno(rc)) {
|
||||
.SUCCESS => {},
|
||||
.NOSYS => unreachable, // constant op known good value
|
||||
.AGAIN => {}, // contents of uaddr != val
|
||||
.INVAL => unreachable, // invalid timeout
|
||||
.TIMEDOUT => {}, // timeout
|
||||
.INTR => {}, // a signal arrived
|
||||
.CANCELED => {}, // a signal arrived and SA_RESTART was set
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
.dragonfly => {
|
||||
var timeout_us: c_int = undefined;
|
||||
if (timeout_ns) |ns| {
|
||||
timeout_us = std.math.cast(c_int, ns / std.time.ns_per_us) orelse std.math.maxInt(c_int);
|
||||
} else {
|
||||
timeout_us = 0;
|
||||
}
|
||||
if (thread) |t| try t.beginSyscall();
|
||||
const rc = std.c.umtx_sleep(@ptrCast(ptr), @bitCast(expect), timeout_us);
|
||||
if (thread) |t| t.endSyscall();
|
||||
if (is_debug) switch (std.posix.errno(rc)) {
|
||||
.SUCCESS => {},
|
||||
.BUSY => {}, // ptr != expect
|
||||
.AGAIN => {}, // maybe timed out, or paged out, or hit 2s kernel refresh
|
||||
.INTR => {}, // spurious wake
|
||||
.INVAL => unreachable, // invalid timeout
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
else => if (std.Thread.use_pthreads) {
|
||||
// TODO integrate the following function being called with robust cancelation.
|
||||
return pthreads_futex.wait(ptr, expect, timeout_ns) catch |err| switch (err) {
|
||||
|
|
@ -473,6 +519,23 @@ const Thread = struct {
|
|||
else => unreachable, // deadlock due to operating system bug
|
||||
}
|
||||
},
|
||||
.openbsd => {
|
||||
const rc = std.c.futex(
|
||||
ptr,
|
||||
std.c.FUTEX.WAKE | std.c.FUTEX.PRIVATE_FLAG,
|
||||
@min(max_waiters, std.math.maxInt(c_int)),
|
||||
null, // timeout is ignored
|
||||
null, // uaddr2 is ignored
|
||||
);
|
||||
assert(rc >= 0);
|
||||
},
|
||||
.dragonfly => {
|
||||
// will generally return 0 unless the address is bad
|
||||
_ = std.c.umtx_wakeup(
|
||||
@ptrCast(ptr),
|
||||
@min(max_waiters, std.math.maxInt(c_int)),
|
||||
);
|
||||
},
|
||||
else => if (std.Thread.use_pthreads) {
|
||||
return pthreads_futex.wake(ptr, max_waiters);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -167,6 +167,18 @@ pub const timespec = switch (native_os) {
|
|||
.openbsd, .haiku => extern struct {
|
||||
sec: time_t,
|
||||
nsec: isize,
|
||||
|
||||
/// For use with `utimensat` and `futimens`.
|
||||
pub const NOW: timespec = .{
|
||||
.sec = 0, // ignored
|
||||
.nsec = -2,
|
||||
};
|
||||
|
||||
/// For use with `utimensat` and `futimens`.
|
||||
pub const OMIT: timespec = .{
|
||||
.sec = 0, // ignored
|
||||
.nsec = -1,
|
||||
};
|
||||
},
|
||||
else => void,
|
||||
};
|
||||
|
|
@ -2365,6 +2377,8 @@ pub const S = switch (native_os) {
|
|||
pub const IWOTH = 0o002;
|
||||
pub const IXOTH = 0o001;
|
||||
|
||||
pub const BLKSIZE = 512;
|
||||
|
||||
pub fn ISFIFO(m: u32) bool {
|
||||
return m & IFMT == IFIFO;
|
||||
}
|
||||
|
|
@ -9676,6 +9690,7 @@ pub const NSIG = switch (native_os) {
|
|||
.illumos => 75,
|
||||
// https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42
|
||||
.openbsd, .serenity => 33,
|
||||
.dragonfly => 64,
|
||||
else => {},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -645,6 +645,7 @@ fn contains(entries: *const std.array_list.Managed(Dir.Entry), el: Dir.Entry) bo
|
|||
|
||||
test "Dir.realPath smoke test" {
|
||||
if (native_os == .wasi) return error.SkipZigTest;
|
||||
if (native_os == .openbsd) return error.SkipZigTest;
|
||||
|
||||
try testWithAllSupportedPathTypes(struct {
|
||||
fn impl(ctx: *TestContext) !void {
|
||||
|
|
@ -820,7 +821,7 @@ test "file operations on directories" {
|
|||
try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{}));
|
||||
try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name));
|
||||
switch (native_os) {
|
||||
.dragonfly, .netbsd => {
|
||||
.netbsd => {
|
||||
// no error when reading a directory. See https://github.com/ziglang/zig/issues/5732
|
||||
const buf = try ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited);
|
||||
testing.allocator.free(buf);
|
||||
|
|
@ -1240,6 +1241,7 @@ test "createDirPath, put some files in it, deleteTreeMinStackSize" {
|
|||
|
||||
test "createDirPath in a directory that no longer exists" {
|
||||
if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir
|
||||
if (native_os == .dragonfly) return error.SkipZigTest; // DragonflyBSD does not produce error (hammer2 fs)
|
||||
|
||||
const io = testing.io;
|
||||
|
||||
|
|
|
|||
|
|
@ -364,9 +364,10 @@ test "getrlimit and setrlimit" {
|
|||
}
|
||||
|
||||
test "sigrtmin/max" {
|
||||
if (native_os == .wasi or native_os == .windows or native_os.isDarwin() or native_os == .openbsd) {
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
if (native_os.isDarwin() or switch (native_os) {
|
||||
.wasi, .windows, .openbsd, .dragonfly => true,
|
||||
else => false,
|
||||
}) return error.SkipZigTest;
|
||||
|
||||
try expect(posix.sigrtmin() >= 32);
|
||||
try expect(posix.sigrtmin() >= posix.system.sigrtmin());
|
||||
|
|
@ -397,7 +398,7 @@ fn reserved_signo(i: usize) bool {
|
|||
if (!builtin.link_libc) return false;
|
||||
const max = if (native_os == .netbsd) 32 else 31;
|
||||
if (i > max) return true;
|
||||
if (native_os == .openbsd) return false; // no RT signals
|
||||
if (native_os == .openbsd or native_os == .dragonfly) return false; // no RT signals
|
||||
return i < posix.sigrtmin();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue