Commit bb31695fbf
Changed files (3)
std
os
windows
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();