mirror of
https://github.com/ziglang/zig.git
synced 2026-01-25 08:47:55 +00:00
Merge branch 'threadid' of https://github.com/mdsteele/zig into mdsteele-threadid
This commit is contained in:
commit
647fd0f4f1
@ -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();
|
||||
|
||||
@ -2516,26 +2516,56 @@ pub const Thread = struct {
|
||||
data: Data,
|
||||
|
||||
pub const use_pthreads = is_posix and builtin.link_libc;
|
||||
|
||||
/// An type representing a kernel thread ID.
|
||||
pub const Id = if (use_pthreads)
|
||||
c.pthread_t
|
||||
else switch (builtin.os) {
|
||||
builtin.Os.linux => i32,
|
||||
builtin.Os.windows => windows.HANDLE,
|
||||
else => @compileError("Unsupported OS"),
|
||||
};
|
||||
|
||||
pub const Data = if (use_pthreads)
|
||||
struct {
|
||||
handle: c.pthread_t,
|
||||
handle: Thread.Id,
|
||||
stack_addr: usize,
|
||||
stack_len: usize,
|
||||
}
|
||||
else switch (builtin.os) {
|
||||
builtin.Os.linux => struct {
|
||||
pid: i32,
|
||||
handle: Thread.Id,
|
||||
stack_addr: usize,
|
||||
stack_len: usize,
|
||||
},
|
||||
builtin.Os.windows => struct {
|
||||
handle: windows.HANDLE,
|
||||
handle: Thread.Id,
|
||||
alloc_start: *c_void,
|
||||
heap_handle: windows.HANDLE,
|
||||
},
|
||||
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 c.pthread_self();
|
||||
} else return switch (builtin.os) {
|
||||
builtin.Os.linux => linux.getpid(),
|
||||
builtin.Os.windows => windows.GetCurrentThread(),
|
||||
else => @compileError("Unsupported OS"),
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the ID of this thread.
|
||||
pub fn id(self: *const Thread) Thread.Id {
|
||||
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 +2580,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 +2764,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,
|
||||
|
||||
@ -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 = undefined;
|
||||
const thread = try os.spawnThread(&threadCurrentId, testThreadIdFn);
|
||||
const threadId = thread.id();
|
||||
thread.wait();
|
||||
assert(threadCurrentId == threadId);
|
||||
}
|
||||
|
||||
test "spawn threads" {
|
||||
var shared_ctx: i32 = 1;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user