authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-01 14:57:27-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-02 18:36:40-08:00
log255aeb57b24bc24b604744460a61ebf7c44e42ea
treebdff078adb9b685bec2ee888a1a6a2cdc8d005ee
parente9eadee00654f5f762abe3cdc596359b79893eab

std: introduce atomic.Mutex and use it in heap.SmpAllocator

This allocator implementation uses only lock-free operations.

2 files changed, 22 insertions(+), 5 deletions(-)

lib/std/atomic.zig+21-4
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1const builtin = @import("builtin");
2
3const std = @import("std.zig");
4const AtomicOrder = std.builtin.AtomicOrder;
5const testing = std.testing;
6const assert = std.debug.assert;
7
1/// This is a thin wrapper around a primitive value to prevent accidental data races.8/// This is a thin wrapper around a primitive value to prevent accidental data races.
2pub fn Value(comptime T: type) type {9pub fn Value(comptime T: type) type {
3 return extern struct {10 return extern struct {
...@@ -496,7 +503,17 @@ test "current CPU has a cache line size" {...@@ -496,7 +503,17 @@ test "current CPU has a cache line size" {
496 _ = cache_line;503 _ = cache_line;
497}504}
498505
499const std = @import("std.zig");506/// A lock-free single-owner resource.
500const builtin = @import("builtin");507pub const Mutex = enum(u8) {
501const AtomicOrder = std.builtin.AtomicOrder;508 unlocked,
502const testing = std.testing;509 locked,
510
511 pub fn tryLock(m: *Mutex) bool {
512 return @cmpxchgWeak(Mutex, m, .unlocked, .locked, .acquire, .monotonic) == null;
513 }
514
515 pub fn unlock(m: *Mutex) void {
516 assert(m.* == .locked);
517 @atomicStore(Mutex, m, .unlocked, .release);
518 }
519};
lib/std/heap/SmpAllocator.zig+1-1
...@@ -62,7 +62,7 @@ const Thread = struct {...@@ -62,7 +62,7 @@ const Thread = struct {
62 ///62 ///
63 /// Threads lock this before accessing their own state in order63 /// Threads lock this before accessing their own state in order
64 /// to support freelist reclamation.64 /// to support freelist reclamation.
65 mutex: std.Thread.Mutex = .{},65 mutex: std.atomic.Mutex = .unlocked,
6666
67 /// For each size class, tracks the next address to be returned from67 /// For each size class, tracks the next address to be returned from
68 /// `alloc` when the freelist is empty.68 /// `alloc` when the freelist is empty.