Commit bb31695fbf

emekoi <emekankurumeh@outlook.com>
2018-11-27 04:07:01
fixed mutex on windows
1 parent 207fa38
Changed files (3)
std/os/windows/index.zig
@@ -49,6 +49,7 @@ pub const UNICODE = false;
 pub const WCHAR = u16;
 pub const WORD = u16;
 pub const LARGE_INTEGER = i64;
+pub const LONG = c_long;
 
 pub const TRUE = 1;
 pub const FALSE = 0;
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: *CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; 
+pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; 
+pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;  
 
 pub const LIST_ENTRY = extern struct {
     Flink: *LIST_ENTRY,
@@ -245,9 +245,21 @@ pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {
 
 pub const RTL_CRITICAL_SECTION = extern struct {
     DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,
-    LockCount: i32,
-    RecursionCount: i32,
+    LockCount: LONG,
+    RecursionCount: LONG,
     OwningThread: HANDLE,
     LockSemaphore: HANDLE,
     SpinCount: ULONG_PTR,
 };
+
+pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
+
+pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *PINIT_ONCE, InitFn: PINIT_ONCE_FN, Context: ?PVOID, Parameter: ?*LPVOID) BOOL;
+
+pub const PINIT_ONCE_FN = ?extern fn(InitOnce: *PINIT_ONCE, Parameter: ?PVOID, Context: ?*PVOID) BOOL;
+
+pub const RTL_RUN_ONCE = extern struct {
+    Ptr: PVOID,
+};
+
+pub const PINIT_ONCE = RTL_RUN_ONCE;
std/mutex.zig
@@ -61,31 +61,57 @@ pub const Mutex = switch(builtin.os) {
         }
     },
     builtin.Os.windows => struct {
-        lock: ?*windows.RTL_CRITICAL_SECTION,
+
+        lock: ?windows.CRITICAL_SECTION,
+        init_once: windows.PINIT_ONCE,
 
         pub const Held = struct {
             mutex: *Mutex,
 
             pub fn release(self: Held) void {
-                windows.LeaveCriticalSection(self.mutex.lock);
+                if (self.mutex.lock) |*lock| {
+                    windows.LeaveCriticalSection(lock);
+                }
             }
         };
 
         pub fn init() Mutex {
-            var lock: ?*windows.RTL_CRITICAL_SECTION = null;
-            windows.InitializeCriticalSection(lock);
-            return Mutex { .lock = lock };
+            return Mutex { 
+                .lock = null,
+                .init_once = undefined,
+            };
+        }
+
+        extern fn initCriticalSection(InitOnce: *windows.PINIT_ONCE, Parameter: ?windows.PVOID, Context: ?*windows.PVOID) windows.BOOL {
+            if (Context) |ctx| {
+                var mutex = @ptrCast(*?windows.CRITICAL_SECTION, ctx);
+                if (mutex.* == null) {
+                    var lock: windows.CRITICAL_SECTION = undefined;
+                    windows.InitializeCriticalSection(&lock);
+                    mutex.* = lock;
+                }
+                return windows.TRUE;
+            }
+            return windows.FALSE;
         }
 
         pub fn deinit(self: *Mutex) void {
-            if (self.lock != null) {
-                windows.DeleteCriticalSection(self.lock);
-                self.lock = null;
+            if (self.lock) |*lock| {
+                windows.DeleteCriticalSection(lock);
             }
         }
 
         pub fn acquire(self: *Mutex) Held {
-            windows.EnterCriticalSection(self.lock);
+            if (self.lock) |*lock| {
+                windows.EnterCriticalSection(lock);
+            } else {
+                if (windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, null, @ptrCast(?*windows.PVOID, self)) == windows.TRUE) {
+                    windows.EnterCriticalSection(&self.lock.?);
+                } else {
+                    @panic("unable to initialize Mutex");
+                }
+            }
+
             return Held { .mutex = self };
         }
     },
@@ -116,7 +142,7 @@ pub const Mutex = switch(builtin.os) {
     },
 };
 
-const Context = struct {
+const TestContext = struct {
     mutex: *Mutex,
     data: i128,
 
@@ -136,7 +162,7 @@ test "std.Mutex" {
     var mutex = Mutex.init();
     defer mutex.deinit();
 
-    var context = Context{
+    var context = TestContext{
         .mutex = &mutex,
         .data = 0,
     };
@@ -149,12 +175,12 @@ test "std.Mutex" {
     for (threads) |t|
         t.wait();
 
-    std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);
+    std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
 }
 
-fn worker(ctx: *Context) void {
+fn worker(ctx: *TestContext) void {
     var i: usize = 0;
-    while (i != Context.incr_count) : (i += 1) {
+    while (i != TestContext.incr_count) : (i += 1) {
         const held = ctx.mutex.acquire();
         defer held.release();