std.c reorganization
It is now composed of these main sections:
* Declarations that are shared among all operating systems.
* Declarations that have the same name, but different type signatures
depending on the operating system. Often multiple operating systems
share the same type signatures however.
* Declarations that are specific to a single operating system.
- These are imported one per line so you can see where they come from,
protected by a comptime block to prevent accessing the wrong one.
Closes #19352 by changing the convention to making types `void` and
functions `{}`, so that it becomes possible to update `@hasDecl` sites
to use `@TypeOf(f) != void` or `T != void`. Happily, this ended up
removing some duplicate logic and update some bitrotted feature
detection checks.
A handful of types have been modified to gain namespacing and type
safety. This is a breaking change.
Oh, and the last usage of `usingnamespace` site is eliminated.
This commit is contained in:
@@ -196,7 +196,10 @@ const DarwinImpl = struct {
|
||||
var timeout_overflowed = false;
|
||||
|
||||
const addr: *const anyopaque = ptr;
|
||||
const flags = c.UL_COMPARE_AND_WAIT | c.ULF_NO_ERRNO;
|
||||
const flags: c.UL = .{
|
||||
.op = .COMPARE_AND_WAIT,
|
||||
.NO_ERRNO = true,
|
||||
};
|
||||
const status = blk: {
|
||||
if (supports_ulock_wait2) {
|
||||
break :blk c.__ulock_wait2(flags, addr, expect, timeout_ns, 0);
|
||||
@@ -228,10 +231,11 @@ const DarwinImpl = struct {
|
||||
}
|
||||
|
||||
fn wake(ptr: *const atomic.Value(u32), max_waiters: u32) void {
|
||||
var flags: u32 = c.UL_COMPARE_AND_WAIT | c.ULF_NO_ERRNO;
|
||||
if (max_waiters > 1) {
|
||||
flags |= c.ULF_WAKE_ALL;
|
||||
}
|
||||
const flags: c.UL = .{
|
||||
.op = .COMPARE_AND_WAIT,
|
||||
.NO_ERRNO = true,
|
||||
.WAKE_ALL = max_waiters > 1,
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const addr: *const anyopaque = ptr;
|
||||
@@ -242,7 +246,7 @@ const DarwinImpl = struct {
|
||||
.INTR => continue, // spurious wake()
|
||||
.FAULT => unreachable, // __ulock_wake doesn't generate EFAULT according to darwin pthread_cond_t
|
||||
.NOENT => return, // nothing was woken up
|
||||
.ALREADY => unreachable, // only for ULF_WAKE_THREAD
|
||||
.ALREADY => unreachable, // only for UL.Op.WAKE_THREAD
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -254,8 +258,8 @@ const LinuxImpl = struct {
|
||||
fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout: ?u64) error{Timeout}!void {
|
||||
var ts: linux.timespec = undefined;
|
||||
if (timeout) |timeout_ns| {
|
||||
ts.tv_sec = @as(@TypeOf(ts.tv_sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.tv_nsec = @as(@TypeOf(ts.tv_nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
ts.sec = @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.nsec = @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
}
|
||||
|
||||
const rc = linux.futex_wait(
|
||||
@@ -306,10 +310,10 @@ const FreebsdImpl = struct {
|
||||
tm_ptr = &tm;
|
||||
tm_size = @sizeOf(@TypeOf(tm));
|
||||
|
||||
tm._flags = 0; // use relative time not UMTX_ABSTIME
|
||||
tm._clockid = c.CLOCK.MONOTONIC;
|
||||
tm._timeout.tv_sec = @as(@TypeOf(tm._timeout.tv_sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
tm._timeout.tv_nsec = @as(@TypeOf(tm._timeout.tv_nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
tm.flags = 0; // use relative time not UMTX_ABSTIME
|
||||
tm.clockid = .MONOTONIC;
|
||||
tm.timeout.sec = @as(@TypeOf(tm.timeout.sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
tm.timeout.nsec = @as(@TypeOf(tm.timeout.nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
}
|
||||
|
||||
const rc = c._umtx_op(
|
||||
@@ -356,16 +360,16 @@ const OpenbsdImpl = struct {
|
||||
fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout: ?u64) error{Timeout}!void {
|
||||
var ts: c.timespec = undefined;
|
||||
if (timeout) |timeout_ns| {
|
||||
ts.tv_sec = @as(@TypeOf(ts.tv_sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.tv_nsec = @as(@TypeOf(ts.tv_nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
ts.sec = @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.nsec = @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
}
|
||||
|
||||
const rc = c.futex(
|
||||
@as(*const volatile u32, @ptrCast(&ptr.raw)),
|
||||
c.FUTEX_WAIT | c.FUTEX_PRIVATE_FLAG,
|
||||
c.FUTEX.WAIT | c.FUTEX.PRIVATE_FLAG,
|
||||
@as(c_int, @bitCast(expect)),
|
||||
if (timeout != null) &ts else null,
|
||||
null, // FUTEX_WAIT takes no requeue address
|
||||
null, // FUTEX.WAIT takes no requeue address
|
||||
);
|
||||
|
||||
switch (std.posix.errno(rc)) {
|
||||
@@ -387,10 +391,10 @@ const OpenbsdImpl = struct {
|
||||
fn wake(ptr: *const atomic.Value(u32), max_waiters: u32) void {
|
||||
const rc = c.futex(
|
||||
@as(*const volatile u32, @ptrCast(&ptr.raw)),
|
||||
c.FUTEX_WAKE | c.FUTEX_PRIVATE_FLAG,
|
||||
c.FUTEX.WAKE | c.FUTEX.PRIVATE_FLAG,
|
||||
std.math.cast(c_int, max_waiters) orelse std.math.maxInt(c_int),
|
||||
null, // FUTEX_WAKE takes no timeout ptr
|
||||
null, // FUTEX_WAKE takes no requeue address
|
||||
null, // FUTEX.WAKE takes no timeout ptr
|
||||
null, // FUTEX.WAKE takes no requeue address
|
||||
);
|
||||
|
||||
// returns number of threads woken up.
|
||||
@@ -540,12 +544,12 @@ const PosixImpl = struct {
|
||||
var ts: c.timespec = undefined;
|
||||
if (timeout) |timeout_ns| {
|
||||
std.posix.clock_gettime(c.CLOCK.REALTIME, &ts) catch unreachable;
|
||||
ts.tv_sec +|= @as(@TypeOf(ts.tv_sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.tv_nsec += @as(@TypeOf(ts.tv_nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
ts.sec +|= @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s));
|
||||
ts.nsec += @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s));
|
||||
|
||||
if (ts.tv_nsec >= std.time.ns_per_s) {
|
||||
ts.tv_sec +|= 1;
|
||||
ts.tv_nsec -= std.time.ns_per_s;
|
||||
if (ts.nsec >= std.time.ns_per_s) {
|
||||
ts.sec +|= 1;
|
||||
ts.nsec -= std.time.ns_per_s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,8 +103,8 @@ const SingleThreadedImpl = struct {
|
||||
}
|
||||
};
|
||||
|
||||
// SRWLOCK on windows is almost always faster than Futex solution.
|
||||
// It also implements an efficient Condition with requeue support for us.
|
||||
/// SRWLOCK on windows is almost always faster than Futex solution.
|
||||
/// It also implements an efficient Condition with requeue support for us.
|
||||
const WindowsImpl = struct {
|
||||
srwlock: windows.SRWLOCK = .{},
|
||||
|
||||
@@ -123,7 +123,7 @@ const WindowsImpl = struct {
|
||||
const windows = std.os.windows;
|
||||
};
|
||||
|
||||
// os_unfair_lock on darwin supports priority inheritance and is generally faster than Futex solutions.
|
||||
/// os_unfair_lock on darwin supports priority inheritance and is generally faster than Futex solutions.
|
||||
const DarwinImpl = struct {
|
||||
oul: c.os_unfair_lock = .{},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user