mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
rtl: add racy_read
This commit is contained in:
@@ -30,3 +30,8 @@ pub fn read_struct(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Racily read a pointer on purpose.
|
||||||
|
pub fn racy_read(comptime T: type, ptr: *T) T {
|
||||||
|
return @atomicLoad(T, ptr, .unordered);
|
||||||
|
}
|
||||||
|
|||||||
+4
-4
@@ -24,8 +24,8 @@ pub fn SeqLockType(comptime T: type) type {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relaxed load memcpy is needed here since data races are UB.
|
// Unordered load memcpy is needed here since data races are UB.
|
||||||
rtl.barrier.atomic_load_memcpy(&ret, &self.raw, .monotonic);
|
rtl.barrier.atomic_load_memcpy(&ret, &self.raw, .unordered);
|
||||||
|
|
||||||
// Ensure the sequence read happens *after* the data is fully
|
// Ensure the sequence read happens *after* the data is fully
|
||||||
// loaded.
|
// loaded.
|
||||||
@@ -49,8 +49,8 @@ pub fn SeqLockType(comptime T: type) type {
|
|||||||
// is incremented.
|
// is incremented.
|
||||||
rtl.barrier.fence(.release);
|
rtl.barrier.fence(.release);
|
||||||
|
|
||||||
// Relaxed store memcpy is needed here since data races are UB.
|
// Unordered store memcpy is needed here since data races are UB.
|
||||||
rtl.barrier.atomic_store_memcpy(&self.raw, &data, .monotonic);
|
rtl.barrier.atomic_store_memcpy(&self.raw, &data, .unordered);
|
||||||
|
|
||||||
self.sequence.store(seq + 2, .release);
|
self.sequence.store(seq + 2, .release);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -144,13 +144,12 @@ const Pool = struct {
|
|||||||
|
|
||||||
/// Return whether or not a new worker thread should be added to this pool.
|
/// Return whether or not a new worker thread should be added to this pool.
|
||||||
fn should_grow(self: *Pool) bool {
|
fn should_grow(self: *Pool) bool {
|
||||||
// NOTE: lockless racy check whether or not the queue is empty
|
// Lockless racy check whether or not the queue is empty
|
||||||
// and its active count.
|
// and its active count.
|
||||||
// This is fine as this is best effort anyway and is a heuristic.
|
// This is fine as this is best effort anyway and is a heuristic.
|
||||||
const is_empty = @atomicLoad(
|
const is_empty = rtl.mem.racy_read(
|
||||||
*rtl.List.Entry,
|
*rtl.List.Entry,
|
||||||
&self.queue.items.head.next,
|
&self.queue.items.head.next,
|
||||||
.monotonic,
|
|
||||||
) == &self.queue.items.head;
|
) == &self.queue.items.head;
|
||||||
|
|
||||||
const active = self.queue.active.load(.monotonic);
|
const active = self.queue.active.load(.monotonic);
|
||||||
|
|||||||
@@ -293,11 +293,7 @@ pub fn RingBufferType(data_size_bits: usize, avg_msg_bits: usize) type {
|
|||||||
// Loading the ID here is purposely racey because
|
// Loading the ID here is purposely racey because
|
||||||
// we check if the descriptor is valid anyway.
|
// we check if the descriptor is valid anyway.
|
||||||
const id: Id = @truncate(
|
const id: Id = @truncate(
|
||||||
@atomicLoad(
|
rtl.mem.racy_read(usize, @ptrCast(&blk.id)),
|
||||||
usize,
|
|
||||||
@as(*usize, @ptrCast(&blk.id)),
|
|
||||||
.monotonic,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
const res = self.read_desc(id);
|
const res = self.read_desc(id);
|
||||||
desc = res.desc;
|
desc = res.desc;
|
||||||
|
|||||||
@@ -175,10 +175,9 @@ pub const Mutex = struct {
|
|||||||
|
|
||||||
var gas: usize = 0;
|
var gas: usize = 0;
|
||||||
|
|
||||||
while (@atomicLoad(
|
while (rtl.mem.racy_read(
|
||||||
?*ke.Thread,
|
?*ke.Thread,
|
||||||
cpu_curtd,
|
cpu_curtd,
|
||||||
.unordered,
|
|
||||||
) == owner and gas < optimistic_spins) : (gas += 1) {
|
) == owner and gas < optimistic_spins) : (gas += 1) {
|
||||||
if (m.state.load(.monotonic) == State.uncontended) {
|
if (m.state.load(.monotonic) == State.uncontended) {
|
||||||
// Got released, retry acquiring it.
|
// Got released, retry acquiring it.
|
||||||
|
|||||||
@@ -1779,11 +1779,7 @@ pub fn idle(_: ?*anyopaque) noreturn {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Racy but only a hint anyway
|
// Racy but only a hint anyway
|
||||||
const next = @atomicLoad(
|
const next = rtl.mem.racy_read(?*ke.Thread, &cpu.next_thread);
|
||||||
?*ke.Thread,
|
|
||||||
&cpu.next_thread,
|
|
||||||
.monotonic,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (cpu.load.load(.monotonic) != 0 or next != null) {
|
if (cpu.load.load(.monotonic) != 0 or next != null) {
|
||||||
std.atomic.spinLoopHint();
|
std.atomic.spinLoopHint();
|
||||||
|
|||||||
+2
-2
@@ -736,7 +736,7 @@ pub const Zone = struct {
|
|||||||
// Local depot is empty, rebalance with the zone depot.
|
// Local depot is empty, rebalance with the zone depot.
|
||||||
// Purposefully race against cpu_depot_size because locking is
|
// Purposefully race against cpu_depot_size because locking is
|
||||||
// tricky here, we may get a stale value but it is harmless.
|
// tricky here, we may get a stale value but it is harmless.
|
||||||
const n = @atomicLoad(usize, &self.cpu_depot_size, .monotonic);
|
const n = rtl.mem.racy_read(usize, &self.cpu_depot_size);
|
||||||
|
|
||||||
self.alloc_depot_rebalance(n, cpu);
|
self.alloc_depot_rebalance(n, cpu);
|
||||||
|
|
||||||
@@ -924,7 +924,7 @@ pub const Zone = struct {
|
|||||||
|
|
||||||
// Local depot is empty, rebalance with the zone depot.
|
// Local depot is empty, rebalance with the zone depot.
|
||||||
// Race explained in alloc.
|
// Race explained in alloc.
|
||||||
const n = @atomicLoad(usize, &self.cpu_depot_size, .monotonic);
|
const n = rtl.mem.racy_read(usize, &self.cpu_depot_size);
|
||||||
|
|
||||||
self.free_depot_rebalance(n, cpu);
|
self.free_depot_rebalance(n, cpu);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user