authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-25 10:19:49-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-03-25 10:19:49-04:00
log3869e803318721134170ca8e90190cdfbadbe475
tree5d5282ad4be25d465275a93df202a61faed3b361
parent778dbc17acce77588a46a27074ecb8b418786d94
parent3ccf99c0bd5a681c56c456d1606b5eccfcf31fb7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4793 from LemonBoy/netbsd-forever

Netbsd forever

10 files changed, 283 insertions(+), 87 deletions(-)

lib/std/c.zig+1-1
......@@ -74,7 +74,6 @@ pub extern "c" fn exit(code: c_int) noreturn;
7474pub extern "c" fn isatty(fd: fd_t) c_int;
7575pub extern "c" fn close(fd: fd_t) c_int;
7676pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;
77pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;
7877pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int;
7978pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t;
8079pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int;
......@@ -185,6 +184,7 @@ pub extern "c" fn futimens(fd: fd_t, times: *const [2]timespec) c_int;
185184pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const pthread_attr_t, start_routine: extern fn (?*c_void) ?*c_void, noalias arg: ?*c_void) c_int;
186185pub extern "c" fn pthread_attr_init(attr: *pthread_attr_t) c_int;
187186pub extern "c" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int;
187pub extern "c" fn pthread_attr_setguardsize(attr: *pthread_attr_t, guardsize: usize) c_int;
188188pub extern "c" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int;
189189pub extern "c" fn pthread_self() pthread_t;
190190pub extern "c" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int;
lib/std/c/darwin.zig+1
......@@ -13,6 +13,7 @@ pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
1313pub extern "c" fn _dyld_get_image_name(image_index: u32) [*:0]const u8;
1414
1515pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize;
16pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;
1617
1718pub extern "c" fn mach_absolute_time() u64;
1819pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) void;
lib/std/c/netbsd.zig+10-2
......@@ -1,11 +1,19 @@
11const std = @import("../std.zig");
2const builtin = std.builtin;
3
24usingnamespace std.c;
35
46extern "c" fn __errno() *c_int;
57pub const _errno = __errno;
68
7pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
8pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
9pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
10pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
11
12pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int;
13pub extern "c" fn __clock_gettime50(clk_id: c_int, tp: *timespec) c_int;
14pub extern "c" fn __clock_getres50(clk_id: c_int, tp: *timespec) c_int;
15pub extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int;
16pub extern "c" fn __sigaltstack14(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
917
1018pub const pthread_mutex_t = extern struct {
1119 ptm_magic: c_uint = 0x33330003,
lib/std/debug.zig+4-2
......@@ -654,6 +654,8 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
654654 switch (builtin.os.tag) {
655655 .linux,
656656 .freebsd,
657 .netbsd,
658 .dragonfly,
657659 .macosx,
658660 .windows,
659661 => return DebugInfo.init(allocator),
......@@ -1047,7 +1049,7 @@ const MachoSymbol = struct {
10471049
10481050fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 {
10491051 noasync {
1050 const file = try fs.openFileAbsolute(path, .{ .always_blocking = true });
1052 const file = try fs.cwd().openFile(path, .{ .always_blocking = true });
10511053 defer file.close();
10521054
10531055 const file_len = try math.cast(usize, try file.getEndPos());
......@@ -1621,7 +1623,7 @@ pub const ModuleDebugInfo = switch (builtin.os.tag) {
16211623 };
16221624 }
16231625 },
1624 .linux, .freebsd => struct {
1626 .linux, .netbsd, .freebsd, .dragonfly => struct {
16251627 base_address: usize,
16261628 dwarf: DW.DwarfInfo,
16271629 mapped_memory: []const u8,
lib/std/fs.zig+4-6
......@@ -339,12 +339,10 @@ pub const Dir = struct {
339339 fn nextBsd(self: *Self) !?Entry {
340340 start_over: while (true) {
341341 if (self.index >= self.end_index) {
342 const rc = os.system.getdirentries(
343 self.dir.fd,
344 &self.buf,
345 self.buf.len,
346 &self.seek,
347 );
342 const rc = if (builtin.os.tag == .netbsd)
343 os.system.__getdents30(self.dir.fd, &self.buf, self.buf.len)
344 else
345 os.system.getdents(self.dir.fd, &self.buf, self.buf.len);
348346 switch (os.errno(rc)) {
349347 0 => {},
350348 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
lib/std/os.zig+26-16
......@@ -2531,18 +2531,15 @@ pub const FStatError = error{
25312531
25322532pub fn fstat(fd: fd_t) FStatError!Stat {
25332533 var stat: Stat = undefined;
2534 if (comptime std.Target.current.isDarwin()) {
2535 switch (darwin.getErrno(darwin.@"fstat$INODE64"(fd, &stat))) {
2536 0 => return stat,
2537 EINVAL => unreachable,
2538 EBADF => unreachable, // Always a race condition.
2539 ENOMEM => return error.SystemResources,
2540 EACCES => return error.AccessDenied,
2541 else => |err| return unexpectedErrno(err),
2542 }
2543 }
25442534
2545 switch (errno(system.fstat(fd, &stat))) {
2535 const symbol_name = if (comptime std.Target.current.isDarwin())
2536 "fstat$INODE64"
2537 else if (std.Target.current.os.tag == .netbsd)
2538 "__fstat50"
2539 else
2540 "fstat";
2541
2542 switch (errno(@field(system, symbol_name)(fd, &stat))) {
25462543 0 => return stat,
25472544 EINVAL => unreachable,
25482545 EBADF => unreachable, // Always a race condition.
......@@ -3401,7 +3398,13 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
34013398 }
34023399 return;
34033400 }
3404 switch (errno(system.clock_gettime(clk_id, tp))) {
3401
3402 const symbol_name = if (std.Target.current.os.tag == .netbsd)
3403 "__clock_gettime50"
3404 else
3405 "clock_gettime";
3406
3407 switch (errno(@field(system, symbol_name)(clk_id, tp))) {
34053408 0 => return,
34063409 EFAULT => unreachable,
34073410 EINVAL => return error.UnsupportedClock,
......@@ -3423,7 +3426,12 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
34233426 return;
34243427 }
34253428
3426 switch (errno(system.clock_getres(clk_id, res))) {
3429 const symbol_name = if (std.Target.current.os.tag == .netbsd)
3430 "__clock_getres50"
3431 else
3432 "clock_getres";
3433
3434 switch (errno(@field(system, symbol_name)(clk_id, res))) {
34273435 0 => return,
34283436 EFAULT => unreachable,
34293437 EINVAL => return error.UnsupportedClock,
......@@ -3489,10 +3497,12 @@ pub const SigaltstackError = error{
34893497} || UnexpectedError;
34903498
34913499pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
3492 if (builtin.os.tag == .windows or builtin.os.tag == .uefi or builtin.os.tag == .wasi)
3493 @compileError("std.os.sigaltstack not available for this target");
3500 const symbol_name = if (std.Target.current.os.tag == .netbsd)
3501 "__sigaltstack14"
3502 else
3503 "sigaltstack";
34943504
3495 switch (errno(system.sigaltstack(ss, old_ss))) {
3505 switch (errno(@field(system, symbol_name)(ss, old_ss))) {
34963506 0 => return,
34973507 EFAULT => unreachable,
34983508 EINVAL => unreachable,
lib/std/os/bits/netbsd.zig+161-30
......@@ -1,9 +1,12 @@
11const std = @import("../../std.zig");
22const maxInt = std.math.maxInt;
33
4pub const fd_t = c_int;
5pub const pid_t = c_int;
6pub const mode_t = c_uint;
4pub const fd_t = i32;
5pub const pid_t = i32;
6pub const mode_t = u32;
7pub const ino_t = u64;
8pub const off_t = i64;
9pub const socklen_t = u32;
710
811/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
912pub const Kevent = extern struct {
......@@ -22,6 +25,65 @@ pub const dl_phdr_info = extern struct {
2225 dlpi_phnum: u16,
2326};
2427
28pub const addrinfo = extern struct {
29 flags: i32,
30 family: i32,
31 socktype: i32,
32 protocol: i32,
33 addrlen: socklen_t,
34 canonname: ?[*:0]u8,
35 addr: ?*sockaddr,
36 next: ?*addrinfo,
37};
38
39pub const EAI = extern enum(c_int) {
40 /// address family for hostname not supported
41 ADDRFAMILY = 1,
42
43 /// name could not be resolved at this time
44 AGAIN = 2,
45
46 /// flags parameter had an invalid value
47 BADFLAGS = 3,
48
49 /// non-recoverable failure in name resolution
50 FAIL = 4,
51
52 /// address family not recognized
53 FAMILY = 5,
54
55 /// memory allocation failure
56 MEMORY = 6,
57
58 /// no address associated with hostname
59 NODATA = 7,
60
61 /// name does not resolve
62 NONAME = 8,
63
64 /// service not recognized for socket type
65 SERVICE = 9,
66
67 /// intended socket type was not recognized
68 SOCKTYPE = 10,
69
70 /// system error returned in errno
71 SYSTEM = 11,
72
73 /// invalid value for hints
74 BADHINTS = 12,
75
76 /// resolved protocol is unknown
77 PROTOCOL = 13,
78
79 /// argument buffer overflow
80 OVERFLOW = 14,
81
82 _,
83};
84
85pub const EAI_MAX = 15;
86
2587pub const msghdr = extern struct {
2688 /// optional address
2789 msg_name: ?*sockaddr,
......@@ -68,9 +130,6 @@ pub const msghdr_const = extern struct {
68130 msg_flags: i32,
69131};
70132
71pub const off_t = i64;
72pub const ino_t = u64;
73
74133/// Renamed to Stat to not conflict with the stat function.
75134/// atime, mtime, and ctime have functions to return `timespec`,
76135/// because although this is a POSIX API, the layout and names of
......@@ -122,7 +181,6 @@ pub const dirent = extern struct {
122181 d_reclen: u16,
123182 d_namlen: u16,
124183 d_type: u8,
125 d_off: i64,
126184 d_name: [512]u8,
127185
128186 pub fn reclen(self: dirent) u16 {
......@@ -146,7 +204,7 @@ pub const sockaddr = extern struct {
146204
147205pub const sockaddr_in = extern struct {
148206 len: u8 = @sizeOf(sockaddr_in),
149 family: sa_family_t,
207 family: sa_family_t = AF_INET,
150208 port: in_port_t,
151209 addr: u32,
152210 zero: [8]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
......@@ -154,7 +212,7 @@ pub const sockaddr_in = extern struct {
154212
155213pub const sockaddr_in6 = extern struct {
156214 len: u8 = @sizeOf(sockaddr_in6),
157 family: sa_family_t,
215 family: sa_family_t = AF_INET6,
158216 port: in_port_t,
159217 flowinfo: u32,
160218 addr: [16]u8,
......@@ -167,12 +225,27 @@ pub const sockaddr_un = extern struct {
167225 len: u8 = @sizeOf(sockaddr_un),
168226
169227 /// AF_LOCAL
170 family: sa_family_t,
228 family: sa_family_t = AF_LOCAL,
171229
172230 /// path name
173231 path: [104]u8,
174232};
175233
234/// get address to use bind()
235pub const AI_PASSIVE = 0x00000001;
236
237/// fill ai_canonname
238pub const AI_CANONNAME = 0x00000002;
239
240/// prevent host name resolution
241pub const AI_NUMERICHOST = 0x00000004;
242
243/// prevent service name resolution
244pub const AI_NUMERICSERV = 0x00000008;
245
246/// only if any address is assigned
247pub const AI_ADDRCONFIG = 0x00000400;
248
176249pub const CTL_KERN = 1;
177250pub const CTL_DEBUG = 5;
178251
......@@ -274,30 +347,71 @@ pub const X_OK = 1; // test for execute or search permission
274347pub const W_OK = 2; // test for write permission
275348pub const R_OK = 4; // test for read permission
276349
277pub const O_RDONLY = 0x0000;
278pub const O_WRONLY = 0x0001;
279pub const O_RDWR = 0x0002;
280pub const O_ACCMODE = 0x0003;
281
282pub const O_CREAT = 0x0200;
283pub const O_EXCL = 0x0800;
284pub const O_NOCTTY = 0x8000;
285pub const O_TRUNC = 0x0400;
286pub const O_APPEND = 0x0008;
287pub const O_NONBLOCK = 0x0004;
350/// open for reading only
351pub const O_RDONLY = 0x00000000;
352
353/// open for writing only
354pub const O_WRONLY = 0x00000001;
355
356/// open for reading and writing
357pub const O_RDWR = 0x00000002;
358
359/// mask for above modes
360pub const O_ACCMODE = 0x00000003;
361
362/// no delay
363pub const O_NONBLOCK = 0x00000004;
364
365/// set append mode
366pub const O_APPEND = 0x00000008;
367
368/// open with shared file lock
369pub const O_SHLOCK = 0x00000010;
370
371/// open with exclusive file lock
372pub const O_EXLOCK = 0x00000020;
373
374/// signal pgrp when data ready
375pub const O_ASYNC = 0x00000040;
376
377/// synchronous writes
378pub const O_SYNC = 0x00000080;
379
380/// don't follow symlinks on the last
381pub const O_NOFOLLOW = 0x00000100;
382
383/// create if nonexistent
384pub const O_CREAT = 0x00000200;
385
386/// truncate to zero length
387pub const O_TRUNC = 0x00000400;
388
389/// error if already exists
390pub const O_EXCL = 0x00000800;
391
392/// don't assign controlling terminal
393pub const O_NOCTTY = 0x00008000;
394
395/// write: I/O data completion
288396pub const O_DSYNC = 0x00010000;
289pub const O_SYNC = 0x0080;
397
398/// read: I/O completion as for write
290399pub const O_RSYNC = 0x00020000;
291pub const O_DIRECTORY = 0x00080000;
292pub const O_NOFOLLOW = 0x00000100;
293pub const O_CLOEXEC = 0x00400000;
294400
295pub const O_ASYNC = 0x0040;
401/// use alternate i/o semantics
402pub const O_ALT_IO = 0x00040000;
403
404/// direct I/O hint
296405pub const O_DIRECT = 0x00080000;
297pub const O_NOATIME = 0;
298pub const O_PATH = 0;
299pub const O_TMPFILE = 0;
300pub const O_NDELAY = O_NONBLOCK;
406
407/// fail if not a directory
408pub const O_DIRECTORY = 0x00200000;
409
410/// set close on exec
411pub const O_CLOEXEC = 0x00400000;
412
413/// skip search permission checks
414pub const O_SEARCH = 0x00800000;
301415
302416pub const F_DUPFD = 0;
303417pub const F_GETFD = 1;
......@@ -816,6 +930,23 @@ pub fn S_IWHT(m: u32) bool {
816930 return m & S_IFMT == S_IFWHT;
817931}
818932
933/// Magic value that specify the use of the current working directory
934/// to determine the target of relative file paths in the openat() and
935/// similar syscalls.
936pub const AT_FDCWD = -100;
937
938/// Check access using effective user and group ID
939pub const AT_EACCESS = 0x0100;
940
941/// Do not follow symbolic links
942pub const AT_SYMLINK_NOFOLLOW = 0x0200;
943
944/// Follow symbolic link
945pub const AT_SYMLINK_FOLLOW = 0x0400;
946
947/// Remove directory instead of file
948pub const AT_REMOVEDIR = 0x0800;
949
819950pub const HOST_NAME_MAX = 255;
820951
821952/// dummy for IP
lib/std/thread.zig+73-26
......@@ -292,32 +292,69 @@ pub const Thread = struct {
292292 l += tls_img.alloc_size;
293293 }
294294 }
295 break :blk l;
295 // Round the size to the page size.
296 break :blk mem.alignForward(l, mem.page_size);
296297 };
297 // Map the whole stack with no rw permissions to avoid committing the
298 // whole region right away
299 const mmap_slice = os.mmap(
300 null,
301 mem.alignForward(mmap_len, mem.page_size),
302 os.PROT_NONE,
303 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
304 -1,
305 0,
306 ) catch |err| switch (err) {
307 error.MemoryMappingNotSupported => unreachable,
308 error.AccessDenied => unreachable,
309 error.PermissionDenied => unreachable,
310 else => |e| return e,
311 };
312 errdefer os.munmap(mmap_slice);
313
314 // Map everything but the guard page as rw
315 os.mprotect(
316 mmap_slice,
317 os.PROT_READ | os.PROT_WRITE,
318 ) catch |err| switch (err) {
319 error.AccessDenied => unreachable,
320 else => |e| return e,
298
299 const mmap_slice = mem: {
300 if (std.Target.current.os.tag != .netbsd) {
301 // Map the whole stack with no rw permissions to avoid
302 // committing the whole region right away
303 const mmap_slice = os.mmap(
304 null,
305 mmap_len,
306 os.PROT_NONE,
307 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
308 -1,
309 0,
310 ) catch |err| switch (err) {
311 error.MemoryMappingNotSupported => unreachable,
312 error.AccessDenied => unreachable,
313 error.PermissionDenied => unreachable,
314 else => |e| return e,
315 };
316 errdefer os.munmap(mmap_slice);
317
318 // Map everything but the guard page as rw
319 os.mprotect(
320 mmap_slice[guard_end_offset..],
321 os.PROT_READ | os.PROT_WRITE,
322 ) catch |err| switch (err) {
323 error.AccessDenied => unreachable,
324 else => |e| return e,
325 };
326
327 break :mem mmap_slice;
328 } else {
329 // NetBSD mprotect is very strict and doesn't allow to "upgrade"
330 // a PROT_NONE mapping to a RW one so let's allocate everything
331 // right away
332 const mmap_slice = os.mmap(
333 null,
334 mmap_len,
335 os.PROT_READ | os.PROT_WRITE,
336 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
337 -1,
338 0,
339 ) catch |err| switch (err) {
340 error.MemoryMappingNotSupported => unreachable,
341 error.AccessDenied => unreachable,
342 error.PermissionDenied => unreachable,
343 else => |e| return e,
344 };
345 errdefer os.munmap(mmap_slice);
346
347 // Remap the guard page with no permissions
348 os.mprotect(
349 mmap_slice[0..guard_end_offset],
350 os.PROT_NONE,
351 ) catch |err| switch (err) {
352 error.AccessDenied => unreachable,
353 else => |e| return e,
354 };
355
356 break :mem mmap_slice;
357 }
321358 };
322359
323360 const mmap_addr = @ptrToInt(mmap_slice.ptr);
......@@ -338,7 +375,17 @@ pub const Thread = struct {
338375 if (c.pthread_attr_init(&attr) != 0) return error.SystemResources;
339376 defer assert(c.pthread_attr_destroy(&attr) == 0);
340377
341 assert(c.pthread_attr_setstack(&attr, mmap_slice.ptr, stack_end_offset) == 0);
378 // Tell pthread where the effective stack start is and its size
379 assert(c.pthread_attr_setstack(
380 &attr,
381 mmap_slice.ptr + guard_end_offset,
382 stack_end_offset - guard_end_offset,
383 ) == 0);
384 // Even though pthread's man pages state that the guard size is
385 // ignored when the stack address is explicitly given, on some
386 // plaforms such as NetBSD we still have to zero it to prevent
387 // random crashes in pthread_join calls
388 assert(c.pthread_attr_setguardsize(&attr, 0) == 0);
342389
343390 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
344391 switch (err) {
src/link.cpp+3-1
......@@ -1799,7 +1799,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
17991799 lj->args.append("-lm");
18001800 }
18011801
1802 if (g->zig_target->os == OsFreeBSD) {
1802 if (g->zig_target->os == OsFreeBSD ||
1803 g->zig_target->os == OsNetBSD)
1804 {
18031805 lj->args.append("-lpthread");
18041806 }
18051807 } else if (target_is_glibc(g->zig_target)) {
src/os.cpp-3
......@@ -1161,9 +1161,6 @@ Error os_update_file(Buf *src_path, Buf *dst_path) {
11611161 fclose(dst_libc_file);
11621162 return err;
11631163 }
1164 if (fflush(src_libc_file) == -1) {
1165 return ErrorUnexpected;
1166 }
11671164 if (fflush(dst_libc_file) == -1) {
11681165 return ErrorUnexpected;
11691166 }