authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-09 18:27:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-09 18:31:03-07:00
log008b0ec5e58fc7e31f3b989868a7d1ea4df3f41d
tree99374a7b0f5dc0bf56fc5daff702eecb7758d4f5
parent65e518e8e8ab74b276c5a284caebfad4e5aa502c

std.Thread.Mutex: change API to lock() and unlock()

This is a breaking change. Before, usage looked like this: ```zig const held = mutex.acquire(); defer held.release(); ``` Now it looks like this: ```zig mutex.lock(); defer mutex.unlock(); ``` The `Held` type was an idea to make mutexes slightly safer by making it more difficult to forget to release an aquired lock. However, this ultimately caused more problems than it solved, when any data structures needed to store a held mutex. Simplify everything by reducing the API down to the primitives: lock() and unlock(). Closes #8051 Closes #8246 Closes #10105

18 files changed, 140 insertions(+), 179 deletions(-)

lib/std/Progress.zig+9-9
......@@ -56,7 +56,7 @@ done: bool = true,
5656/// Protects the `refresh` function, as well as `node.recently_updated_child`.
5757/// Without this, callsites would call `Node.end` and then free `Node` memory
5858/// while it was still being accessed by the `refresh` function.
59update_lock: std.Thread.Mutex = .{},
59update_mutex: std.Thread.Mutex = .{},
6060
6161/// Keeps track of how many columns in the terminal have been output, so that
6262/// we can move the cursor back later.
......@@ -103,14 +103,14 @@ pub const Node = struct {
103103 self.context.maybeRefresh();
104104 if (self.parent) |parent| {
105105 {
106 const held = self.context.update_lock.acquire();
107 defer held.release();
106 self.context.update_mutex.lock();
107 defer self.context.update_mutex.unlock();
108108 _ = @cmpxchgStrong(?*Node, &parent.recently_updated_child, self, null, .Monotonic, .Monotonic);
109109 }
110110 parent.completeOne();
111111 } else {
112 const held = self.context.update_lock.acquire();
113 defer held.release();
112 self.context.update_mutex.lock();
113 defer self.context.update_mutex.unlock();
114114 self.context.done = true;
115115 self.context.refreshWithHeldLock();
116116 }
......@@ -170,8 +170,8 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*
170170pub fn maybeRefresh(self: *Progress) void {
171171 const now = self.timer.read();
172172 if (now < self.initial_delay_ns) return;
173 const held = self.update_lock.tryAcquire() orelse return;
174 defer held.release();
173 if (!self.update_mutex.tryLock()) return;
174 defer self.update_mutex.unlock();
175175 // TODO I have observed this to happen sometimes. I think we need to follow Rust's
176176 // lead and guarantee monotonically increasing times in the std lib itself.
177177 if (now < self.prev_refresh_timestamp) return;
......@@ -181,8 +181,8 @@ pub fn maybeRefresh(self: *Progress) void {
181181
182182/// Updates the terminal and resets `self.next_refresh_timestamp`. Thread-safe.
183183pub fn refresh(self: *Progress) void {
184 const held = self.update_lock.tryAcquire() orelse return;
185 defer held.release();
184 if (!self.update_mutex.tryLock()) return;
185 defer self.update_mutex.unlock();
186186
187187 return self.refreshWithHeldLock();
188188}
lib/std/Thread/Condition.zig+6-6
......@@ -145,8 +145,8 @@ pub const AtomicCondition = struct {
145145 var waiter = QueueList.Node{ .data = .{} };
146146
147147 {
148 const held = cond.queue_mutex.acquire();
149 defer held.release();
148 cond.queue_mutex.lock();
149 defer cond.queue_mutex.unlock();
150150
151151 cond.queue_list.prepend(&waiter);
152152 @atomicStore(bool, &cond.pending, true, .SeqCst);
......@@ -162,8 +162,8 @@ pub const AtomicCondition = struct {
162162 return;
163163
164164 const maybe_waiter = blk: {
165 const held = cond.queue_mutex.acquire();
166 defer held.release();
165 cond.queue_mutex.lock();
166 defer cond.queue_mutex.unlock();
167167
168168 const maybe_waiter = cond.queue_list.popFirst();
169169 @atomicStore(bool, &cond.pending, cond.queue_list.first != null, .SeqCst);
......@@ -181,8 +181,8 @@ pub const AtomicCondition = struct {
181181 @atomicStore(bool, &cond.pending, false, .SeqCst);
182182
183183 var waiters = blk: {
184 const held = cond.queue_mutex.acquire();
185 defer held.release();
184 cond.queue_mutex.lock();
185 defer cond.queue_mutex.unlock();
186186
187187 const waiters = cond.queue_list;
188188 cond.queue_list = .{};
lib/std/Thread/Mutex.zig+32-74
......@@ -8,13 +8,13 @@
88//! Example usage:
99//! var m = Mutex{};
1010//!
11//! const lock = m.acquire();
12//! defer lock.release();
11//! m.lock();
12//! defer m.release();
1313//! ... critical code
1414//!
1515//! Non-blocking:
16//! if (m.tryAcquire) |lock| {
17//! defer lock.release();
16//! if (m.tryLock()) {
17//! defer m.unlock();
1818//! // ... critical section
1919//! } else {
2020//! // ... lock not acquired
......@@ -32,30 +32,22 @@ const linux = os.linux;
3232const testing = std.testing;
3333const StaticResetEvent = std.thread.StaticResetEvent;
3434
35/// Try to acquire the mutex without blocking. Returns `null` if the mutex is
36/// unavailable. Otherwise returns `Held`. Call `release` on `Held`, or use
37/// releaseDirect().
38pub fn tryAcquire(m: *Mutex) ?Held {
39 return m.impl.tryAcquire();
35/// Try to acquire the mutex without blocking. Returns `false` if the mutex is
36/// unavailable. Otherwise returns `true`. Call `unlock` on the mutex to release.
37pub fn tryLock(m: *Mutex) bool {
38 return m.impl.tryLock();
4039}
4140
4241/// Acquire the mutex. Deadlocks if the mutex is already
4342/// held by the calling thread.
44pub fn acquire(m: *Mutex) Held {
45 return m.impl.acquire();
43pub fn lock(m: *Mutex) void {
44 m.impl.lock();
4645}
4746
48/// Release the mutex. Prefer Held.release() if available.
49pub fn releaseDirect(m: *Mutex) void {
50 return m.impl.releaseDirect();
47pub fn unlock(m: *Mutex) void {
48 m.impl.unlock();
5149}
5250
53/// A held mutex handle. Call release to allow other threads to
54/// take the mutex. Do not call release() more than once.
55/// For more complex scenarios, this handle can be discarded
56/// and Mutex.releaseDirect can be called instead.
57pub const Held = Impl.Held;
58
5951const Impl = if (builtin.single_threaded)
6052 Dummy
6153else if (builtin.os.tag == .windows)
......@@ -65,32 +57,6 @@ else if (std.Thread.use_pthreads)
6557else
6658 AtomicMutex;
6759
68fn HeldInterface(comptime MutexType: type) type {
69 return struct {
70 const Mixin = @This();
71 pub const Held = struct {
72 mutex: *MutexType,
73
74 pub fn release(held: Mixin.Held) void {
75 held.mutex.releaseDirect();
76 }
77 };
78
79 pub fn tryAcquire(m: *MutexType) ?Mixin.Held {
80 if (m.tryAcquireDirect()) {
81 return Mixin.Held{ .mutex = m };
82 } else {
83 return null;
84 }
85 }
86
87 pub fn acquire(m: *MutexType) Mixin.Held {
88 m.acquireDirect();
89 return Mixin.Held{ .mutex = m };
90 }
91 };
92}
93
9460pub const AtomicMutex = struct {
9561 state: State = .unlocked,
9662
......@@ -100,9 +66,7 @@ pub const AtomicMutex = struct {
10066 waiting,
10167 };
10268
103 pub usingnamespace HeldInterface(@This());
104
105 fn tryAcquireDirect(m: *AtomicMutex) bool {
69 pub fn tryLock(m: *AtomicMutex) bool {
10670 return @cmpxchgStrong(
10771 State,
10872 &m.state,
......@@ -113,14 +77,14 @@ pub const AtomicMutex = struct {
11377 ) == null;
11478 }
11579
116 fn acquireDirect(m: *AtomicMutex) void {
80 pub fn lock(m: *AtomicMutex) void {
11781 switch (@atomicRmw(State, &m.state, .Xchg, .locked, .Acquire)) {
11882 .unlocked => {},
11983 else => |s| m.lockSlow(s),
12084 }
12185 }
12286
123 fn releaseDirect(m: *AtomicMutex) void {
87 pub fn unlock(m: *AtomicMutex) void {
12488 switch (@atomicRmw(State, &m.state, .Xchg, .unlocked, .Release)) {
12589 .unlocked => unreachable,
12690 .locked => {},
......@@ -202,18 +166,16 @@ pub const AtomicMutex = struct {
202166pub const PthreadMutex = struct {
203167 pthread_mutex: std.c.pthread_mutex_t = .{},
204168
205 pub usingnamespace HeldInterface(@This());
206
207169 /// Try to acquire the mutex without blocking. Returns true if
208170 /// the mutex is unavailable. Otherwise returns false. Call
209171 /// release when done.
210 fn tryAcquireDirect(m: *PthreadMutex) bool {
172 pub fn tryLock(m: *PthreadMutex) bool {
211173 return std.c.pthread_mutex_trylock(&m.pthread_mutex) == .SUCCESS;
212174 }
213175
214176 /// Acquire the mutex. Will deadlock if the mutex is already
215177 /// held by the calling thread.
216 fn acquireDirect(m: *PthreadMutex) void {
178 pub fn lock(m: *PthreadMutex) void {
217179 switch (std.c.pthread_mutex_lock(&m.pthread_mutex)) {
218180 .SUCCESS => {},
219181 .INVAL => unreachable,
......@@ -225,7 +187,7 @@ pub const PthreadMutex = struct {
225187 }
226188 }
227189
228 fn releaseDirect(m: *PthreadMutex) void {
190 pub fn unlock(m: *PthreadMutex) void {
229191 switch (std.c.pthread_mutex_unlock(&m.pthread_mutex)) {
230192 .SUCCESS => return,
231193 .INVAL => unreachable,
......@@ -239,51 +201,47 @@ pub const PthreadMutex = struct {
239201/// This has the sematics as `Mutex`, however it does not actually do any
240202/// synchronization. Operations are safety-checked no-ops.
241203pub const Dummy = struct {
242 lock: @TypeOf(lock_init) = lock_init,
243
244 pub usingnamespace HeldInterface(@This());
204 locked: @TypeOf(lock_init) = lock_init,
245205
246206 const lock_init = if (std.debug.runtime_safety) false else {};
247207
248208 /// Try to acquire the mutex without blocking. Returns false if
249209 /// the mutex is unavailable. Otherwise returns true.
250 fn tryAcquireDirect(m: *Dummy) bool {
210 pub fn tryLock(m: *Dummy) bool {
251211 if (std.debug.runtime_safety) {
252 if (m.lock) return false;
253 m.lock = true;
212 if (m.locked) return false;
213 m.locked = true;
254214 }
255215 return true;
256216 }
257217
258218 /// Acquire the mutex. Will deadlock if the mutex is already
259219 /// held by the calling thread.
260 fn acquireDirect(m: *Dummy) void {
261 if (!m.tryAcquireDirect()) {
220 pub fn lock(m: *Dummy) void {
221 if (!m.tryLock()) {
262222 @panic("deadlock detected");
263223 }
264224 }
265225
266 fn releaseDirect(m: *Dummy) void {
226 pub fn unlock(m: *Dummy) void {
267227 if (std.debug.runtime_safety) {
268 m.lock = false;
228 m.locked = false;
269229 }
270230 }
271231};
272232
273const WindowsMutex = struct {
233pub const WindowsMutex = struct {
274234 srwlock: windows.SRWLOCK = windows.SRWLOCK_INIT,
275235
276 pub usingnamespace HeldInterface(@This());
277
278 fn tryAcquireDirect(m: *WindowsMutex) bool {
236 pub fn tryLock(m: *WindowsMutex) bool {
279237 return windows.kernel32.TryAcquireSRWLockExclusive(&m.srwlock) != windows.FALSE;
280238 }
281239
282 fn acquireDirect(m: *WindowsMutex) void {
240 pub fn lock(m: *WindowsMutex) void {
283241 windows.kernel32.AcquireSRWLockExclusive(&m.srwlock);
284242 }
285243
286 fn releaseDirect(m: *WindowsMutex) void {
244 pub fn unlock(m: *WindowsMutex) void {
287245 windows.kernel32.ReleaseSRWLockExclusive(&m.srwlock);
288246 }
289247};
......@@ -322,8 +280,8 @@ test "basic usage" {
322280fn worker(ctx: *TestContext) void {
323281 var i: usize = 0;
324282 while (i != TestContext.incr_count) : (i += 1) {
325 const held = ctx.mutex.acquire();
326 defer held.release();
283 ctx.mutex.lock();
284 defer ctx.mutex.unlock();
327285
328286 ctx.data += 1;
329287 }
lib/std/Thread/Semaphore.zig+4-4
......@@ -13,8 +13,8 @@ const Mutex = std.Thread.Mutex;
1313const Condition = std.Thread.Condition;
1414
1515pub fn wait(sem: *Semaphore) void {
16 const held = sem.mutex.acquire();
17 defer held.release();
16 sem.mutex.lock();
17 defer sem.mutex.unlock();
1818
1919 while (sem.permits == 0)
2020 sem.cond.wait(&sem.mutex);
......@@ -25,8 +25,8 @@ pub fn wait(sem: *Semaphore) void {
2525}
2626
2727pub fn post(sem: *Semaphore) void {
28 const held = sem.mutex.acquire();
29 defer held.release();
28 sem.mutex.lock();
29 defer sem.mutex.unlock();
3030
3131 sem.permits += 1;
3232 sem.cond.signal();
lib/std/atomic/queue.zig+12-12
......@@ -31,8 +31,8 @@ pub fn Queue(comptime T: type) type {
3131 pub fn put(self: *Self, node: *Node) void {
3232 node.next = null;
3333
34 const held = self.mutex.acquire();
35 defer held.release();
34 self.mutex.lock();
35 defer self.mutex.unlock();
3636
3737 node.prev = self.tail;
3838 self.tail = node;
......@@ -48,8 +48,8 @@ pub fn Queue(comptime T: type) type {
4848 /// It is safe to `get()` a node from the queue while another thread tries
4949 /// to `remove()` the same node at the same time.
5050 pub fn get(self: *Self) ?*Node {
51 const held = self.mutex.acquire();
52 defer held.release();
51 self.mutex.lock();
52 defer self.mutex.unlock();
5353
5454 const head = self.head orelse return null;
5555 self.head = head.next;
......@@ -67,8 +67,8 @@ pub fn Queue(comptime T: type) type {
6767 pub fn unget(self: *Self, node: *Node) void {
6868 node.prev = null;
6969
70 const held = self.mutex.acquire();
71 defer held.release();
70 self.mutex.lock();
71 defer self.mutex.unlock();
7272
7373 const opt_head = self.head;
7474 self.head = node;
......@@ -84,8 +84,8 @@ pub fn Queue(comptime T: type) type {
8484 /// It is safe to `remove()` a node from the queue while another thread tries
8585 /// to `get()` the same node at the same time.
8686 pub fn remove(self: *Self, node: *Node) bool {
87 const held = self.mutex.acquire();
88 defer held.release();
87 self.mutex.lock();
88 defer self.mutex.unlock();
8989
9090 if (node.prev == null and node.next == null and self.head != node) {
9191 return false;
......@@ -110,8 +110,8 @@ pub fn Queue(comptime T: type) type {
110110 /// Note that in a multi-consumer environment a return value of `false`
111111 /// does not mean that `get` will yield a non-`null` value!
112112 pub fn isEmpty(self: *Self) bool {
113 const held = self.mutex.acquire();
114 defer held.release();
113 self.mutex.lock();
114 defer self.mutex.unlock();
115115 return self.head == null;
116116 }
117117
......@@ -144,8 +144,8 @@ pub fn Queue(comptime T: type) type {
144144 }
145145 }
146146 };
147 const held = self.mutex.acquire();
148 defer held.release();
147 self.mutex.lock();
148 defer self.mutex.unlock();
149149
150150 try stream.print("head: ", .{});
151151 try S.dumpRecursive(stream, self.head, 0, 4);
lib/std/debug.zig+4-4
......@@ -62,8 +62,8 @@ pub const warn = print;
6262/// Print to stderr, unbuffered, and silently returning on failure. Intended
6363/// for use in "printf debugging." Use `std.log` functions for proper logging.
6464pub fn print(comptime fmt: []const u8, args: anytype) void {
65 const held = stderr_mutex.acquire();
66 defer held.release();
65 stderr_mutex.lock();
66 defer stderr_mutex.unlock();
6767 const stderr = io.getStdErr().writer();
6868 nosuspend stderr.print(fmt, args) catch return;
6969}
......@@ -286,8 +286,8 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
286286
287287 // Make sure to release the mutex when done
288288 {
289 const held = panic_mutex.acquire();
290 defer held.release();
289 panic_mutex.lock();
290 defer panic_mutex.unlock();
291291
292292 const stderr = io.getStdErr().writer();
293293 if (builtin.single_threaded) {
lib/std/event/lock.zig+5-5
......@@ -32,7 +32,7 @@ pub const Lock = struct {
3232 }
3333
3434 pub fn acquire(self: *Lock) Held {
35 const held = self.mutex.acquire();
35 self.mutex.lock();
3636
3737 // self.head transitions from multiple stages depending on the value:
3838 // UNLOCKED -> LOCKED:
......@@ -44,7 +44,7 @@ pub const Lock = struct {
4444
4545 if (self.head == UNLOCKED) {
4646 self.head = LOCKED;
47 held.release();
47 self.mutex.unlock();
4848 return Held{ .lock = self };
4949 }
5050
......@@ -71,7 +71,7 @@ pub const Lock = struct {
7171 .next = undefined,
7272 .data = @frame(),
7373 };
74 held.release();
74 self.mutex.unlock();
7575 }
7676
7777 return Held{ .lock = self };
......@@ -82,8 +82,8 @@ pub const Lock = struct {
8282
8383 pub fn release(self: Held) void {
8484 const waiter = blk: {
85 const held = self.lock.mutex.acquire();
86 defer held.release();
85 self.lock.mutex.lock();
86 defer self.lock.mutex.unlock();
8787
8888 // self.head goes through the reverse transition from acquire():
8989 // <head ptr> -> <new head ptr>:
lib/std/event/loop.zig+2-2
......@@ -925,8 +925,8 @@ pub const Loop = struct {
925925 }
926926
927927 fn peekExpiringEntry(self: *Waiters) ?*Entry {
928 const held = self.entries.mutex.acquire();
929 defer held.release();
928 self.entries.mutex.lock();
929 defer self.entries.mutex.unlock();
930930
931931 // starting from the head
932932 var head = self.entries.head orelse return null;
lib/std/heap/general_purpose_allocator.zig+4-4
......@@ -615,8 +615,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
615615 ) Error!usize {
616616 const self = @fieldParentPtr(Self, "allocator", allocator);
617617
618 const held = self.mutex.acquire();
619 defer held.release();
618 self.mutex.lock();
619 defer self.mutex.unlock();
620620
621621 assert(old_mem.len != 0);
622622
......@@ -758,8 +758,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
758758 fn alloc(allocator: *Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8 {
759759 const self = @fieldParentPtr(Self, "allocator", allocator);
760760
761 const held = self.mutex.acquire();
762 defer held.release();
761 self.mutex.lock();
762 defer self.mutex.unlock();
763763
764764 if (!self.isAllocationAllowed(len)) {
765765 return error.OutOfMemory;
lib/std/json.zig+2-2
......@@ -1319,8 +1319,8 @@ pub const Value = union(enum) {
13191319 }
13201320
13211321 pub fn dump(self: Value) void {
1322 var held = std.debug.getStderrMutex().acquire();
1323 defer held.release();
1322 std.debug.getStderrMutex().lock();
1323 defer std.debug.getStderrMutex().unlock();
13241324
13251325 const stderr = std.io.getStdErr().writer();
13261326 std.json.stringify(self, std.json.StringifyOptions{ .whitespace = null }, stderr) catch return;
lib/std/log.zig+4-4
......@@ -41,8 +41,8 @@
4141//! const prefix = "[" ++ level.asText() ++ "] " ++ scope_prefix;
4242//!
4343//! // Print the message to stderr, silently ignoring any errors
44//! const held = std.debug.getStderrMutex().acquire();
45//! defer held.release();
44//! std.debug.getStderrMutex().lock();
45//! defer std.debug.getStderrMutex().unlock();
4646//! const stderr = std.io.getStdErr().writer();
4747//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
4848//! }
......@@ -165,8 +165,8 @@ pub fn defaultLog(
165165 const level_txt = comptime message_level.asText();
166166 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
167167 const stderr = std.io.getStdErr().writer();
168 const held = std.debug.getStderrMutex().acquire();
169 defer held.release();
168 std.debug.getStderrMutex().lock();
169 defer std.debug.getStderrMutex().unlock();
170170 nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;
171171}
172172
lib/std/once.zig+2-2
......@@ -26,8 +26,8 @@ pub fn Once(comptime f: fn () void) type {
2626 fn callSlow(self: *@This()) void {
2727 @setCold(true);
2828
29 const T = self.mutex.acquire();
30 defer T.release();
29 self.mutex.lock();
30 defer self.mutex.unlock();
3131
3232 // The first thread to acquire the mutex gets to run the initializer
3333 if (!self.done) {
lib/std/os/windows.zig+2-2
......@@ -1324,8 +1324,8 @@ pub fn WSASocketW(
13241324 if (!first) return error.Unexpected;
13251325 first = false;
13261326
1327 var held = wsa_startup_mutex.acquire();
1328 defer held.release();
1327 wsa_startup_mutex.lock();
1328 defer wsa_startup_mutex.unlock();
13291329
13301330 // Here we could use a flag to prevent multiple threads to prevent
13311331 // multiple calls to WSAStartup, but it doesn't matter. We're globally
src/Compilation.zig+14-14
......@@ -339,8 +339,8 @@ pub const AllErrors = struct {
339339 },
340340
341341 pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
342 const held = std.debug.getStderrMutex().acquire();
343 defer held.release();
342 std.debug.getStderrMutex().lock();
343 defer std.debug.getStderrMutex().unlock();
344344 const stderr = std.io.getStdErr();
345345 return msg.renderToStdErrInner(ttyconf, stderr, "error:", .Red, 0) catch return;
346346 }
......@@ -2691,8 +2691,8 @@ fn workerAstGenFile(
26912691 const import_path = file.zir.nullTerminatedString(item.data.name);
26922692
26932693 const import_result = blk: {
2694 const lock = comp.mutex.acquire();
2695 defer lock.release();
2694 comp.mutex.lock();
2695 defer comp.mutex.unlock();
26962696
26972697 break :blk mod.importFile(file, import_path) catch continue;
26982698 };
......@@ -2933,8 +2933,8 @@ fn reportRetryableCObjectError(
29332933 .column = 0,
29342934 };
29352935 {
2936 const lock = comp.mutex.acquire();
2937 defer lock.release();
2936 comp.mutex.lock();
2937 defer comp.mutex.unlock();
29382938 try comp.failed_c_objects.putNoClobber(comp.gpa, c_object, c_obj_err_msg);
29392939 }
29402940}
......@@ -2981,8 +2981,8 @@ fn reportRetryableAstGenError(
29812981 errdefer err_msg.destroy(gpa);
29822982
29832983 {
2984 const lock = comp.mutex.acquire();
2985 defer lock.release();
2984 comp.mutex.lock();
2985 defer comp.mutex.unlock();
29862986 try mod.failed_files.putNoClobber(gpa, file, err_msg);
29872987 }
29882988}
......@@ -3011,8 +3011,8 @@ fn reportRetryableEmbedFileError(
30113011 errdefer err_msg.destroy(gpa);
30123012
30133013 {
3014 const lock = comp.mutex.acquire();
3015 defer lock.release();
3014 comp.mutex.lock();
3015 defer comp.mutex.unlock();
30163016 try mod.failed_embed_files.putNoClobber(gpa, embed_file, err_msg);
30173017 }
30183018}
......@@ -3031,8 +3031,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
30313031
30323032 if (c_object.clearStatus(comp.gpa)) {
30333033 // There was previous failure.
3034 const lock = comp.mutex.acquire();
3035 defer lock.release();
3034 comp.mutex.lock();
3035 defer comp.mutex.unlock();
30363036 // If the failure was OOM, there will not be an entry here, so we do
30373037 // not assert discard.
30383038 _ = comp.failed_c_objects.swapRemove(c_object);
......@@ -3576,8 +3576,8 @@ fn failCObjWithOwnedErrorMsg(
35763576) SemaError {
35773577 @setCold(true);
35783578 {
3579 const lock = comp.mutex.acquire();
3580 defer lock.release();
3579 comp.mutex.lock();
3580 defer comp.mutex.unlock();
35813581 {
35823582 errdefer err_msg.destroy(comp.gpa);
35833583 try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1);
src/Module.zig+10-10
......@@ -2629,8 +2629,8 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
26292629 // TODO don't report compile errors until Sema @importFile
26302630 if (file.zir.hasCompileErrors()) {
26312631 {
2632 const lock = comp.mutex.acquire();
2633 defer lock.release();
2632 comp.mutex.lock();
2633 defer comp.mutex.unlock();
26342634 try mod.failed_files.putNoClobber(gpa, file, null);
26352635 }
26362636 file.status = .astgen_failure;
......@@ -2742,8 +2742,8 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
27422742 }
27432743
27442744 {
2745 const lock = comp.mutex.acquire();
2746 defer lock.release();
2745 comp.mutex.lock();
2746 defer comp.mutex.unlock();
27472747 try mod.failed_files.putNoClobber(gpa, file, err_msg);
27482748 }
27492749 file.status = .parse_failure;
......@@ -2817,8 +2817,8 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
28172817
28182818 if (file.zir.hasCompileErrors()) {
28192819 {
2820 const lock = comp.mutex.acquire();
2821 defer lock.release();
2820 comp.mutex.lock();
2821 defer comp.mutex.unlock();
28222822 try mod.failed_files.putNoClobber(gpa, file, null);
28232823 }
28242824 file.status = .astgen_failure;
......@@ -3701,8 +3701,8 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
37013701 embed_file.stat_mtime = stat.mtime;
37023702 embed_file.stat_inode = stat.inode;
37033703
3704 const lock = mod.comp.mutex.acquire();
3705 defer lock.release();
3704 mod.comp.mutex.lock();
3705 defer mod.comp.mutex.unlock();
37063706 try mod.comp.work_queue.writeItem(.{ .update_embed_file = embed_file });
37073707}
37083708
......@@ -4459,8 +4459,8 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void {
44594459 switch (file.status) {
44604460 .success_zir, .retryable_failure => {},
44614461 .never_loaded, .parse_failure, .astgen_failure => {
4462 const lock = mod.comp.mutex.acquire();
4463 defer lock.release();
4462 mod.comp.mutex.lock();
4463 defer mod.comp.mutex.unlock();
44644464 if (mod.failed_files.fetchSwapRemove(file)) |kv| {
44654465 if (kv.value) |msg| msg.destroy(mod.gpa); // Delete previous error message.
44664466 }
src/ThreadPool.zig+17-14
......@@ -7,7 +7,7 @@ const std = @import("std");
77const builtin = @import("builtin");
88const ThreadPool = @This();
99
10lock: std.Thread.Mutex = .{},
10mutex: std.Thread.Mutex = .{},
1111is_running: bool = true,
1212allocator: *std.mem.Allocator,
1313workers: []Worker,
......@@ -28,26 +28,28 @@ const Worker = struct {
2828 idle_node: IdleQueue.Node,
2929
3030 fn run(worker: *Worker) void {
31 const pool = worker.pool;
32
3133 while (true) {
32 const held = worker.pool.lock.acquire();
34 pool.mutex.lock();
3335
34 if (worker.pool.run_queue.popFirst()) |run_node| {
35 held.release();
36 if (pool.run_queue.popFirst()) |run_node| {
37 pool.mutex.unlock();
3638 (run_node.data.runFn)(&run_node.data);
3739 continue;
3840 }
3941
40 if (worker.pool.is_running) {
42 if (pool.is_running) {
4143 worker.idle_node.data.reset();
4244
43 worker.pool.idle_queue.prepend(&worker.idle_node);
44 held.release();
45 pool.idle_queue.prepend(&worker.idle_node);
46 pool.mutex.unlock();
4547
4648 worker.idle_node.data.wait();
4749 continue;
4850 }
4951
50 held.release();
52 pool.mutex.unlock();
5153 return;
5254 }
5355 }
......@@ -88,8 +90,8 @@ fn destroyWorkers(self: *ThreadPool, spawned: usize) void {
8890
8991pub fn deinit(self: *ThreadPool) void {
9092 {
91 const held = self.lock.acquire();
92 defer held.release();
93 self.mutex.lock();
94 defer self.mutex.unlock();
9395
9496 self.is_running = false;
9597 while (self.idle_queue.popFirst()) |idle_node|
......@@ -117,14 +119,15 @@ pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void {
117119 const closure = @fieldParentPtr(@This(), "run_node", run_node);
118120 @call(.{}, func, closure.arguments);
119121
120 const held = closure.pool.lock.acquire();
121 defer held.release();
122 const mutex = &closure.pool.mutex;
123 mutex.lock();
124 defer mutex.unlock();
122125 closure.pool.allocator.destroy(closure);
123126 }
124127 };
125128
126 const held = self.lock.acquire();
127 defer held.release();
129 self.mutex.lock();
130 defer self.mutex.unlock();
128131
129132 const closure = try self.allocator.create(Closure);
130133 closure.* = .{
src/WaitGroup.zig+9-9
......@@ -6,13 +6,13 @@
66const std = @import("std");
77const WaitGroup = @This();
88
9lock: std.Thread.Mutex = .{},
9mutex: std.Thread.Mutex = .{},
1010counter: usize = 0,
1111event: std.Thread.ResetEvent,
1212
1313pub fn init(self: *WaitGroup) !void {
1414 self.* = .{
15 .lock = .{},
15 .mutex = .{},
1616 .counter = 0,
1717 .event = undefined,
1818 };
......@@ -25,15 +25,15 @@ pub fn deinit(self: *WaitGroup) void {
2525}
2626
2727pub fn start(self: *WaitGroup) void {
28 const held = self.lock.acquire();
29 defer held.release();
28 self.mutex.lock();
29 defer self.mutex.unlock();
3030
3131 self.counter += 1;
3232}
3333
3434pub fn finish(self: *WaitGroup) void {
35 const held = self.lock.acquire();
36 defer held.release();
35 self.mutex.lock();
36 defer self.mutex.unlock();
3737
3838 self.counter -= 1;
3939
......@@ -44,14 +44,14 @@ pub fn finish(self: *WaitGroup) void {
4444
4545pub fn wait(self: *WaitGroup) void {
4646 while (true) {
47 const held = self.lock.acquire();
47 self.mutex.lock();
4848
4949 if (self.counter == 0) {
50 held.release();
50 self.mutex.unlock();
5151 return;
5252 }
5353
54 held.release();
54 self.mutex.unlock();
5555 self.event.wait();
5656 }
5757}
src/crash_report.zig+2-2
......@@ -422,7 +422,7 @@ const PanicSwitch = struct {
422422
423423 state.recover_stage = .release_ref_count;
424424
425 _ = panic_mutex.acquire();
425 panic_mutex.lock();
426426
427427 state.recover_stage = .release_mutex;
428428
......@@ -482,7 +482,7 @@ const PanicSwitch = struct {
482482 noinline fn releaseMutex(state: *volatile PanicState) noreturn {
483483 state.recover_stage = .abort;
484484
485 panic_mutex.releaseDirect();
485 panic_mutex.unlock();
486486
487487 goTo(releaseRefCount, .{state});
488488 }