aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Thread
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-28 12:41:24 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-28 12:41:24 -0700
commit6aeab0f323ff14d7ad248e18c372573f7a5a8cd1 (patch)
tree7080297f629f39baa0b742985c5804cf6a2047e8 /lib/std/Thread
parent47f7ed1c4cb8acf7fed99a057fb84202962e4b1b (diff)
parent05cf44933d753f7a5a53ab289ea60fd43761de57 (diff)
downloadzig-6aeab0f323ff14d7ad248e18c372573f7a5a8cd1.tar.gz
zig-6aeab0f323ff14d7ad248e18c372573f7a5a8cd1.zip
Merge remote-tracking branch 'origin/master' into llvm13
Conflicts: lib/libcxx/include/__config d57c0cc3bfeff9af297279759ec2b631e6d95140 added support for DragonFlyBSD to libc++ by updating some ifdefs. This needed to be synced with llvm13.
Diffstat (limited to 'lib/std/Thread')
-rw-r--r--lib/std/Thread/AutoResetEvent.zig6
-rw-r--r--lib/std/Thread/Condition.zig22
-rw-r--r--lib/std/Thread/Futex.zig84
-rw-r--r--lib/std/Thread/Mutex.zig38
-rw-r--r--lib/std/Thread/ResetEvent.zig30
-rw-r--r--lib/std/Thread/RwLock.zig30
-rw-r--r--lib/std/Thread/Semaphore.zig6
-rw-r--r--lib/std/Thread/StaticResetEvent.zig16
8 files changed, 91 insertions, 141 deletions
diff --git a/lib/std/Thread/AutoResetEvent.zig b/lib/std/Thread/AutoResetEvent.zig
index 13e404d602..49639d60e9 100644
--- a/lib/std/Thread/AutoResetEvent.zig
+++ b/lib/std/Thread/AutoResetEvent.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! Similar to `StaticResetEvent` but on `set()` it also (atomically) does `reset()`.
//! Unlike StaticResetEvent, `wait()` can only be called by one thread (MPSC-like).
//!
diff --git a/lib/std/Thread/Condition.zig b/lib/std/Thread/Condition.zig
index 8485f84aa4..647a50b913 100644
--- a/lib/std/Thread/Condition.zig
+++ b/lib/std/Thread/Condition.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! A condition provides a way for a kernel thread to block until it is signaled
//! to wake up. Spurious wakeups are possible.
//! This API supports static initialization and does not require deinitialization.
@@ -81,17 +75,17 @@ pub const PthreadCondition = struct {
pub fn wait(cond: *PthreadCondition, mutex: *Mutex) void {
const rc = std.c.pthread_cond_wait(&cond.cond, &mutex.impl.pthread_mutex);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
pub fn signal(cond: *PthreadCondition) void {
const rc = std.c.pthread_cond_signal(&cond.cond);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
pub fn broadcast(cond: *PthreadCondition) void {
const rc = std.c.pthread_cond_broadcast(&cond.cond);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
};
@@ -115,9 +109,9 @@ pub const AtomicCondition = struct {
0,
null,
))) {
- 0 => {},
- std.os.EINTR => {},
- std.os.EAGAIN => {},
+ .SUCCESS => {},
+ .INTR => {},
+ .AGAIN => {},
else => unreachable,
}
},
@@ -136,8 +130,8 @@ pub const AtomicCondition = struct {
linux.FUTEX_PRIVATE_FLAG | linux.FUTEX_WAKE,
1,
))) {
- 0 => {},
- std.os.EFAULT => {},
+ .SUCCESS => {},
+ .FAULT => {},
else => unreachable,
}
},
diff --git a/lib/std/Thread/Futex.zig b/lib/std/Thread/Futex.zig
index 81dba07996..5a3da5cd94 100644
--- a/lib/std/Thread/Futex.zig
+++ b/lib/std/Thread/Futex.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! Futex is a mechanism used to block (`wait`) and unblock (`wake`) threads using a 32bit memory address as hints.
//! Blocking a thread is acknowledged only if the 32bit memory address is equal to a given value.
//! This check helps avoid block/unblock deadlocks which occur if a `wake()` happens before a `wait()`.
@@ -152,12 +146,12 @@ const LinuxFutex = struct {
@bitCast(i32, expect),
ts_ptr,
))) {
- 0 => {}, // notified by `wake()`
- std.os.EINTR => {}, // spurious wakeup
- std.os.EAGAIN => {}, // ptr.* != expect
- std.os.ETIMEDOUT => return error.TimedOut,
- std.os.EINVAL => {}, // possibly timeout overflow
- std.os.EFAULT => unreachable,
+ .SUCCESS => {}, // notified by `wake()`
+ .INTR => {}, // spurious wakeup
+ .AGAIN => {}, // ptr.* != expect
+ .TIMEDOUT => return error.TimedOut,
+ .INVAL => {}, // possibly timeout overflow
+ .FAULT => unreachable,
else => unreachable,
}
}
@@ -168,9 +162,9 @@ const LinuxFutex = struct {
linux.FUTEX_PRIVATE_FLAG | linux.FUTEX_WAKE,
std.math.cast(i32, num_waiters) catch std.math.maxInt(i32),
))) {
- 0 => {}, // successful wake up
- std.os.EINVAL => {}, // invalid futex_wait() on ptr done elsewhere
- std.os.EFAULT => {}, // pointer became invalid while doing the wake
+ .SUCCESS => {}, // successful wake up
+ .INVAL => {}, // invalid futex_wait() on ptr done elsewhere
+ .FAULT => {}, // pointer became invalid while doing the wake
else => unreachable,
}
}
@@ -215,13 +209,13 @@ const DarwinFutex = struct {
};
if (status >= 0) return;
- switch (-status) {
- darwin.EINTR => {},
+ switch (@intToEnum(std.os.E, -status)) {
+ .INTR => {},
// Address of the futex is paged out. This is unlikely, but possible in theory, and
// pthread/libdispatch on darwin bother to handle it. In this case we'll return
// without waiting, but the caller should retry anyway.
- darwin.EFAULT => {},
- darwin.ETIMEDOUT => if (!timeout_overflowed) return error.TimedOut,
+ .FAULT => {},
+ .TIMEDOUT => if (!timeout_overflowed) return error.TimedOut,
else => unreachable,
}
}
@@ -237,11 +231,11 @@ const DarwinFutex = struct {
const status = darwin.__ulock_wake(flags, addr, 0);
if (status >= 0) return;
- switch (-status) {
- darwin.EINTR => continue, // spurious wake()
- darwin.EFAULT => continue, // address of the lock was paged out
- darwin.ENOENT => return, // nothing was woken up
- darwin.EALREADY => unreachable, // only for ULF_WAKE_THREAD
+ switch (@intToEnum(std.os.E, -status)) {
+ .INTR => continue, // spurious wake()
+ .FAULT => continue, // address of the lock was paged out
+ .NOENT => return, // nothing was woken up
+ .ALREADY => unreachable, // only for ULF_WAKE_THREAD
else => unreachable,
}
}
@@ -255,8 +249,8 @@ const PosixFutex = struct {
var waiter: List.Node = undefined;
{
- assert(std.c.pthread_mutex_lock(&bucket.mutex) == 0);
- defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == 0);
+ assert(std.c.pthread_mutex_lock(&bucket.mutex) == .SUCCESS);
+ defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == .SUCCESS);
if (ptr.load(.SeqCst) != expect) {
return;
@@ -272,8 +266,8 @@ const PosixFutex = struct {
waiter.data.wait(null) catch unreachable;
};
- assert(std.c.pthread_mutex_lock(&bucket.mutex) == 0);
- defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == 0);
+ assert(std.c.pthread_mutex_lock(&bucket.mutex) == .SUCCESS);
+ defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == .SUCCESS);
if (waiter.data.address == address) {
timed_out = true;
@@ -297,8 +291,8 @@ const PosixFutex = struct {
waiter.data.notify();
};
- assert(std.c.pthread_mutex_lock(&bucket.mutex) == 0);
- defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == 0);
+ assert(std.c.pthread_mutex_lock(&bucket.mutex) == .SUCCESS);
+ defer assert(std.c.pthread_mutex_unlock(&bucket.mutex) == .SUCCESS);
var waiters = bucket.list.first;
while (waiters) |waiter| {
@@ -340,16 +334,13 @@ const PosixFutex = struct {
};
fn deinit(self: *Self) void {
- const rc = std.c.pthread_cond_destroy(&self.cond);
- assert(rc == 0 or rc == std.os.EINVAL);
-
- const rm = std.c.pthread_mutex_destroy(&self.mutex);
- assert(rm == 0 or rm == std.os.EINVAL);
+ _ = std.c.pthread_cond_destroy(&self.cond);
+ _ = std.c.pthread_mutex_destroy(&self.mutex);
}
fn wait(self: *Self, timeout: ?u64) error{TimedOut}!void {
- assert(std.c.pthread_mutex_lock(&self.mutex) == 0);
- defer assert(std.c.pthread_mutex_unlock(&self.mutex) == 0);
+ assert(std.c.pthread_mutex_lock(&self.mutex) == .SUCCESS);
+ defer assert(std.c.pthread_mutex_unlock(&self.mutex) == .SUCCESS);
switch (self.state) {
.empty => self.state = .waiting,
@@ -378,28 +369,31 @@ const PosixFutex = struct {
}
const ts_ref = ts_ptr orelse {
- assert(std.c.pthread_cond_wait(&self.cond, &self.mutex) == 0);
+ assert(std.c.pthread_cond_wait(&self.cond, &self.mutex) == .SUCCESS);
continue;
};
const rc = std.c.pthread_cond_timedwait(&self.cond, &self.mutex, ts_ref);
- assert(rc == 0 or rc == std.os.ETIMEDOUT);
- if (rc == std.os.ETIMEDOUT) {
- self.state = .empty;
- return error.TimedOut;
+ switch (rc) {
+ .SUCCESS => {},
+ .TIMEDOUT => {
+ self.state = .empty;
+ return error.TimedOut;
+ },
+ else => unreachable,
}
}
}
fn notify(self: *Self) void {
- assert(std.c.pthread_mutex_lock(&self.mutex) == 0);
- defer assert(std.c.pthread_mutex_unlock(&self.mutex) == 0);
+ assert(std.c.pthread_mutex_lock(&self.mutex) == .SUCCESS);
+ defer assert(std.c.pthread_mutex_unlock(&self.mutex) == .SUCCESS);
switch (self.state) {
.empty => self.state = .notified,
.waiting => {
self.state = .notified;
- assert(std.c.pthread_cond_signal(&self.cond) == 0);
+ assert(std.c.pthread_cond_signal(&self.cond) == .SUCCESS);
},
.notified => unreachable,
}
diff --git a/lib/std/Thread/Mutex.zig b/lib/std/Thread/Mutex.zig
index 35095b2a3c..ee54a1582b 100644
--- a/lib/std/Thread/Mutex.zig
+++ b/lib/std/Thread/Mutex.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! Lock may be held only once. If the same thread tries to acquire
//! the same mutex twice, it deadlocks. This type supports static
//! initialization and is at most `@sizeOf(usize)` in size. When an
@@ -143,9 +137,9 @@ pub const AtomicMutex = struct {
@enumToInt(new_state),
null,
))) {
- 0 => {},
- std.os.EINTR => {},
- std.os.EAGAIN => {},
+ .SUCCESS => {},
+ .INTR => {},
+ .AGAIN => {},
else => unreachable,
}
},
@@ -164,8 +158,8 @@ pub const AtomicMutex = struct {
linux.FUTEX_PRIVATE_FLAG | linux.FUTEX_WAKE,
1,
))) {
- 0 => {},
- std.os.EFAULT => {},
+ .SUCCESS => {},
+ .FAULT => unreachable, // invalid pointer passed to futex_wake
else => unreachable,
}
},
@@ -182,10 +176,10 @@ pub const PthreadMutex = struct {
pub fn release(held: Held) void {
switch (std.c.pthread_mutex_unlock(&held.mutex.pthread_mutex)) {
- 0 => return,
- std.c.EINVAL => unreachable,
- std.c.EAGAIN => unreachable,
- std.c.EPERM => unreachable,
+ .SUCCESS => return,
+ .INVAL => unreachable,
+ .AGAIN => unreachable,
+ .PERM => unreachable,
else => unreachable,
}
}
@@ -195,7 +189,7 @@ pub const PthreadMutex = struct {
/// the mutex is unavailable. Otherwise returns Held. Call
/// release on Held.
pub fn tryAcquire(m: *PthreadMutex) ?Held {
- if (std.c.pthread_mutex_trylock(&m.pthread_mutex) == 0) {
+ if (std.c.pthread_mutex_trylock(&m.pthread_mutex) == .SUCCESS) {
return Held{ .mutex = m };
} else {
return null;
@@ -206,12 +200,12 @@ pub const PthreadMutex = struct {
/// held by the calling thread.
pub fn acquire(m: *PthreadMutex) Held {
switch (std.c.pthread_mutex_lock(&m.pthread_mutex)) {
- 0 => return Held{ .mutex = m },
- std.c.EINVAL => unreachable,
- std.c.EBUSY => unreachable,
- std.c.EAGAIN => unreachable,
- std.c.EDEADLK => unreachable,
- std.c.EPERM => unreachable,
+ .SUCCESS => return Held{ .mutex = m },
+ .INVAL => unreachable,
+ .BUSY => unreachable,
+ .AGAIN => unreachable,
+ .DEADLK => unreachable,
+ .PERM => unreachable,
else => unreachable,
}
}
diff --git a/lib/std/Thread/ResetEvent.zig b/lib/std/Thread/ResetEvent.zig
index 356b8eb78d..d9304dd70b 100644
--- a/lib/std/Thread/ResetEvent.zig
+++ b/lib/std/Thread/ResetEvent.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! A thread-safe resource which supports blocking until signaled.
//! This API is for kernel threads, not evented I/O.
//! This API requires being initialized at runtime, and initialization
@@ -130,7 +124,7 @@ pub const PosixEvent = struct {
pub fn init(ev: *PosixEvent) !void {
switch (c.getErrno(c.sem_init(&ev.sem, 0, 0))) {
- 0 => return,
+ .SUCCESS => return,
else => return error.SystemResources,
}
}
@@ -147,9 +141,9 @@ pub const PosixEvent = struct {
pub fn wait(ev: *PosixEvent) void {
while (true) {
switch (c.getErrno(c.sem_wait(&ev.sem))) {
- 0 => return,
- c.EINTR => continue,
- c.EINVAL => unreachable,
+ .SUCCESS => return,
+ .INTR => continue,
+ .INVAL => unreachable,
else => unreachable,
}
}
@@ -165,10 +159,10 @@ pub const PosixEvent = struct {
ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.ns_per_s));
while (true) {
switch (c.getErrno(c.sem_timedwait(&ev.sem, &ts))) {
- 0 => return .event_set,
- c.EINTR => continue,
- c.EINVAL => unreachable,
- c.ETIMEDOUT => return .timed_out,
+ .SUCCESS => return .event_set,
+ .INTR => continue,
+ .INVAL => unreachable,
+ .TIMEDOUT => return .timed_out,
else => unreachable,
}
}
@@ -177,10 +171,10 @@ pub const PosixEvent = struct {
pub fn reset(ev: *PosixEvent) void {
while (true) {
switch (c.getErrno(c.sem_trywait(&ev.sem))) {
- 0 => continue, // Need to make it go to zero.
- c.EINTR => continue,
- c.EINVAL => unreachable,
- c.EAGAIN => return, // The semaphore currently has the value zero.
+ .SUCCESS => continue, // Need to make it go to zero.
+ .INTR => continue,
+ .INVAL => unreachable,
+ .AGAIN => return, // The semaphore currently has the value zero.
else => unreachable,
}
}
diff --git a/lib/std/Thread/RwLock.zig b/lib/std/Thread/RwLock.zig
index 1d606a9cf1..cfe06c76e8 100644
--- a/lib/std/Thread/RwLock.zig
+++ b/lib/std/Thread/RwLock.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! A lock that supports one writer or many readers.
//! This API is for kernel threads, not evented I/O.
//! This API requires being initialized at runtime, and initialization
@@ -13,7 +7,7 @@ impl: Impl,
const RwLock = @This();
const std = @import("../std.zig");
-const builtin = std.builtin;
+const builtin = @import("builtin");
const assert = std.debug.assert;
const Mutex = std.Thread.Mutex;
const Semaphore = std.Semaphore;
@@ -165,43 +159,41 @@ pub const PthreadRwLock = struct {
}
pub fn deinit(rwl: *PthreadRwLock) void {
- const safe_rc = switch (std.builtin.os.tag) {
- .dragonfly, .netbsd => std.os.EAGAIN,
- else => 0,
+ const safe_rc: std.os.E = switch (builtin.os.tag) {
+ .dragonfly, .netbsd => .AGAIN,
+ else => .SUCCESS,
};
-
const rc = std.c.pthread_rwlock_destroy(&rwl.rwlock);
- assert(rc == 0 or rc == safe_rc);
-
+ assert(rc == .SUCCESS or rc == safe_rc);
rwl.* = undefined;
}
pub fn tryLock(rwl: *PthreadRwLock) bool {
- return pthread_rwlock_trywrlock(&rwl.rwlock) == 0;
+ return pthread_rwlock_trywrlock(&rwl.rwlock) == .SUCCESS;
}
pub fn lock(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_wrlock(&rwl.rwlock);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
pub fn unlock(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_unlock(&rwl.rwlock);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
pub fn tryLockShared(rwl: *PthreadRwLock) bool {
- return pthread_rwlock_tryrdlock(&rwl.rwlock) == 0;
+ return pthread_rwlock_tryrdlock(&rwl.rwlock) == .SUCCESS;
}
pub fn lockShared(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_rdlock(&rwl.rwlock);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
pub fn unlockShared(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_unlock(&rwl.rwlock);
- assert(rc == 0);
+ assert(rc == .SUCCESS);
}
};
diff --git a/lib/std/Thread/Semaphore.zig b/lib/std/Thread/Semaphore.zig
index 169975b362..b5bde88d73 100644
--- a/lib/std/Thread/Semaphore.zig
+++ b/lib/std/Thread/Semaphore.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! A semaphore is an unsigned integer that blocks the kernel thread if
//! the number would become negative.
//! This API supports static initialization and does not require deinitialization.
diff --git a/lib/std/Thread/StaticResetEvent.zig b/lib/std/Thread/StaticResetEvent.zig
index 40974938d0..d779a4de9e 100644
--- a/lib/std/Thread/StaticResetEvent.zig
+++ b/lib/std/Thread/StaticResetEvent.zig
@@ -1,9 +1,3 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
//! A thread-safe resource which supports blocking until signaled.
//! This API is for kernel threads, not evented I/O.
//! This API is statically initializable. It cannot fail to be initialized
@@ -201,7 +195,7 @@ pub const AtomicEvent = struct {
const waiting = std.math.maxInt(i32); // wake_count
const ptr = @ptrCast(*const i32, waiters);
const rc = linux.futex_wake(ptr, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, waiting);
- assert(linux.getErrno(rc) == 0);
+ assert(linux.getErrno(rc) == .SUCCESS);
}
fn wait(waiters: *u32, timeout: ?u64) !void {
@@ -221,10 +215,10 @@ pub const AtomicEvent = struct {
const ptr = @ptrCast(*const i32, waiters);
const rc = linux.futex_wait(ptr, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, expected, ts_ptr);
switch (linux.getErrno(rc)) {
- 0 => continue,
- os.ETIMEDOUT => return error.TimedOut,
- os.EINTR => continue,
- os.EAGAIN => return,
+ .SUCCESS => continue,
+ .TIMEDOUT => return error.TimedOut,
+ .INTR => continue,
+ .AGAIN => return,
else => unreachable,
}
}