| author | |
| committer | |
| log | 86d1cc8e2fffed9c93e41b28605d764e6b1749dc |
| tree | 0cf017f35e7f9800978c1d04f39562f5b31bccdf |
| parent | 9bd8b01650f9cf21e601117951711b21aa5fd216 |
4 files changed, 48 insertions(+), 0 deletions(-)
std/c/index.zig+1| ... | @@ -58,6 +58,7 @@ pub extern "pthread" fn pthread_create(noalias newthread: *pthread_t, noalias at | ... | @@ -58,6 +58,7 @@ pub extern "pthread" fn pthread_create(noalias newthread: *pthread_t, noalias at |
| 58 | pub extern "pthread" fn pthread_attr_init(attr: *pthread_attr_t) c_int; | 58 | pub extern "pthread" fn pthread_attr_init(attr: *pthread_attr_t) c_int; |
| 59 | pub extern "pthread" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int; | 59 | pub extern "pthread" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int; |
| 60 | pub extern "pthread" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int; | 60 | pub extern "pthread" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int; |
| 61 | pub extern "pthread" fn pthread_self() pthread_t; | ||
| 61 | pub extern "pthread" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int; | 62 | pub extern "pthread" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int; |
| 62 | 63 | ||
| 63 | pub const pthread_t = *@OpaqueType(); | 64 | pub const pthread_t = *@OpaqueType(); |
std/os/index.zig+33| ... | @@ -2516,6 +2516,10 @@ pub const Thread = struct { | ... | @@ -2516,6 +2516,10 @@ 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 opaque type representing a kernel thread ID. | ||
| 2521 | pub const Id = *@OpaqueType(); | ||
| 2522 | |||
| 2519 | pub const Data = if (use_pthreads) | 2523 | pub const Data = if (use_pthreads) |
| 2520 | struct { | 2524 | struct { |
| 2521 | handle: c.pthread_t, | 2525 | handle: c.pthread_t, |
| ... | @@ -2536,6 +2540,35 @@ pub const Thread = struct { | ... | @@ -2536,6 +2540,35 @@ pub const Thread = struct { |
| 2536 | else => @compileError("Unsupported OS"), | 2540 | else => @compileError("Unsupported OS"), |
| 2537 | }; | 2541 | }; |
| 2538 | 2542 | ||
| 2543 | /// Returns the ID of the calling thread. | ||
| 2544 | pub fn currentId() Thread.Id { | ||
| 2545 | // TODO: As-is, this function is potentially expensive (making a | ||
| 2546 | // syscall on every call). Once we have support for thread-local | ||
| 2547 | // storage (https://github.com/ziglang/zig/issues/924), we could | ||
| 2548 | // memoize it. | ||
| 2549 | if (use_pthreads) { | ||
| 2550 | return @ptrCast(Thread.Id, c.pthread_self()); | ||
| 2551 | } else return switch (builtin.os) { | ||
| 2552 | builtin.Os.linux => | ||
| 2553 | @intToPtr(Thread.Id, @bitCast(u32, linux.getpid())), | ||
| 2554 | builtin.Os.windows => | ||
| 2555 | @ptrCast(Thread.Id, windows.GetCurrentThread()), | ||
| 2556 | else => @compileError("Unsupported OS"), | ||
| 2557 | }; | ||
| 2558 | } | ||
| 2559 | |||
| 2560 | /// Returns the ID of this thread object. | ||
| 2561 | pub fn id(self: *const Thread) Thread.Id { | ||
| 2562 | if (use_pthreads) { | ||
| 2563 | return @ptrCast(Thread.Id, self.data.handle); | ||
| 2564 | } else return switch (builtin.os) { | ||
| 2565 | builtin.Os.linux => | ||
| 2566 | @intToPtr(Thread.Id, @bitCast(u32, self.data.pid)), | ||
| 2567 | builtin.Os.windows => @ptrCast(Thread.Id, self.data.handle), | ||
| 2568 | else => @compileError("Unsupported OS"), | ||
| 2569 | }; | ||
| 2570 | } | ||
| 2571 | |||
| 2539 | pub fn wait(self: *const Thread) void { | 2572 | pub fn wait(self: *const Thread) void { |
| 2540 | if (use_pthreads) { | 2573 | if (use_pthreads) { |
| 2541 | const err = c.pthread_join(self.data.handle, null); | 2574 | const err = c.pthread_join(self.data.handle, null); |
std/os/test.zig+12| ... | @@ -34,6 +34,18 @@ test "access file" { | ... | @@ -34,6 +34,18 @@ test "access file" { |
| 34 | try os.deleteTree(a, "os_test_tmp"); | 34 | try os.deleteTree(a, "os_test_tmp"); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | fn testThreadIdFn(threadId: *?os.Thread.Id) void { | ||
| 38 | threadId.* = os.Thread.currentId(); | ||
| 39 | } | ||
| 40 | |||
| 41 | test "std.os.Thread.currentId" { | ||
| 42 | var threadCurrentId: ?os.Thread.Id = null; | ||
| 43 | const thread = try os.spawnThread(&threadCurrentId, testThreadIdFn); | ||
| 44 | const threadId = thread.id(); | ||
| 45 | thread.wait(); | ||
| 46 | assert(threadCurrentId == threadId); | ||
| 47 | } | ||
| 48 | |||
| 37 | test "spawn threads" { | 49 | test "spawn threads" { |
| 38 | var shared_ctx: i32 = 1; | 50 | var shared_ctx: i32 = 1; |
| 39 | 51 |
std/os/windows/kernel32.zig+2| ... | @@ -63,6 +63,8 @@ pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out | ... | @@ -63,6 +63,8 @@ pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out |
| 63 | 63 | ||
| 64 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) DWORD; | 64 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) DWORD; |
| 65 | 65 | ||
| 66 | pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE; | ||
| 67 | |||
| 66 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8; | 68 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8; |
| 67 | 69 | ||
| 68 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD; | 70 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD; |