aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-08-06 17:32:55 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-08-06 17:32:55 -0400
commitc02ed805122cb05dfb21a30e626e25994b3eb698 (patch)
treed63d84c3eba4cd1d9c28a41ac7979eeff4784843 /std
parent72bac72338af64a73668721cd035dfdf1ff2badb (diff)
parent24d74cbf44b34b180b2df5557927d9d2e4c9e443 (diff)
downloadzig-c02ed805122cb05dfb21a30e626e25994b3eb698.tar.gz
zig-c02ed805122cb05dfb21a30e626e25994b3eb698.zip
Merge branch 'mdsteele-threadid'
Diffstat (limited to 'std')
-rw-r--r--std/c/index.zig1
-rw-r--r--std/os/index.zig54
-rw-r--r--std/os/linux/index.zig4
-rw-r--r--std/os/test.zig17
-rw-r--r--std/os/windows/kernel32.zig3
5 files changed, 72 insertions, 7 deletions
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..d47444d67d 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -160,7 +160,7 @@ test "os.getRandomBytes" {
try getRandomBytes(buf_b[0..]);
// Check if random (not 100% conclusive)
- assert( !mem.eql(u8, buf_a, buf_b) );
+ assert(!mem.eql(u8, buf_a, buf_b));
}
/// Raises a signal in the current kernel thread, ending its execution.
@@ -2516,26 +2516,66 @@ pub const Thread = struct {
data: Data,
pub const use_pthreads = is_posix and builtin.link_libc;
+
+ /// Represents a kernel thread handle.
+ /// May be an integer or a pointer depending on the platform.
+ /// On Linux and POSIX, this is the same as Id.
+ pub const Handle = if (use_pthreads)
+ c.pthread_t
+ else switch (builtin.os) {
+ builtin.Os.linux => i32,
+ builtin.Os.windows => windows.HANDLE,
+ else => @compileError("Unsupported OS"),
+ };
+
+ /// Represents a unique ID per thread.
+ /// May be an integer or pointer depending on the platform.
+ /// On Linux and POSIX, this is the same as Handle.
+ pub const Id = switch (builtin.os) {
+ builtin.Os.windows => windows.DWORD,
+ else => Handle,
+ };
+
pub const Data = if (use_pthreads)
struct {
- handle: c.pthread_t,
+ handle: Thread.Handle,
stack_addr: usize,
stack_len: usize,
}
else switch (builtin.os) {
builtin.Os.linux => struct {
- pid: i32,
+ handle: Thread.Handle,
stack_addr: usize,
stack_len: usize,
},
builtin.Os.windows => struct {
- handle: windows.HANDLE,
+ handle: Thread.Handle,
alloc_start: *c_void,
heap_handle: windows.HANDLE,
},
else => @compileError("Unsupported OS"),
};
+ /// Returns the ID of the calling thread.
+ /// Makes a syscall every time the function is called.
+ /// On Linux and POSIX, this Id is the same as a Handle.
+ pub fn getCurrentId() Id {
+ if (use_pthreads) {
+ return c.pthread_self();
+ } else
+ return switch (builtin.os) {
+ builtin.Os.linux => linux.gettid(),
+ builtin.Os.windows => windows.GetCurrentThreadId(),
+ else => @compileError("Unsupported OS"),
+ };
+ }
+
+ /// Returns the handle of this thread.
+ /// On Linux and POSIX, this is the same as Id.
+ pub fn handle(self: Thread) Handle {
+ return self.data.handle;
+ }
+
pub fn wait(self: *const Thread) void {
if (use_pthreads) {
const err = c.pthread_join(self.data.handle, null);
@@ -2550,9 +2590,9 @@ pub const Thread = struct {
} else switch (builtin.os) {
builtin.Os.linux => {
while (true) {
- const pid_value = @atomicLoad(i32, &self.data.pid, builtin.AtomicOrder.SeqCst);
+ const pid_value = @atomicLoad(i32, &self.data.handle, builtin.AtomicOrder.SeqCst);
if (pid_value == 0) break;
- const rc = linux.futex_wait(@ptrToInt(&self.data.pid), linux.FUTEX_WAIT, pid_value, null);
+ const rc = linux.futex_wait(@ptrToInt(&self.data.handle), linux.FUTEX_WAIT, pid_value, null);
switch (linux.getErrno(rc)) {
0 => continue,
posix.EINTR => continue,
@@ -2734,7 +2774,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
// use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly
const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED;
const newtls: usize = 0;
- const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid);
+ const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
const err = posix.getErrno(rc);
switch (err) {
0 => return thread_ptr,
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index 15607ea6c0..15ca649f06 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -947,6 +947,10 @@ pub fn getpid() i32 {
return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid)));
}
+pub fn gettid() i32 {
+ return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid)));
+}
+
pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
}
diff --git a/std/os/test.zig b/std/os/test.zig
index 9e795e8ad2..82054d3f32 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -34,6 +34,23 @@ test "access file" {
try os.deleteTree(a, "os_test_tmp");
}
+fn testThreadIdFn(thread_id: *os.Thread.Id) void {
+ thread_id.* = os.Thread.getCurrentId();
+}
+
+test "std.os.Thread.getCurrentId" {
+ var thread_current_id: os.Thread.Id = undefined;
+ const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
+ const thread_id = thread.handle();
+ thread.wait();
+ switch (builtin.os) {
+ builtin.Os.windows => assert(os.Thread.getCurrentId() != thread_current_id),
+ else => {
+ assert(thread_current_id == thread_id);
+ },
+ }
+}
+
test "spawn threads" {
var shared_ctx: i32 = 1;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index fa3473ad05..daeebf1021 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -63,6 +63,9 @@ 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 GetCurrentThreadId() DWORD;
+
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;