mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
feat(libzigc): add common implementations of pthread_spin_*
* and remove their mingw, musl and wasi implementations
This commit is contained in:
@@ -68,6 +68,7 @@ comptime {
|
|||||||
_ = @import("c/malloc.zig");
|
_ = @import("c/malloc.zig");
|
||||||
}
|
}
|
||||||
_ = @import("c/math.zig");
|
_ = @import("c/math.zig");
|
||||||
|
_ = @import("c/pthread.zig");
|
||||||
_ = @import("c/search.zig");
|
_ = @import("c/search.zig");
|
||||||
_ = @import("c/stdlib.zig");
|
_ = @import("c/stdlib.zig");
|
||||||
_ = @import("c/string.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;
|
|
||||||
}
|
|
||||||
+19
-1
@@ -7898,6 +7898,12 @@ pub const Stat = switch (native_os) {
|
|||||||
else => void,
|
else => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const pthread_spinlock_t = switch (native_os) {
|
||||||
|
.openbsd => openbsd.pthread_spinlock_t,
|
||||||
|
.windows => isize,
|
||||||
|
else => c_int,
|
||||||
|
};
|
||||||
|
|
||||||
pub const pthread_mutex_t = switch (native_os) {
|
pub const pthread_mutex_t = switch (native_os) {
|
||||||
.linux => extern struct {
|
.linux => extern struct {
|
||||||
data: [data_len]u8 align(@alignOf(usize)) = [_]u8{0} ** data_len,
|
data: [data_len]u8 align(@alignOf(usize)) = [_]u8{0} ** data_len,
|
||||||
@@ -10956,6 +10962,19 @@ pub extern "c" fn dn_expand(
|
|||||||
length: c_int,
|
length: c_int,
|
||||||
) 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) E;
|
||||||
|
pub extern "c" fn pthread_spin_lock(spin: *pthread_spinlock_t) E;
|
||||||
|
pub extern "c" fn pthread_spin_unlock(spin: *pthread_spinlock_t) E;
|
||||||
|
pub extern "c" fn pthread_spin_trylock(spin: *pthread_spinlock_t) E;
|
||||||
|
pub extern "c" fn pthread_spin_destroy(spin: *pthread_spinlock_t) E;
|
||||||
|
|
||||||
pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = .{};
|
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_lock(mutex: *pthread_mutex_t) E;
|
||||||
pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) E;
|
pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) E;
|
||||||
@@ -11268,7 +11287,6 @@ pub const login_getcaptime = openbsd.login_getcaptime;
|
|||||||
pub const login_getclass = openbsd.login_getclass;
|
pub const login_getclass = openbsd.login_getclass;
|
||||||
pub const login_getstyle = openbsd.login_getstyle;
|
pub const login_getstyle = openbsd.login_getstyle;
|
||||||
pub const pledge = openbsd.pledge;
|
pub const pledge = openbsd.pledge;
|
||||||
pub const pthread_spinlock_t = openbsd.pthread_spinlock_t;
|
|
||||||
pub const pw_dup = openbsd.pw_dup;
|
pub const pw_dup = openbsd.pw_dup;
|
||||||
pub const setclasscontext = openbsd.setclasscontext;
|
pub const setclasscontext = openbsd.setclasscontext;
|
||||||
pub const setpassent = openbsd.setpassent;
|
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 ++ "rwlock.c",
|
||||||
"winpthreads" ++ path.sep_str ++ "sched.c",
|
"winpthreads" ++ path.sep_str ++ "sched.c",
|
||||||
"winpthreads" ++ path.sep_str ++ "sem.c",
|
"winpthreads" ++ path.sep_str ++ "sem.c",
|
||||||
"winpthreads" ++ path.sep_str ++ "spinlock.c",
|
|
||||||
"winpthreads" ++ path.sep_str ++ "thread.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_setschedprio.c",
|
||||||
"musl/src/thread/pthread_setspecific.c",
|
"musl/src/thread/pthread_setspecific.c",
|
||||||
"musl/src/thread/pthread_sigmask.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/pthread_testcancel.c",
|
||||||
"musl/src/thread/riscv32/clone.s",
|
"musl/src/thread/riscv32/clone.s",
|
||||||
"musl/src/thread/riscv32/__set_thread_area.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_setcancelstate.c",
|
||||||
"musl/src/thread/pthread_setcanceltype.c",
|
"musl/src/thread/pthread_setcanceltype.c",
|
||||||
"musl/src/thread/pthread_setspecific.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/pthread_testcancel.c",
|
||||||
"musl/src/thread/thrd_sleep.c",
|
"musl/src/thread/thrd_sleep.c",
|
||||||
"musl/src/time/asctime.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_trywrlock.c",
|
||||||
"wasi/thread-stub/pthread_rwlock_unlock.c",
|
"wasi/thread-stub/pthread_rwlock_unlock.c",
|
||||||
"wasi/thread-stub/pthread_rwlock_wrlock.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";
|
const crt1_command_src_file = "wasi/libc-bottom-half/crt/crt1-command.c";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const std = @import("std");
|
|||||||
test {
|
test {
|
||||||
_ = @import("c/inttypes.zig");
|
_ = @import("c/inttypes.zig");
|
||||||
_ = @import("c/math.zig");
|
_ = @import("c/math.zig");
|
||||||
|
_ = @import("c/pthread.zig");
|
||||||
_ = @import("c/search.zig");
|
_ = @import("c/search.zig");
|
||||||
_ = @import("c/stdlib.zig");
|
_ = @import("c/stdlib.zig");
|
||||||
_ = @import("c/string.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(.SUCCESS, c.pthread_spin_trylock(&spin));
|
||||||
|
try std.testing.expectEqual(.SUCCESS, c.pthread_spin_unlock(&spin));
|
||||||
|
|
||||||
|
try std.testing.expectEqual(.SUCCESS, c.pthread_spin_lock(&spin));
|
||||||
|
try std.testing.expectEqual(.SUCCESS, c.pthread_spin_unlock(&spin));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user