Commit 19459840fe
Changed files (2)
lib
lib/std/c/linux.zig
@@ -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;
lib/std/reset_event.zig
@@ -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 {