authorgravatar for justus@klausecker.deJustus Klausecker <justus@klausecker.de> 2026-03-07 11:13:02+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-12 21:02:43+01:00
log4d6bef538ef1ba25b21a57b19d09a66ad4d7e4f9
treeec78866e1b85074f0f7092990405374e57f4a835
parent47597a6d7cb7bbea313c15ba4c9f5dcecb972e64

std.heap.ArenaAllocator: relax memory ordering for stealing free list

We only need acquire instead of acq_rel here, since we're always swapping in `null` there's no node whose content we'd need to release.

1 files changed, 6 insertions(+), 5 deletions(-)

lib/std/heap/ArenaAllocator.zig+6-5
......@@ -248,8 +248,8 @@ const Node = struct {
248248 };
249249
250250 fn loadBuf(node: *Node) []u8 {
251 // monotonic is fine since `size` can only ever grow, so the buffer returned
252 // by this function is always valid memory.
251 // `size` can only ever grow, so the buffer returned by this function is
252 // always valid memory.
253253 const size = @atomicLoad(Size, &node.size, .monotonic);
254254 return @as([*]u8, @ptrCast(node))[0..size.toInt()][@sizeOf(Node)..];
255255 }
......@@ -298,8 +298,9 @@ fn tryPushNode(arena: *ArenaAllocator, node: *Node) PushResult {
298298}
299299
300300fn stealFreeList(arena: *ArenaAllocator) ?*Node {
301 // syncs with acq_rel in other `stealFreeList` calls or release in `pushFreeList`
302 return @atomicRmw(?*Node, &arena.state.free_list, .Xchg, null, .acq_rel);
301 // We don't need acq_rel here because we're always swapping in `null`, so
302 // there's no node we'd need to release.
303 return @atomicRmw(?*Node, &arena.state.free_list, .Xchg, null, .acquire); // syncs with release in `pushFreeList`
303304}
304305
305306fn pushFreeList(arena: *ArenaAllocator, first: *Node, last: *Node) void {
......@@ -311,7 +312,7 @@ fn pushFreeList(arena: *ArenaAllocator, first: *Node, last: *Node) void {
311312 &arena.state.free_list,
312313 last.next,
313314 first,
314 .release, // syncs with acquire part of acq_rel in `stealFreeList`
315 .release, // syncs with acquire in `stealFreeList`
315316 .monotonic, // we never access any fields of `old_free_list`, we only care about the pointer
316317 )) |old_free_list| {
317318 last.next = old_free_list;