mirror of
https://github.com/ziglang/zig.git
synced 2024-12-03 10:28:48 +00:00
std.ResetEvent: pthreads sem_t cannot be statically initialized
because it is allowed for the implementation to use a file descriptor, which would require making a syscall at runtime.
This commit is contained in:
parent
028af97df4
commit
19459840fe
@ -123,6 +123,10 @@ pub const pthread_mutex_t = extern struct {
|
||||
pub const pthread_cond_t = extern struct {
|
||||
size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,
|
||||
};
|
||||
pub const sem_t = extern struct {
|
||||
__size: [__SIZEOF_SEM_T]u8 align(@alignOf(usize)),
|
||||
};
|
||||
|
||||
const __SIZEOF_PTHREAD_COND_T = 48;
|
||||
const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os.tag == .fuchsia) 40 else switch (builtin.abi) {
|
||||
.musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,
|
||||
@ -134,38 +138,7 @@ const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os.tag == .fuchsia) 40 else switch
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
pub const sem_t = switch (builtin.abi) {
|
||||
.musl, .musleabi, .musleabihf => extern struct {
|
||||
__val: [4 * @sizeOf(c_long) / @sizeOf(c_int)]c_int,
|
||||
|
||||
pub fn init(pshared: c_int, value: c_uint) @This() {
|
||||
var result: @This() = undefined;
|
||||
result.__val[0] = @bitCast(c_int, value);
|
||||
result.__val[1] = 0;
|
||||
result.__val[2] = if (pshared != 0) 0 else 128;
|
||||
return result;
|
||||
}
|
||||
},
|
||||
.gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => extern struct {
|
||||
__lock: c_int,
|
||||
__queue: ?*pthread_t,
|
||||
__pshared: c_int,
|
||||
__value: c_int,
|
||||
__data: ?*c_void,
|
||||
|
||||
pub fn init(pshared: c_int, value: c_uint) @This() {
|
||||
return .{
|
||||
.__lock = 0,
|
||||
.__queue = null,
|
||||
.__pshared = pshared,
|
||||
.__value = @bitCast(c_int, value),
|
||||
.__data = null,
|
||||
};
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
const __SIZEOF_SEM_T = 4 * @sizeOf(usize);
|
||||
|
||||
pub const RTLD_LAZY = 1;
|
||||
pub const RTLD_NOW = 2;
|
||||
|
@ -101,30 +101,48 @@ const DebugEvent = struct {
|
||||
};
|
||||
|
||||
const PosixEvent = struct {
|
||||
sem: c.sem_t,
|
||||
sem: c.sem_t = undefined,
|
||||
/// Sadly this is needed because pthreads semaphore API does not
|
||||
/// support static initialization.
|
||||
init_mutex: std.mutex.PthreadMutex = .{},
|
||||
state: enum { uninit, init } = .uninit,
|
||||
|
||||
fn init() PosixEvent {
|
||||
return PosixEvent{
|
||||
.sem = c.sem_t.init(0, 0),
|
||||
};
|
||||
return .{};
|
||||
}
|
||||
|
||||
/// Not thread-safe.
|
||||
fn deinit(self: *PosixEvent) void {
|
||||
assert(c.sem_destroy(&self.sem) == 0);
|
||||
switch (self.state) {
|
||||
.uninit => {},
|
||||
.init => {
|
||||
assert(c.sem_destroy(&self.sem) == 0);
|
||||
},
|
||||
}
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
fn reset(self: *PosixEvent) void {
|
||||
self.deinit();
|
||||
assert(c.sem_init(&self.sem, 0, 0) == 0);
|
||||
const sem = self.getInitializedSem();
|
||||
while (true) {
|
||||
switch (c.getErrno(c.sem_trywait(sem))) {
|
||||
0 => continue, // Need to make it go to zero.
|
||||
c.EINTR => continue,
|
||||
c.EINVAL => unreachable,
|
||||
c.EAGAIN => return, // The semaphore currently has the value zero.
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set(self: *PosixEvent) void {
|
||||
assert(c.sem_post(&self.sem) == 0);
|
||||
assert(c.sem_post(self.getInitializedSem()) == 0);
|
||||
}
|
||||
|
||||
fn wait(self: *PosixEvent) void {
|
||||
const sem = self.getInitializedSem();
|
||||
while (true) {
|
||||
switch (c.getErrno(c.sem_wait(&self.sem))) {
|
||||
switch (c.getErrno(c.sem_wait(sem))) {
|
||||
0 => return,
|
||||
c.EINTR => continue,
|
||||
c.EINVAL => unreachable,
|
||||
@ -148,6 +166,7 @@ const PosixEvent = struct {
|
||||
}
|
||||
ts.tv_sec = @intCast(@TypeOf(ts.tv_sec), @divFloor(timeout_abs, time.ns_per_s));
|
||||
ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.ns_per_s));
|
||||
const sem = self.getInitializedSem();
|
||||
while (true) {
|
||||
switch (c.getErrno(c.sem_timedwait(&self.sem, &ts))) {
|
||||
0 => return,
|
||||
@ -158,6 +177,20 @@ const PosixEvent = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn getInitializedSem(self: *PosixEvent) *c.sem_t {
|
||||
const held = self.init_mutex.acquire();
|
||||
defer held.release();
|
||||
|
||||
switch (self.state) {
|
||||
.init => return &self.sem,
|
||||
.uninit => {
|
||||
self.state = .init;
|
||||
assert(c.sem_init(&self.sem, 0, 0) == 0);
|
||||
return &self.sem;
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const AtomicEvent = struct {
|
||||
|
Loading…
Reference in New Issue
Block a user