commit 255aeb57b24bc24b604744460a61ebf7c44e42ea (tree)
parent e9eadee00654f5f762abe3cdc596359b79893eab
Author: Andrew Kelley <andrew@ziglang.org>
Date: Sun, 1 Feb 2026 14:57:27 -0800
std: introduce atomic.Mutex and use it in heap.SmpAllocator
This allocator implementation uses only lock-free operations.
Diffstat:
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig
@@ -1,3 +1,10 @@
+const builtin = @import("builtin");
+
+const std = @import("std.zig");
+const AtomicOrder = std.builtin.AtomicOrder;
+const testing = std.testing;
+const assert = std.debug.assert;
+
/// This is a thin wrapper around a primitive value to prevent accidental data races.
pub fn Value(comptime T: type) type {
return extern struct {
@@ -496,7 +503,17 @@ test "current CPU has a cache line size" {
_ = cache_line;
}
-const std = @import("std.zig");
-const builtin = @import("builtin");
-const AtomicOrder = std.builtin.AtomicOrder;
-const testing = std.testing;
+/// A lock-free single-owner resource.
+pub const Mutex = enum(u8) {
+ unlocked,
+ locked,
+
+ pub fn tryLock(m: *Mutex) bool {
+ return @cmpxchgWeak(Mutex, m, .unlocked, .locked, .acquire, .monotonic) == null;
+ }
+
+ pub fn unlock(m: *Mutex) void {
+ assert(m.* == .locked);
+ @atomicStore(Mutex, m, .unlocked, .release);
+ }
+};
diff --git a/lib/std/heap/SmpAllocator.zig b/lib/std/heap/SmpAllocator.zig
@@ -62,7 +62,7 @@ const Thread = struct {
///
/// Threads lock this before accessing their own state in order
/// to support freelist reclamation.
- mutex: std.Thread.Mutex = .{},
+ mutex: std.atomic.Mutex = .unlocked,
/// For each size class, tracks the next address to be returned from
/// `alloc` when the freelist is empty.