| ... | ... | @@ -160,7 +160,7 @@ test "os.getRandomBytes" { |
| 160 | 160 | try getRandomBytes(buf_b[0..]); |
| 161 | 161 | |
| 162 | 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 | 166 | /// Raises a signal in the current kernel thread, ending its execution. |
| ... | ... | @@ -2516,26 +2516,66 @@ pub const Thread = struct { |
| 2516 | 2516 | data: Data, |
| 2517 | 2517 | |
| 2518 | 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 | 2539 | pub const Data = if (use_pthreads) |
| 2520 | 2540 | struct { |
| 2521 | | handle: c.pthread_t, |
| 2541 | handle: Thread.Handle, |
| 2522 | 2542 | stack_addr: usize, |
| 2523 | 2543 | stack_len: usize, |
| 2524 | 2544 | } |
| 2525 | 2545 | else switch (builtin.os) { |
| 2526 | 2546 | builtin.Os.linux => struct { |
| 2527 | | pid: i32, |
| 2547 | handle: Thread.Handle, |
| 2528 | 2548 | stack_addr: usize, |
| 2529 | 2549 | stack_len: usize, |
| 2530 | 2550 | }, |
| 2531 | 2551 | builtin.Os.windows => struct { |
| 2532 | | handle: windows.HANDLE, |
| 2552 | handle: Thread.Handle, |
| 2533 | 2553 | alloc_start: *c_void, |
| 2534 | 2554 | heap_handle: windows.HANDLE, |
| 2535 | 2555 | }, |
| 2536 | 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 | 2579 | pub fn wait(self: *const Thread) void { |
| 2540 | 2580 | if (use_pthreads) { |
| 2541 | 2581 | const err = c.pthread_join(self.data.handle, null); |
| ... | ... | @@ -2550,9 +2590,9 @@ pub const Thread = struct { |
| 2550 | 2590 | } else switch (builtin.os) { |
| 2551 | 2591 | builtin.Os.linux => { |
| 2552 | 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 | 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 | 2596 | switch (linux.getErrno(rc)) { |
| 2557 | 2597 | 0 => continue, |
| 2558 | 2598 | posix.EINTR => continue, |
| ... | ... | @@ -2734,7 +2774,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 2734 | 2774 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly |
| 2735 | 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 | 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 | 2778 | const err = posix.getErrno(rc); |
| 2739 | 2779 | switch (err) { |
| 2740 | 2780 | 0 => return thread_ptr, |