| ... | @@ -2516,26 +2516,56 @@ pub const Thread = struct { | ... | @@ -2516,26 +2516,56 @@ pub const Thread = struct { |
| 2516 | data: Data, | 2516 | data: Data, |
| 2517 | | 2517 | |
| 2518 | pub const use_pthreads = is_posix and builtin.link_libc; | 2518 | pub const use_pthreads = is_posix and builtin.link_libc; |
| | 2519 | |
| | 2520 | /// An type representing a kernel thread ID. |
| | 2521 | pub const Id = if (use_pthreads) |
| | 2522 | c.pthread_t |
| | 2523 | else switch (builtin.os) { |
| | 2524 | builtin.Os.linux => i32, |
| | 2525 | builtin.Os.windows => windows.HANDLE, |
| | 2526 | else => @compileError("Unsupported OS"), |
| | 2527 | }; |
| | 2528 | |
| 2519 | pub const Data = if (use_pthreads) | 2529 | pub const Data = if (use_pthreads) |
| 2520 | struct { | 2530 | struct { |
| 2521 | handle: c.pthread_t, | 2531 | handle: Thread.Id, |
| 2522 | stack_addr: usize, | 2532 | stack_addr: usize, |
| 2523 | stack_len: usize, | 2533 | stack_len: usize, |
| 2524 | } | 2534 | } |
| 2525 | else switch (builtin.os) { | 2535 | else switch (builtin.os) { |
| 2526 | builtin.Os.linux => struct { | 2536 | builtin.Os.linux => struct { |
| 2527 | pid: i32, | 2537 | handle: Thread.Id, |
| 2528 | stack_addr: usize, | 2538 | stack_addr: usize, |
| 2529 | stack_len: usize, | 2539 | stack_len: usize, |
| 2530 | }, | 2540 | }, |
| 2531 | builtin.Os.windows => struct { | 2541 | builtin.Os.windows => struct { |
| 2532 | handle: windows.HANDLE, | 2542 | handle: Thread.Id, |
| 2533 | alloc_start: *c_void, | 2543 | alloc_start: *c_void, |
| 2534 | heap_handle: windows.HANDLE, | 2544 | heap_handle: windows.HANDLE, |
| 2535 | }, | 2545 | }, |
| 2536 | else => @compileError("Unsupported OS"), | 2546 | else => @compileError("Unsupported OS"), |
| 2537 | }; | 2547 | }; |
| 2538 | | 2548 | |
| | 2549 | /// Returns the ID of the calling thread. |
| | 2550 | pub fn currentId() Thread.Id { |
| | 2551 | // TODO: As-is, this function is potentially expensive (making a |
| | 2552 | // syscall on every call). Once we have support for thread-local |
| | 2553 | // storage (https://github.com/ziglang/zig/issues/924), we could |
| | 2554 | // memoize it. |
| | 2555 | if (use_pthreads) { |
| | 2556 | return c.pthread_self(); |
| | 2557 | } else return switch (builtin.os) { |
| | 2558 | builtin.Os.linux => linux.getpid(), |
| | 2559 | builtin.Os.windows => windows.GetCurrentThread(), |
| | 2560 | else => @compileError("Unsupported OS"), |
| | 2561 | }; |
| | 2562 | } |
| | 2563 | |
| | 2564 | /// Returns the ID of this thread. |
| | 2565 | pub fn id(self: *const Thread) Thread.Id { |
| | 2566 | return self.data.handle; |
| | 2567 | } |
| | 2568 | |
| 2539 | pub fn wait(self: *const Thread) void { | 2569 | pub fn wait(self: *const Thread) void { |
| 2540 | if (use_pthreads) { | 2570 | if (use_pthreads) { |
| 2541 | const err = c.pthread_join(self.data.handle, null); | 2571 | const err = c.pthread_join(self.data.handle, null); |
| ... | @@ -2550,9 +2580,9 @@ pub const Thread = struct { | ... | @@ -2550,9 +2580,9 @@ pub const Thread = struct { |
| 2550 | } else switch (builtin.os) { | 2580 | } else switch (builtin.os) { |
| 2551 | builtin.Os.linux => { | 2581 | builtin.Os.linux => { |
| 2552 | while (true) { | 2582 | while (true) { |
| 2553 | const pid_value = @atomicLoad(i32, &self.data.pid, builtin.AtomicOrder.SeqCst); | 2583 | const pid_value = @atomicLoad(i32, &self.data.handle, builtin.AtomicOrder.SeqCst); |
| 2554 | if (pid_value == 0) break; | 2584 | if (pid_value == 0) break; |
| 2555 | const rc = linux.futex_wait(@ptrToInt(&self.data.pid), linux.FUTEX_WAIT, pid_value, null); | 2585 | const rc = linux.futex_wait(@ptrToInt(&self.data.handle), linux.FUTEX_WAIT, pid_value, null); |
| 2556 | switch (linux.getErrno(rc)) { | 2586 | switch (linux.getErrno(rc)) { |
| 2557 | 0 => continue, | 2587 | 0 => continue, |
| 2558 | posix.EINTR => continue, | 2588 | posix.EINTR => continue, |
| ... | @@ -2734,7 +2764,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -2734,7 +2764,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 2734 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly | 2764 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly |
| 2735 | 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; | 2765 | 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; |
| 2736 | const newtls: usize = 0; | 2766 | const newtls: usize = 0; |
| 2737 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid); | 2767 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); |
| 2738 | const err = posix.getErrno(rc); | 2768 | const err = posix.getErrno(rc); |
| 2739 | switch (err) { | 2769 | switch (err) { |
| 2740 | 0 => return thread_ptr, | 2770 | 0 => return thread_ptr, |