authorgravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2018-11-26 21:07:01-06:00
committergravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2019-01-11 09:56:35-06:00
logbb31695fbfbf7c808dc3fd8c3cfc0b654ed15e5e
treee37c6c34280ef1e7e540fcdc51e11b373cc4ff55
parent207fa3849ca61a6b22084d2d173b36f23ec841bd

fixed mutex on windows


3 files changed, 59 insertions(+), 20 deletions(-)

std/mutex.zig+40-14
...@@ -61,31 +61,57 @@ pub const Mutex = switch(builtin.os) {...@@ -61,31 +61,57 @@ pub const Mutex = switch(builtin.os) {
61 }61 }
62 },62 },
63 builtin.Os.windows => struct {63 builtin.Os.windows => struct {
64 lock: ?*windows.RTL_CRITICAL_SECTION,64
65 lock: ?windows.CRITICAL_SECTION,
66 init_once: windows.PINIT_ONCE,
6567
66 pub const Held = struct {68 pub const Held = struct {
67 mutex: *Mutex,69 mutex: *Mutex,
6870
69 pub fn release(self: Held) void {71 pub fn release(self: Held) void {
70 windows.LeaveCriticalSection(self.mutex.lock);72 if (self.mutex.lock) |*lock| {
73 windows.LeaveCriticalSection(lock);
74 }
71 }75 }
72 };76 };
7377
74 pub fn init() Mutex {78 pub fn init() Mutex {
75 var lock: ?*windows.RTL_CRITICAL_SECTION = null;79 return Mutex {
76 windows.InitializeCriticalSection(lock);80 .lock = null,
77 return Mutex { .lock = lock };81 .init_once = undefined,
82 };
83 }
84
85 extern fn initCriticalSection(InitOnce: *windows.PINIT_ONCE, Parameter: ?windows.PVOID, Context: ?*windows.PVOID) windows.BOOL {
86 if (Context) |ctx| {
87 var mutex = @ptrCast(*?windows.CRITICAL_SECTION, ctx);
88 if (mutex.* == null) {
89 var lock: windows.CRITICAL_SECTION = undefined;
90 windows.InitializeCriticalSection(&lock);
91 mutex.* = lock;
92 }
93 return windows.TRUE;
94 }
95 return windows.FALSE;
78 }96 }
7997
80 pub fn deinit(self: *Mutex) void {98 pub fn deinit(self: *Mutex) void {
81 if (self.lock != null) {99 if (self.lock) |*lock| {
82 windows.DeleteCriticalSection(self.lock);100 windows.DeleteCriticalSection(lock);
83 self.lock = null;
84 }101 }
85 }102 }
86103
87 pub fn acquire(self: *Mutex) Held {104 pub fn acquire(self: *Mutex) Held {
88 windows.EnterCriticalSection(self.lock);105 if (self.lock) |*lock| {
106 windows.EnterCriticalSection(lock);
107 } else {
108 if (windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, null, @ptrCast(?*windows.PVOID, self)) == windows.TRUE) {
109 windows.EnterCriticalSection(&self.lock.?);
110 } else {
111 @panic("unable to initialize Mutex");
112 }
113 }
114
89 return Held { .mutex = self };115 return Held { .mutex = self };
90 }116 }
91 },117 },
...@@ -116,7 +142,7 @@ pub const Mutex = switch(builtin.os) {...@@ -116,7 +142,7 @@ pub const Mutex = switch(builtin.os) {
116 },142 },
117};143};
118144
119const Context = struct {145const TestContext = struct {
120 mutex: *Mutex,146 mutex: *Mutex,
121 data: i128,147 data: i128,
122148
...@@ -136,7 +162,7 @@ test "std.Mutex" {...@@ -136,7 +162,7 @@ test "std.Mutex" {
136 var mutex = Mutex.init();162 var mutex = Mutex.init();
137 defer mutex.deinit();163 defer mutex.deinit();
138164
139 var context = Context{165 var context = TestContext{
140 .mutex = &mutex,166 .mutex = &mutex,
141 .data = 0,167 .data = 0,
142 };168 };
...@@ -149,12 +175,12 @@ test "std.Mutex" {...@@ -149,12 +175,12 @@ test "std.Mutex" {
149 for (threads) |t|175 for (threads) |t|
150 t.wait();176 t.wait();
151177
152 std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);178 std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
153}179}
154180
155fn worker(ctx: *Context) void {181fn worker(ctx: *TestContext) void {
156 var i: usize = 0;182 var i: usize = 0;
157 while (i != Context.incr_count) : (i += 1) {183 while (i != TestContext.incr_count) : (i += 1) {
158 const held = ctx.mutex.acquire();184 const held = ctx.mutex.acquire();
159 defer held.release();185 defer held.release();
160186
std/os/windows/index.zig+1
...@@ -49,6 +49,7 @@ pub const UNICODE = false;...@@ -49,6 +49,7 @@ pub const UNICODE = false;
49pub const WCHAR = u16;49pub const WCHAR = u16;
50pub const WORD = u16;50pub const WORD = u16;
51pub const LARGE_INTEGER = i64;51pub const LARGE_INTEGER = i64;
52pub const LONG = c_long;
5253
53pub const TRUE = 1;54pub const TRUE = 1;
54pub const FALSE = 0;55pub const FALSE = 0;
std/os/windows/kernel32.zig+18-6
...@@ -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: *CRITICAL_SECTION) void;
225pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void; 225pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void; 226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: ?*RTL_CRITICAL_SECTION) void; 227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
228228
229pub const LIST_ENTRY = extern struct {229pub const LIST_ENTRY = extern struct {
230 Flink: *LIST_ENTRY,230 Flink: *LIST_ENTRY,
...@@ -245,9 +245,21 @@ pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {...@@ -245,9 +245,21 @@ pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {
245245
246pub const RTL_CRITICAL_SECTION = extern struct {246pub const RTL_CRITICAL_SECTION = extern struct {
247 DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,247 DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,
248 LockCount: i32,248 LockCount: LONG,
249 RecursionCount: i32,249 RecursionCount: LONG,
250 OwningThread: HANDLE,250 OwningThread: HANDLE,
251 LockSemaphore: HANDLE,251 LockSemaphore: HANDLE,
252 SpinCount: ULONG_PTR,252 SpinCount: ULONG_PTR,
253};253};
254
255pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
256
257pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *PINIT_ONCE, InitFn: PINIT_ONCE_FN, Context: ?PVOID, Parameter: ?*LPVOID) BOOL;
258
259pub const PINIT_ONCE_FN = ?extern fn(InitOnce: *PINIT_ONCE, Parameter: ?PVOID, Context: ?*PVOID) BOOL;
260
261pub const RTL_RUN_ONCE = extern struct {
262 Ptr: PVOID,
263};
264
265pub const PINIT_ONCE = RTL_RUN_ONCE;