Zig 0.17.0-dev (Split by item)
This is an example of documentation generated by
ZigDoc , an alternative to Zig's built-in
Auto Doc feature. See also
examples in other modes/formats . The project being documented here (as the example) is the Zig library itself.
Zig › compiler_rt/ › atomics.zig › SpinlockTable
SpinlockTable
atomics.SpinlockTable
const SpinlockTable = struct
File
Code
const SpinlockTable = struct {
const max_spinlocks = 64 ;
const Spinlock = struct {
// We'll use that as a sign that the lock is currently held.
// See also: Section B.7 in SPARCv8 spec & A.29 in SPARCv9 spec.
const sparc_lock : type = enum (u8 ) { Unlocked = 0 , Locked = 255 };
const other_lock : type = enum (usize ) { Unlocked = 0 , Locked };
// consecutive spinlock elements
v : if (arch .isSPARC ()) sparc_lock else other_lock align (cache_line_size ) = .Unlocked ,
fn acquire (self : *@This ()) void {
while (true ) {
const flag = if (comptime arch .isSPARC ()) flag : {
break :flag asm volatile ("ldstub [%[addr]], %[flag]"
: [flag ] "=r" (-> @TypeOf (self .v )),
: [addr ] "r" (&self .v ),
: .{ .memory = true });
} else flag : {
break :flag @atomicRmw (@TypeOf (self .v ), &self .v , .Xchg , .Locked , .acquire );
};
switch (flag ) {
.Unlocked => break ,
.Locked => {},
}
}
}
fn release (self : *@This ()) void {
if (comptime arch .isSPARC ()) {
_ = asm volatile ("clrb [%[addr]]"
:
: [addr ] "r" (&self .v ),
: .{ .memory = true });
} else {
@atomicStore (@TypeOf (self .v ), &self .v , .Unlocked , .release );
}
}
};
list : [max_spinlocks ]Spinlock = @splat (.{}),
// addresses to spinlocks. The mapping is not unique but that's only a
// performance problem as the lock will be contended by more than a pair of
// threads.
fn get (self : *@This (), address : usize ) *Spinlock {
var sl = &self .list [(address >> 3 ) % max_spinlocks ];
sl .acquire ();
return sl ;
}
}