Merge pull request #7546 from hoanga/haiku-support

initial support for haiku
This commit is contained in:
Andrew Kelley 2021-02-25 16:00:00 -08:00 committed by GitHub
commit 7edb204edf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1707 additions and 43 deletions

View File

@ -487,31 +487,42 @@ pub const CpuCountError = error{
};
pub fn cpuCount() CpuCountError!usize {
if (std.Target.current.os.tag == .linux) {
const cpu_set = try os.sched_getaffinity(0);
return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast
switch (std.Target.current.os.tag) {
.linux => {
const cpu_set = try os.sched_getaffinity(0);
return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast
},
.windows => {
return os.windows.peb().NumberOfProcessors;
},
.openbsd => {
var count: c_int = undefined;
var count_size: usize = @sizeOf(c_int);
const mib = [_]c_int{ os.CTL_HW, os.HW_NCPUONLINE };
os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) {
error.NameTooLong, error.UnknownName => unreachable,
else => |e| return e,
};
return @intCast(usize, count);
},
.haiku => {
var count: u32 = undefined;
var system_info: os.system_info = undefined;
const rc = os.system.get_system_info(&system_info);
count = system_info.cpu_count;
return @intCast(usize, count);
},
else => {
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu";
os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) {
error.NameTooLong, error.UnknownName => unreachable,
else => |e| return e,
};
return @intCast(usize, count);
},
}
if (std.Target.current.os.tag == .windows) {
return os.windows.peb().NumberOfProcessors;
}
if (std.Target.current.os.tag == .openbsd) {
var count: c_int = undefined;
var count_size: usize = @sizeOf(c_int);
const mib = [_]c_int{ os.CTL_HW, os.HW_NCPUONLINE };
os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) {
error.NameTooLong, error.UnknownName => unreachable,
else => |e| return e,
};
return @intCast(usize, count);
}
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu";
os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) {
error.NameTooLong, error.UnknownName => unreachable,
else => |e| return e,
};
return @intCast(usize, count);
}
pub fn getCurrentThreadId() u64 {
@ -538,6 +549,9 @@ pub fn getCurrentThreadId() u64 {
.openbsd => {
return @bitCast(u32, c.getthrid());
},
.haiku => {
return @bitCast(u32, c.find_thread(null));
},
else => {
@compileError("getCurrentThreadId not implemented for this platform");
},

View File

@ -3,6 +3,49 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
//
const std = @import("../std.zig");
const builtin = std.builtin;
usingnamespace std.c;
extern "c" fn _errnop() *c_int;
pub const _errno = _errnop;
pub extern "c" fn find_directory(which: c_int, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
pub extern "c" fn find_thread(thread_name: ?*c_void) i32;
pub extern "c" fn get_system_info(system_info: *system_info) usize;
// TODO revisit if abi changes or better option becomes apparent
pub extern "c" fn _get_next_image_info(team: c_int, cookie: *i32, image_info: *image_info) usize;
pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize;
pub extern "c" fn _kern_read_stat(fd: c_int, path_ptr: [*]u8, traverse_link: bool, libc_stat: *libc_stat, stat_size: i32) usize;
pub extern "c" fn _kern_get_current_team() i32;
pub const sem_t = extern struct {
_magic: u32,
_kern: extern struct {
_count: u32,
_flags: u32,
},
_padding: u32,
};
pub const pthread_attr_t = extern struct {
__detach_state: i32,
__sched_priority: i32,
__stack_size: i32,
__guard_size: i32,
__stack_address: ?*c_void,
};
pub const pthread_mutex_t = extern struct {
flags: u32 = 0,
lock: i32 = 0,

View File

@ -29,6 +29,7 @@ const os_has_fork = switch (std.Target.current.os.tag) {
.solaris,
.tvos,
.watchos,
.haiku,
=> true,
else => false,

View File

@ -1125,12 +1125,15 @@ pub const DebugInfo = struct {
}
pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
if (comptime std.Target.current.isDarwin())
return self.lookupModuleDyld(address)
else if (builtin.os.tag == .windows)
return self.lookupModuleWin32(address)
else
if (comptime std.Target.current.isDarwin()) {
return self.lookupModuleDyld(address);
} else if (builtin.os.tag == .windows) {
return self.lookupModuleWin32(address);
} else if (builtin.os.tag == .haiku) {
return self.lookupModuleHaiku(address);
} else {
return self.lookupModuleDl(address);
}
}
fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
@ -1336,6 +1339,10 @@ pub const DebugInfo = struct {
return obj_di;
}
fn lookupModuleHaiku(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
@panic("TODO implement lookup module for Haiku");
}
};
const SymbolInfo = struct {

View File

@ -39,7 +39,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
/// fit into a UTF-8 encoded array of this length.
/// The byte count includes room for a null sentinel byte.
pub const MAX_PATH_BYTES = switch (builtin.os.tag) {
.linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd => os.PATH_MAX,
.linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku => os.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
// If it would require 4 UTF-8 bytes, then there would be a surrogate
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
@ -427,6 +427,78 @@ pub const Dir = struct {
}
}
},
.haiku => struct {
dir: Dir,
buf: [8192]u8, // TODO align(@alignOf(os.dirent64)),
index: usize,
end_index: usize,
const Self = @This();
pub const Error = IteratorError;
/// Memory such as file names referenced in this returned entry becomes invalid
/// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
pub fn next(self: *Self) Error!?Entry {
start_over: while (true) {
// TODO: find a better max
const HAIKU_MAX_COUNT = 10000;
if (self.index >= self.end_index) {
const rc = os.system._kern_read_dir(
self.dir.fd,
&self.buf,
self.buf.len,
HAIKU_MAX_COUNT,
);
if (rc == 0) return null;
if (rc < 0) {
switch (os.errno(rc)) {
os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
os.EFAULT => unreachable,
os.ENOTDIR => unreachable,
os.EINVAL => unreachable,
else => |err| return os.unexpectedErrno(err),
}
}
self.index = 0;
self.end_index = @intCast(usize, rc);
}
const haiku_entry = @ptrCast(*align(1) os.dirent, &self.buf[self.index]);
const next_index = self.index + haiku_entry.reclen();
self.index = next_index;
const name = mem.spanZ(@ptrCast([*:0]u8, &haiku_entry.d_name));
if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (haiku_entry.d_ino == 0)) {
continue :start_over;
}
var stat_info: os.libc_stat = undefined;
const rc2 = os.system._kern_read_stat(
self.dir.fd,
&haiku_entry.d_name,
false,
&stat_info,
0,
);
const statmode = stat_info.mode & os.S_IFMT;
const entry_kind = switch (statmode) {
os.S_IFDIR => Entry.Kind.Directory,
os.S_IFBLK => Entry.Kind.BlockDevice,
os.S_IFCHR => Entry.Kind.CharacterDevice,
os.S_IFLNK => Entry.Kind.SymLink,
os.S_IFREG => Entry.Kind.File,
os.S_IFIFO => Entry.Kind.NamedPipe,
else => Entry.Kind.Unknown,
};
return Entry{
.name = name,
.kind = entry_kind,
};
}
}
},
.linux => struct {
dir: Dir,
buf: [8192]u8, // TODO align(@alignOf(os.dirent64)),
@ -621,14 +693,20 @@ pub const Dir = struct {
pub fn iterate(self: Dir) Iterator {
switch (builtin.os.tag) {
.macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd => return Iterator{
.macos,
.ios,
.freebsd,
.netbsd,
.dragonfly,
.openbsd,
=> return Iterator{
.dir = self,
.seek = 0,
.index = 0,
.end_index = 0,
.buf = undefined,
},
.linux => return Iterator{
.linux, .haiku => return Iterator{
.dir = self,
.index = 0,
.end_index = 0,
@ -2339,7 +2417,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
// TODO could this slice from 0 to out_len instead?
return mem.spanZ(std.meta.assumeSentinel(out_buffer.ptr, 0));
},
.openbsd => {
.openbsd, .haiku => {
// OpenBSD doesn't support getting the path of a running process, so try to guess it
if (os.argv.len == 0)
return error.FileNotFound;

View File

@ -56,6 +56,18 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
};
return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname });
},
.haiku => {
var dir_path_ptr: [*:0]u8 = undefined;
// TODO look into directory_which
const be_user_settings = 0xbbe;
const rc = os.system.find_directory(be_user_settings, -1, true, dir_path_ptr, 1) ;
const settings_dir = try allocator.dupeZ(u8, mem.spanZ(dir_path_ptr));
defer allocator.free(settings_dir);
switch (rc) {
0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }),
else => return error.AppDataDirUnavailable,
}
},
else => @compileError("Unsupported OS"),
}
}

View File

@ -32,6 +32,7 @@ const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
pub const darwin = @import("os/darwin.zig");
pub const dragonfly = @import("os/dragonfly.zig");
pub const freebsd = @import("os/freebsd.zig");
pub const haiku = @import("os/haiku.zig");
pub const netbsd = @import("os/netbsd.zig");
pub const openbsd = @import("os/openbsd.zig");
pub const linux = @import("os/linux.zig");
@ -52,6 +53,7 @@ test {
_ = uefi;
_ = wasi;
_ = windows;
_ = haiku;
_ = @import("os/test.zig");
}
@ -66,6 +68,7 @@ else if (builtin.link_libc)
else switch (builtin.os.tag) {
.macos, .ios, .watchos, .tvos => darwin,
.freebsd => freebsd,
.haiku => haiku,
.linux => linux,
.netbsd => netbsd,
.openbsd => openbsd,
@ -599,7 +602,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
/// On these systems, the read races with concurrent writes to the same file descriptor.
pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
const have_pread_but_not_preadv = switch (std.Target.current.os.tag) {
.windows, .macos, .ios, .watchos, .tvos => true,
.windows, .macos, .ios, .watchos, .tvos, .haiku => true,
else => false,
};
if (have_pread_but_not_preadv) {
@ -932,7 +935,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
/// If `iov.len` is larger than will fit in a `u31`, a partial write will occur.
pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usize {
const have_pwrite_but_not_pwritev = switch (std.Target.current.os.tag) {
.windows, .macos, .ios, .watchos, .tvos => true,
.windows, .macos, .ios, .watchos, .tvos, .haiku => true,
else => false,
};
@ -3889,6 +3892,21 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t {
}
}
}
if (std.Target.current.os.tag == .haiku) {
var fds: [2]fd_t = try pipe();
if (flags == 0) return fds;
errdefer {
close(fds[0]);
close(fds[1]);
}
for (fds) |fd| switch (errno(system.fcntl(fd, F_SETFL, flags))) {
0 => {},
EINVAL => unreachable, // Invalid flags
EBADF => unreachable, // Always a race condition
else => |err| return unexpectedErrno(err),
};
return fds;
}
const new_flags = flags & ~@as(u32, O_CLOEXEC);
// Set every other flag affecting the file status using F_SETFL.
@ -3921,7 +3939,10 @@ pub fn sysctl(
newlen: usize,
) SysCtlError!void {
if (builtin.os.tag == .wasi) {
@panic("unsupported");
@panic("unsupported"); // TODO should be compile error, not panic
}
if (builtin.os.tag == .haiku) {
@panic("unsupported"); // TODO should be compile error, not panic
}
const name_len = math.cast(c_uint, name.len) catch return error.NameTooLong;
@ -3945,7 +3966,10 @@ pub fn sysctlbynameZ(
newlen: usize,
) SysCtlError!void {
if (builtin.os.tag == .wasi) {
@panic("unsupported");
@panic("unsupported"); // TODO should be compile error, not panic
}
if (builtin.os.tag == .haiku) {
@panic("unsupported"); // TODO should be compile error, not panic
}
switch (errno(system.sysctlbyname(name, oldp, oldlenp, newp, newlen))) {

View File

@ -15,6 +15,7 @@ pub usingnamespace switch (std.Target.current.os.tag) {
.macos, .ios, .tvos, .watchos => @import("bits/darwin.zig"),
.dragonfly => @import("bits/dragonfly.zig"),
.freebsd => @import("bits/freebsd.zig"),
.haiku => @import("bits/haiku.zig"),
.linux => @import("bits/linux.zig"),
.netbsd => @import("bits/netbsd.zig"),
.openbsd => @import("bits/openbsd.zig"),

1450
lib/std/os/bits/haiku.zig Normal file

File diff suppressed because it is too large Load Diff

8
lib/std/os/haiku.zig Normal file
View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2015-2020 Zig Contributors
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("../std.zig");
pub usingnamespace std.c;
pub usingnamespace @import("bits.zig");

View File

@ -609,7 +609,7 @@ pub const UserInfo = struct {
/// POSIX function which gets a uid from username.
pub fn getUserInfo(name: []const u8) !UserInfo {
return switch (builtin.os.tag) {
.linux, .macos, .watchos, .tvos, .ios, .freebsd, .netbsd, .openbsd => posixGetUserInfo(name),
.linux, .macos, .watchos, .tvos, .ios, .freebsd, .netbsd, .openbsd, .haiku => posixGetUserInfo(name),
else => @compileError("Unsupported OS"),
};
}
@ -777,6 +777,24 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]
}
return paths.toOwnedSlice();
},
// revisit if Haiku implements dl_iterat_phdr (https://dev.haiku-os.org/ticket/15743)
.haiku => {
var paths = List.init(allocator);
errdefer {
const slice = paths.toOwnedSlice();
for (slice) |item| {
allocator.free(item);
}
allocator.free(slice);
}
var b = "/boot/system/runtime_loader";
const item = try allocator.dupeZ(u8, mem.spanZ(b));
errdefer allocator.free(item);
try paths.append(item);
return paths.toOwnedSlice();
},
else => @compileError("getSelfExeSharedLibPaths unimplemented for this target"),
}
}

View File

@ -379,6 +379,7 @@ pub const Target = struct {
.watchos,
.dragonfly,
.openbsd,
.haiku,
=> true,
.linux,
@ -390,7 +391,6 @@ pub const Target = struct {
.kfreebsd,
.lv2,
.solaris,
.haiku,
.minix,
.rtems,
.nacl,
@ -468,7 +468,6 @@ pub const Target = struct {
.dragonfly,
.lv2,
.solaris,
.haiku,
.minix,
.rtems,
.nacl,
@ -495,6 +494,7 @@ pub const Target = struct {
.kfreebsd,
.netbsd,
.hurd,
.haiku,
=> return .gnu,
.windows,
.uefi,
@ -1562,6 +1562,9 @@ pub const Target = struct {
.other,
=> return result,
// TODO revisit when multi-arch for Haiku is available
.haiku => return copy(&result, "/system/runtime_loader"),
// TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it.
.ananas,
@ -1570,7 +1573,6 @@ pub const Target = struct {
.kfreebsd,
.lv2,
.solaris,
.haiku,
.minix,
.rtems,
.nacl,

View File

@ -196,6 +196,7 @@ pub const LibCInstallation = struct {
switch (Target.current.os.tag) {
.freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"),
.linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)),
.haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"),
else => {},
}
break :blk batch.wait();

View File

@ -61,7 +61,7 @@ typedef SSIZE_T ssize_t;
#endif
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD)
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD) || defined(ZIG_OS_HAIKU)
#include <link.h>
#endif

View File

@ -31,6 +31,8 @@
#define ZIG_OS_DRAGONFLY
#elif defined(__OpenBSD__)
#define ZIG_OS_OPENBSD
#elif defined(__HAIKU__)
#define ZIG_OS_HAIKU
#else
#define ZIG_OS_UNKNOWN
#endif

View File

@ -379,6 +379,9 @@ Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
#elif defined(ZIG_OS_OPENBSD)
*out_os = OsOpenBSD;
return ErrorNone;
#elif defined(ZIG_OS_HAIKU)
*out_os = OsHaiku;
return ErrorNone;
#else
zig_panic("stage1 is unable to detect native target for this OS");
#endif
@ -645,6 +648,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case OsDragonFly:
case OsOpenBSD:
case OsWASI:
case OsHaiku:
case OsEmscripten:
switch (id) {
case CIntTypeShort:
@ -703,7 +707,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case OsKFreeBSD:
case OsLv2:
case OsSolaris:
case OsHaiku:
case OsMinix:
case OsRTEMS:
case OsNaCl: