authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-25 13:07:44-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 18:32:44-04:00
log7cb6279ac0cec065234347bda5944be64fe8b3da
tree0eb4befe9a7eb24f5a393559e0621e92e26a4c59
parentca6debcaf4a4f85b7aff94c7b5fe821530b0f195
signature Commit is signed but in an unrecognized format.

clean up references to posix


28 files changed, 1390 insertions(+), 1392 deletions(-)

CMakeLists.txt-1
......@@ -620,7 +620,6 @@ set(ZIG_STD_FILES
620620 "os/freebsd.zig"
621621 "os/linux.zig"
622622 "os/linux/arm64.zig"
623 "os/linux/sys.zig"
624623 "os/linux/tls.zig"
625624 "os/linux/vdso.zig"
626625 "os/linux/x86_64.zig"
std/atomic/queue.zig+4-4
......@@ -186,13 +186,13 @@ test "std.atomic.Queue" {
186186 }
187187 }
188188 } else {
189 var putters: [put_thread_count]*std.os.Thread = undefined;
189 var putters: [put_thread_count]*std.Thread = undefined;
190190 for (putters) |*t| {
191 t.* = try std.os.spawnThread(&context, startPuts);
191 t.* = try std.Thread.spawn(&context, startPuts);
192192 }
193 var getters: [put_thread_count]*std.os.Thread = undefined;
193 var getters: [put_thread_count]*std.Thread = undefined;
194194 for (getters) |*t| {
195 t.* = try std.os.spawnThread(&context, startGets);
195 t.* = try std.Thread.spawn(&context, startGets);
196196 }
197197
198198 for (putters) |t|
std/atomic/stack.zig+4-4
......@@ -120,13 +120,13 @@ test "std.atomic.stack" {
120120 }
121121 }
122122 } else {
123 var putters: [put_thread_count]*std.os.Thread = undefined;
123 var putters: [put_thread_count]*std.Thread = undefined;
124124 for (putters) |*t| {
125 t.* = try std.os.spawnThread(&context, startPuts);
125 t.* = try std.Thread.spawn(&context, startPuts);
126126 }
127 var getters: [put_thread_count]*std.os.Thread = undefined;
127 var getters: [put_thread_count]*std.Thread = undefined;
128128 for (getters) |*t| {
129 t.* = try std.os.spawnThread(&context, startGets);
129 t.* = try std.Thread.spawn(&context, startGets);
130130 }
131131
132132 for (putters) |t|
std/c/darwin.zig+1-1
......@@ -3,7 +3,7 @@ const assert = std.debug.assert;
33const builtin = @import("builtin");
44const macho = std.macho;
55
6use @import("posix/darwin.zig");
6use @import("../os/bits.zig");
77
88extern "c" fn __error() *c_int;
99pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
std/c/linux.zig+1
......@@ -2,6 +2,7 @@ const std = @import("../std.zig");
22use std.c;
33
44pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
5pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
56extern "c" fn __errno_location() *c_int;
67pub const _errno = __errno_location;
78
std/child_process.zig+9-9
......@@ -351,22 +351,22 @@ pub const ChildProcess = struct {
351351 const err_pipe = try os.pipe();
352352 errdefer destroyPipe(err_pipe);
353353
354 const pid_result = try posix.fork();
354 const pid_result = try os.fork();
355355 if (pid_result == 0) {
356356 // we are the child
357 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
358 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
359 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
357 setUpChildIo(self.stdin_behavior, stdin_pipe[0], os.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
358 setUpChildIo(self.stdout_behavior, stdout_pipe[1], os.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
359 setUpChildIo(self.stderr_behavior, stderr_pipe[1], os.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
360360
361 if (self.stdin_behavior == StdIo.Pipe) {
361 if (self.stdin_behavior == .Pipe) {
362362 os.close(stdin_pipe[0]);
363363 os.close(stdin_pipe[1]);
364364 }
365 if (self.stdout_behavior == StdIo.Pipe) {
365 if (self.stdout_behavior == .Pipe) {
366366 os.close(stdout_pipe[0]);
367367 os.close(stdout_pipe[1]);
368368 }
369 if (self.stderr_behavior == StdIo.Pipe) {
369 if (self.stderr_behavior == .Pipe) {
370370 os.close(stderr_pipe[0]);
371371 os.close(stderr_pipe[1]);
372372 }
......@@ -383,7 +383,7 @@ pub const ChildProcess = struct {
383383 os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
384384 }
385385
386 os.posix.execve(self.allocator, self.argv, env_map) catch |err| forkChildErrReport(err_pipe[1], err);
386 os.execve(self.allocator, self.argv, env_map) catch |err| forkChildErrReport(err_pipe[1], err);
387387 }
388388
389389 // we are the parent
......@@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void {
736736// Then the child exits.
737737fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
738738 writeIntFd(fd, ErrInt(@errorToInt(err))) catch {};
739 posix.exit(1);
739 os.exit(1);
740740}
741741
742742const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
std/crypto.zig+1-1
......@@ -33,7 +33,7 @@ pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
3333pub const X25519 = @import("crypto/x25519.zig").X25519;
3434
3535const std = @import("std.zig");
36pub const randomBytes = std.posix.getrandom;
36pub const randomBytes = std.os.getrandom;
3737
3838test "crypto" {
3939 _ = @import("crypto/blake2.zig");
std/debug.zig+4-5
......@@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
10121012 errdefer S.self_exe_file.close();
10131013
10141014 const self_exe_mmap_len = try S.self_exe_file.getEndPos();
1015 const self_exe_mmap = os.posix.mmap(
1015 const self_exe_mmap = try os.mmap(
10161016 null,
10171017 self_exe_mmap_len,
1018 os.posix.PROT_READ,
1019 os.posix.MAP_SHARED,
1018 os.PROT_READ,
1019 os.MAP_SHARED,
10201020 S.self_exe_file.handle,
10211021 0,
10221022 );
1023 if (self_exe_mmap == os.posix.MAP_FAILED) return error.OutOfMemory;
1024 errdefer assert(os.posix.munmap(self_exe_mmap, self_exe_mmap_len) == 0);
1023 errdefer os.munmap(self_exe_mmap, self_exe_mmap_len);
10251024
10261025 const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];
10271026 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);
std/event/fs.zig+17-21
......@@ -5,10 +5,9 @@ const assert = std.debug.assert;
55const testing = std.testing;
66const os = std.os;
77const mem = std.mem;
8const posix = os.posix;
98const windows = os.windows;
109const Loop = event.Loop;
11const fd_t = posix.fd_t;
10const fd_t = os.fd_t;
1211const File = std.fs.File;
1312
1413pub const RequestNode = std.atomic.Queue(Request).Node;
......@@ -33,7 +32,7 @@ pub const Request = struct {
3332
3433 pub const PWriteV = struct {
3534 fd: fd_t,
36 iov: []const os.posix.iovec_const,
35 iov: []const os.iovec_const,
3736 offset: usize,
3837 result: Error!void,
3938
......@@ -42,7 +41,7 @@ pub const Request = struct {
4241
4342 pub const PReadV = struct {
4443 fd: fd_t,
45 iov: []const os.posix.iovec,
44 iov: []const os.iovec,
4645 offset: usize,
4746 result: Error!usize,
4847
......@@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us
8988 builtin.Os.freebsd,
9089 builtin.Os.netbsd,
9190 => {
92 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
91 const iovecs = try loop.allocator.alloc(os.iovec_const, data.len);
9392 defer loop.allocator.free(iovecs);
9493
9594 for (data) |buf, i| {
96 iovecs[i] = os.posix.iovec_const{
95 iovecs[i] = os.iovec_const{
9796 .iov_base = buf.ptr,
9897 .iov_len = buf.len,
9998 };
......@@ -171,7 +170,7 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64)
171170pub async fn pwritevPosix(
172171 loop: *Loop,
173172 fd: fd_t,
174 iovecs: []const posix.iovec_const,
173 iovecs: []const os.iovec_const,
175174 offset: usize,
176175) os.PosixWriteError!void {
177176 // workaround for https://github.com/ziglang/zig/issues/1194
......@@ -226,11 +225,11 @@ pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PR
226225 builtin.Os.freebsd,
227226 builtin.Os.netbsd,
228227 => {
229 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
228 const iovecs = try loop.allocator.alloc(os.iovec, data.len);
230229 defer loop.allocator.free(iovecs);
231230
232231 for (data) |buf, i| {
233 iovecs[i] = os.posix.iovec{
232 iovecs[i] = os.iovec{
234233 .iov_base = buf.ptr,
235234 .iov_len = buf.len,
236235 };
......@@ -319,7 +318,7 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize
319318pub async fn preadvPosix(
320319 loop: *Loop,
321320 fd: fd_t,
322 iovecs: []const posix.iovec,
321 iovecs: []const os.iovec,
323322 offset: usize,
324323) os.PosixReadError!usize {
325324 // workaround for https://github.com/ziglang/zig/issues/1194
......@@ -405,7 +404,7 @@ pub async fn openPosix(
405404pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
406405 switch (builtin.os) {
407406 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
408 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
407 const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
409408 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
410409 },
411410
......@@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.
435434 builtin.Os.freebsd,
436435 builtin.Os.netbsd,
437436 => {
438 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
437 const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
439438 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
440439 },
441440 builtin.Os.windows => return os.windowsOpen(
......@@ -457,7 +456,7 @@ pub async fn openReadWrite(
457456) File.OpenError!fd_t {
458457 switch (builtin.os) {
459458 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
460 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
459 const flags = os.O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC;
461460 return await (async openPosix(loop, path, flags, mode) catch unreachable);
462461 },
463462
......@@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type {
888887 var close_op_consumed = false;
889888 defer if (!close_op_consumed) close_op.finish();
890889
891 const flags = switch (builtin.os) {
892 builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY,
893 else => 0,
894 };
890 const flags = if (os.darwin.is_the_target) os.O_SYMLINK | os.O_EVTONLY else 0;
895891 const mode = 0;
896892 const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
897893 close_op.setHandle(fd);
......@@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type {
943939 while (true) {
944940 if (await (async self.channel.loop.bsdWaitKev(
945941 @intCast(usize, close_op.getHandle()),
946 posix.EVFILT_VNODE,
947 posix.NOTE_WRITE | posix.NOTE_DELETE,
942 os.EVFILT_VNODE,
943 os.NOTE_WRITE | os.NOTE_DELETE,
948944 ) catch unreachable)) |kev| {
949945 // TODO handle EV_ERROR
950 if (kev.fflags & posix.NOTE_DELETE != 0) {
946 if (kev.fflags & os.NOTE_DELETE != 0) {
951947 await (async self.channel.put(Self.Event{
952948 .id = Event.Id.Delete,
953949 .data = value_copy,
954950 }) catch unreachable);
955 } else if (kev.fflags & posix.NOTE_WRITE != 0) {
951 } else if (kev.fflags & os.NOTE_WRITE != 0) {
956952 await (async self.channel.put(Self.Event{
957953 .id = Event.Id.CloseWrite,
958954 .data = value_copy,
std/event/loop.zig+71-71
......@@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
77const AtomicOrder = builtin.AtomicOrder;
88const fs = std.event.fs;
99const os = std.os;
10const posix = os.posix;
1110const windows = os.windows;
1211const maxInt = std.math.maxInt;
12const Thread = std.Thread;
1313
1414pub const Loop = struct {
1515 allocator: *mem.Allocator,
......@@ -17,7 +17,7 @@ pub const Loop = struct {
1717 os_data: OsData,
1818 final_resume_node: ResumeNode,
1919 pending_event_count: usize,
20 extra_threads: []*os.Thread,
20 extra_threads: []*Thread,
2121
2222 // pre-allocated eventfds. all permanently active.
2323 // this is how we send promises to be resumed on other threads.
......@@ -65,7 +65,7 @@ pub const Loop = struct {
6565
6666 const KEventFd = struct {
6767 base: ResumeNode,
68 kevent: posix.Kevent,
68 kevent: os.Kevent,
6969 };
7070
7171 pub const Basic = switch (builtin.os) {
......@@ -81,7 +81,7 @@ pub const Loop = struct {
8181
8282 const KEventBasic = struct {
8383 base: ResumeNode,
84 kev: posix.Kevent,
84 kev: os.Kevent,
8585 };
8686 };
8787
......@@ -127,7 +127,7 @@ pub const Loop = struct {
127127 );
128128 errdefer self.allocator.free(self.eventfd_resume_nodes);
129129
130 self.extra_threads = try self.allocator.alloc(*os.Thread, extra_thread_count);
130 self.extra_threads = try self.allocator.alloc(*Thread, extra_thread_count);
131131 errdefer self.allocator.free(self.extra_threads);
132132
133133 try self.initOsData(extra_thread_count);
......@@ -172,32 +172,32 @@ pub const Loop = struct {
172172 .handle = undefined,
173173 .overlapped = ResumeNode.overlapped_init,
174174 },
175 .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),
176 .epoll_op = posix.EPOLL_CTL_ADD,
175 .eventfd = try os.linuxEventFd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK),
176 .epoll_op = os.EPOLL_CTL_ADD,
177177 },
178178 .next = undefined,
179179 };
180180 self.available_eventfd_resume_nodes.push(eventfd_node);
181181 }
182182
183 self.os_data.epollfd = try os.linuxEpollCreate(posix.EPOLL_CLOEXEC);
183 self.os_data.epollfd = try os.linuxEpollCreate(os.EPOLL_CLOEXEC);
184184 errdefer os.close(self.os_data.epollfd);
185185
186 self.os_data.final_eventfd = try os.linuxEventFd(0, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK);
186 self.os_data.final_eventfd = try os.linuxEventFd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
187187 errdefer os.close(self.os_data.final_eventfd);
188188
189 self.os_data.final_eventfd_event = posix.epoll_event{
190 .events = posix.EPOLLIN,
191 .data = posix.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },
189 self.os_data.final_eventfd_event = os.epoll_event{
190 .events = os.EPOLLIN,
191 .data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },
192192 };
193193 try os.linuxEpollCtl(
194194 self.os_data.epollfd,
195 posix.EPOLL_CTL_ADD,
195 os.EPOLL_CTL_ADD,
196196 self.os_data.final_eventfd,
197197 &self.os_data.final_eventfd_event,
198198 );
199199
200 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);
200 self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
201201 errdefer {
202202 self.posixFsRequest(&self.os_data.fs_end_request);
203203 self.os_data.fs_thread.wait();
......@@ -218,7 +218,7 @@ pub const Loop = struct {
218218 }
219219 }
220220 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
221 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
221 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
222222 }
223223 },
224224 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
......@@ -240,7 +240,7 @@ pub const Loop = struct {
240240 },
241241 };
242242
243 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
243 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
244244
245245 for (self.eventfd_resume_nodes) |*eventfd_node, i| {
246246 eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
......@@ -251,10 +251,10 @@ pub const Loop = struct {
251251 .overlapped = ResumeNode.overlapped_init,
252252 },
253253 // this one is for sending events
254 .kevent = posix.Kevent{
254 .kevent = os.Kevent{
255255 .ident = i,
256 .filter = posix.EVFILT_USER,
257 .flags = posix.EV_CLEAR | posix.EV_ADD | posix.EV_DISABLE,
256 .filter = os.EVFILT_USER,
257 .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE,
258258 .fflags = 0,
259259 .data = 0,
260260 .udata = @ptrToInt(&eventfd_node.data.base),
......@@ -263,46 +263,46 @@ pub const Loop = struct {
263263 .next = undefined,
264264 };
265265 self.available_eventfd_resume_nodes.push(eventfd_node);
266 const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.data.kevent);
266 const kevent_array = (*const [1]os.Kevent)(&eventfd_node.data.kevent);
267267 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);
268 eventfd_node.data.kevent.flags = posix.EV_CLEAR | posix.EV_ENABLE;
269 eventfd_node.data.kevent.fflags = posix.NOTE_TRIGGER;
268 eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE;
269 eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER;
270270 }
271271
272272 // Pre-add so that we cannot get error.SystemResources
273273 // later when we try to activate it.
274 self.os_data.final_kevent = posix.Kevent{
274 self.os_data.final_kevent = os.Kevent{
275275 .ident = extra_thread_count,
276 .filter = posix.EVFILT_USER,
277 .flags = posix.EV_ADD | posix.EV_DISABLE,
276 .filter = os.EVFILT_USER,
277 .flags = os.EV_ADD | os.EV_DISABLE,
278278 .fflags = 0,
279279 .data = 0,
280280 .udata = @ptrToInt(&self.final_resume_node),
281281 };
282 const final_kev_arr = (*const [1]posix.Kevent)(&self.os_data.final_kevent);
282 const final_kev_arr = (*const [1]os.Kevent)(&self.os_data.final_kevent);
283283 _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);
284 self.os_data.final_kevent.flags = posix.EV_ENABLE;
285 self.os_data.final_kevent.fflags = posix.NOTE_TRIGGER;
284 self.os_data.final_kevent.flags = os.EV_ENABLE;
285 self.os_data.final_kevent.fflags = os.NOTE_TRIGGER;
286286
287 self.os_data.fs_kevent_wake = posix.Kevent{
287 self.os_data.fs_kevent_wake = os.Kevent{
288288 .ident = 0,
289 .filter = posix.EVFILT_USER,
290 .flags = posix.EV_ADD | posix.EV_ENABLE,
291 .fflags = posix.NOTE_TRIGGER,
289 .filter = os.EVFILT_USER,
290 .flags = os.EV_ADD | os.EV_ENABLE,
291 .fflags = os.NOTE_TRIGGER,
292292 .data = 0,
293293 .udata = undefined,
294294 };
295295
296 self.os_data.fs_kevent_wait = posix.Kevent{
296 self.os_data.fs_kevent_wait = os.Kevent{
297297 .ident = 0,
298 .filter = posix.EVFILT_USER,
299 .flags = posix.EV_ADD | posix.EV_CLEAR,
298 .filter = os.EVFILT_USER,
299 .flags = os.EV_ADD | os.EV_CLEAR,
300300 .fflags = 0,
301301 .data = 0,
302302 .udata = undefined,
303303 };
304304
305 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);
305 self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
306306 errdefer {
307307 self.posixFsRequest(&self.os_data.fs_end_request);
308308 self.os_data.fs_thread.wait();
......@@ -322,7 +322,7 @@ pub const Loop = struct {
322322 }
323323 }
324324 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
325 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
325 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
326326 }
327327 },
328328 builtin.Os.windows => {
......@@ -371,7 +371,7 @@ pub const Loop = struct {
371371 }
372372 }
373373 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
374 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
374 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
375375 }
376376 },
377377 else => {},
......@@ -400,19 +400,19 @@ pub const Loop = struct {
400400 /// resume_node must live longer than the promise that it holds a reference to.
401401 /// flags must contain EPOLLET
402402 pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void {
403 assert(flags & posix.EPOLLET == posix.EPOLLET);
403 assert(flags & os.EPOLLET == os.EPOLLET);
404404 self.beginOneEvent();
405405 errdefer self.finishOneEvent();
406406 try self.linuxModFd(
407407 fd,
408 posix.EPOLL_CTL_ADD,
408 os.EPOLL_CTL_ADD,
409409 flags,
410410 resume_node,
411411 );
412412 }
413413
414414 pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void {
415 assert(flags & posix.EPOLLET == posix.EPOLLET);
415 assert(flags & os.EPOLLET == os.EPOLLET);
416416 var ev = os.linux.epoll_event{
417417 .events = flags,
418418 .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },
......@@ -440,7 +440,7 @@ pub const Loop = struct {
440440 }
441441 }
442442
443 pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !posix.Kevent {
443 pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent {
444444 // TODO #1194
445445 suspend {
446446 resume @handle();
......@@ -464,30 +464,30 @@ pub const Loop = struct {
464464 pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void {
465465 self.beginOneEvent();
466466 errdefer self.finishOneEvent();
467 var kev = posix.Kevent{
467 var kev = os.Kevent{
468468 .ident = ident,
469469 .filter = filter,
470 .flags = posix.EV_ADD | posix.EV_ENABLE | posix.EV_CLEAR,
470 .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR,
471471 .fflags = fflags,
472472 .data = 0,
473473 .udata = @ptrToInt(&resume_node.base),
474474 };
475 const kevent_array = (*const [1]posix.Kevent)(&kev);
476 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
475 const kevent_array = (*const [1]os.Kevent)(&kev);
476 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
477477 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);
478478 }
479479
480480 pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void {
481 var kev = posix.Kevent{
481 var kev = os.Kevent{
482482 .ident = ident,
483483 .filter = filter,
484 .flags = posix.EV_DELETE,
484 .flags = os.EV_DELETE,
485485 .fflags = 0,
486486 .data = 0,
487487 .udata = 0,
488488 };
489 const kevent_array = (*const [1]posix.Kevent)(&kev);
490 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
489 const kevent_array = (*const [1]os.Kevent)(&kev);
490 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
491491 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined;
492492 self.finishOneEvent();
493493 }
......@@ -502,8 +502,8 @@ pub const Loop = struct {
502502 eventfd_node.base.handle = next_tick_node.data;
503503 switch (builtin.os) {
504504 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
505 const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.kevent);
506 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
505 const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent);
506 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
507507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
508508 self.next_tick_queue.unget(next_tick_node);
509509 self.available_eventfd_resume_nodes.push(resume_stack_node);
......@@ -512,7 +512,7 @@ pub const Loop = struct {
512512 },
513513 builtin.Os.linux => {
514514 // the pending count is already accounted for
515 const epoll_events = posix.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT |
515 const epoll_events = os.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT |
516516 os.linux.EPOLLET;
517517 self.linuxModFd(
518518 eventfd_node.eventfd,
......@@ -631,8 +631,8 @@ pub const Loop = struct {
631631 },
632632 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
633633 self.posixFsRequest(&self.os_data.fs_end_request);
634 const final_kevent = (*const [1]posix.Kevent)(&self.os_data.final_kevent);
635 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
634 const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent);
635 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
636636 // cannot fail because we already added it and this just enables it
637637 _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable;
638638 return;
......@@ -676,7 +676,7 @@ pub const Loop = struct {
676676 ResumeNode.Id.Stop => return,
677677 ResumeNode.Id.EventFd => {
678678 const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
679 event_fd_node.epoll_op = posix.EPOLL_CTL_MOD;
679 event_fd_node.epoll_op = os.EPOLL_CTL_MOD;
680680 const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
681681 self.available_eventfd_resume_nodes.push(stack_node);
682682 },
......@@ -688,8 +688,8 @@ pub const Loop = struct {
688688 }
689689 },
690690 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
691 var eventlist: [1]posix.Kevent = undefined;
692 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
691 var eventlist: [1]os.Kevent = undefined;
692 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
693693 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
694694 for (eventlist[0..count]) |ev| {
695695 const resume_node = @intToPtr(*ResumeNode, ev.udata);
......@@ -751,8 +751,8 @@ pub const Loop = struct {
751751 self.os_data.fs_queue.put(request_node);
752752 switch (builtin.os) {
753753 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
754 const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wake);
755 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
754 const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wake);
755 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
756756 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
757757 },
758758 builtin.Os.linux => {
......@@ -760,7 +760,7 @@ pub const Loop = struct {
760760 const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
761761 switch (os.linux.getErrno(rc)) {
762762 0 => {},
763 posix.EINVAL => unreachable,
763 os.EINVAL => unreachable,
764764 else => unreachable,
765765 }
766766 },
......@@ -793,8 +793,8 @@ pub const Loop = struct {
793793 },
794794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
795795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
796 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |
797 posix.O_CLOEXEC | posix.O_TRUNC;
796 const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT |
797 os.O_CLOEXEC | os.O_TRUNC;
798798 const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
799799 msg.result = err;
800800 break :blk;
......@@ -816,13 +816,13 @@ pub const Loop = struct {
816816 builtin.Os.linux => {
817817 const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
818818 switch (os.linux.getErrno(rc)) {
819 0, posix.EINTR, posix.EAGAIN => continue,
819 0, os.EINTR, os.EAGAIN => continue,
820820 else => unreachable,
821821 }
822822 },
823823 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
824 const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wait);
825 var out_kevs: [1]posix.Kevent = undefined;
824 const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wait);
825 var out_kevs: [1]os.Kevent = undefined;
826826 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
827827 },
828828 else => @compileError("Unsupported OS"),
......@@ -842,10 +842,10 @@ pub const Loop = struct {
842842
843843 const KEventData = struct {
844844 kqfd: i32,
845 final_kevent: posix.Kevent,
846 fs_kevent_wake: posix.Kevent,
847 fs_kevent_wait: posix.Kevent,
848 fs_thread: *os.Thread,
845 final_kevent: os.Kevent,
846 fs_kevent_wake: os.Kevent,
847 fs_kevent_wait: os.Kevent,
848 fs_thread: *Thread,
849849 fs_kqfd: i32,
850850 fs_queue: std.atomic.Queue(fs.Request),
851851 fs_end_request: fs.RequestNode,
......@@ -855,7 +855,7 @@ pub const Loop = struct {
855855 epollfd: i32,
856856 final_eventfd: i32,
857857 final_eventfd_event: os.linux.epoll_event,
858 fs_thread: *os.Thread,
858 fs_thread: *Thread,
859859 fs_queue_item: i32,
860860 fs_queue: std.atomic.Queue(fs.Request),
861861 fs_end_request: fs.RequestNode,
std/event/net.zig+54-59
......@@ -4,11 +4,9 @@ const testing = std.testing;
44const event = std.event;
55const mem = std.mem;
66const os = std.os;
7const posix = os.posix;
87const Loop = std.event.Loop;
98const File = std.fs.File;
10
11const fd_t = posix.fd_t;
9const fd_t = os.fd_t;
1210
1311pub const Server = struct {
1412 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
......@@ -47,19 +45,19 @@ pub const Server = struct {
4745 ) !void {
4846 self.handleRequestFn = handleRequestFn;
4947
50 const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
48 const sockfd = try os.posixSocket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
5149 errdefer os.close(sockfd);
5250 self.sockfd = sockfd;
5351
5452 try os.posixBind(sockfd, &address.os_addr);
55 try os.posixListen(sockfd, posix.SOMAXCONN);
53 try os.posixListen(sockfd, os.SOMAXCONN);
5654 self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd));
5755
5856 self.accept_coro = try async<self.loop.allocator> Server.handler(self);
5957 errdefer cancel self.accept_coro.?;
6058
6159 self.listen_resume_node.handle = self.accept_coro.?;
62 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
60 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
6361 errdefer self.loop.removeFd(sockfd);
6462 }
6563
......@@ -78,7 +76,7 @@ pub const Server = struct {
7876 while (true) {
7977 var accepted_addr: std.net.Address = undefined;
8078 // TODO just inline the following function here and don't expose it as posixAsyncAccept
81 if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {
79 if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, os.SOCK_NONBLOCK | os.SOCK_CLOEXEC)) |accepted_fd| {
8280 if (accepted_fd == -1) {
8381 // would block
8482 suspend; // we will get resumed by epoll_wait in the event loop
......@@ -108,22 +106,22 @@ pub const Server = struct {
108106
109107pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
110108 const sockfd = try os.posixSocket(
111 posix.AF_UNIX,
112 posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK,
109 os.AF_UNIX,
110 os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK,
113111 0,
114112 );
115113 errdefer os.close(sockfd);
116114
117 var sock_addr = posix.sockaddr_un{
118 .family = posix.AF_UNIX,
115 var sock_addr = os.sockaddr_un{
116 .family = os.AF_UNIX,
119117 .path = undefined,
120118 };
121119
122120 if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong;
123121 mem.copy(u8, sock_addr.path[0..], path);
124 const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len);
122 const size = @intCast(u32, @sizeOf(os.sa_family_t) + path.len);
125123 try os.posixConnectAsync(sockfd, &sock_addr, size);
126 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
124 try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
127125 try os.posixGetSockOptConnectError(sockfd);
128126
129127 return sockfd;
......@@ -143,50 +141,48 @@ pub const ReadError = error{
143141
144142/// returns number of bytes read. 0 means EOF.
145143pub async fn read(loop: *std.event.Loop, fd: fd_t, buffer: []u8) ReadError!usize {
146 const iov = posix.iovec{
144 const iov = os.iovec{
147145 .iov_base = buffer.ptr,
148146 .iov_len = buffer.len,
149147 };
150 const iovs: *const [1]posix.iovec = &iov;
148 const iovs: *const [1]os.iovec = &iov;
151149 return await (async readvPosix(loop, fd, iovs, 1) catch unreachable);
152150}
153151
154152pub const WriteError = error{};
155153
156154pub async fn write(loop: *std.event.Loop, fd: fd_t, buffer: []const u8) WriteError!void {
157 const iov = posix.iovec_const{
155 const iov = os.iovec_const{
158156 .iov_base = buffer.ptr,
159157 .iov_len = buffer.len,
160158 };
161 const iovs: *const [1]posix.iovec_const = &iov;
159 const iovs: *const [1]os.iovec_const = &iov;
162160 return await (async writevPosix(loop, fd, iovs, 1) catch unreachable);
163161}
164162
165pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, count: usize) !void {
163pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const os.iovec_const, count: usize) !void {
166164 while (true) {
167165 switch (builtin.os) {
168 builtin.Os.macosx, builtin.Os.linux => {
169 const rc = posix.writev(fd, iov, count);
170 const err = posix.getErrno(rc);
171 switch (err) {
166 .macosx, .linux => {
167 switch (os.errno(os.system.writev(fd, iov, count))) {
172168 0 => return,
173 posix.EINTR => continue,
174 posix.ESPIPE => unreachable,
175 posix.EINVAL => unreachable,
176 posix.EFAULT => unreachable,
177 posix.EAGAIN => {
178 try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLOUT) catch unreachable);
169 os.EINTR => continue,
170 os.ESPIPE => unreachable,
171 os.EINVAL => unreachable,
172 os.EFAULT => unreachable,
173 os.EAGAIN => {
174 try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLOUT) catch unreachable);
179175 continue;
180176 },
181 posix.EBADF => unreachable, // always a race condition
182 posix.EDESTADDRREQ => unreachable, // connect was never called
183 posix.EDQUOT => unreachable,
184 posix.EFBIG => unreachable,
185 posix.EIO => return error.InputOutput,
186 posix.ENOSPC => unreachable,
187 posix.EPERM => return error.AccessDenied,
188 posix.EPIPE => unreachable,
189 else => return os.unexpectedErrorPosix(err),
177 os.EBADF => unreachable, // always a race condition
178 os.EDESTADDRREQ => unreachable, // connect was never called
179 os.EDQUOT => unreachable,
180 os.EFBIG => unreachable,
181 os.EIO => return error.InputOutput,
182 os.ENOSPC => unreachable,
183 os.EPERM => return error.AccessDenied,
184 os.EPIPE => unreachable,
185 else => |err| return os.unexpectedErrno(err),
190186 }
191187 },
192188 else => @compileError("Unsupported OS"),
......@@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const,
195191}
196192
197193/// returns number of bytes read. 0 means EOF.
198pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, count: usize) !usize {
194pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]os.iovec, count: usize) !usize {
199195 while (true) {
200196 switch (builtin.os) {
201197 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => {
202 const rc = posix.readv(fd, iov, count);
203 const err = posix.getErrno(rc);
204 switch (err) {
198 const rc = os.system.readv(fd, iov, count);
199 switch (os.errno(rc)) {
205200 0 => return rc,
206 posix.EINTR => continue,
207 posix.EINVAL => unreachable,
208 posix.EFAULT => unreachable,
209 posix.EAGAIN => {
210 try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLIN) catch unreachable);
201 os.EINTR => continue,
202 os.EINVAL => unreachable,
203 os.EFAULT => unreachable,
204 os.EAGAIN => {
205 try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN) catch unreachable);
211206 continue;
212207 },
213 posix.EBADF => unreachable, // always a race condition
214 posix.EIO => return error.InputOutput,
215 posix.EISDIR => unreachable,
216 posix.ENOBUFS => return error.SystemResources,
217 posix.ENOMEM => return error.SystemResources,
218 else => return os.unexpectedErrorPosix(err),
208 os.EBADF => unreachable, // always a race condition
209 os.EIO => return error.InputOutput,
210 os.EISDIR => unreachable,
211 os.ENOBUFS => return error.SystemResources,
212 os.ENOMEM => return error.SystemResources,
213 else => |err| return os.unexpectedErrno(err),
219214 }
220215 },
221216 else => @compileError("Unsupported OS"),
......@@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou
224219}
225220
226221pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {
227 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
222 const iovecs = try loop.allocator.alloc(os.iovec_const, data.len);
228223 defer loop.allocator.free(iovecs);
229224
230225 for (data) |buf, i| {
231 iovecs[i] = os.posix.iovec_const{
226 iovecs[i] = os.iovec_const{
232227 .iov_base = buf.ptr,
233228 .iov_len = buf.len,
234229 };
......@@ -238,11 +233,11 @@ pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {
238233}
239234
240235pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
241 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
236 const iovecs = try loop.allocator.alloc(os.iovec, data.len);
242237 defer loop.allocator.free(iovecs);
243238
244239 for (data) |buf, i| {
245 iovecs[i] = os.posix.iovec{
240 iovecs[i] = os.iovec{
246241 .iov_base = buf.ptr,
247242 .iov_len = buf.len,
248243 };
......@@ -254,11 +249,11 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
254249pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
255250 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
256251
257 const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
252 const sockfd = try os.posixSocket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
258253 errdefer os.close(sockfd);
259254
260 try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));
261 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
255 try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in));
256 try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
262257 try os.posixGetSockOptConnectError(sockfd);
263258
264259 return File.openHandle(sockfd);
std/fs/path.zig+17-20
......@@ -9,24 +9,21 @@ const fmt = std.fmt;
99const Allocator = mem.Allocator;
1010const os = std.os;
1111const math = std.math;
12const posix = os.posix;
1312const windows = os.windows;
1413const cstr = std.cstr;
1514
1615pub const sep_windows = '\\';
1716pub const sep_posix = '/';
18pub const sep = if (is_windows) sep_windows else sep_posix;
17pub const sep = if (windows.is_the_target) sep_windows else sep_posix;
1918
2019pub const sep_str = [1]u8{sep};
2120
2221pub const delimiter_windows = ';';
2322pub const delimiter_posix = ':';
24pub const delimiter = if (is_windows) delimiter_windows else delimiter_posix;
25
26const is_windows = builtin.os == builtin.Os.windows;
23pub const delimiter = if (windows.is_the_target) delimiter_windows else delimiter_posix;
2724
2825pub fn isSep(byte: u8) bool {
29 if (is_windows) {
26 if (windows.is_the_target) {
3027 return byte == '/' or byte == '\\';
3128 } else {
3229 return byte == '/';
......@@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
7673 return buf;
7774}
7875
79pub const join = if (is_windows) joinWindows else joinPosix;
76pub const join = if (windows.is_the_target) joinWindows else joinPosix;
8077
8178/// Naively combines a series of paths with the native path seperator.
8279/// Allocates memory for the result, which must be freed by the caller.
......@@ -133,7 +130,7 @@ test "join" {
133130}
134131
135132pub fn isAbsolute(path: []const u8) bool {
136 if (is_windows) {
133 if (windows.is_the_target) {
137134 return isAbsoluteWindows(path);
138135 } else {
139136 return isAbsolutePosix(path);
......@@ -312,7 +309,7 @@ test "windowsParsePath" {
312309}
313310
314311pub fn diskDesignator(path: []const u8) []const u8 {
315 if (is_windows) {
312 if (windows.is_the_target) {
316313 return diskDesignatorWindows(path);
317314 } else {
318315 return "";
......@@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
377374
378375/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
379376pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
380 if (is_windows) {
377 if (windows.is_the_target) {
381378 return resolveWindows(allocator, paths);
382379 } else {
383380 return resolvePosix(allocator, paths);
......@@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
394391/// Without performing actual syscalls, resolving `..` could be incorrect.
395392pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
396393 if (paths.len == 0) {
397 assert(is_windows); // resolveWindows called on non windows can't use getCwd
394 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
398395 return os.getCwdAlloc(allocator);
399396 }
400397
......@@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
489486 result_disk_designator = result[0..result_index];
490487 },
491488 WindowsPath.Kind.None => {
492 assert(is_windows); // resolveWindows called on non windows can't use getCwd
489 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
493490 const cwd = try os.getCwdAlloc(allocator);
494491 defer allocator.free(cwd);
495492 const parsed_cwd = windowsParsePath(cwd);
......@@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
504501 },
505502 }
506503 } else {
507 assert(is_windows); // resolveWindows called on non windows can't use getCwd
504 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
508505 // TODO call get cwd for the result_disk_designator instead of the global one
509506 const cwd = try os.getCwdAlloc(allocator);
510507 defer allocator.free(cwd);
......@@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
575572/// Without performing actual syscalls, resolving `..` could be incorrect.
576573pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
577574 if (paths.len == 0) {
578 assert(!is_windows); // resolvePosix called on windows can't use getCwd
575 assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
579576 return os.getCwdAlloc(allocator);
580577 }
581578
......@@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
597594 if (have_abs) {
598595 result = try allocator.alloc(u8, max_size);
599596 } else {
600 assert(!is_windows); // resolvePosix called on windows can't use getCwd
597 assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
601598 const cwd = try os.getCwdAlloc(allocator);
602599 defer allocator.free(cwd);
603600 result = try allocator.alloc(u8, max_size + cwd.len + 1);
......@@ -638,7 +635,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
638635
639636test "resolve" {
640637 const cwd = try os.getCwdAlloc(debug.global_allocator);
641 if (is_windows) {
638 if (windows.is_the_target) {
642639 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
643640 cwd[0] = asciiUpper(cwd[0]);
644641 }
......@@ -650,7 +647,7 @@ test "resolve" {
650647}
651648
652649test "resolveWindows" {
653 if (is_windows) {
650 if (windows.is_the_target) {
654651 const cwd = try os.getCwdAlloc(debug.global_allocator);
655652 const parsed_cwd = windowsParsePath(cwd);
656653 {
......@@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 {
716713/// If the path is a file in the current directory (no directory component)
717714/// then returns null
718715pub fn dirname(path: []const u8) ?[]const u8 {
719 if (is_windows) {
716 if (windows.is_the_target) {
720717 return dirnameWindows(path);
721718 } else {
722719 return dirnamePosix(path);
......@@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
848845}
849846
850847pub fn basename(path: []const u8) []const u8 {
851 if (is_windows) {
848 if (windows.is_the_target) {
852849 return basenameWindows(path);
853850 } else {
854851 return basenamePosix(path);
......@@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
964961/// string is returned.
965962/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
966963pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
967 if (is_windows) {
964 if (windows.is_the_target) {
968965 return relativeWindows(allocator, from, to);
969966 } else {
970967 return relativePosix(allocator, from, to);
std/heap.zig+156-168
......@@ -5,7 +5,6 @@ const testing = std.testing;
55const mem = std.mem;
66const os = std.os;
77const builtin = @import("builtin");
8const Os = builtin.Os;
98const c = std.c;
109const maxInt = std.math.maxInt;
1110
......@@ -51,201 +50,190 @@ pub const DirectAllocator = struct {
5150 if (n == 0)
5251 return (([*]u8)(undefined))[0..0];
5352
54 switch (builtin.os) {
55 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
56 const p = os.posix;
57 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
58 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
59 if (addr == p.MAP_FAILED) return error.OutOfMemory;
60 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
61
62 const aligned_addr = mem.alignForward(addr, alignment);
63
64 // Unmap the extra bytes that were only requested in order to guarantee
65 // that the range of memory we were provided had a proper alignment in
66 // it somewhere. The extra bytes could be at the beginning, or end, or both.
67 const unused_start_len = aligned_addr - addr;
68 if (unused_start_len != 0) {
69 const err = p.munmap(addr, unused_start_len);
70 assert(p.getErrno(err) == 0);
71 }
72 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
73 const unused_end_len = addr + alloc_size - aligned_end_addr;
74 if (unused_end_len != 0) {
75 const err = p.munmap(aligned_end_addr, unused_end_len);
76 assert(p.getErrno(err) == 0);
77 }
53 if (os.windows.is_the_target) {
54 const w = os.windows;
55
56 // Although officially it's at least aligned to page boundary,
57 // Windows is known to reserve pages on a 64K boundary. It's
58 // even more likely that the requested alignment is <= 64K than
59 // 4K, so we're just allocating blindly and hoping for the best.
60 // see https://devblogs.microsoft.com/oldnewthing/?p=42223
61 const addr = w.VirtualAlloc(
62 null,
63 n,
64 w.MEM_COMMIT | w.MEM_RESERVE,
65 w.PAGE_READWRITE,
66 ) catch return error.OutOfMemory;
67
68 // If the allocation is sufficiently aligned, use it.
69 if (@ptrToInt(addr) & (alignment - 1) == 0) {
70 return @ptrCast([*]u8, addr)[0..n];
71 }
7872
79 return @intToPtr([*]u8, aligned_addr)[0..n];
80 },
81 .windows => {
82 const w = os.windows;
83
84 // Although officially it's at least aligned to page boundary,
85 // Windows is known to reserve pages on a 64K boundary. It's
86 // even more likely that the requested alignment is <= 64K than
87 // 4K, so we're just allocating blindly and hoping for the best.
88 // see https://devblogs.microsoft.com/oldnewthing/?p=42223
89 const addr = w.VirtualAlloc(
73 // If it wasn't, actually do an explicitely aligned allocation.
74 w.VirtualFree(addr, 0, w.MEM_RELEASE);
75 const alloc_size = n + alignment;
76
77 const final_addr = while (true) {
78 // Reserve a range of memory large enough to find a sufficiently
79 // aligned address.
80 const reserved_addr = w.VirtualAlloc(
9081 null,
82 alloc_size,
83 w.MEM_RESERVE,
84 w.PAGE_NOACCESS,
85 ) catch return error.OutOfMemory;
86 const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);
87
88 // Release the reserved pages (not actually used).
89 w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE);
90
91 // At this point, it is possible that another thread has
92 // obtained some memory space that will cause the next
93 // VirtualAlloc call to fail. To handle this, we will retry
94 // until it succeeds.
95 return w.VirtualAlloc(
96 @intToPtr(*c_void, aligned_addr),
9197 n,
9298 w.MEM_COMMIT | w.MEM_RESERVE,
9399 w.PAGE_READWRITE,
94 ) orelse return error.OutOfMemory;
100 ) catch continue;
101 };
95102
96 // If the allocation is sufficiently aligned, use it.
97 if (@ptrToInt(addr) & (alignment - 1) == 0) {
98 return @ptrCast([*]u8, addr)[0..n];
99 }
103 return @ptrCast([*]u8, final_addr)[0..n];
104 }
100105
101 // If it wasn't, actually do an explicitely aligned allocation.
102 if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable;
103 const alloc_size = n + alignment;
104
105 const final_addr = while (true) {
106 // Reserve a range of memory large enough to find a sufficiently
107 // aligned address.
108 const reserved_addr = w.VirtualAlloc(
109 null,
110 alloc_size,
111 w.MEM_RESERVE,
112 w.PAGE_NOACCESS,
113 ) orelse return error.OutOfMemory;
114 const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);
115
116 // Release the reserved pages (not actually used).
117 if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable;
118
119 // At this point, it is possible that another thread has
120 // obtained some memory space that will cause the next
121 // VirtualAlloc call to fail. To handle this, we will retry
122 // until it succeeds.
123 if (w.VirtualAlloc(
124 @intToPtr(*c_void, aligned_addr),
125 n,
126 w.MEM_COMMIT | w.MEM_RESERVE,
127 w.PAGE_READWRITE,
128 )) |ptr| break ptr;
129 } else unreachable; // TODO else unreachable should not be necessary
130
131 return @ptrCast([*]u8, final_addr)[0..n];
132 },
133 else => @compileError("Unsupported OS"),
106 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
107 const addr = os.mmap(
108 null,
109 alloc_size,
110 os.PROT_READ | os.PROT_WRITE,
111 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
112 -1,
113 0,
114 ) catch return error.OutOfMemory;
115 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
116
117 const aligned_addr = mem.alignForward(addr, alignment);
118
119 // Unmap the extra bytes that were only requested in order to guarantee
120 // that the range of memory we were provided had a proper alignment in
121 // it somewhere. The extra bytes could be at the beginning, or end, or both.
122 const unused_start_len = aligned_addr - addr;
123 if (unused_start_len != 0) {
124 os.munmap(addr, unused_start_len);
125 }
126 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
127 const unused_end_len = addr + alloc_size - aligned_end_addr;
128 if (unused_end_len != 0) {
129 os.munmap(aligned_end_addr, unused_end_len);
134130 }
131
132 return @intToPtr([*]u8, aligned_addr)[0..n];
135133 }
136134
137135 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
138 switch (builtin.os) {
139 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
136 if (os.windows.is_the_target) {
137 const w = os.windows;
138 if (new_size == 0) {
139 // From the docs:
140 // "If the dwFreeType parameter is MEM_RELEASE, this parameter
141 // must be 0 (zero). The function frees the entire region that
142 // is reserved in the initial allocation call to VirtualAlloc."
143 // So we can only use MEM_RELEASE when actually releasing the
144 // whole allocation.
145 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
146 } else {
140147 const base_addr = @ptrToInt(old_mem.ptr);
141148 const old_addr_end = base_addr + old_mem.len;
142149 const new_addr_end = base_addr + new_size;
143150 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
144151 if (old_addr_end > new_addr_end_rounded) {
145 _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
146 }
147 return old_mem[0..new_size];
148 },
149 .windows => {
150 const w = os.windows;
151 if (new_size == 0) {
152 // From the docs:
153 // "If the dwFreeType parameter is MEM_RELEASE, this parameter
154 // must be 0 (zero). The function frees the entire region that
155 // is reserved in the initial allocation call to VirtualAlloc."
156 // So we can only use MEM_RELEASE when actually releasing the
157 // whole allocation.
158 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
159 } else {
160 const base_addr = @ptrToInt(old_mem.ptr);
161 const old_addr_end = base_addr + old_mem.len;
162 const new_addr_end = base_addr + new_size;
163 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
164 if (old_addr_end > new_addr_end_rounded) {
165 // For shrinking that is not releasing, we will only
166 // decommit the pages not needed anymore.
167 if (w.VirtualFree(
168 @intToPtr(*c_void, new_addr_end_rounded),
169 old_addr_end - new_addr_end_rounded,
170 w.MEM_DECOMMIT,
171 ) == 0) unreachable;
172 }
152 // For shrinking that is not releasing, we will only
153 // decommit the pages not needed anymore.
154 w.VirtualFree(
155 @intToPtr(*c_void, new_addr_end_rounded),
156 old_addr_end - new_addr_end_rounded,
157 w.MEM_DECOMMIT,
158 );
173159 }
174 return old_mem[0..new_size];
175 },
176 else => @compileError("Unsupported OS"),
160 }
161 return old_mem[0..new_size];
177162 }
163 const base_addr = @ptrToInt(old_mem.ptr);
164 const old_addr_end = base_addr + old_mem.len;
165 const new_addr_end = base_addr + new_size;
166 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
167 if (old_addr_end > new_addr_end_rounded) {
168 os.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
169 }
170 return old_mem[0..new_size];
178171 }
179172
180173 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
181 switch (builtin.os) {
182 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
183 if (new_size <= old_mem.len and new_align <= old_align) {
184 return shrink(allocator, old_mem, old_align, new_size, new_align);
185 }
186 const result = try alloc(allocator, new_size, new_align);
187 if (old_mem.len != 0) {
188 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
189 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
190 }
191 return result;
192 },
193 .windows => {
194 if (old_mem.len == 0) {
195 return alloc(allocator, new_size, new_align);
196 }
197
198 if (new_size <= old_mem.len and new_align <= old_align) {
199 return shrink(allocator, old_mem, old_align, new_size, new_align);
200 }
201
202 const w = os.windows;
203 const base_addr = @ptrToInt(old_mem.ptr);
174 if (os.windows.is_the_target) {
175 if (old_mem.len == 0) {
176 return alloc(allocator, new_size, new_align);
177 }
204178
205 if (new_align > old_align and base_addr & (new_align - 1) != 0) {
206 // Current allocation doesn't satisfy the new alignment.
207 // For now we'll do a new one no matter what, but maybe
208 // there is something smarter to do instead.
209 const result = try alloc(allocator, new_size, new_align);
210 assert(old_mem.len != 0);
211 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
212 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
179 if (new_size <= old_mem.len and new_align <= old_align) {
180 return shrink(allocator, old_mem, old_align, new_size, new_align);
181 }
213182
214 return result;
215 }
183 const w = os.windows;
184 const base_addr = @ptrToInt(old_mem.ptr);
216185
217 const old_addr_end = base_addr + old_mem.len;
218 const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);
219 const new_addr_end = base_addr + new_size;
220 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
221 if (new_addr_end_rounded == old_addr_end_rounded) {
222 // The reallocation fits in the already allocated pages.
223 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
224 }
225 assert(new_addr_end_rounded > old_addr_end_rounded);
186 if (new_align > old_align and base_addr & (new_align - 1) != 0) {
187 // Current allocation doesn't satisfy the new alignment.
188 // For now we'll do a new one no matter what, but maybe
189 // there is something smarter to do instead.
190 const result = try alloc(allocator, new_size, new_align);
191 assert(old_mem.len != 0);
192 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
193 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
226194
227 // We need to commit new pages.
228 const additional_size = new_addr_end - old_addr_end_rounded;
229 const realloc_addr = w.VirtualAlloc(
230 @intToPtr(*c_void, old_addr_end_rounded),
231 additional_size,
232 w.MEM_COMMIT | w.MEM_RESERVE,
233 w.PAGE_READWRITE,
234 ) orelse {
235 // Committing new pages at the end of the existing allocation
236 // failed, we need to try a new one.
237 const new_alloc_mem = try alloc(allocator, new_size, new_align);
238 @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
239 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
240
241 return new_alloc_mem;
242 };
195 return result;
196 }
243197
244 assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);
198 const old_addr_end = base_addr + old_mem.len;
199 const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);
200 const new_addr_end = base_addr + new_size;
201 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
202 if (new_addr_end_rounded == old_addr_end_rounded) {
203 // The reallocation fits in the already allocated pages.
245204 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
246 },
247 else => @compileError("Unsupported OS"),
205 }
206 assert(new_addr_end_rounded > old_addr_end_rounded);
207
208 // We need to commit new pages.
209 const additional_size = new_addr_end - old_addr_end_rounded;
210 const realloc_addr = w.kernel32.VirtualAlloc(
211 @intToPtr(*c_void, old_addr_end_rounded),
212 additional_size,
213 w.MEM_COMMIT | w.MEM_RESERVE,
214 w.PAGE_READWRITE,
215 ) orelse {
216 // Committing new pages at the end of the existing allocation
217 // failed, we need to try a new one.
218 const new_alloc_mem = try alloc(allocator, new_size, new_align);
219 @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
220 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
221
222 return new_alloc_mem;
223 };
224
225 assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);
226 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
227 }
228 if (new_size <= old_mem.len and new_align <= old_align) {
229 return shrink(allocator, old_mem, old_align, new_size, new_align);
248230 }
231 const result = try alloc(allocator, new_size, new_align);
232 if (old_mem.len != 0) {
233 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
234 os.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
235 }
236 return result;
249237 }
250238};
251239
std/mem.zig+3-3
......@@ -1466,17 +1466,17 @@ test "std.mem.alignForward" {
14661466pub fn getBaseAddress() usize {
14671467 switch (builtin.os) {
14681468 .linux => {
1469 const base = std.os.posix.getauxval(std.elf.AT_BASE);
1469 const base = std.os.system.getauxval(std.elf.AT_BASE);
14701470 if (base != 0) {
14711471 return base;
14721472 }
1473 const phdr = std.os.posix.getauxval(std.elf.AT_PHDR);
1473 const phdr = std.os.system.getauxval(std.elf.AT_PHDR);
14741474 return phdr - @sizeOf(std.elf.Ehdr);
14751475 },
14761476 .macosx, .freebsd, .netbsd => {
14771477 return @ptrToInt(&std.c._mh_execute_header);
14781478 },
1479 .windows => return @ptrToInt(windows.GetModuleHandleW(null)),
1479 .windows => return @ptrToInt(windows.kernel32.GetModuleHandleW(null)),
14801480 else => @compileError("Unsupported OS"),
14811481 }
14821482}
std/mutex.zig+2-2
......@@ -152,9 +152,9 @@ test "std.Mutex" {
152152 testing.expect(context.data == TestContext.incr_count);
153153 } else {
154154 const thread_count = 10;
155 var threads: [thread_count]*std.os.Thread = undefined;
155 var threads: [thread_count]*std.Thread = undefined;
156156 for (threads) |*t| {
157 t.* = try std.os.spawnThread(&context, worker);
157 t.* = try std.Thread.spawn(&context, worker);
158158 }
159159 for (threads) |t|
160160 t.wait();
std/net.zig+12-12
......@@ -2,8 +2,8 @@ const std = @import("std.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
44const net = @This();
5const posix = std.os.posix;
65const mem = std.mem;
6const os = std.os;
77
88pub const TmpWinAddr = struct {
99 family: u8,
......@@ -12,7 +12,7 @@ pub const TmpWinAddr = struct {
1212
1313pub const OsAddress = switch (builtin.os) {
1414 builtin.Os.windows => TmpWinAddr,
15 else => posix.sockaddr,
15 else => os.sockaddr,
1616};
1717
1818pub const Address = struct {
......@@ -20,9 +20,9 @@ pub const Address = struct {
2020
2121 pub fn initIp4(ip4: u32, _port: u16) Address {
2222 return Address{
23 .os_addr = posix.sockaddr{
24 .in = posix.sockaddr_in{
25 .family = posix.AF_INET,
23 .os_addr = os.sockaddr{
24 .in = os.sockaddr_in{
25 .family = os.AF_INET,
2626 .port = mem.nativeToBig(u16, _port),
2727 .addr = ip4,
2828 .zero = []u8{0} ** 8,
......@@ -33,10 +33,10 @@ pub const Address = struct {
3333
3434 pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address {
3535 return Address{
36 .family = posix.AF_INET6,
37 .os_addr = posix.sockaddr{
38 .in6 = posix.sockaddr_in6{
39 .family = posix.AF_INET6,
36 .family = os.AF_INET6,
37 .os_addr = os.sockaddr{
38 .in6 = os.sockaddr_in6{
39 .family = os.AF_INET6,
4040 .port = mem.nativeToBig(u16, _port),
4141 .flowinfo = 0,
4242 .addr = ip6.addr,
......@@ -50,18 +50,18 @@ pub const Address = struct {
5050 return mem.bigToNative(u16, self.os_addr.in.port);
5151 }
5252
53 pub fn initPosix(addr: posix.sockaddr) Address {
53 pub fn initPosix(addr: os.sockaddr) Address {
5454 return Address{ .os_addr = addr };
5555 }
5656
5757 pub fn format(self: *const Address, out_stream: var) !void {
5858 switch (self.os_addr.in.family) {
59 posix.AF_INET => {
59 os.AF_INET => {
6060 const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
6161 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
6262 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
6363 },
64 posix.AF_INET6 => {
64 os.AF_INET6 => {
6565 const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
6666 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
6767 },
std/os.zig+19-16
......@@ -164,7 +164,7 @@ pub fn raise(sig: u8) RaiseError!void {
164164 }
165165
166166 if (windows.is_the_target) {
167 @compileError("TODO implement std.posix.raise for Windows");
167 @compileError("TODO implement std.os.raise for Windows");
168168 }
169169
170170 var set: system.sigset_t = undefined;
......@@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 {
690690 return getenv(mem.toSliceConst(u8, key));
691691}
692692
693/// See std.elf for the constants.
694pub fn getauxval(index: usize) usize {
695 if (builtin.link_libc) {
696 return usize(system.getauxval(index));
697 } else if (linux.elf_aux_maybe) |auxv| {
698 var i: usize = 0;
699 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
700 if (auxv[i].a_type == index)
701 return auxv[i].a_un.a_val;
702 }
703 }
704 return 0;
705}
706
707693pub const GetCwdError = error{
708694 NameTooLong,
709695 CurrentWorkingDirectoryUnlinked,
......@@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool {
11981184 return windows.kernel32.GetConsoleMode(handle, &out) != 0;
11991185 }
12001186 if (wasi.is_the_target) {
1201 @compileError("TODO implement std.os.posix.isatty for WASI");
1187 @compileError("TODO implement std.os.isatty for WASI");
12021188 }
12031189 if (linux.is_the_target) {
12041190 var wsz: system.winsize = undefined;
......@@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
23652351 }
23662352}
23672353
2354pub const SchedGetAffinityError = error{
2355 PermissionDenied,
2356 Unexpected,
2357};
2358
2359pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
2360 var set: cpu_set_t = undefined;
2361 switch (errno(system.sched_getaffinity(pid, &set))) {
2362 0 => return set,
2363 EFAULT => unreachable,
2364 EINVAL => unreachable,
2365 ESRCH => unreachable,
2366 EPERM => return error.PermissionDenied,
2367 else => |err| return unexpectedErrno(err),
2368 }
2369}
2370
23682371/// Used to convert a slice to a null terminated slice on the stack.
23692372/// TODO https://github.com/ziglang/zig/issues/287
23702373pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
std/os/bits/linux.zig+25
......@@ -1,3 +1,5 @@
1const std = @import("../../std.zig");
2
13pub use @import("linux/errno.zig");
24pub use switch (builtin.arch) {
35 .x86_64 => @import("linux/x86_64.zig"),
......@@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct {
907909 __size: [56]u8,
908910 __align: c_long,
909911};
912
913pub const CPU_SETSIZE = 128;
914pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
915pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8));
916
917pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
918 var sum: cpu_count_t = 0;
919 for (set) |x| {
920 sum += @popCount(usize, x);
921 }
922 return sum;
923}
924
925// TODO port these over
926//#define CPU_SET(i, set) CPU_SET_S(i,sizeof(cpu_set_t),set)
927//#define CPU_CLR(i, set) CPU_CLR_S(i,sizeof(cpu_set_t),set)
928//#define CPU_ISSET(i, set) CPU_ISSET_S(i,sizeof(cpu_set_t),set)
929//#define CPU_AND(d,s1,s2) CPU_AND_S(sizeof(cpu_set_t),d,s1,s2)
930//#define CPU_OR(d,s1,s2) CPU_OR_S(sizeof(cpu_set_t),d,s1,s2)
931//#define CPU_XOR(d,s1,s2) CPU_XOR_S(sizeof(cpu_set_t),d,s1,s2)
932//#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set)
933//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
934//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
std/os/linux.zig+872-2
......@@ -1,8 +1,878 @@
1// This file provides the system interface functions for Linux matching those
2// that are provided by libc, whether or not libc is linked. The following
3// abstractions are made:
4// * Work around kernel bugs and limitations. For example, see sendmmsg.
5// * Implement all the syscalls in the same way that libc functions will
6// provide `rename` when only the `renameat` syscall exists.
7// * Does not support POSIX thread cancellation.
18const std = @import("../std.zig");
29const builtin = @import("builtin");
10const assert = std.debug.assert;
11const maxInt = std.math.maxInt;
12const elf = std.elf;
13const vdso = @import("linux/vdso.zig");
14const dl = @import("../dynamic_library.zig");
15
316pub const is_the_target = builtin.os == .linux;
4pub const sys = @import("linux/sys.zig");
5pub use if (builtin.link_libc) std.c else sys;
17pub use switch (builtin.arch) {
18 .x86_64 => @import("linux/x86_64.zig"),
19 .aarch64 => @import("linux/arm64.zig"),
20 else => struct {},
21};
22pub use @import("bits.zig");
23
24/// Set by startup code, used by `getauxval`.
25pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
26
27/// See `std.elf` for the constants.
28pub fn getauxval(index: usize) usize {
29 const auxv = elf_aux_maybe orelse return 0;
30 var i: usize = 0;
31 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
32 if (auxv[i].a_type == index)
33 return auxv[i].a_un.a_val;
34 }
35 return 0;
36}
37
38/// Get the errno from a syscall return value, or 0 for no error.
39pub fn getErrno(r: usize) u12 {
40 const signed_r = @bitCast(isize, r);
41 return if (signed_r > -4096 and signed_r < 0) @intCast(u12, -signed_r) else 0;
42}
43
44pub fn dup2(old: i32, new: i32) usize {
45 if (@hasDecl(@This(), "SYS_dup2")) {
46 return syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
47 } else {
48 if (old == new) {
49 if (std.debug.runtime_safety) {
50 const rc = syscall2(SYS_fcntl, @bitCast(usize, isize(old)), F_GETFD);
51 if (@bitCast(isize, rc) < 0) return rc;
52 }
53 return @intCast(usize, old);
54 } else {
55 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), 0);
56 }
57 }
58}
59
60pub fn dup3(old: i32, new: i32, flags: u32) usize {
61 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
62}
63
64// TODO https://github.com/ziglang/zig/issues/265
65pub fn chdir(path: [*]const u8) usize {
66 return syscall1(SYS_chdir, @ptrToInt(path));
67}
68
69// TODO https://github.com/ziglang/zig/issues/265
70pub fn chroot(path: [*]const u8) usize {
71 return syscall1(SYS_chroot, @ptrToInt(path));
72}
73
74// TODO https://github.com/ziglang/zig/issues/265
75pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
76 return syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
77}
78
79pub fn fork() usize {
80 if (@hasDecl(@This(), "SYS_fork")) {
81 return syscall0(SYS_fork);
82 } else {
83 return syscall2(SYS_clone, SIGCHLD, 0);
84 }
85}
86
87/// This must be inline, and inline call the syscall function, because if the
88/// child does a return it will clobber the parent's stack.
89/// It is advised to avoid this function and use clone instead, because
90/// the compiler is not aware of how vfork affects control flow and you may
91/// see different results in optimized builds.
92pub inline fn vfork() usize {
93 return @inlineCall(syscall0, SYS_vfork);
94}
95
96pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize {
97 return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout));
98}
99
100pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize {
101 return syscall3(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val));
102}
103
104pub fn getcwd(buf: [*]u8, size: usize) usize {
105 return syscall2(SYS_getcwd, @ptrToInt(buf), size);
106}
107
108pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
109 return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
110}
111
112pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
113 return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
114}
115
116pub fn inotify_init1(flags: u32) usize {
117 return syscall1(SYS_inotify_init1, flags);
118}
119
120pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
121 return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
122}
123
124pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
125 return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
126}
127
128// TODO https://github.com/ziglang/zig/issues/265
129pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
130 if (@hasDecl(@This(), "SYS_readlink")) {
131 return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
132 } else {
133 return syscall4(SYS_readlinkat, AT_FDCWD, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
134 }
135}
136
137// TODO https://github.com/ziglang/zig/issues/265
138pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
139 return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
140}
141
142// TODO https://github.com/ziglang/zig/issues/265
143pub fn mkdir(path: [*]const u8, mode: u32) usize {
144 if (@hasDecl(@This(), "SYS_mkdir")) {
145 return syscall2(SYS_mkdir, @ptrToInt(path), mode);
146 } else {
147 return syscall3(SYS_mkdirat, AT_FDCWD, @ptrToInt(path), mode);
148 }
149}
150
151// TODO https://github.com/ziglang/zig/issues/265
152pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
153 return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
154}
155
156// TODO https://github.com/ziglang/zig/issues/265
157pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: u32, data: usize) usize {
158 return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
159}
160
161// TODO https://github.com/ziglang/zig/issues/265
162pub fn umount(special: [*]const u8) usize {
163 return syscall2(SYS_umount2, @ptrToInt(special), 0);
164}
165
166// TODO https://github.com/ziglang/zig/issues/265
167pub fn umount2(special: [*]const u8, flags: u32) usize {
168 return syscall2(SYS_umount2, @ptrToInt(special), flags);
169}
170
171pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
172 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
173}
174
175pub fn mprotect(address: usize, length: usize, protection: usize) usize {
176 return syscall3(SYS_mprotect, address, length, protection);
177}
178
179pub fn munmap(address: usize, length: usize) usize {
180 return syscall2(SYS_munmap, address, length);
181}
182
183pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
184 return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
185}
186
187pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
188 return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
189}
190
191pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
192 return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
193}
194
195pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
196 return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
197}
198
199pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
200 return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
201}
202
203// TODO https://github.com/ziglang/zig/issues/265
204pub fn rmdir(path: [*]const u8) usize {
205 if (@hasDecl(@This(), "SYS_rmdir")) {
206 return syscall1(SYS_rmdir, @ptrToInt(path));
207 } else {
208 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), AT_REMOVEDIR);
209 }
210}
211
212// TODO https://github.com/ziglang/zig/issues/265
213pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
214 if (@hasDecl(@This(), "SYS_symlink")) {
215 return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
216 } else {
217 return syscall3(SYS_symlinkat, @ptrToInt(existing), AT_FDCWD, @ptrToInt(new));
218 }
219}
220
221// TODO https://github.com/ziglang/zig/issues/265
222pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
223 return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
224}
225
226// TODO https://github.com/ziglang/zig/issues/265
227pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
228 return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
229}
230
231// TODO https://github.com/ziglang/zig/issues/265
232pub fn access(path: [*]const u8, mode: u32) usize {
233 return syscall2(SYS_access, @ptrToInt(path), mode);
234}
235
236// TODO https://github.com/ziglang/zig/issues/265
237pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
238 return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
239}
240
241pub fn pipe(fd: *[2]i32) usize {
242 if (@hasDecl(@This(), "SYS_pipe")) {
243 return syscall1(SYS_pipe, @ptrToInt(fd));
244 } else {
245 return syscall2(SYS_pipe2, @ptrToInt(fd), 0);
246 }
247}
248
249pub fn pipe2(fd: *[2]i32, flags: u32) usize {
250 return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
251}
252
253pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
254 return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
255}
256
257pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
258 return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
259}
260
261// TODO https://github.com/ziglang/zig/issues/265
262pub fn rename(old: [*]const u8, new: [*]const u8) usize {
263 if (@hasDecl(@This(), "SYS_rename")) {
264 return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
265 } else if (@hasDecl(@This(), "SYS_renameat")) {
266 return syscall4(SYS_renameat, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new));
267 } else {
268 return syscall5(SYS_renameat2, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new), 0);
269 }
270}
271
272pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
273 if (@hasDecl(@This(), "SYS_renameat")) {
274 return syscall4(
275 SYS_renameat,
276 @bitCast(usize, isize(oldfd)),
277 @ptrToInt(old),
278 @bitCast(usize, isize(newfd)),
279 @ptrToInt(new),
280 );
281 } else {
282 return syscall5(
283 SYS_renameat2,
284 @bitCast(usize, isize(oldfd)),
285 @ptrToInt(old),
286 @bitCast(usize, isize(newfd)),
287 @ptrToInt(new),
288 0,
289 );
290 }
291}
292
293// TODO https://github.com/ziglang/zig/issues/265
294pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
295 return syscall5(
296 SYS_renameat2,
297 @bitCast(usize, isize(oldfd)),
298 @ptrToInt(oldpath),
299 @bitCast(usize, isize(newfd)),
300 @ptrToInt(newpath),
301 flags,
302 );
303}
304
305// TODO https://github.com/ziglang/zig/issues/265
306pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
307 return syscall3(SYS_open, @ptrToInt(path), flags, perm);
308}
309
310// TODO https://github.com/ziglang/zig/issues/265
311pub fn create(path: [*]const u8, perm: usize) usize {
312 return syscall2(SYS_creat, @ptrToInt(path), perm);
313}
314
315// TODO https://github.com/ziglang/zig/issues/265
316pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
317 // dirfd could be negative, for example AT_FDCWD is -100
318 return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
319}
320
321/// See also `clone` (from the arch-specific include)
322pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid: *i32, newtls: usize) usize {
323 return syscall5(SYS_clone, flags, child_stack_ptr, @ptrToInt(parent_tid), @ptrToInt(child_tid), newtls);
324}
325
326/// See also `clone` (from the arch-specific include)
327pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
328 return syscall2(SYS_clone, flags, child_stack_ptr);
329}
330
331pub fn close(fd: i32) usize {
332 return syscall1(SYS_close, @bitCast(usize, isize(fd)));
333}
334
335/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
336pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
337 return syscall5(
338 SYS__llseek,
339 @bitCast(usize, isize(fd)),
340 @truncate(usize, offset >> 32),
341 @truncate(usize, offset),
342 @ptrToInt(result),
343 whence,
344 );
345}
346
347/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
348pub fn lseek(fd: i32, offset: i64, whence: usize) usize {
349 return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence);
350}
351
352pub fn exit(status: i32) noreturn {
353 _ = syscall1(SYS_exit, @bitCast(usize, isize(status)));
354 unreachable;
355}
356
357pub fn exit_group(status: i32) noreturn {
358 _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status)));
359 unreachable;
360}
361
362pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
363 return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags);
364}
365
366pub fn kill(pid: i32, sig: i32) usize {
367 return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
368}
369
370// TODO https://github.com/ziglang/zig/issues/265
371pub fn unlink(path: [*]const u8) usize {
372 if (@hasDecl(@This(), "SYS_unlink")) {
373 return syscall1(SYS_unlink, @ptrToInt(path));
374 } else {
375 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), 0);
376 }
377}
378
379// TODO https://github.com/ziglang/zig/issues/265
380pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
381 return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
382}
383
384pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
385 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
386}
387
388var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
389
390// We must follow the C calling convention when we call into the VDSO
391const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize;
392
393pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
394 if (VDSO_CGT_SYM.len != 0) {
395 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
396 if (ptr) |fn_ptr| {
397 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
398 const rc = f(clk_id, tp);
399 switch (rc) {
400 0, @bitCast(usize, isize(-EINVAL)) => return rc,
401 else => {},
402 }
403 }
404 }
405 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
406}
407
408extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
409 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
410 // Note that we may not have a VDSO at all, update the stub address anyway
411 // so that clock_gettime will fall back on the good old (and slow) syscall
412 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
413 // Call into the VDSO if available
414 if (ptr) |fn_ptr| {
415 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
416 return f(clk, ts);
417 }
418 return @bitCast(usize, isize(-ENOSYS));
419}
420
421pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
422 return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
423}
424
425pub fn clock_settime(clk_id: i32, tp: *const timespec) usize {
426 return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
427}
428
429pub fn gettimeofday(tv: *timeval, tz: *timezone) usize {
430 return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz));
431}
432
433pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize {
434 return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz));
435}
436
437pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
438 return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
439}
440
441pub fn setuid(uid: u32) usize {
442 return syscall1(SYS_setuid, uid);
443}
444
445pub fn setgid(gid: u32) usize {
446 return syscall1(SYS_setgid, gid);
447}
448
449pub fn setreuid(ruid: u32, euid: u32) usize {
450 return syscall2(SYS_setreuid, ruid, euid);
451}
452
453pub fn setregid(rgid: u32, egid: u32) usize {
454 return syscall2(SYS_setregid, rgid, egid);
455}
456
457pub fn getuid() u32 {
458 return u32(syscall0(SYS_getuid));
459}
460
461pub fn getgid() u32 {
462 return u32(syscall0(SYS_getgid));
463}
464
465pub fn geteuid() u32 {
466 return u32(syscall0(SYS_geteuid));
467}
468
469pub fn getegid() u32 {
470 return u32(syscall0(SYS_getegid));
471}
472
473pub fn seteuid(euid: u32) usize {
474 return syscall1(SYS_seteuid, euid);
475}
476
477pub fn setegid(egid: u32) usize {
478 return syscall1(SYS_setegid, egid);
479}
480
481pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
482 return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
483}
484
485pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
486 return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
487}
488
489pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
490 return syscall3(SYS_setresuid, ruid, euid, suid);
491}
492
493pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
494 return syscall3(SYS_setresgid, rgid, egid, sgid);
495}
496
497pub fn getgroups(size: usize, list: *u32) usize {
498 return syscall2(SYS_getgroups, size, @ptrToInt(list));
499}
500
501pub fn setgroups(size: usize, list: *const u32) usize {
502 return syscall2(SYS_setgroups, size, @ptrToInt(list));
503}
504
505pub fn getpid() i32 {
506 return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid)));
507}
508
509pub fn gettid() i32 {
510 return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid)));
511}
512
513pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
514 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
515}
516
517pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
518 assert(sig >= 1);
519 assert(sig != SIGKILL);
520 assert(sig != SIGSTOP);
521 var ksa = k_sigaction{
522 .handler = act.handler,
523 .flags = act.flags | SA_RESTORER,
524 .mask = undefined,
525 .restorer = @ptrCast(extern fn () void, restore_rt),
526 };
527 var ksa_old: k_sigaction = undefined;
528 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
529 const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
530 const err = getErrno(result);
531 if (err != 0) {
532 return result;
533 }
534 if (oact) |old| {
535 old.handler = ksa_old.handler;
536 old.flags = @truncate(u32, ksa_old.flags);
537 @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
538 }
539 return 0;
540}
541
542fn blockAllSignals(set: *sigset_t) void {
543 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8);
544}
545
546fn blockAppSignals(set: *sigset_t) void {
547 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8);
548}
549
550fn restoreSignals(set: *sigset_t) void {
551 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8);
552}
553
554pub fn sigaddset(set: *sigset_t, sig: u6) void {
555 const s = sig - 1;
556 (set.*)[@intCast(usize, s) / usize.bit_count] |= @intCast(usize, 1) << (s & (usize.bit_count - 1));
557}
558
559pub fn sigismember(set: *const sigset_t, sig: u6) bool {
560 const s = sig - 1;
561 return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;
562}
563
564pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
565 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
566}
567
568pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
569 return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
570}
571
572pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
573 return syscall3(SYS_socket, domain, socket_type, protocol);
574}
575
576pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
577 return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
578}
579
580pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
581 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
582}
583
584pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
585 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
586}
587
588pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
589 if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
590 // workaround kernel brokenness:
591 // if adding up all iov_len overflows a i32 then split into multiple calls
592 // see https://www.openwall.com/lists/musl/2014/06/07/5
593 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
594 var next_unsent: usize = 0;
595 for (msgvec[0..kvlen]) |*msg, i| {
596 var size: i32 = 0;
597 const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
598 for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
599 if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
600 // batch-send all messages up to the current message
601 if (next_unsent < i) {
602 const batch_size = i - next_unsent;
603 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
604 if (getErrno(r) != 0) return next_unsent;
605 if (r < batch_size) return next_unsent + r;
606 }
607 // send current message as own packet
608 const r = sendmsg(fd, &msg.msg_hdr, flags);
609 if (getErrno(r) != 0) return r;
610 // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
611 msg.msg_len = @intCast(u32, r);
612 next_unsent = i + 1;
613 break;
614 }
615 }
616 }
617 if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
618 const batch_size = kvlen - next_unsent;
619 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
620 if (getErrno(r) != 0) return r;
621 return next_unsent + r;
622 }
623 return kvlen;
624 }
625 return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
626}
627
628pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
629 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
630}
631
632pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
633 return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
634}
635
636pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
637 return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
638}
639
640pub fn shutdown(fd: i32, how: i32) usize {
641 return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
642}
643
644pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
645 return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
646}
647
648pub fn listen(fd: i32, backlog: u32) usize {
649 return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
650}
651
652pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
653 return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
654}
655
656pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
657 return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
658}
659
660pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
661 return accept4(fd, addr, len, 0);
662}
663
664pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
665 return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
666}
667
668pub fn fstat(fd: i32, stat_buf: *Stat) usize {
669 return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
670}
671
672// TODO https://github.com/ziglang/zig/issues/265
673pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
674 return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
675}
676
677// TODO https://github.com/ziglang/zig/issues/265
678pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
679 return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
680}
681
682// TODO https://github.com/ziglang/zig/issues/265
683pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
684 return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
685}
686
687// TODO https://github.com/ziglang/zig/issues/265
688pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
689 return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
690}
691
692// TODO https://github.com/ziglang/zig/issues/265
693pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
694 return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size);
695}
696
697pub fn flistxattr(fd: usize, list: [*]u8, size: usize) usize {
698 return syscall3(SYS_flistxattr, fd, @ptrToInt(list), size);
699}
700
701// TODO https://github.com/ziglang/zig/issues/265
702pub fn getxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
703 return syscall4(SYS_getxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
704}
705
706// TODO https://github.com/ziglang/zig/issues/265
707pub fn lgetxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
708 return syscall4(SYS_lgetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
709}
710
711// TODO https://github.com/ziglang/zig/issues/265
712pub fn fgetxattr(fd: usize, name: [*]const u8, value: [*]u8, size: usize) usize {
713 return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
714}
715
716// TODO https://github.com/ziglang/zig/issues/265
717pub fn setxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
718 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
719}
720
721// TODO https://github.com/ziglang/zig/issues/265
722pub fn lsetxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
723 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
724}
725
726// TODO https://github.com/ziglang/zig/issues/265
727pub fn fsetxattr(fd: usize, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
728 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
729}
730
731// TODO https://github.com/ziglang/zig/issues/265
732pub fn removexattr(path: [*]const u8, name: [*]const u8) usize {
733 return syscall2(SYS_removexattr, @ptrToInt(path), @ptrToInt(name));
734}
735
736// TODO https://github.com/ziglang/zig/issues/265
737pub fn lremovexattr(path: [*]const u8, name: [*]const u8) usize {
738 return syscall2(SYS_lremovexattr, @ptrToInt(path), @ptrToInt(name));
739}
740
741// TODO https://github.com/ziglang/zig/issues/265
742pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
743 return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
744}
745
746pub fn sched_getaffinity(pid: i32, size: usize, set: *cpu_set_t) usize {
747 const rc = syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), size, @ptrToInt(set));
748 if (@bitCast(isize, rc) < 0) return rc;
749 if (rc < size) @memset(@ptrCast([*]u8, set) + rc, 0, size - rc);
750 return 0;
751}
752
753pub fn epoll_create() usize {
754 return epoll_create1(0);
755}
756
757pub fn epoll_create1(flags: usize) usize {
758 return syscall1(SYS_epoll_create1, flags);
759}
760
761pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
762 return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
763}
764
765pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
766 return syscall4(
767 SYS_epoll_wait,
768 @bitCast(usize, isize(epoll_fd)),
769 @ptrToInt(events),
770 maxevents,
771 @bitCast(usize, isize(timeout)),
772 );
773}
774
775pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
776 return syscall6(
777 SYS_epoll_pwait,
778 @bitCast(usize, isize(epoll_fd)),
779 @ptrToInt(events),
780 @intCast(usize, maxevents),
781 @bitCast(usize, isize(timeout)),
782 @ptrToInt(sigmask),
783 @sizeOf(sigset_t),
784 );
785}
786
787pub fn eventfd(count: u32, flags: u32) usize {
788 return syscall2(SYS_eventfd2, count, flags);
789}
790
791pub fn timerfd_create(clockid: i32, flags: u32) usize {
792 return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
793}
794
795pub const itimerspec = extern struct {
796 it_interval: timespec,
797 it_value: timespec,
798};
799
800pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
801 return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
802}
803
804pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
805 return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
806}
807
808pub fn unshare(flags: usize) usize {
809 return syscall1(SYS_unshare, flags);
810}
811
812pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
813 return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap));
814}
815
816pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
817 return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
818}
819
820// XXX: This should be weak
821extern const __ehdr_start: elf.Ehdr = undefined;
822
823pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
824 if (builtin.link_libc) {
825 return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
826 }
827
828 const elf_base = @ptrToInt(&__ehdr_start);
829 const n_phdr = __ehdr_start.e_phnum;
830 const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
831
832 var it = dl.linkmap_iterator(phdrs) catch return 0;
833
834 // The executable has no dynamic link segment, create a single entry for
835 // the whole ELF image
836 if (it.end()) {
837 var info = dl_phdr_info{
838 .dlpi_addr = elf_base,
839 .dlpi_name = c"/proc/self/exe",
840 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
841 .dlpi_phnum = __ehdr_start.e_phnum,
842 };
843
844 return callback(&info, @sizeOf(dl_phdr_info), data);
845 }
846
847 // Last return value from the callback function
848 var last_r: isize = 0;
849 while (it.next()) |entry| {
850 var dlpi_phdr: usize = undefined;
851 var dlpi_phnum: u16 = undefined;
852
853 if (entry.l_addr != 0) {
854 const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
855 dlpi_phdr = entry.l_addr + elf_header.e_phoff;
856 dlpi_phnum = elf_header.e_phnum;
857 } else {
858 // This is the running ELF image
859 dlpi_phdr = elf_base + __ehdr_start.e_phoff;
860 dlpi_phnum = __ehdr_start.e_phnum;
861 }
862
863 var info = dl_phdr_info{
864 .dlpi_addr = entry.l_addr,
865 .dlpi_name = entry.l_name,
866 .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
867 .dlpi_phnum = dlpi_phnum,
868 };
869
870 last_r = callback(&info, @sizeOf(dl_phdr_info), data);
871 if (last_r != 0) break;
872 }
873
874 return last_r;
875}
6876
7877test "" {
8878 if (is_the_target) {
std/os/linux/sys.zig deleted-859
......@@ -1,859 +0,0 @@
1// This file provides the system interface functions for Linux matching those
2// that are provided by libc, whether or not libc is linked. The following
3// abstractions are made:
4// * Work around kernel bugs and limitations. For example, see sendmmsg.
5// * Implement all the syscalls in the same way that libc functions will
6// provide `rename` when only the `renameat` syscall exists.
7// * Does not support POSIX thread cancellation.
8const std = @import("../../std.zig");
9const builtin = @import("builtin");
10const assert = std.debug.assert;
11const maxInt = std.math.maxInt;
12const elf = std.elf;
13const vdso = @import("vdso.zig");
14const dl = @import("../../dynamic_library.zig");
15pub use switch (builtin.arch) {
16 .x86_64 => @import("x86_64.zig"),
17 .aarch64 => @import("arm64.zig"),
18 else => struct {},
19};
20pub use @import("../bits.zig");
21
22/// See `std.os.posix.getauxval`.
23pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
24
25/// Get the errno from a syscall return value, or 0 for no error.
26pub fn getErrno(r: usize) u12 {
27 const signed_r = @bitCast(isize, r);
28 return if (signed_r > -4096 and signed_r < 0) @intCast(u12, -signed_r) else 0;
29}
30
31pub fn dup2(old: i32, new: i32) usize {
32 if (@hasDecl(@This(), "SYS_dup2")) {
33 return syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
34 } else {
35 if (old == new) {
36 if (std.debug.runtime_safety) {
37 const rc = syscall2(SYS_fcntl, @bitCast(usize, isize(old)), F_GETFD);
38 if (@bitCast(isize, rc) < 0) return rc;
39 }
40 return @intCast(usize, old);
41 } else {
42 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), 0);
43 }
44 }
45}
46
47pub fn dup3(old: i32, new: i32, flags: u32) usize {
48 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
49}
50
51// TODO https://github.com/ziglang/zig/issues/265
52pub fn chdir(path: [*]const u8) usize {
53 return syscall1(SYS_chdir, @ptrToInt(path));
54}
55
56// TODO https://github.com/ziglang/zig/issues/265
57pub fn chroot(path: [*]const u8) usize {
58 return syscall1(SYS_chroot, @ptrToInt(path));
59}
60
61// TODO https://github.com/ziglang/zig/issues/265
62pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
63 return syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
64}
65
66pub fn fork() usize {
67 if (@hasDecl(@This(), "SYS_fork")) {
68 return syscall0(SYS_fork);
69 } else {
70 return syscall2(SYS_clone, SIGCHLD, 0);
71 }
72}
73
74/// This must be inline, and inline call the syscall function, because if the
75/// child does a return it will clobber the parent's stack.
76/// It is advised to avoid this function and use clone instead, because
77/// the compiler is not aware of how vfork affects control flow and you may
78/// see different results in optimized builds.
79pub inline fn vfork() usize {
80 return @inlineCall(syscall0, SYS_vfork);
81}
82
83pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize {
84 return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout));
85}
86
87pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize {
88 return syscall3(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val));
89}
90
91pub fn getcwd(buf: [*]u8, size: usize) usize {
92 return syscall2(SYS_getcwd, @ptrToInt(buf), size);
93}
94
95pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
96 return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
97}
98
99pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
100 return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
101}
102
103pub fn inotify_init1(flags: u32) usize {
104 return syscall1(SYS_inotify_init1, flags);
105}
106
107pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
108 return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
109}
110
111pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
112 return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
113}
114
115// TODO https://github.com/ziglang/zig/issues/265
116pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
117 if (@hasDecl(@This(), "SYS_readlink")) {
118 return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
119 } else {
120 return syscall4(SYS_readlinkat, AT_FDCWD, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
121 }
122}
123
124// TODO https://github.com/ziglang/zig/issues/265
125pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
126 return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
127}
128
129// TODO https://github.com/ziglang/zig/issues/265
130pub fn mkdir(path: [*]const u8, mode: u32) usize {
131 if (@hasDecl(@This(), "SYS_mkdir")) {
132 return syscall2(SYS_mkdir, @ptrToInt(path), mode);
133 } else {
134 return syscall3(SYS_mkdirat, AT_FDCWD, @ptrToInt(path), mode);
135 }
136}
137
138// TODO https://github.com/ziglang/zig/issues/265
139pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
140 return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
141}
142
143// TODO https://github.com/ziglang/zig/issues/265
144pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: u32, data: usize) usize {
145 return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
146}
147
148// TODO https://github.com/ziglang/zig/issues/265
149pub fn umount(special: [*]const u8) usize {
150 return syscall2(SYS_umount2, @ptrToInt(special), 0);
151}
152
153// TODO https://github.com/ziglang/zig/issues/265
154pub fn umount2(special: [*]const u8, flags: u32) usize {
155 return syscall2(SYS_umount2, @ptrToInt(special), flags);
156}
157
158pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
159 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
160}
161
162pub fn mprotect(address: usize, length: usize, protection: usize) usize {
163 return syscall3(SYS_mprotect, address, length, protection);
164}
165
166pub fn munmap(address: usize, length: usize) usize {
167 return syscall2(SYS_munmap, address, length);
168}
169
170pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
171 return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
172}
173
174pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
175 return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
176}
177
178pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
179 return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
180}
181
182pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
183 return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
184}
185
186pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
187 return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
188}
189
190// TODO https://github.com/ziglang/zig/issues/265
191pub fn rmdir(path: [*]const u8) usize {
192 if (@hasDecl(@This(), "SYS_rmdir")) {
193 return syscall1(SYS_rmdir, @ptrToInt(path));
194 } else {
195 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), AT_REMOVEDIR);
196 }
197}
198
199// TODO https://github.com/ziglang/zig/issues/265
200pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
201 if (@hasDecl(@This(), "SYS_symlink")) {
202 return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
203 } else {
204 return syscall3(SYS_symlinkat, @ptrToInt(existing), AT_FDCWD, @ptrToInt(new));
205 }
206}
207
208// TODO https://github.com/ziglang/zig/issues/265
209pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
210 return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
211}
212
213// TODO https://github.com/ziglang/zig/issues/265
214pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
215 return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
216}
217
218// TODO https://github.com/ziglang/zig/issues/265
219pub fn access(path: [*]const u8, mode: u32) usize {
220 return syscall2(SYS_access, @ptrToInt(path), mode);
221}
222
223// TODO https://github.com/ziglang/zig/issues/265
224pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
225 return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
226}
227
228pub fn pipe(fd: *[2]i32) usize {
229 if (@hasDecl(@This(), "SYS_pipe")) {
230 return syscall1(SYS_pipe, @ptrToInt(fd));
231 } else {
232 return syscall2(SYS_pipe2, @ptrToInt(fd), 0);
233 }
234}
235
236pub fn pipe2(fd: *[2]i32, flags: u32) usize {
237 return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
238}
239
240pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
241 return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
242}
243
244pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
245 return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
246}
247
248// TODO https://github.com/ziglang/zig/issues/265
249pub fn rename(old: [*]const u8, new: [*]const u8) usize {
250 if (@hasDecl(@This(), "SYS_rename")) {
251 return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
252 } else if (@hasDecl(@This(), "SYS_renameat")) {
253 return syscall4(SYS_renameat, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new));
254 } else {
255 return syscall5(SYS_renameat2, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new), 0);
256 }
257}
258
259pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
260 if (@hasDecl(@This(), "SYS_renameat")) {
261 return syscall4(
262 SYS_renameat,
263 @bitCast(usize, isize(oldfd)),
264 @ptrToInt(old),
265 @bitCast(usize, isize(newfd)),
266 @ptrToInt(new),
267 );
268 } else {
269 return syscall5(
270 SYS_renameat2,
271 @bitCast(usize, isize(oldfd)),
272 @ptrToInt(old),
273 @bitCast(usize, isize(newfd)),
274 @ptrToInt(new),
275 0,
276 );
277 }
278}
279
280// TODO https://github.com/ziglang/zig/issues/265
281pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
282 return syscall5(
283 SYS_renameat2,
284 @bitCast(usize, isize(oldfd)),
285 @ptrToInt(oldpath),
286 @bitCast(usize, isize(newfd)),
287 @ptrToInt(newpath),
288 flags,
289 );
290}
291
292// TODO https://github.com/ziglang/zig/issues/265
293pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
294 return syscall3(SYS_open, @ptrToInt(path), flags, perm);
295}
296
297// TODO https://github.com/ziglang/zig/issues/265
298pub fn create(path: [*]const u8, perm: usize) usize {
299 return syscall2(SYS_creat, @ptrToInt(path), perm);
300}
301
302// TODO https://github.com/ziglang/zig/issues/265
303pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
304 // dirfd could be negative, for example AT_FDCWD is -100
305 return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
306}
307
308/// See also `clone` (from the arch-specific include)
309pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid: *i32, newtls: usize) usize {
310 return syscall5(SYS_clone, flags, child_stack_ptr, @ptrToInt(parent_tid), @ptrToInt(child_tid), newtls);
311}
312
313/// See also `clone` (from the arch-specific include)
314pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
315 return syscall2(SYS_clone, flags, child_stack_ptr);
316}
317
318pub fn close(fd: i32) usize {
319 return syscall1(SYS_close, @bitCast(usize, isize(fd)));
320}
321
322/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
323pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
324 return syscall5(
325 SYS__llseek,
326 @bitCast(usize, isize(fd)),
327 @truncate(usize, offset >> 32),
328 @truncate(usize, offset),
329 @ptrToInt(result),
330 whence,
331 );
332}
333
334/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
335pub fn lseek(fd: i32, offset: i64, whence: usize) usize {
336 return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence);
337}
338
339pub fn exit(status: i32) noreturn {
340 _ = syscall1(SYS_exit, @bitCast(usize, isize(status)));
341 unreachable;
342}
343
344pub fn exit_group(status: i32) noreturn {
345 _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status)));
346 unreachable;
347}
348
349pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
350 return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags);
351}
352
353pub fn kill(pid: i32, sig: i32) usize {
354 return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
355}
356
357// TODO https://github.com/ziglang/zig/issues/265
358pub fn unlink(path: [*]const u8) usize {
359 if (@hasDecl(@This(), "SYS_unlink")) {
360 return syscall1(SYS_unlink, @ptrToInt(path));
361 } else {
362 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), 0);
363 }
364}
365
366// TODO https://github.com/ziglang/zig/issues/265
367pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
368 return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
369}
370
371pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
372 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
373}
374
375var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
376
377// We must follow the C calling convention when we call into the VDSO
378const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize;
379
380pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
381 if (VDSO_CGT_SYM.len != 0) {
382 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
383 if (ptr) |fn_ptr| {
384 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
385 const rc = f(clk_id, tp);
386 switch (rc) {
387 0, @bitCast(usize, isize(-EINVAL)) => return rc,
388 else => {},
389 }
390 }
391 }
392 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
393}
394
395extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
396 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
397 // Note that we may not have a VDSO at all, update the stub address anyway
398 // so that clock_gettime will fall back on the good old (and slow) syscall
399 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
400 // Call into the VDSO if available
401 if (ptr) |fn_ptr| {
402 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
403 return f(clk, ts);
404 }
405 return @bitCast(usize, isize(-ENOSYS));
406}
407
408pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
409 return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
410}
411
412pub fn clock_settime(clk_id: i32, tp: *const timespec) usize {
413 return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
414}
415
416pub fn gettimeofday(tv: *timeval, tz: *timezone) usize {
417 return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz));
418}
419
420pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize {
421 return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz));
422}
423
424pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
425 return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
426}
427
428pub fn setuid(uid: u32) usize {
429 return syscall1(SYS_setuid, uid);
430}
431
432pub fn setgid(gid: u32) usize {
433 return syscall1(SYS_setgid, gid);
434}
435
436pub fn setreuid(ruid: u32, euid: u32) usize {
437 return syscall2(SYS_setreuid, ruid, euid);
438}
439
440pub fn setregid(rgid: u32, egid: u32) usize {
441 return syscall2(SYS_setregid, rgid, egid);
442}
443
444pub fn getuid() u32 {
445 return u32(syscall0(SYS_getuid));
446}
447
448pub fn getgid() u32 {
449 return u32(syscall0(SYS_getgid));
450}
451
452pub fn geteuid() u32 {
453 return u32(syscall0(SYS_geteuid));
454}
455
456pub fn getegid() u32 {
457 return u32(syscall0(SYS_getegid));
458}
459
460pub fn seteuid(euid: u32) usize {
461 return syscall1(SYS_seteuid, euid);
462}
463
464pub fn setegid(egid: u32) usize {
465 return syscall1(SYS_setegid, egid);
466}
467
468pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
469 return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
470}
471
472pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
473 return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
474}
475
476pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
477 return syscall3(SYS_setresuid, ruid, euid, suid);
478}
479
480pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
481 return syscall3(SYS_setresgid, rgid, egid, sgid);
482}
483
484pub fn getgroups(size: usize, list: *u32) usize {
485 return syscall2(SYS_getgroups, size, @ptrToInt(list));
486}
487
488pub fn setgroups(size: usize, list: *const u32) usize {
489 return syscall2(SYS_setgroups, size, @ptrToInt(list));
490}
491
492pub fn getpid() i32 {
493 return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid)));
494}
495
496pub fn gettid() i32 {
497 return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid)));
498}
499
500pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
501 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
502}
503
504pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
505 assert(sig >= 1);
506 assert(sig != SIGKILL);
507 assert(sig != SIGSTOP);
508 var ksa = k_sigaction{
509 .handler = act.handler,
510 .flags = act.flags | SA_RESTORER,
511 .mask = undefined,
512 .restorer = @ptrCast(extern fn () void, restore_rt),
513 };
514 var ksa_old: k_sigaction = undefined;
515 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
516 const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
517 const err = getErrno(result);
518 if (err != 0) {
519 return result;
520 }
521 if (oact) |old| {
522 old.handler = ksa_old.handler;
523 old.flags = @truncate(u32, ksa_old.flags);
524 @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
525 }
526 return 0;
527}
528
529fn blockAllSignals(set: *sigset_t) void {
530 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8);
531}
532
533fn blockAppSignals(set: *sigset_t) void {
534 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8);
535}
536
537fn restoreSignals(set: *sigset_t) void {
538 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8);
539}
540
541pub fn sigaddset(set: *sigset_t, sig: u6) void {
542 const s = sig - 1;
543 (set.*)[@intCast(usize, s) / usize.bit_count] |= @intCast(usize, 1) << (s & (usize.bit_count - 1));
544}
545
546pub fn sigismember(set: *const sigset_t, sig: u6) bool {
547 const s = sig - 1;
548 return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;
549}
550
551pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
552 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
553}
554
555pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
556 return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
557}
558
559pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
560 return syscall3(SYS_socket, domain, socket_type, protocol);
561}
562
563pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
564 return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
565}
566
567pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
568 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
569}
570
571pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
572 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
573}
574
575pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
576 if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
577 // workaround kernel brokenness:
578 // if adding up all iov_len overflows a i32 then split into multiple calls
579 // see https://www.openwall.com/lists/musl/2014/06/07/5
580 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
581 var next_unsent: usize = 0;
582 for (msgvec[0..kvlen]) |*msg, i| {
583 var size: i32 = 0;
584 const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
585 for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
586 if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
587 // batch-send all messages up to the current message
588 if (next_unsent < i) {
589 const batch_size = i - next_unsent;
590 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
591 if (getErrno(r) != 0) return next_unsent;
592 if (r < batch_size) return next_unsent + r;
593 }
594 // send current message as own packet
595 const r = sendmsg(fd, &msg.msg_hdr, flags);
596 if (getErrno(r) != 0) return r;
597 // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
598 msg.msg_len = @intCast(u32, r);
599 next_unsent = i + 1;
600 break;
601 }
602 }
603 }
604 if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
605 const batch_size = kvlen - next_unsent;
606 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
607 if (getErrno(r) != 0) return r;
608 return next_unsent + r;
609 }
610 return kvlen;
611 }
612 return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
613}
614
615pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
616 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
617}
618
619pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
620 return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
621}
622
623pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
624 return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
625}
626
627pub fn shutdown(fd: i32, how: i32) usize {
628 return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
629}
630
631pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
632 return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
633}
634
635pub fn listen(fd: i32, backlog: u32) usize {
636 return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
637}
638
639pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
640 return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
641}
642
643pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
644 return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
645}
646
647pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
648 return accept4(fd, addr, len, 0);
649}
650
651pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
652 return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
653}
654
655pub fn fstat(fd: i32, stat_buf: *Stat) usize {
656 return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
657}
658
659// TODO https://github.com/ziglang/zig/issues/265
660pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
661 return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
662}
663
664// TODO https://github.com/ziglang/zig/issues/265
665pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
666 return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
667}
668
669// TODO https://github.com/ziglang/zig/issues/265
670pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
671 return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
672}
673
674// TODO https://github.com/ziglang/zig/issues/265
675pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
676 return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
677}
678
679// TODO https://github.com/ziglang/zig/issues/265
680pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
681 return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size);
682}
683
684pub fn flistxattr(fd: usize, list: [*]u8, size: usize) usize {
685 return syscall3(SYS_flistxattr, fd, @ptrToInt(list), size);
686}
687
688// TODO https://github.com/ziglang/zig/issues/265
689pub fn getxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
690 return syscall4(SYS_getxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
691}
692
693// TODO https://github.com/ziglang/zig/issues/265
694pub fn lgetxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
695 return syscall4(SYS_lgetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
696}
697
698// TODO https://github.com/ziglang/zig/issues/265
699pub fn fgetxattr(fd: usize, name: [*]const u8, value: [*]u8, size: usize) usize {
700 return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
701}
702
703// TODO https://github.com/ziglang/zig/issues/265
704pub fn setxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
705 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
706}
707
708// TODO https://github.com/ziglang/zig/issues/265
709pub fn lsetxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
710 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
711}
712
713// TODO https://github.com/ziglang/zig/issues/265
714pub fn fsetxattr(fd: usize, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
715 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
716}
717
718// TODO https://github.com/ziglang/zig/issues/265
719pub fn removexattr(path: [*]const u8, name: [*]const u8) usize {
720 return syscall2(SYS_removexattr, @ptrToInt(path), @ptrToInt(name));
721}
722
723// TODO https://github.com/ziglang/zig/issues/265
724pub fn lremovexattr(path: [*]const u8, name: [*]const u8) usize {
725 return syscall2(SYS_lremovexattr, @ptrToInt(path), @ptrToInt(name));
726}
727
728// TODO https://github.com/ziglang/zig/issues/265
729pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
730 return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
731}
732
733pub fn sched_getaffinity(pid: i32, set: []usize) usize {
734 return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr));
735}
736
737pub fn epoll_create() usize {
738 return epoll_create1(0);
739}
740
741pub fn epoll_create1(flags: usize) usize {
742 return syscall1(SYS_epoll_create1, flags);
743}
744
745pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
746 return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
747}
748
749pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
750 return syscall4(
751 SYS_epoll_wait,
752 @bitCast(usize, isize(epoll_fd)),
753 @ptrToInt(events),
754 maxevents,
755 @bitCast(usize, isize(timeout)),
756 );
757}
758
759pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
760 return syscall6(
761 SYS_epoll_pwait,
762 @bitCast(usize, isize(epoll_fd)),
763 @ptrToInt(events),
764 @intCast(usize, maxevents),
765 @bitCast(usize, isize(timeout)),
766 @ptrToInt(sigmask),
767 @sizeOf(sigset_t),
768 );
769}
770
771pub fn eventfd(count: u32, flags: u32) usize {
772 return syscall2(SYS_eventfd2, count, flags);
773}
774
775pub fn timerfd_create(clockid: i32, flags: u32) usize {
776 return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
777}
778
779pub const itimerspec = extern struct {
780 it_interval: timespec,
781 it_value: timespec,
782};
783
784pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
785 return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
786}
787
788pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
789 return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
790}
791
792pub fn unshare(flags: usize) usize {
793 return syscall1(SYS_unshare, flags);
794}
795
796pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
797 return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap));
798}
799
800pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
801 return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
802}
803
804// XXX: This should be weak
805extern const __ehdr_start: elf.Ehdr = undefined;
806
807pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
808 if (builtin.link_libc) {
809 return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
810 }
811
812 const elf_base = @ptrToInt(&__ehdr_start);
813 const n_phdr = __ehdr_start.e_phnum;
814 const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
815
816 var it = dl.linkmap_iterator(phdrs) catch return 0;
817
818 // The executable has no dynamic link segment, create a single entry for
819 // the whole ELF image
820 if (it.end()) {
821 var info = dl_phdr_info{
822 .dlpi_addr = elf_base,
823 .dlpi_name = c"/proc/self/exe",
824 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
825 .dlpi_phnum = __ehdr_start.e_phnum,
826 };
827
828 return callback(&info, @sizeOf(dl_phdr_info), data);
829 }
830
831 // Last return value from the callback function
832 var last_r: isize = 0;
833 while (it.next()) |entry| {
834 var dlpi_phdr: usize = undefined;
835 var dlpi_phnum: u16 = undefined;
836
837 if (entry.l_addr != 0) {
838 const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
839 dlpi_phdr = entry.l_addr + elf_header.e_phoff;
840 dlpi_phnum = elf_header.e_phnum;
841 } else {
842 // This is the running ELF image
843 dlpi_phdr = elf_base + __ehdr_start.e_phoff;
844 dlpi_phnum = __ehdr_start.e_phnum;
845 }
846
847 var info = dl_phdr_info{
848 .dlpi_addr = entry.l_addr,
849 .dlpi_name = entry.l_name,
850 .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
851 .dlpi_phnum = dlpi_phnum,
852 };
853
854 last_r = callback(&info, @sizeOf(dl_phdr_info), data);
855 if (last_r != 0) break;
856 }
857
858 return last_r;
859}
std/os/linux/tls.zig+9-4
......@@ -1,6 +1,6 @@
11const std = @import("std");
2const os = std.os;
23const mem = std.mem;
3const posix = std.os.posix;
44const elf = std.elf;
55const builtin = @import("builtin");
66const assert = std.debug.assert;
......@@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize {
237237 return @ptrToInt(&main_thread_tls_buffer);
238238 }
239239
240 const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0);
241
242 if (posix.getErrno(addr) != 0) @panic("out of memory");
240 const addr = os.mmap(
241 null,
242 size,
243 os.PROT_READ | os.PROT_WRITE,
244 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
245 -1,
246 0,
247 ) catch @panic("out of memory");
243248
244249 return addr;
245250}
std/os/linux/x86_64.zig+1-1
......@@ -1,4 +1,4 @@
1use @import("posix/x86_64.zig");
1use @import("../bits.zig");
22
33pub fn syscall0(number: usize) usize {
44 return asm volatile ("syscall"
std/os/test.zig+15-14
......@@ -5,6 +5,7 @@ const expect = std.testing.expect;
55const io = std.io;
66const mem = std.mem;
77const File = std.fs.File;
8const Thread = std.Thread;
89
910const a = std.debug.global_allocator;
1011
......@@ -37,25 +38,25 @@ test "access file" {
3738 try os.deleteTree(a, "os_test_tmp");
3839}
3940
40fn testThreadIdFn(thread_id: *os.Thread.Id) void {
41 thread_id.* = os.Thread.getCurrentId();
41fn testThreadIdFn(thread_id: *Thread.Id) void {
42 thread_id.* = Thread.getCurrentId();
4243}
4344
44test "std.os.Thread.getCurrentId" {
45test "std.Thread.getCurrentId" {
4546 if (builtin.single_threaded) return error.SkipZigTest;
4647
47 var thread_current_id: os.Thread.Id = undefined;
48 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
48 var thread_current_id: Thread.Id = undefined;
49 const thread = try Thread.spawn(&thread_current_id, testThreadIdFn);
4950 const thread_id = thread.handle();
5051 thread.wait();
51 if (os.Thread.use_pthreads) {
52 if (Thread.use_pthreads) {
5253 expect(thread_current_id == thread_id);
5354 } else {
5455 switch (builtin.os) {
55 builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id),
56 builtin.Os.windows => expect(Thread.getCurrentId() != thread_current_id),
5657 else => {
5758 // If the thread completes very quickly, then thread_id can be 0. See the
58 // documentation comments for `std.os.Thread.handle`.
59 // documentation comments for `std.Thread.handle`.
5960 expect(thread_id == 0 or thread_current_id == thread_id);
6061 },
6162 }
......@@ -67,10 +68,10 @@ test "spawn threads" {
6768
6869 var shared_ctx: i32 = 1;
6970
70 const thread1 = try std.os.spawnThread({}, start1);
71 const thread2 = try std.os.spawnThread(&shared_ctx, start2);
72 const thread3 = try std.os.spawnThread(&shared_ctx, start2);
73 const thread4 = try std.os.spawnThread(&shared_ctx, start2);
71 const thread1 = try Thread.spawn({}, start1);
72 const thread2 = try Thread.spawn(&shared_ctx, start2);
73 const thread3 = try Thread.spawn(&shared_ctx, start2);
74 const thread4 = try Thread.spawn(&shared_ctx, start2);
7475
7576 thread1.wait();
7677 thread2.wait();
......@@ -116,8 +117,8 @@ test "AtomicFile" {
116117
117118test "thread local storage" {
118119 if (builtin.single_threaded) return error.SkipZigTest;
119 const thread1 = try std.os.spawnThread({}, testTls);
120 const thread2 = try std.os.spawnThread({}, testTls);
120 const thread1 = try Thread.spawn({}, testTls);
121 const thread2 = try Thread.spawn({}, testTls);
121122 testTls({});
122123 thread1.wait();
123124 thread2.wait();
std/os/windows.zig+15-1
......@@ -591,7 +591,7 @@ pub fn CreateFileW(
591591 ERROR.ACCESS_DENIED => return error.AccessDenied,
592592 ERROR.PIPE_BUSY => return error.PipeBusy,
593593 ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,
594 else => |err| return unexpectedErrorWindows(err),
594 else => |err| return unexpectedError(err),
595595 }
596596 }
597597
......@@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError
10891089 }
10901090}
10911091
1092pub const VirtualAllocError = error{Unexpected};
1093
1094pub fn VirtualAlloc(addr: ?LPVOID, size: usize, alloc_type: DWORD, flProtect: DWORD) VirtualAllocError!LPVOID {
1095 return kernel32.VirtualAlloc(addr, size, alloc_type, flProtect) orelse {
1096 switch (kernel32.GetLastError()) {
1097 else => |err| return unexpectedError(err),
1098 }
1099 };
1100}
1101
1102pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {
1103 assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);
1104}
1105
10921106pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
10931107 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
10941108}
std/process.zig+17-17
......@@ -1,13 +1,13 @@
11const std = @import("std.zig");
2const posix = std.os.posix;
2const os = std.os;
33const BufMap = std.BufMap;
44const mem = std.mem;
55const Allocator = mem.Allocator;
66const assert = std.debug.assert;
77const testing = std.testing;
88
9pub const abort = posix.abort;
10pub const exit = posix.exit;
9pub const abort = os.abort;
10pub const exit = os.exit;
1111
1212/// Caller must free result when done.
1313/// TODO make this go through libc when we have it
......@@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
4242
4343 try result.setMove(key, value);
4444 }
45 } else if (builtin.os == Os.wasi) {
45 } else if (builtin.os == .wasi) {
4646 var environ_count: usize = undefined;
4747 var environ_buf_size: usize = undefined;
4848
49 const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);
49 const environ_sizes_get_ret = os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);
5050 if (environ_sizes_get_ret != os.wasi.ESUCCESS) {
51 return unexpectedErrorPosix(environ_sizes_get_ret);
51 return os.unexpectedErrno(environ_sizes_get_ret);
5252 }
5353
5454 // TODO: Verify that the documentation is incorrect
......@@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
5858 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
5959 defer allocator.free(environ_buf);
6060
61 const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr);
61 const environ_get_ret = os.wasi.environ_get(environ.ptr, environ_buf.ptr);
6262 if (environ_get_ret != os.wasi.ESUCCESS) {
63 return unexpectedErrorPosix(environ_get_ret);
63 return os.unexpectedErrno(environ_get_ret);
6464 }
6565
6666 for (environ) |env| {
......@@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
7474 }
7575 return result;
7676 } else {
77 for (posix.environ) |ptr| {
77 for (os.environ) |ptr| {
7878 var line_i: usize = 0;
7979 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
8080 const key = ptr[0..line_i];
......@@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct {
331331};
332332
333333pub const ArgIterator = struct {
334 const InnerType = if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix;
334 const InnerType = if (builtin.os == .windows) ArgIteratorWindows else ArgIteratorPosix;
335335
336336 inner: InnerType,
337337
338338 pub fn init() ArgIterator {
339 if (builtin.os == Os.wasi) {
339 if (builtin.os == .wasi) {
340340 // TODO: Figure out a compatible interface accomodating WASI
341341 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
342342 }
......@@ -348,7 +348,7 @@ pub const ArgIterator = struct {
348348
349349 /// You must free the returned memory when done.
350350 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {
351 if (builtin.os == Os.windows) {
351 if (builtin.os == .windows) {
352352 return self.inner.next(allocator);
353353 } else {
354354 return mem.dupe(allocator, u8, self.inner.next() orelse return null);
......@@ -373,13 +373,13 @@ pub fn args() ArgIterator {
373373
374374/// Caller must call argsFree on result.
375375pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
376 if (builtin.os == Os.wasi) {
376 if (builtin.os == .wasi) {
377377 var count: usize = undefined;
378378 var buf_size: usize = undefined;
379379
380380 const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);
381381 if (args_sizes_get_ret != os.wasi.ESUCCESS) {
382 return unexpectedErrorPosix(args_sizes_get_ret);
382 return os.unexpectedErrno(args_sizes_get_ret);
383383 }
384384
385385 var argv = try allocator.alloc([*]u8, count);
......@@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
388388 var argv_buf = try allocator.alloc(u8, buf_size);
389389 const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);
390390 if (args_get_ret != os.wasi.ESUCCESS) {
391 return unexpectedErrorPosix(args_get_ret);
391 return os.unexpectedErrno(args_get_ret);
392392 }
393393
394394 var result_slice = try allocator.alloc([]u8, count);
......@@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
438438}
439439
440440pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
441 if (builtin.os == Os.wasi) {
441 if (builtin.os == .wasi) {
442442 const last_item = args_alloc[args_alloc.len - 1];
443443 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
444444 const first_item_ptr = args_alloc[0].ptr;
......@@ -491,7 +491,7 @@ pub const UserInfo = struct {
491491/// POSIX function which gets a uid from username.
492492pub fn getUserInfo(name: []const u8) !UserInfo {
493493 return switch (builtin.os) {
494 .linux, .macosx, .ios, .freebsd, .netbsd => posixGetUserInfo(name),
494 .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name),
495495 else => @compileError("Unsupported OS"),
496496 };
497497}
std/special/bootstrap.zig+2-2
......@@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn {
9292 }
9393 }
9494
95 std.os.posix.exit(callMainWithArgs(argc, argv, envp));
95 std.os.exit(callMainWithArgs(argc, argv, envp));
9696}
9797
9898// This is marked inline because for some reason LLVM in release mode fails to inline it,
9999// and we want fewer call frames in stack traces.
100100inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
101101 std.os.ArgIteratorPosix.raw = argv[0..argc];
102 std.os.posix.environ = envp;
102 std.os.environ = envp;
103103 return callMain();
104104}
105105
std/statically_initialized_mutex.zig+2-2
......@@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" {
9696 expect(context.data == TestContext.incr_count);
9797 } else {
9898 const thread_count = 10;
99 var threads: [thread_count]*std.os.Thread = undefined;
99 var threads: [thread_count]*std.Thread = undefined;
100100 for (threads) |*t| {
101 t.* = try std.os.spawnThread(&context, TestContext.worker);
101 t.* = try std.Thread.spawn(&context, TestContext.worker);
102102 }
103103 for (threads) |t|
104104 t.wait();
std/thread.zig+57-93
......@@ -1,6 +1,8 @@
11const builtin = @import("builtin");
22const std = @import("std.zig");
3const os = std.os;
34const windows = std.os.windows;
5const c = std.c;
46
57pub const Thread = struct {
68 data: Data,
......@@ -13,8 +15,8 @@ pub const Thread = struct {
1315 pub const Handle = if (use_pthreads)
1416 c.pthread_t
1517 else switch (builtin.os) {
16 builtin.Os.linux => i32,
17 builtin.Os.windows => windows.HANDLE,
18 .linux => i32,
19 .windows => windows.HANDLE,
1820 else => @compileError("Unsupported OS"),
1921 };
2022
......@@ -22,7 +24,7 @@ pub const Thread = struct {
2224 /// May be an integer or pointer depending on the platform.
2325 /// On Linux and POSIX, this is the same as Handle.
2426 pub const Id = switch (builtin.os) {
25 builtin.Os.windows => windows.DWORD,
27 .windows => windows.DWORD,
2628 else => Handle,
2729 };
2830
......@@ -33,12 +35,12 @@ pub const Thread = struct {
3335 mmap_len: usize,
3436 }
3537 else switch (builtin.os) {
36 builtin.Os.linux => struct {
38 .linux => struct {
3739 handle: Thread.Handle,
3840 mmap_addr: usize,
3941 mmap_len: usize,
4042 },
41 builtin.Os.windows => struct {
43 .windows => struct {
4244 handle: Thread.Handle,
4345 alloc_start: *c_void,
4446 heap_handle: windows.HANDLE,
......@@ -54,8 +56,8 @@ pub const Thread = struct {
5456 return c.pthread_self();
5557 } else
5658 return switch (builtin.os) {
57 builtin.Os.linux => linux.gettid(),
58 builtin.Os.windows => windows.GetCurrentThreadId(),
59 .linux => linux.gettid(),
60 .windows => windows.GetCurrentThreadId(),
5961 else => @compileError("Unsupported OS"),
6062 };
6163 }
......@@ -75,28 +77,28 @@ pub const Thread = struct {
7577 const err = c.pthread_join(self.data.handle, null);
7678 switch (err) {
7779 0 => {},
78 posix.EINVAL => unreachable,
79 posix.ESRCH => unreachable,
80 posix.EDEADLK => unreachable,
80 os.EINVAL => unreachable,
81 os.ESRCH => unreachable,
82 os.EDEADLK => unreachable,
8183 else => unreachable,
8284 }
83 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
85 os.munmap(self.data.mmap_addr, self.data.mmap_len);
8486 } else switch (builtin.os) {
85 builtin.Os.linux => {
87 .linux => {
8688 while (true) {
8789 const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);
8890 if (pid_value == 0) break;
8991 const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null);
9092 switch (linux.getErrno(rc)) {
9193 0 => continue,
92 posix.EINTR => continue,
93 posix.EAGAIN => continue,
94 os.EINTR => continue,
95 os.EAGAIN => continue,
9496 else => unreachable,
9597 }
9698 }
97 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
99 os.munmap(self.data.mmap_addr, self.data.mmap_len);
98100 },
99 builtin.Os.windows => {
101 .windows => {
100102 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
101103 assert(windows.CloseHandle(self.data.handle) != 0);
102104 assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0);
......@@ -153,10 +155,10 @@ pub const Thread = struct {
153155 extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD {
154156 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
155157 switch (@typeId(@typeOf(startFn).ReturnType)) {
156 builtin.TypeId.Int => {
158 .Int => {
157159 return startFn(arg);
158160 },
159 builtin.TypeId.Void => {
161 .Void => {
160162 startFn(arg);
161163 return 0;
162164 },
......@@ -196,10 +198,10 @@ pub const Thread = struct {
196198 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
197199
198200 switch (@typeId(@typeOf(startFn).ReturnType)) {
199 builtin.TypeId.Int => {
201 .Int => {
200202 return startFn(arg);
201203 },
202 builtin.TypeId.Void => {
204 .Void => {
203205 startFn(arg);
204206 return 0;
205207 },
......@@ -217,7 +219,7 @@ pub const Thread = struct {
217219 }
218220 };
219221
220 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;
222 const MAP_GROWSDOWN = if (builtin.os == .linux) linux.MAP_GROWSDOWN else 0;
221223
222224 var stack_end_offset: usize = undefined;
223225 var thread_start_offset: usize = undefined;
......@@ -247,9 +249,8 @@ pub const Thread = struct {
247249 }
248250 break :blk l;
249251 };
250 const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
251 if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory;
252 errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0);
252 const mmap_addr = try os.mmap(null, mmap_len, os.PROT_READ | os.PROT_WRITE, os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
253 errdefer os.munmap(mmap_addr, mmap_len);
253254
254255 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
255256 thread_ptr.data.mmap_addr = mmap_addr;
......@@ -273,31 +274,30 @@ pub const Thread = struct {
273274 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
274275 switch (err) {
275276 0 => return thread_ptr,
276 posix.EAGAIN => return error.SystemResources,
277 posix.EPERM => unreachable,
278 posix.EINVAL => unreachable,
279 else => return unexpectedErrorPosix(@intCast(usize, err)),
277 os.EAGAIN => return error.SystemResources,
278 os.EPERM => unreachable,
279 os.EINVAL => unreachable,
280 else => return os.unexpectedErrno(@intCast(usize, err)),
280281 }
281 } else if (builtin.os == builtin.Os.linux) {
282 var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND |
283 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
284 posix.CLONE_DETACHED;
282 } else if (builtin.os == .linux) {
283 var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |
284 os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |
285 os.CLONE_DETACHED;
285286 var newtls: usize = undefined;
286287 if (linux.tls.tls_image) |tls_img| {
287288 newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);
288 flags |= posix.CLONE_SETTLS;
289 flags |= os.CLONE_SETTLS;
289290 }
290 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
291 const err = posix.getErrno(rc);
292 switch (err) {
291 const rc = os.linux.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
292 switch (os.errno(rc)) {
293293 0 => return thread_ptr,
294 posix.EAGAIN => return error.ThreadQuotaExceeded,
295 posix.EINVAL => unreachable,
296 posix.ENOMEM => return error.SystemResources,
297 posix.ENOSPC => unreachable,
298 posix.EPERM => unreachable,
299 posix.EUSERS => unreachable,
300 else => return unexpectedErrorPosix(err),
294 os.EAGAIN => return error.ThreadQuotaExceeded,
295 os.EINVAL => unreachable,
296 os.ENOMEM => return error.SystemResources,
297 os.ENOSPC => unreachable,
298 os.EPERM => unreachable,
299 os.EUSERS => unreachable,
300 else => |err| return os.unexpectedErrno(err),
301301 }
302302 } else {
303303 @compileError("Unsupported OS");
......@@ -310,56 +310,20 @@ pub const Thread = struct {
310310 Unexpected,
311311 };
312312
313 pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
314 switch (builtin.os) {
315 .macosx, .freebsd, .netbsd => {
316 var count: c_int = undefined;
317 var count_len: usize = @sizeOf(c_int);
318 const name = switch (builtin.os) {
319 builtin.Os.macosx => c"hw.logicalcpu",
320 else => c"hw.ncpu",
321 };
322 try posix.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0);
323 return @intCast(usize, count);
324 },
325 .linux => {
326 const usize_count = 16;
327 const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get();
328
329 var set = try allocator.alloc(usize, usize_count);
330 defer allocator.free(set);
331
332 while (true) {
333 const rc = posix.sched_getaffinity(0, set);
334 const err = posix.getErrno(rc);
335 switch (err) {
336 0 => {
337 if (rc < set.len * @sizeOf(usize)) {
338 const result = set[0 .. rc / @sizeOf(usize)];
339 var sum: usize = 0;
340 for (result) |x| {
341 sum += @popCount(usize, x);
342 }
343 return sum;
344 } else {
345 set = try allocator.realloc(set, set.len * 2);
346 continue;
347 }
348 },
349 posix.EFAULT => unreachable,
350 posix.EINVAL => unreachable,
351 posix.EPERM => return CpuCountError.PermissionDenied,
352 posix.ESRCH => unreachable,
353 else => return os.unexpectedErrorPosix(err),
354 }
355 }
356 },
357 .windows => {
358 var system_info: windows.SYSTEM_INFO = undefined;
359 windows.GetSystemInfo(&system_info);
360 return @intCast(usize, system_info.dwNumberOfProcessors);
361 },
362 else => @compileError("unsupported OS"),
313 pub fn cpuCount() CpuCountError!usize {
314 if (os.linux.is_the_target) {
315 const cpu_set = try os.sched_getaffinity(0);
316 return os.CPU_COUNT(cpu_set);
317 }
318 if (os.windows.is_the_target) {
319 var system_info: windows.SYSTEM_INFO = undefined;
320 windows.GetSystemInfo(&system_info);
321 return @intCast(usize, system_info.dwNumberOfProcessors);
363322 }
323 var count: c_int = undefined;
324 var count_len: usize = @sizeOf(c_int);
325 const name = if (os.darwin.is_the_target) c"hw.logicalcpu" else c"hw.ncpu";
326 try os.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0);
327 return @intCast(usize, count);
364328 }
365329};