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:
Andrew Kelley
2024-07-18 23:35:19 -07:00
parent 16604a93b9
commit e8c4e79499
48 changed files with 9448 additions and 11229 deletions

View File

@@ -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;
}
}

View File

@@ -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 = .{},