| ... | @@ -20,7 +20,6 @@ pub const Pool = @import("Thread/Pool.zig"); | ... | @@ -20,7 +20,6 @@ pub const Pool = @import("Thread/Pool.zig"); |
| 20 | pub const WaitGroup = @import("Thread/WaitGroup.zig"); | 20 | pub const WaitGroup = @import("Thread/WaitGroup.zig"); |
| 21 | | 21 | |
| 22 | pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc; | 22 | pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc; |
| 23 | const is_gnu = target.abi.isGnu(); | | |
| 24 | | 23 | |
| 25 | const Thread = @This(); | 24 | const Thread = @This(); |
| 26 | const Impl = if (target.os.tag == .windows) | 25 | const Impl = if (target.os.tag == .windows) |
| ... | @@ -64,18 +63,20 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { | ... | @@ -64,18 +63,20 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { |
| 64 | | 63 | |
| 65 | switch (target.os.tag) { | 64 | switch (target.os.tag) { |
| 66 | .linux => if (use_pthreads) { | 65 | .linux => if (use_pthreads) { |
| 67 | const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr); | 66 | if (self.getHandle() == std.c.pthread_self()) { |
| 68 | switch (err) { | 67 | // Set the name of the calling thread (no thread id required). |
| 69 | .SUCCESS => return, | 68 | const err = try os.prctl(.SET_NAME, .{@ptrToInt(name_with_terminator.ptr)}); |
| 70 | .RANGE => unreachable, | 69 | switch (@intToEnum(os.E, err)) { |
| 71 | else => |e| return os.unexpectedErrno(e), | 70 | .SUCCESS => return, |
| 72 | } | 71 | else => |e| return os.unexpectedErrno(e), |
| 73 | } else if (use_pthreads and self.getHandle() == std.c.pthread_self()) { | 72 | } |
| 74 | // TODO: this is dead code. what did the author of this code intend to happen here? | 73 | } else { |
| 75 | const err = try os.prctl(.SET_NAME, .{@ptrToInt(name_with_terminator.ptr)}); | 74 | const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr); |
| 76 | switch (@intToEnum(os.E, err)) { | 75 | switch (err) { |
| 77 | .SUCCESS => return, | 76 | .SUCCESS => return, |
| 78 | else => |e| return os.unexpectedErrno(e), | 77 | .RANGE => unreachable, |
| | 78 | else => |e| return os.unexpectedErrno(e), |
| | 79 | } |
| 79 | } | 80 | } |
| 80 | } else { | 81 | } else { |
| 81 | var buf: [32]u8 = undefined; | 82 | var buf: [32]u8 = undefined; |
| ... | @@ -171,20 +172,23 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co | ... | @@ -171,20 +172,23 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co |
| 171 | var buffer: [:0]u8 = buffer_ptr; | 172 | var buffer: [:0]u8 = buffer_ptr; |
| 172 | | 173 | |
| 173 | switch (target.os.tag) { | 174 | switch (target.os.tag) { |
| 174 | .linux => if (use_pthreads and is_gnu) { | 175 | .linux => if (use_pthreads) { |
| 175 | const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1); | 176 | if (self.getHandle() == std.c.pthread_self()) { |
| 176 | switch (err) { | 177 | // Get the name of the calling thread (no thread id required). |
| 177 | .SUCCESS => return std.mem.sliceTo(buffer, 0), | 178 | const err = try os.prctl(.GET_NAME, .{@ptrToInt(buffer.ptr)}); |
| 178 | .RANGE => unreachable, | 179 | switch (@intToEnum(os.E, err)) { |
| 179 | else => |e| return os.unexpectedErrno(e), | 180 | .SUCCESS => return std.mem.sliceTo(buffer, 0), |
| 180 | } | 181 | else => |e| return os.unexpectedErrno(e), |
| 181 | } else if (use_pthreads and self.getHandle() == std.c.pthread_self()) { | 182 | } |
| 182 | const err = try os.prctl(.GET_NAME, .{@ptrToInt(buffer.ptr)}); | 183 | } else { |
| 183 | switch (@intToEnum(os.E, err)) { | 184 | const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1); |
| 184 | .SUCCESS => return std.mem.sliceTo(buffer, 0), | 185 | switch (err) { |
| 185 | else => |e| return os.unexpectedErrno(e), | 186 | .SUCCESS => return std.mem.sliceTo(buffer, 0), |
| | 187 | .RANGE => unreachable, |
| | 188 | else => |e| return os.unexpectedErrno(e), |
| | 189 | } |
| 186 | } | 190 | } |
| 187 | } else if (!use_pthreads) { | 191 | } else { |
| 188 | var buf: [32]u8 = undefined; | 192 | var buf: [32]u8 = undefined; |
| 189 | const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); | 193 | const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); |
| 190 | | 194 | |
| ... | @@ -194,9 +198,6 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co | ... | @@ -194,9 +198,6 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co |
| 194 | const data_len = try file.reader().readAll(buffer_ptr[0 .. max_name_len + 1]); | 198 | const data_len = try file.reader().readAll(buffer_ptr[0 .. max_name_len + 1]); |
| 195 | | 199 | |
| 196 | return if (data_len >= 1) buffer[0 .. data_len - 1] else null; | 200 | return if (data_len >= 1) buffer[0 .. data_len - 1] else null; |
| 197 | } else { | | |
| 198 | // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread. | | |
| 199 | return error.Unsupported; | | |
| 200 | }, | 201 | }, |
| 201 | .windows => { | 202 | .windows => { |
| 202 | const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); | 203 | const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); |
| ... | @@ -327,10 +328,10 @@ pub const SpawnError = error{ | ... | @@ -327,10 +328,10 @@ pub const SpawnError = error{ |
| 327 | Unexpected, | 328 | Unexpected, |
| 328 | }; | 329 | }; |
| 329 | | 330 | |
| 330 | /// Spawns a new thread which executes `function` using `args` and returns a handle the spawned thread. | 331 | /// Spawns a new thread which executes `function` using `args` and returns a handle to the spawned thread. |
| 331 | /// `config` can be used as hints to the platform for now to spawn and execute the `function`. | 332 | /// `config` can be used as hints to the platform for now to spawn and execute the `function`. |
| 332 | /// The caller must eventually either call `join()` to wait for the thread to finish and free its resources | 333 | /// The caller must eventually either call `join()` to wait for the thread to finish and free its resources |
| 333 | /// or call `detach()` to excuse the caller from calling `join()` and have the thread clean up its resources on completion`. | 334 | /// or call `detach()` to excuse the caller from calling `join()` and have the thread clean up its resources on completion. |
| 334 | pub fn spawn(config: SpawnConfig, comptime function: anytype, args: anytype) SpawnError!Thread { | 335 | pub fn spawn(config: SpawnConfig, comptime function: anytype, args: anytype) SpawnError!Thread { |
| 335 | if (builtin.single_threaded) { | 336 | if (builtin.single_threaded) { |
| 336 | @compileError("Cannot spawn thread when building in single-threaded mode"); | 337 | @compileError("Cannot spawn thread when building in single-threaded mode"); |
| ... | @@ -1133,16 +1134,7 @@ test "setName, getName" { | ... | @@ -1133,16 +1134,7 @@ test "setName, getName" { |
| 1133 | error.Unsupported => return error.SkipZigTest, | 1134 | error.Unsupported => return error.SkipZigTest, |
| 1134 | else => return err, | 1135 | else => return err, |
| 1135 | }, | 1136 | }, |
| 1136 | else => |tag| if (tag == .linux and use_pthreads and comptime target.abi.isMusl()) { | 1137 | else => try testThreadName(&thread), |
| 1137 | try thread.setName("foobar"); | | |
| 1138 | | | |
| 1139 | var name_buffer: [max_name_len:0]u8 = undefined; | | |
| 1140 | const res = thread.getName(&name_buffer); | | |
| 1141 | | | |
| 1142 | try std.testing.expectError(error.Unsupported, res); | | |
| 1143 | } else { | | |
| 1144 | try testThreadName(&thread); | | |
| 1145 | }, | | |
| 1146 | } | 1138 | } |
| 1147 | | 1139 | |
| 1148 | context.thread_done_event.set(); | 1140 | context.thread_done_event.set(); |