mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Merge pull request 'libc: add common implementations of pthread_spin_*' (#31990) from GasInfinity/zig:pthread-spin into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31990 Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
@@ -68,6 +68,7 @@ comptime {
|
||||
_ = @import("c/malloc.zig");
|
||||
}
|
||||
_ = @import("c/math.zig");
|
||||
_ = @import("c/pthread.zig");
|
||||
_ = @import("c/search.zig");
|
||||
_ = @import("c/stdlib.zig");
|
||||
_ = @import("c/string.zig");
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const std = @import("std");
|
||||
const c = std.c;
|
||||
|
||||
const symbol = @import("../c.zig").symbol;
|
||||
|
||||
comptime {
|
||||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC() or builtin.target.isMinGW()) {
|
||||
symbol(&pthread_spin_init, "pthread_spin_init");
|
||||
symbol(&pthread_spin_destroy, "pthread_spin_destroy");
|
||||
symbol(&pthread_spin_trylock, "pthread_spin_trylock");
|
||||
symbol(&pthread_spin_lock, "pthread_spin_lock");
|
||||
symbol(&pthread_spin_unlock, "pthread_spin_unlock");
|
||||
}
|
||||
}
|
||||
|
||||
const SpinLock = enum(c.pthread_spinlock_t) {
|
||||
unlocked = if (builtin.target.isMinGW()) -1 else 0,
|
||||
locked = if (builtin.target.isMinGW()) 0 else @intFromEnum(c.E.BUSY),
|
||||
};
|
||||
|
||||
fn pthread_spin_init(s: *c.pthread_spinlock_t, pshared: c_int) callconv(.c) c_int {
|
||||
_ = pshared;
|
||||
const spin: *SpinLock = @ptrCast(s);
|
||||
spin.* = .unlocked;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn pthread_spin_destroy(s: *c.pthread_spinlock_t) callconv(.c) c_int {
|
||||
const spin: *SpinLock = @ptrCast(s);
|
||||
spin.* = undefined;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn pthread_spin_trylock(s: *c.pthread_spinlock_t) callconv(.c) c_int {
|
||||
const spin: *SpinLock = @ptrCast(s);
|
||||
return if (@cmpxchgStrong(SpinLock, spin, .unlocked, .locked, .acquire, .monotonic)) |_| @intFromEnum(c.E.BUSY) else 0;
|
||||
}
|
||||
|
||||
fn pthread_spin_lock(s: *c.pthread_spinlock_t) callconv(.c) c_int {
|
||||
const spin: *SpinLock = @ptrCast(s);
|
||||
if (builtin.single_threaded and @atomicLoad(SpinLock, spin, .monotonic) == .locked) return @intFromEnum(c.E.DEADLK);
|
||||
|
||||
while (@cmpxchgWeak(SpinLock, spin, .unlocked, .locked, .acquire, .monotonic)) |_| {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn pthread_spin_unlock(s: *c.pthread_spinlock_t) callconv(.c) c_int {
|
||||
const spin: *SpinLock = @ptrCast(s);
|
||||
|
||||
// "The results are undefined if the lock is not held by the calling thread"
|
||||
std.debug.assert(@atomicRmw(SpinLock, spin, .Xchg, .unlocked, .release) == .locked);
|
||||
return 0;
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2013 mingw-w64 project
|
||||
Copyright (c) 2015 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
/* public header files */
|
||||
#include "pthread.h"
|
||||
/* internal header files */
|
||||
#include "misc.h"
|
||||
|
||||
/* We use the pthread_spinlock_t itself as a lock:
|
||||
-1 is free, 0 is locked.
|
||||
(This is dictated by PTHREAD_SPINLOCK_INITIALIZER, which we can't change
|
||||
without breaking binary compatibility.) */
|
||||
typedef intptr_t spinlock_word_t;
|
||||
|
||||
int
|
||||
pthread_spin_init (pthread_spinlock_t *lock, int pshared)
|
||||
{
|
||||
spinlock_word_t *lk = (spinlock_word_t *)lock;
|
||||
*lk = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pthread_spin_destroy (pthread_spinlock_t *lock)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pthread_spin_lock (pthread_spinlock_t *lock)
|
||||
{
|
||||
volatile spinlock_word_t *lk = (volatile spinlock_word_t *)lock;
|
||||
while (unlikely(InterlockedExchangePointer((PVOID volatile *)lk, 0) == 0))
|
||||
do {
|
||||
YieldProcessor();
|
||||
} while (*lk == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pthread_spin_trylock (pthread_spinlock_t *lock)
|
||||
{
|
||||
spinlock_word_t *lk = (spinlock_word_t *)lock;
|
||||
return InterlockedExchangePointer((PVOID volatile *)lk, 0) == 0 ? EBUSY : 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pthread_spin_unlock (pthread_spinlock_t *lock)
|
||||
{
|
||||
volatile spinlock_word_t *lk = (volatile spinlock_word_t *)lock;
|
||||
*lk = -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_destroy(pthread_spinlock_t *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_init(pthread_spinlock_t *s, int shared)
|
||||
{
|
||||
return *s = 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <errno.h>
|
||||
|
||||
int pthread_spin_lock(pthread_spinlock_t *s)
|
||||
{
|
||||
while (*(volatile int *)s || a_cas(s, 0, EBUSY)) a_spin();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <errno.h>
|
||||
|
||||
int pthread_spin_trylock(pthread_spinlock_t *s)
|
||||
{
|
||||
return a_cas(s, 0, EBUSY);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_unlock(pthread_spinlock_t *s)
|
||||
{
|
||||
a_store(s, 0);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_lock(pthread_spinlock_t *s)
|
||||
{
|
||||
if (*s) return EDEADLK;
|
||||
*s = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_trylock(pthread_spinlock_t *s)
|
||||
{
|
||||
if (*s) return EBUSY;
|
||||
*s = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "pthread_impl.h"
|
||||
|
||||
int pthread_spin_unlock(pthread_spinlock_t *s)
|
||||
{
|
||||
*s = 0;
|
||||
return 0;
|
||||
}
|
||||
+27
-1
@@ -7898,6 +7898,20 @@ pub const Stat = switch (native_os) {
|
||||
else => void,
|
||||
};
|
||||
|
||||
pub const pthread_spinlock_t = switch (native_os) {
|
||||
.openbsd => openbsd.pthread_spinlock_t,
|
||||
.freebsd => extern struct {
|
||||
inner: ?*anyopaque = null,
|
||||
},
|
||||
.netbsd => extern struct {
|
||||
pts_magic: c_uint,
|
||||
spin: pthread_spin_t,
|
||||
pts_flags: c_int,
|
||||
},
|
||||
.windows => isize,
|
||||
else => c_int,
|
||||
};
|
||||
|
||||
pub const pthread_mutex_t = switch (native_os) {
|
||||
.linux => extern struct {
|
||||
data: [data_len]u8 align(@alignOf(usize)) = [_]u8{0} ** data_len,
|
||||
@@ -10956,6 +10970,19 @@ pub extern "c" fn dn_expand(
|
||||
length: c_int,
|
||||
) c_int;
|
||||
|
||||
pub const PTHREAD_PROCESS_PRIVATE: c_int = if (native_os.isDarwin())
|
||||
2
|
||||
else
|
||||
0;
|
||||
|
||||
pub const PTHREAD_PROCESS_SHARED: c_int = 1;
|
||||
|
||||
pub extern "c" fn pthread_spin_init(spin: *pthread_spinlock_t, pshared: c_int) c_int;
|
||||
pub extern "c" fn pthread_spin_lock(spin: *pthread_spinlock_t) c_int;
|
||||
pub extern "c" fn pthread_spin_unlock(spin: *pthread_spinlock_t) c_int;
|
||||
pub extern "c" fn pthread_spin_trylock(spin: *pthread_spinlock_t) c_int;
|
||||
pub extern "c" fn pthread_spin_destroy(spin: *pthread_spinlock_t) c_int;
|
||||
|
||||
pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = .{};
|
||||
pub extern "c" fn pthread_mutex_lock(mutex: *pthread_mutex_t) E;
|
||||
pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) E;
|
||||
@@ -11268,7 +11295,6 @@ pub const login_getcaptime = openbsd.login_getcaptime;
|
||||
pub const login_getclass = openbsd.login_getclass;
|
||||
pub const login_getstyle = openbsd.login_getstyle;
|
||||
pub const pledge = openbsd.pledge;
|
||||
pub const pthread_spinlock_t = openbsd.pthread_spinlock_t;
|
||||
pub const pw_dup = openbsd.pw_dup;
|
||||
pub const setclasscontext = openbsd.setclasscontext;
|
||||
pub const setpassent = openbsd.setpassent;
|
||||
|
||||
@@ -913,7 +913,6 @@ const mingw32_winpthreads_src = [_][]const u8{
|
||||
"winpthreads" ++ path.sep_str ++ "rwlock.c",
|
||||
"winpthreads" ++ path.sep_str ++ "sched.c",
|
||||
"winpthreads" ++ path.sep_str ++ "sem.c",
|
||||
"winpthreads" ++ path.sep_str ++ "spinlock.c",
|
||||
"winpthreads" ++ path.sep_str ++ "thread.c",
|
||||
};
|
||||
|
||||
|
||||
@@ -1663,11 +1663,6 @@ const src_files = [_][]const u8{
|
||||
"musl/src/thread/pthread_setschedprio.c",
|
||||
"musl/src/thread/pthread_setspecific.c",
|
||||
"musl/src/thread/pthread_sigmask.c",
|
||||
"musl/src/thread/pthread_spin_destroy.c",
|
||||
"musl/src/thread/pthread_spin_init.c",
|
||||
"musl/src/thread/pthread_spin_lock.c",
|
||||
"musl/src/thread/pthread_spin_trylock.c",
|
||||
"musl/src/thread/pthread_spin_unlock.c",
|
||||
"musl/src/thread/pthread_testcancel.c",
|
||||
"musl/src/thread/riscv32/clone.s",
|
||||
"musl/src/thread/riscv32/__set_thread_area.s",
|
||||
|
||||
@@ -939,8 +939,6 @@ const libc_top_half_src_files = [_][]const u8{
|
||||
"musl/src/thread/pthread_setcancelstate.c",
|
||||
"musl/src/thread/pthread_setcanceltype.c",
|
||||
"musl/src/thread/pthread_setspecific.c",
|
||||
"musl/src/thread/pthread_spin_destroy.c",
|
||||
"musl/src/thread/pthread_spin_init.c",
|
||||
"musl/src/thread/pthread_testcancel.c",
|
||||
"musl/src/thread/thrd_sleep.c",
|
||||
"musl/src/time/asctime.c",
|
||||
@@ -1086,9 +1084,6 @@ const libc_top_half_src_files = [_][]const u8{
|
||||
"wasi/thread-stub/pthread_rwlock_trywrlock.c",
|
||||
"wasi/thread-stub/pthread_rwlock_unlock.c",
|
||||
"wasi/thread-stub/pthread_rwlock_wrlock.c",
|
||||
"wasi/thread-stub/pthread_spin_lock.c",
|
||||
"wasi/thread-stub/pthread_spin_trylock.c",
|
||||
"wasi/thread-stub/pthread_spin_unlock.c",
|
||||
};
|
||||
|
||||
const crt1_command_src_file = "wasi/libc-bottom-half/crt/crt1-command.c";
|
||||
|
||||
@@ -4,6 +4,7 @@ const std = @import("std");
|
||||
test {
|
||||
_ = @import("c/inttypes.zig");
|
||||
_ = @import("c/math.zig");
|
||||
_ = @import("c/pthread.zig");
|
||||
_ = @import("c/search.zig");
|
||||
_ = @import("c/stdlib.zig");
|
||||
_ = @import("c/string.zig");
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
|
||||
test "pthread_spinlock_t" {
|
||||
if (builtin.target.os.tag.isDarwin()) return; // Darwin doesn't have `pthread_spin_*`
|
||||
|
||||
var spin: c.pthread_spinlock_t = undefined;
|
||||
_ = c.pthread_spin_init(&spin, c.PTHREAD_PROCESS_PRIVATE);
|
||||
defer _ = c.pthread_spin_destroy(&spin);
|
||||
|
||||
try std.testing.expectEqual(@intFromEnum(c.E.SUCCESS), c.pthread_spin_trylock(&spin));
|
||||
try std.testing.expectEqual(@intFromEnum(c.E.SUCCESS), c.pthread_spin_unlock(&spin));
|
||||
|
||||
try std.testing.expectEqual(@intFromEnum(c.E.SUCCESS), c.pthread_spin_lock(&spin));
|
||||
try std.testing.expectEqual(@intFromEnum(c.E.SUCCESS), c.pthread_spin_unlock(&spin));
|
||||
}
|
||||
Reference in New Issue
Block a user