Commit 207fa3849c
Changed files (2)
std
os
windows
std/os/windows/kernel32.zig
@@ -221,10 +221,10 @@ pub const FOREGROUND_GREEN = 2;
pub const FOREGROUND_RED = 4;
pub const FOREGROUND_INTENSITY = 8;
-pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void;
-pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void;
-pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void;
-pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
pub const LIST_ENTRY = extern struct {
Flink: *LIST_ENTRY,
std/mutex.zig
@@ -12,116 +12,108 @@ const windows = std.os.windows;
/// The Linux implementation is based on mutex3 from
/// https://www.akkadia.org/drepper/futex.pdf
pub const Mutex = switch(builtin.os) {
- builtin.Os.linux => MutexLinux,
- builtin.Os.windows => MutexWindows,
- else => MutexSpinLock,
-};
+ builtin.Os.linux => struct {
+ /// 0: unlocked
+ /// 1: locked, no waiters
+ /// 2: locked, one or more waiters
+ lock: i32,
+
+ pub const Held = struct {
+ mutex: *Mutex,
+
+ pub fn release(self: Held) void {
+ const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
+ if (c != 1) {
+ _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
+ const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
+ switch (linux.getErrno(rc)) {
+ 0 => {},
+ linux.EINVAL => unreachable,
+ else => unreachable,
+ }
+ }
+ }
+ };
-const MutexLinux = struct {
- /// 0: unlocked
- /// 1: locked, no waiters
- /// 2: locked, one or more waiters
- lock: i32,
+ pub fn init() Mutex {
+ return Mutex {
+ .lock = 0,
+ };
+ }
- pub const Held = struct {
- mutex: *Mutex,
+ pub fn deinit(self: *Mutex) void {}
- pub fn release(self: Held) void {
- const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
- if (c != 1) {
- _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
- const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
+ pub fn acquire(self: *Mutex) Held {
+ var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
+ return Held{ .mutex = self };
+ if (c != 2)
+ c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
+ while (c != 0) {
+ const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
switch (linux.getErrno(rc)) {
- 0 => {},
+ 0, linux.EINTR, linux.EAGAIN => {},
linux.EINVAL => unreachable,
else => unreachable,
}
+ c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
}
+ return Held { .mutex = self };
}
- };
+ },
+ builtin.Os.windows => struct {
+ lock: ?*windows.RTL_CRITICAL_SECTION,
- pub fn init() Mutex {
- return Mutex {
- .lock = 0,
- };
- }
+ pub const Held = struct {
+ mutex: *Mutex,
- pub fn deinit(self: *Mutex) void {}
-
- pub fn acquire(self: *Mutex) Held {
- var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
- return Held{ .mutex = self };
- if (c != 2)
- c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
- while (c != 0) {
- const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
- switch (linux.getErrno(rc)) {
- 0, linux.EINTR, linux.EAGAIN => {},
- linux.EINVAL => unreachable,
- else => unreachable,
+ pub fn release(self: Held) void {
+ windows.LeaveCriticalSection(self.mutex.lock);
}
- c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
- }
- return Held { .mutex = self };
- }
-};
-
-const MutexWindows = struct {
- lock: ?windows.RTL_CRITICAL_SECTION,
-
- pub const Held = struct {
- mutex: *Mutex,
-
- pub fn release(self: Held) void {
- windows.LeaveCriticalSection(&self.mutex.lock);
- }
- };
-
- pub fn init() Mutex {
- return Mutex {
- .lock = null,
};
- }
- pub fn deinit(self: *Mutex) void {
- windows.DeleteCriticalSection(&self.lock);
- self.lock = null;
- }
+ pub fn init() Mutex {
+ var lock: ?*windows.RTL_CRITICAL_SECTION = null;
+ windows.InitializeCriticalSection(lock);
+ return Mutex { .lock = lock };
+ }
- pub fn acquire(self: *Mutex) Held {
- if (self.lock == null) {
- windows.InitializeCriticalSection(&self.lock);
+ pub fn deinit(self: *Mutex) void {
+ if (self.lock != null) {
+ windows.DeleteCriticalSection(self.lock);
+ self.lock = null;
+ }
}
- windows.EnterCriticalSection(&self.lock);
- return Held { .mutex = self };
- }
-};
+ pub fn acquire(self: *Mutex) Held {
+ windows.EnterCriticalSection(self.lock);
+ return Held { .mutex = self };
+ }
+ },
+ else => struct {
+ /// TODO better implementation than spin lock
+ lock: SpinLock,
-const MutexSpinLock = struct {
- /// TODO better implementation than spin lock
- lock: SpinLock,
+ pub const Held = struct {
+ mutex: *Mutex,
- pub const Held = struct {
- mutex: *Mutex,
+ pub fn release(self: Held) void {
+ SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
+ }
+ };
- pub fn release(self: Held) void {
- SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
+ pub fn init() Mutex {
+ return Mutex {
+ .lock = SpinLock.init(),
+ };
}
- };
-
- pub fn init() Mutex {
- return Mutex {
- .lock = SpinLock.init(),
- };
- }
- pub fn deinit(self: *Mutex) void {}
+ pub fn deinit(self: *Mutex) void {}
- pub fn acquire(self: *Mutex) Held {
- _ = self.lock.acquire();
- return Held { .mutex = self };
- }
+ pub fn acquire(self: *Mutex) Held {
+ _ = self.lock.acquire();
+ return Held { .mutex = self };
+ }
+ },
};
const Context = struct {