mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 15:48:21 +00:00
ke(mutex): do optimistic spinning
This commit is contained in:
+13
-6
@@ -2,6 +2,9 @@ const std = @import("std");
|
|||||||
const ke = @import("root").ke;
|
const ke = @import("root").ke;
|
||||||
const ki = ke.private;
|
const ki = ke.private;
|
||||||
|
|
||||||
|
/// Number of spins before blocking.
|
||||||
|
const optimistic_spins = 10000;
|
||||||
|
|
||||||
pub const Mutex = struct {
|
pub const Mutex = struct {
|
||||||
/// The thread currently holding the mutex, null if unlocked.
|
/// The thread currently holding the mutex, null if unlocked.
|
||||||
owner: std.atomic.Value(?*ke.Thread),
|
owner: std.atomic.Value(?*ke.Thread),
|
||||||
@@ -14,10 +17,14 @@ pub const Mutex = struct {
|
|||||||
const ipl = ke.ipl.raise(.Dispatch);
|
const ipl = ke.ipl.raise(.Dispatch);
|
||||||
const curtd = ki.sched.percpu.local().current_thread.?;
|
const curtd = ki.sched.percpu.local().current_thread.?;
|
||||||
|
|
||||||
// Fast path: try to acquire without a turnstile.
|
// Fast path: try to acquire without a turnstile by spinning a bit.
|
||||||
if (m.owner.cmpxchgStrong(null, curtd, .acquire, .monotonic) == null) {
|
for (0..optimistic_spins) |_| {
|
||||||
ke.ipl.lower(ipl);
|
if (m.owner.cmpxchgStrong(null, curtd, .acquire, .monotonic) == null) {
|
||||||
return;
|
ke.ipl.lower(ipl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.atomic.spinLoopHint();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slow path: contended, block on a turnstile.
|
// Slow path: contended, block on a turnstile.
|
||||||
@@ -35,7 +42,7 @@ pub const Mutex = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Block until woken.
|
// Block until woken.
|
||||||
ki.turnstile.block(ts, m, owner.?, .Shared);
|
ki.turnstile.block(ts, m, owner.?, .Exclusive);
|
||||||
|
|
||||||
// Re-try acquisition after wakeup.
|
// Re-try acquisition after wakeup.
|
||||||
if (m.owner.cmpxchgStrong(null, curtd, .acquire, .monotonic) == null) {
|
if (m.owner.cmpxchgStrong(null, curtd, .acquire, .monotonic) == null) {
|
||||||
@@ -62,7 +69,7 @@ pub const Mutex = struct {
|
|||||||
// Note: wake up all waiters. This so-called "lock barging" (name from WTF::ParkingLot)
|
// Note: wake up all waiters. This so-called "lock barging" (name from WTF::ParkingLot)
|
||||||
// has been shown to be better because this avoids lock convoys, see this mysterious 70s paper:
|
// has been shown to be better because this avoids lock convoys, see this mysterious 70s paper:
|
||||||
// https://dl.acm.org/doi/pdf/10.1145/850657.850659
|
// https://dl.acm.org/doi/pdf/10.1145/850657.850659
|
||||||
ki.turnstile.wakeup(ts.?, .Exlusive, ts.?.waiters, null);
|
ki.turnstile.wakeup(ts.?, .Exclusive, ts.?.waiters, null);
|
||||||
|
|
||||||
ke.ipl.lower(ipl);
|
ke.ipl.lower(ipl);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user