mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
move SpinLock definitions around
This commit is contained in:
parent
92dac89d01
commit
b535e86cc0
@ -158,6 +158,7 @@ pub extern "c" fn pthread_attr_init(attr: *pthread_attr_t) c_int;
|
||||
pub extern "c" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int;
|
||||
pub extern "c" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int;
|
||||
pub extern "c" fn pthread_self() pthread_t;
|
||||
pub extern "c" fn pthread_yield() c_int;
|
||||
pub extern "c" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int;
|
||||
|
||||
pub extern "c" fn kqueue() c_int;
|
||||
|
||||
@ -46,11 +46,11 @@ else struct {
|
||||
const Locked = 2;
|
||||
|
||||
/// number of iterations to spin yielding the cpu
|
||||
const SpinCpu = 4;
|
||||
const SPIN_CPU = 4;
|
||||
/// number of iterations to perform in the cpu yield loop
|
||||
const SpinCpuCount = 30;
|
||||
const SPIN_CPU_COUNT = 30;
|
||||
/// number of iterations to spin yielding the thread
|
||||
const SpinThread = 1;
|
||||
const SPIN_THREAD = 1;
|
||||
|
||||
pub fn init() Mutex {
|
||||
return Mutex{
|
||||
@ -86,20 +86,21 @@ else struct {
|
||||
|
||||
while (true) {
|
||||
// try and acquire the lock using cpu spinning on failure
|
||||
for (([SpinCpu]void)(undefined)) |_| {
|
||||
var spin: usize = 0;
|
||||
while (spin < SPIN_CPU) : (spin += 1) {
|
||||
var value = @atomicLoad(u32, &self.state, .Monotonic);
|
||||
while (value == Unlocked)
|
||||
value = @cmpxchgWeak(u32, &self.state, Unlocked, state, .Acquire, .Monotonic) orelse return Held{ .mutex = self };
|
||||
for (([SpinCpuCount]void)(undefined)) |_|
|
||||
SpinLock.yieldCpu();
|
||||
SpinLock.yield(SPIN_CPU_COUNT);
|
||||
}
|
||||
|
||||
// try and acquire the lock using thread rescheduling on failure
|
||||
for (([SpinThread]void)(undefined)) |_| {
|
||||
spin = 0;
|
||||
while (spin < SPIN_THREAD) : (spin += 1) {
|
||||
var value = @atomicLoad(u32, &self.state, .Monotonic);
|
||||
while (value == Unlocked)
|
||||
value = @cmpxchgWeak(u32, &self.state, Unlocked, state, .Acquire, .Monotonic) orelse return Held{ .mutex = self };
|
||||
SpinLock.yieldThread();
|
||||
std.os.yield();
|
||||
}
|
||||
|
||||
// failed to acquire the lock, go to sleep until woken up by `Held.release()`
|
||||
|
||||
@ -3169,3 +3169,13 @@ pub fn dn_expand(
|
||||
}
|
||||
return error.InvalidDnsPacket;
|
||||
}
|
||||
|
||||
pub fn yield() void {
|
||||
switch (builtin.os) {
|
||||
.windows => _ = windows.kernel32.SwitchToThread(),
|
||||
.linux => _ = assert(linux.sched_yield() == 0),
|
||||
else => if (builtin.link_libc) {
|
||||
assert(std.c.pthread_yield() == 0);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -954,6 +954,10 @@ pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
|
||||
return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
|
||||
}
|
||||
|
||||
pub fn sched_yield() usize {
|
||||
return syscall0(SYS_sched_yield);
|
||||
}
|
||||
|
||||
pub fn sched_getaffinity(pid: i32, size: usize, set: *cpu_set_t) usize {
|
||||
const rc = syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), size, @ptrToInt(set));
|
||||
if (@bitCast(isize, rc) < 0) return rc;
|
||||
|
||||
@ -28,22 +28,17 @@ pub const SpinLock = struct {
|
||||
return Held{ .spinlock = self };
|
||||
}
|
||||
|
||||
pub fn yieldCpu() void {
|
||||
switch (builtin.arch) {
|
||||
.i386, .x86_64 => asm volatile("pause" ::: "memory"),
|
||||
// .arm, .aarch64 => asm volatile("yield"),
|
||||
//
|
||||
// Causes CI to fail
|
||||
// See: https://github.com/ziglang/zig/pull/3585#issuecomment-549962765
|
||||
else => time.sleep(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yieldThread() void {
|
||||
switch (builtin.os) {
|
||||
.linux => assert(linux.syscall0(linux.SYS_sched_yield) == 0),
|
||||
.windows => _ = windows.kernel32.SwitchToThread(),
|
||||
else => time.sleep(1 * time.microsecond),
|
||||
pub fn yield(iterations: usize) void {
|
||||
var i = iterations;
|
||||
while (i != 0) : (i -= 1) {
|
||||
switch (builtin.arch) {
|
||||
.i386, .x86_64 => asm volatile("pause" ::: "memory"),
|
||||
// .arm, .aarch64 => asm volatile("yield"),
|
||||
//
|
||||
// Causes CI to fail
|
||||
// See: https://github.com/ziglang/zig/pull/3585#issuecomment-549962765
|
||||
else => time.sleep(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,16 +50,14 @@ pub const SpinLock = struct {
|
||||
return @This(){ .iteration = 0 };
|
||||
}
|
||||
|
||||
/// Hybrid yielding from
|
||||
/// Modified hybrid yielding from
|
||||
/// http://www.1024cores.net/home/lock-free-algorithms/tricks/spinning
|
||||
pub fn yield(self: *@This()) void {
|
||||
defer self.iteration +%= 1;
|
||||
if (self.iteration < 10) {
|
||||
yieldCpu();
|
||||
} else if (self.iteration < 20) {
|
||||
for (([30]void)(undefined)) |_| yieldCpu();
|
||||
if (self.iteration < 20) {
|
||||
SpinLock.yield(self.iteration);
|
||||
} else if (self.iteration < 24) {
|
||||
yieldThread();
|
||||
os.yield();
|
||||
} else if (self.iteration < 26) {
|
||||
time.sleep(1 * time.millisecond);
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user