From 86d1cc8e2fffed9c93e41b28605d764e6b1749dc Mon Sep 17 00:00:00 2001 From: "Matthew D. Steele" Date: Thu, 2 Aug 2018 17:44:20 -0400 Subject: Add thread ID support to std.os.Thread (fixes #1316) --- std/c/index.zig | 1 + std/os/index.zig | 33 +++++++++++++++++++++++++++++++++ std/os/test.zig | 12 ++++++++++++ std/os/windows/kernel32.zig | 2 ++ 4 files changed, 48 insertions(+) (limited to 'std') diff --git a/std/c/index.zig b/std/c/index.zig index 7de8634d07..738b2f9c05 100644 --- a/std/c/index.zig +++ b/std/c/index.zig @@ -58,6 +58,7 @@ pub extern "pthread" fn pthread_create(noalias newthread: *pthread_t, noalias at pub extern "pthread" fn pthread_attr_init(attr: *pthread_attr_t) c_int; pub extern "pthread" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int; pub extern "pthread" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int; +pub extern "pthread" fn pthread_self() pthread_t; pub extern "pthread" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int; pub const pthread_t = *@OpaqueType(); diff --git a/std/os/index.zig b/std/os/index.zig index 425a900a71..c946e13046 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -2516,6 +2516,10 @@ pub const Thread = struct { data: Data, pub const use_pthreads = is_posix and builtin.link_libc; + + /// An opaque type representing a kernel thread ID. + pub const Id = *@OpaqueType(); + pub const Data = if (use_pthreads) struct { handle: c.pthread_t, @@ -2536,6 +2540,35 @@ pub const Thread = struct { else => @compileError("Unsupported OS"), }; + /// Returns the ID of the calling thread. + pub fn currentId() Thread.Id { + // TODO: As-is, this function is potentially expensive (making a + // syscall on every call). Once we have support for thread-local + // storage (https://github.com/ziglang/zig/issues/924), we could + // memoize it. + if (use_pthreads) { + return @ptrCast(Thread.Id, c.pthread_self()); + } else return switch (builtin.os) { + builtin.Os.linux => + @intToPtr(Thread.Id, @bitCast(u32, linux.getpid())), + builtin.Os.windows => + @ptrCast(Thread.Id, windows.GetCurrentThread()), + else => @compileError("Unsupported OS"), + }; + } + + /// Returns the ID of this thread object. + pub fn id(self: *const Thread) Thread.Id { + if (use_pthreads) { + return @ptrCast(Thread.Id, self.data.handle); + } else return switch (builtin.os) { + builtin.Os.linux => + @intToPtr(Thread.Id, @bitCast(u32, self.data.pid)), + builtin.Os.windows => @ptrCast(Thread.Id, self.data.handle), + else => @compileError("Unsupported OS"), + }; + } + pub fn wait(self: *const Thread) void { if (use_pthreads) { const err = c.pthread_join(self.data.handle, null); diff --git a/std/os/test.zig b/std/os/test.zig index 9e795e8ad2..6ef38c6764 100644 --- a/std/os/test.zig +++ b/std/os/test.zig @@ -34,6 +34,18 @@ test "access file" { try os.deleteTree(a, "os_test_tmp"); } +fn testThreadIdFn(threadId: *?os.Thread.Id) void { + threadId.* = os.Thread.currentId(); +} + +test "std.os.Thread.currentId" { + var threadCurrentId: ?os.Thread.Id = null; + const thread = try os.spawnThread(&threadCurrentId, testThreadIdFn); + const threadId = thread.id(); + thread.wait(); + assert(threadCurrentId == threadId); +} + test "spawn threads" { var shared_ctx: i32 = 1; diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig index fa3473ad05..a28179f4eb 100644 --- a/std/os/windows/kernel32.zig +++ b/std/os/windows/kernel32.zig @@ -63,6 +63,8 @@ pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) DWORD; +pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE; + pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8; pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD; -- cgit v1.2.3