authorgravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2018-11-19 13:52:10-06:00
committergravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2019-01-11 09:56:34-06:00
log207fa3849ca61a6b22084d2d173b36f23ec841bd
tree2ce45e89c54d6219e9f558ed338b995b8134b5e7
parent25d7f5b65475d087ee1f046a364f8a9e6cd60135

moved to InitializeCriticalSection to init


2 files changed, 83 insertions(+), 91 deletions(-)

std/mutex.zig+79-87
...@@ -12,116 +12,108 @@ const windows = std.os.windows;...@@ -12,116 +12,108 @@ const windows = std.os.windows;
12/// The Linux implementation is based on mutex3 from12/// The Linux implementation is based on mutex3 from
13/// https://www.akkadia.org/drepper/futex.pdf13/// https://www.akkadia.org/drepper/futex.pdf
14pub const Mutex = switch(builtin.os) {14pub const Mutex = switch(builtin.os) {
15 builtin.Os.linux => MutexLinux,15 builtin.Os.linux => struct {
16 builtin.Os.windows => MutexWindows,16 /// 0: unlocked
17 else => MutexSpinLock,17 /// 1: locked, no waiters
18};18 /// 2: locked, one or more waiters
19 lock: i32,
20
21 pub const Held = struct {
22 mutex: *Mutex,
23
24 pub fn release(self: Held) void {
25 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
26 if (c != 1) {
27 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
28 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
29 switch (linux.getErrno(rc)) {
30 0 => {},
31 linux.EINVAL => unreachable,
32 else => unreachable,
33 }
34 }
35 }
36 };
1937
20const MutexLinux = struct {38 pub fn init() Mutex {
21 /// 0: unlocked39 return Mutex {
22 /// 1: locked, no waiters40 .lock = 0,
23 /// 2: locked, one or more waiters41 };
24 lock: i32,42 }
2543
26 pub const Held = struct {44 pub fn deinit(self: *Mutex) void {}
27 mutex: *Mutex,
2845
29 pub fn release(self: Held) void {46 pub fn acquire(self: *Mutex) Held {
30 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);47 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
31 if (c != 1) {48 return Held{ .mutex = self };
32 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);49 if (c != 2)
33 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);50 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
51 while (c != 0) {
52 const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
34 switch (linux.getErrno(rc)) {53 switch (linux.getErrno(rc)) {
35 0 => {},54 0, linux.EINTR, linux.EAGAIN => {},
36 linux.EINVAL => unreachable,55 linux.EINVAL => unreachable,
37 else => unreachable,56 else => unreachable,
38 }57 }
58 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
39 }59 }
60 return Held { .mutex = self };
40 }61 }
41 };62 },
63 builtin.Os.windows => struct {
64 lock: ?*windows.RTL_CRITICAL_SECTION,
4265
43 pub fn init() Mutex {66 pub const Held = struct {
44 return Mutex {67 mutex: *Mutex,
45 .lock = 0,
46 };
47 }
4868
49 pub fn deinit(self: *Mutex) void {}69 pub fn release(self: Held) void {
5070 windows.LeaveCriticalSection(self.mutex.lock);
51 pub fn acquire(self: *Mutex) Held {
52 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
53 return Held{ .mutex = self };
54 if (c != 2)
55 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
56 while (c != 0) {
57 const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
58 switch (linux.getErrno(rc)) {
59 0, linux.EINTR, linux.EAGAIN => {},
60 linux.EINVAL => unreachable,
61 else => unreachable,
62 }71 }
63 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
64 }
65 return Held { .mutex = self };
66 }
67};
68
69const MutexWindows = struct {
70 lock: ?windows.RTL_CRITICAL_SECTION,
71
72 pub const Held = struct {
73 mutex: *Mutex,
74
75 pub fn release(self: Held) void {
76 windows.LeaveCriticalSection(&self.mutex.lock);
77 }
78 };
79
80 pub fn init() Mutex {
81 return Mutex {
82 .lock = null,
83 };72 };
84 }
8573
86 pub fn deinit(self: *Mutex) void {74 pub fn init() Mutex {
87 windows.DeleteCriticalSection(&self.lock);75 var lock: ?*windows.RTL_CRITICAL_SECTION = null;
88 self.lock = null;76 windows.InitializeCriticalSection(lock);
89 }77 return Mutex { .lock = lock };
78 }
9079
91 pub fn acquire(self: *Mutex) Held {80 pub fn deinit(self: *Mutex) void {
92 if (self.lock == null) {81 if (self.lock != null) {
93 windows.InitializeCriticalSection(&self.lock);82 windows.DeleteCriticalSection(self.lock);
83 self.lock = null;
84 }
94 }85 }
9586
96 windows.EnterCriticalSection(&self.lock);87 pub fn acquire(self: *Mutex) Held {
97 return Held { .mutex = self };88 windows.EnterCriticalSection(self.lock);
98 }89 return Held { .mutex = self };
99};90 }
91 },
92 else => struct {
93 /// TODO better implementation than spin lock
94 lock: SpinLock,
10095
101const MutexSpinLock = struct {96 pub const Held = struct {
102 /// TODO better implementation than spin lock97 mutex: *Mutex,
103 lock: SpinLock,
10498
105 pub const Held = struct {99 pub fn release(self: Held) void {
106 mutex: *Mutex,100 SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
101 }
102 };
107103
108 pub fn release(self: Held) void {104 pub fn init() Mutex {
109 SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });105 return Mutex {
106 .lock = SpinLock.init(),
107 };
110 }108 }
111 };
112
113 pub fn init() Mutex {
114 return Mutex {
115 .lock = SpinLock.init(),
116 };
117 }
118109
119 pub fn deinit(self: *Mutex) void {}110 pub fn deinit(self: *Mutex) void {}
120111
121 pub fn acquire(self: *Mutex) Held {112 pub fn acquire(self: *Mutex) Held {
122 _ = self.lock.acquire();113 _ = self.lock.acquire();
123 return Held { .mutex = self };114 return Held { .mutex = self };
124 }115 }
116 },
125};117};
126118
127const Context = struct {119const Context = struct {
std/os/windows/kernel32.zig+4-4
...@@ -221,10 +221,10 @@ pub const FOREGROUND_GREEN = 2;...@@ -221,10 +221,10 @@ pub const FOREGROUND_GREEN = 2;
221pub const FOREGROUND_RED = 4;221pub const FOREGROUND_RED = 4;
222pub const FOREGROUND_INTENSITY = 8;222pub const FOREGROUND_INTENSITY = 8;
223223
224pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void;224pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
225pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void; 225pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void; 226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *?RTL_CRITICAL_SECTION) void; 227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
228228
229pub const LIST_ENTRY = extern struct {229pub const LIST_ENTRY = extern struct {
230 Flink: *LIST_ENTRY,230 Flink: *LIST_ENTRY,