| ... | @@ -29,8 +29,8 @@ const ws2_32 = std.os.windows.ws2_32; | ... | @@ -29,8 +29,8 @@ const ws2_32 = std.os.windows.ws2_32; |
| 29 | /// * scanning environment variables on some targets | 29 | /// * scanning environment variables on some targets |
| 30 | /// * memory-mapping when mmap or equivalent is not available | 30 | /// * memory-mapping when mmap or equivalent is not available |
| 31 | allocator: Allocator, | 31 | allocator: Allocator, |
| 32 | mutex: Io.Mutex = .init, | 32 | mutex: Mutex = .init, |
| 33 | cond: Io.Condition = .init, | 33 | cond: Condition = .init, |
| 34 | run_queue: std.SinglyLinkedList = .{}, | 34 | run_queue: std.SinglyLinkedList = .{}, |
| 35 | join_requested: bool = false, | 35 | join_requested: bool = false, |
| 36 | stack_size: usize, | 36 | stack_size: usize, |
| ... | @@ -14299,9 +14299,10 @@ const Wsa = struct { | ... | @@ -14299,9 +14299,10 @@ const Wsa = struct { |
| 14299 | }; | 14299 | }; |
| 14300 | | 14300 | |
| 14301 | fn initializeWsa(t: *Threaded) error{ NetworkDown, Canceled }!void { | 14301 | fn initializeWsa(t: *Threaded) error{ NetworkDown, Canceled }!void { |
| | 14302 | const t_io = io(t); |
| 14302 | const wsa = &t.wsa; | 14303 | const wsa = &t.wsa; |
| 14303 | try mutexLock(&wsa.mutex); | 14304 | try wsa.mutex.lock(t_io); |
| 14304 | defer mutexUnlock(&wsa.mutex); | 14305 | defer wsa.mutex.unlock(t_io); |
| 14305 | switch (wsa.status) { | 14306 | switch (wsa.status) { |
| 14306 | .uninitialized => { | 14307 | .uninitialized => { |
| 14307 | var wsa_data: ws2_32.WSADATA = undefined; | 14308 | var wsa_data: ws2_32.WSADATA = undefined; |
| ... | @@ -16877,7 +16878,7 @@ const parking_futex = struct { | ... | @@ -16877,7 +16878,7 @@ const parking_futex = struct { |
| 16877 | /// avoid a race. | 16878 | /// avoid a race. |
| 16878 | num_waiters: std.atomic.Value(u32), | 16879 | num_waiters: std.atomic.Value(u32), |
| 16879 | /// Protects `waiters`. | 16880 | /// Protects `waiters`. |
| 16880 | mutex: Io.Mutex, | 16881 | mutex: Mutex, |
| 16881 | waiters: std.DoublyLinkedList, | 16882 | waiters: std.DoublyLinkedList, |
| 16882 | | 16883 | |
| 16883 | /// Prevent false sharing between buckets. | 16884 | /// Prevent false sharing between buckets. |
| ... | @@ -18102,8 +18103,14 @@ fn eventSet(event: *Io.Event) void { | ... | @@ -18102,8 +18103,14 @@ fn eventSet(event: *Io.Event) void { |
| 18102 | } | 18103 | } |
| 18103 | } | 18104 | } |
| 18104 | | 18105 | |
| | 18106 | const Condition = if (!is_windows) Io.Condition else struct { |
| | 18107 | condition: windows.CONDITION_VARIABLE, |
| | 18108 | const init: @This() = .{ .condition = .{} }; |
| | 18109 | }; |
| | 18110 | |
| 18105 | /// Same as `Io.Condition.broadcast` but avoids the VTable. | 18111 | /// Same as `Io.Condition.broadcast` but avoids the VTable. |
| 18106 | fn condBroadcast(cond: *Io.Condition) void { | 18112 | fn condBroadcast(cond: *Condition) void { |
| | 18113 | if (is_windows) return windows.ntdll.RtlWakeAllConditionVariable(&cond.condition); |
| 18107 | var prev_state = cond.state.load(.monotonic); | 18114 | var prev_state = cond.state.load(.monotonic); |
| 18108 | while (prev_state.waiters > prev_state.signals) { | 18115 | while (prev_state.waiters > prev_state.signals) { |
| 18109 | @branchHint(.unlikely); | 18116 | @branchHint(.unlikely); |
| ... | @@ -18123,7 +18130,8 @@ fn condBroadcast(cond: *Io.Condition) void { | ... | @@ -18123,7 +18130,8 @@ fn condBroadcast(cond: *Io.Condition) void { |
| 18123 | } | 18130 | } |
| 18124 | | 18131 | |
| 18125 | /// Same as `Io.Condition.signal` but avoids the VTable. | 18132 | /// Same as `Io.Condition.signal` but avoids the VTable. |
| 18126 | fn condSignal(cond: *Io.Condition) void { | 18133 | fn condSignal(cond: *Condition) void { |
| | 18134 | if (is_windows) return windows.ntdll.RtlWakeConditionVariable(&cond.condition); |
| 18127 | var prev_state = cond.state.load(.monotonic); | 18135 | var prev_state = cond.state.load(.monotonic); |
| 18128 | while (prev_state.waiters > prev_state.signals) { | 18136 | while (prev_state.waiters > prev_state.signals) { |
| 18129 | @branchHint(.unlikely); | 18137 | @branchHint(.unlikely); |
| ... | @@ -18143,7 +18151,11 @@ fn condSignal(cond: *Io.Condition) void { | ... | @@ -18143,7 +18151,11 @@ fn condSignal(cond: *Io.Condition) void { |
| 18143 | } | 18151 | } |
| 18144 | | 18152 | |
| 18145 | /// Same as `Io.Condition.waitUncancelable` but avoids the VTable. | 18153 | /// Same as `Io.Condition.waitUncancelable` but avoids the VTable. |
| 18146 | fn condWait(cond: *Io.Condition, mutex: *Io.Mutex) void { | 18154 | fn condWait(cond: *Condition, mutex: *Mutex) void { |
| | 18155 | if (is_windows) { |
| | 18156 | _ = windows.kernel32.SleepConditionVariableSRW(&cond.condition, &mutex.srwlock, windows.INFINITE, 0); |
| | 18157 | return; |
| | 18158 | } |
| 18147 | var epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before state load | 18159 | var epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before state load |
| 18148 | | 18160 | |
| 18149 | { | 18161 | { |
| ... | @@ -18172,6 +18184,11 @@ fn condWait(cond: *Io.Condition, mutex: *Io.Mutex) void { | ... | @@ -18172,6 +18184,11 @@ fn condWait(cond: *Io.Condition, mutex: *Io.Mutex) void { |
| 18172 | } | 18184 | } |
| 18173 | } | 18185 | } |
| 18174 | | 18186 | |
| | 18187 | const Mutex = if (!is_windows) Io.Mutex else struct { |
| | 18188 | srwlock: windows.SRWLOCK, |
| | 18189 | const init: @This() = .{ .srwlock = .{} }; |
| | 18190 | }; |
| | 18191 | |
| 18175 | /// Same as `Io.Mutex.lockUncancelable` but avoids the VTable. | 18192 | /// Same as `Io.Mutex.lockUncancelable` but avoids the VTable. |
| 18176 | fn mutexLock(m: *Io.Mutex) Io.Cancelable!void { | 18193 | fn mutexLock(m: *Io.Mutex) Io.Cancelable!void { |
| 18177 | const initial_state = m.state.cmpxchgWeak( | 18194 | const initial_state = m.state.cmpxchgWeak( |
| ... | @@ -18192,7 +18209,8 @@ fn mutexLock(m: *Io.Mutex) Io.Cancelable!void { | ... | @@ -18192,7 +18209,8 @@ fn mutexLock(m: *Io.Mutex) Io.Cancelable!void { |
| 18192 | } | 18209 | } |
| 18193 | | 18210 | |
| 18194 | /// Same as `Io.Mutex.lockUncancelable` but avoids the VTable. | 18211 | /// Same as `Io.Mutex.lockUncancelable` but avoids the VTable. |
| 18195 | fn mutexLockUncancelable(m: *Io.Mutex) void { | 18212 | fn mutexLockUncancelable(m: *Mutex) void { |
| | 18213 | if (is_windows) return windows.ntdll.RtlAcquireSRWLockExclusive(&m.srwlock); |
| 18196 | const initial_state = m.state.cmpxchgWeak( | 18214 | const initial_state = m.state.cmpxchgWeak( |
| 18197 | .unlocked, | 18215 | .unlocked, |
| 18198 | .locked_once, | 18216 | .locked_once, |
| ... | @@ -18211,7 +18229,8 @@ fn mutexLockUncancelable(m: *Io.Mutex) void { | ... | @@ -18211,7 +18229,8 @@ fn mutexLockUncancelable(m: *Io.Mutex) void { |
| 18211 | } | 18229 | } |
| 18212 | | 18230 | |
| 18213 | /// Same as `Io.Mutex.unlock` but avoids the VTable. | 18231 | /// Same as `Io.Mutex.unlock` but avoids the VTable. |
| 18214 | fn mutexUnlock(m: *Io.Mutex) void { | 18232 | fn mutexUnlock(m: *Mutex) void { |
| | 18233 | if (is_windows) return windows.ntdll.RtlReleaseSRWLockExclusive(&m.srwlock); |
| 18215 | switch (m.state.swap(.unlocked, .release)) { | 18234 | switch (m.state.swap(.unlocked, .release)) { |
| 18216 | .unlocked => unreachable, | 18235 | .unlocked => unreachable, |
| 18217 | .locked_once => {}, | 18236 | .locked_once => {}, |