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;
1212/// The Linux implementation is based on mutex3 from
1313/// https://www.akkadia.org/drepper/futex.pdf
1414pub const Mutex = switch(builtin.os) {
15 builtin.Os.linux => MutexLinux,
16 builtin.Os.windows => MutexWindows,
17 else => MutexSpinLock,
18};
15 builtin.Os.linux => struct {
16 /// 0: unlocked
17 /// 1: locked, no waiters
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 {
21 /// 0: unlocked
22 /// 1: locked, no waiters
23 /// 2: locked, one or more waiters
24 lock: i32,
38 pub fn init() Mutex {
39 return Mutex {
40 .lock = 0,
41 };
42 }
2543
26 pub const Held = struct {
27 mutex: *Mutex,
44 pub fn deinit(self: *Mutex) void {}
2845
29 pub fn release(self: Held) void {
30 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
31 if (c != 1) {
32 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
33 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
46 pub fn acquire(self: *Mutex) Held {
47 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
48 return Held{ .mutex = self };
49 if (c != 2)
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);
3453 switch (linux.getErrno(rc)) {
35 0 => {},
54 0, linux.EINTR, linux.EAGAIN => {},
3655 linux.EINVAL => unreachable,
3756 else => unreachable,
3857 }
58 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
3959 }
60 return Held { .mutex = self };
4061 }
41 };
62 },
63 builtin.Os.windows => struct {
64 lock: ?*windows.RTL_CRITICAL_SECTION,
4265
43 pub fn init() Mutex {
44 return Mutex {
45 .lock = 0,
46 };
47 }
66 pub const Held = struct {
67 mutex: *Mutex,
4868
49 pub fn deinit(self: *Mutex) void {}
50
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,
69 pub fn release(self: Held) void {
70 windows.LeaveCriticalSection(self.mutex.lock);
6271 }
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,
8372 };
84 }
8573
86 pub fn deinit(self: *Mutex) void {
87 windows.DeleteCriticalSection(&self.lock);
88 self.lock = null;
89 }
74 pub fn init() Mutex {
75 var lock: ?*windows.RTL_CRITICAL_SECTION = null;
76 windows.InitializeCriticalSection(lock);
77 return Mutex { .lock = lock };
78 }
9079
91 pub fn acquire(self: *Mutex) Held {
92 if (self.lock == null) {
93 windows.InitializeCriticalSection(&self.lock);
80 pub fn deinit(self: *Mutex) void {
81 if (self.lock != null) {
82 windows.DeleteCriticalSection(self.lock);
83 self.lock = null;
84 }
9485 }
9586
96 windows.EnterCriticalSection(&self.lock);
97 return Held { .mutex = self };
98 }
99};
87 pub fn acquire(self: *Mutex) Held {
88 windows.EnterCriticalSection(self.lock);
89 return Held { .mutex = self };
90 }
91 },
92 else => struct {
93 /// TODO better implementation than spin lock
94 lock: SpinLock,
10095
101const MutexSpinLock = struct {
102 /// TODO better implementation than spin lock
103 lock: SpinLock,
96 pub const Held = struct {
97 mutex: *Mutex,
10498
105 pub const Held = struct {
106 mutex: *Mutex,
99 pub fn release(self: Held) void {
100 SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
101 }
102 };
107103
108 pub fn release(self: Held) void {
109 SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
104 pub fn init() Mutex {
105 return Mutex {
106 .lock = SpinLock.init(),
107 };
110108 }
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 {
122 _ = self.lock.acquire();
123 return Held { .mutex = self };
124 }
112 pub fn acquire(self: *Mutex) Held {
113 _ = self.lock.acquire();
114 return Held { .mutex = self };
115 }
116 },
125117};
126118
127119const Context = struct {
std/os/windows/kernel32.zig+4-4
......@@ -221,10 +221,10 @@ pub const FOREGROUND_GREEN = 2;
221221pub const FOREGROUND_RED = 4;
222222pub const FOREGROUND_INTENSITY = 8;
223223
224pub extern "kernel32" stdcallcc fn InitializeCriticalSection(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;
227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(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;
226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void;
228228
229229pub const LIST_ENTRY = extern struct {
230230 Flink: *LIST_ENTRY,