| ... | @@ -160,7 +160,7 @@ test "os.getRandomBytes" { | ... | @@ -160,7 +160,7 @@ test "os.getRandomBytes" { |
| 160 | try getRandomBytes(buf_b[0..]); | 160 | try getRandomBytes(buf_b[0..]); |
| 161 | | 161 | |
| 162 | // Check if random (not 100% conclusive) | 162 | // Check if random (not 100% conclusive) |
| 163 | assert( !mem.eql(u8, buf_a, buf_b) ); | 163 | assert(!mem.eql(u8, buf_a, buf_b)); |
| 164 | } | 164 | } |
| 165 | | 165 | |
| 166 | /// Raises a signal in the current kernel thread, ending its execution. | 166 | /// Raises a signal in the current kernel thread, ending its execution. |
| ... | @@ -2516,26 +2516,66 @@ pub const Thread = struct { | ... | @@ -2516,26 +2516,66 @@ 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 | /// Represents a kernel thread handle. |
| | 2521 | /// May be an integer or a pointer depending on the platform. |
| | 2522 | /// On Linux and POSIX, this is the same as Id. |
| | 2523 | pub const Handle = if (use_pthreads) |
| | 2524 | c.pthread_t |
| | 2525 | else switch (builtin.os) { |
| | 2526 | builtin.Os.linux => i32, |
| | 2527 | builtin.Os.windows => windows.HANDLE, |
| | 2528 | else => @compileError("Unsupported OS"), |
| | 2529 | }; |
| | 2530 | |
| | 2531 | /// Represents a unique ID per thread. |
| | 2532 | /// May be an integer or pointer depending on the platform. |
| | 2533 | /// On Linux and POSIX, this is the same as Handle. |
| | 2534 | pub const Id = switch (builtin.os) { |
| | 2535 | builtin.Os.windows => windows.DWORD, |
| | 2536 | else => Handle, |
| | 2537 | }; |
| | 2538 | |
| 2519 | pub const Data = if (use_pthreads) | 2539 | pub const Data = if (use_pthreads) |
| 2520 | struct { | 2540 | struct { |
| 2521 | handle: c.pthread_t, | 2541 | handle: Thread.Handle, |
| 2522 | stack_addr: usize, | 2542 | stack_addr: usize, |
| 2523 | stack_len: usize, | 2543 | stack_len: usize, |
| 2524 | } | 2544 | } |
| 2525 | else switch (builtin.os) { | 2545 | else switch (builtin.os) { |
| 2526 | builtin.Os.linux => struct { | 2546 | builtin.Os.linux => struct { |
| 2527 | pid: i32, | 2547 | handle: Thread.Handle, |
| 2528 | stack_addr: usize, | 2548 | stack_addr: usize, |
| 2529 | stack_len: usize, | 2549 | stack_len: usize, |
| 2530 | }, | 2550 | }, |
| 2531 | builtin.Os.windows => struct { | 2551 | builtin.Os.windows => struct { |
| 2532 | handle: windows.HANDLE, | 2552 | handle: Thread.Handle, |
| 2533 | alloc_start: *c_void, | 2553 | alloc_start: *c_void, |
| 2534 | heap_handle: windows.HANDLE, | 2554 | heap_handle: windows.HANDLE, |
| 2535 | }, | 2555 | }, |
| 2536 | else => @compileError("Unsupported OS"), | 2556 | else => @compileError("Unsupported OS"), |
| 2537 | }; | 2557 | }; |
| 2538 | | 2558 | |
| | 2559 | /// Returns the ID of the calling thread. |
| | 2560 | /// Makes a syscall every time the function is called. |
| | 2561 | /// On Linux and POSIX, this Id is the same as a Handle. |
| | 2562 | pub fn getCurrentId() Id { |
| | 2563 | if (use_pthreads) { |
| | 2564 | return c.pthread_self(); |
| | 2565 | } else |
| | 2566 | return switch (builtin.os) { |
| | 2567 | builtin.Os.linux => linux.gettid(), |
| | 2568 | builtin.Os.windows => windows.GetCurrentThreadId(), |
| | 2569 | else => @compileError("Unsupported OS"), |
| | 2570 | }; |
| | 2571 | } |
| | 2572 | |
| | 2573 | /// Returns the handle of this thread. |
| | 2574 | /// On Linux and POSIX, this is the same as Id. |
| | 2575 | pub fn handle(self: Thread) Handle { |
| | 2576 | return self.data.handle; |
| | 2577 | } |
| | 2578 | |
| 2539 | pub fn wait(self: *const Thread) void { | 2579 | pub fn wait(self: *const Thread) void { |
| 2540 | if (use_pthreads) { | 2580 | if (use_pthreads) { |
| 2541 | const err = c.pthread_join(self.data.handle, null); | 2581 | const err = c.pthread_join(self.data.handle, null); |
| ... | @@ -2550,9 +2590,9 @@ pub const Thread = struct { | ... | @@ -2550,9 +2590,9 @@ pub const Thread = struct { |
| 2550 | } else switch (builtin.os) { | 2590 | } else switch (builtin.os) { |
| 2551 | builtin.Os.linux => { | 2591 | builtin.Os.linux => { |
| 2552 | while (true) { | 2592 | while (true) { |
| 2553 | const pid_value = @atomicLoad(i32, &self.data.pid, builtin.AtomicOrder.SeqCst); | 2593 | const pid_value = @atomicLoad(i32, &self.data.handle, builtin.AtomicOrder.SeqCst); |
| 2554 | if (pid_value == 0) break; | 2594 | if (pid_value == 0) break; |
| 2555 | const rc = linux.futex_wait(@ptrToInt(&self.data.pid), linux.FUTEX_WAIT, pid_value, null); | 2595 | const rc = linux.futex_wait(@ptrToInt(&self.data.handle), linux.FUTEX_WAIT, pid_value, null); |
| 2556 | switch (linux.getErrno(rc)) { | 2596 | switch (linux.getErrno(rc)) { |
| 2557 | 0 => continue, | 2597 | 0 => continue, |
| 2558 | posix.EINTR => continue, | 2598 | posix.EINTR => continue, |
| ... | @@ -2734,7 +2774,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -2734,7 +2774,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 | 2774 | // 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; | 2775 | 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; | 2776 | const newtls: usize = 0; |
| 2737 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid); | 2777 | 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); | 2778 | const err = posix.getErrno(rc); |
| 2739 | switch (err) { | 2779 | switch (err) { |
| 2740 | 0 => return thread_ptr, | 2780 | 0 => return thread_ptr, |