Skip to content

Commit

Permalink
improvment: Preliminary support of OpenBSD/amd64 (#3817)
Browse files Browse the repository at this point in the history
This commit allows to run `sandbox3/run` on OpenBSD-7.5 which should be
released soon. With probability almost 1 it should run on 7.4 and
OpenBSD before than.

Regarding testing:
 - `sbt test-sandbox-gc` works;
 - `sbt test-runtime` works as well.
  • Loading branch information
catap committed Mar 10, 2024
1 parent cea5002 commit d95b063
Show file tree
Hide file tree
Showing 46 changed files with 339 additions and 90 deletions.
2 changes: 1 addition & 1 deletion clib/src/main/resources/scala-native/locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ _Static_assert(offsetof(struct scalanative_lconv, int_p_cs_precedes) ==
offsetof(struct lconv, int_p_cs_precedes),
"Unexpected offset: scalanative_lconv.int_p_cs_precedes");

#ifdef __linux__
#if defined(__linux__) || defined(__OpenBSD__)
_Static_assert(offsetof(struct scalanative_lconv, int_n_cs_precedes) ==
offsetof(struct lconv, int_n_cs_precedes),
"Unexpected offset: scalanative_lconv.int_n_cs_precedes");
Expand Down
6 changes: 3 additions & 3 deletions clib/src/main/scala/scala/scalanative/libc/locale.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package scala.scalanative
package libc

import scalanative.unsafe._
import scalanative.meta.LinktimeInfo.isLinux
import scalanative.meta.LinktimeInfo.{isLinux, isOpenBSD}

/** ISO/IEC C definitions for locale.h
*
Expand Down Expand Up @@ -105,11 +105,11 @@ object localeOpsImpl {
def n_sign_posn(ptr: Ptr[lconv]): CChar = ptr._18
def int_p_cs_precedes(ptr: Ptr[lconv]): CChar = ptr._19._1
def int_p_sep_by_space(ptr: Ptr[lconv]): CChar =
if (isLinux) ptr._19._2
if (isLinux || isOpenBSD) ptr._19._2
else ptr._19._3 // macOS & probably BSDs

def int_n_cs_precedes(ptr: Ptr[lconv]): CChar =
if (isLinux) ptr._19._3
if (isLinux || isOpenBSD) ptr._19._3
else ptr._19._2 // macOS & probably BSDs

def int_n_sep_by_space(ptr: Ptr[lconv]): CChar = ptr._19._4
Expand Down
15 changes: 15 additions & 0 deletions docs/user/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ instructions for your operating system.
$ pkg install sbt
```

**OpenBSD**

``` shell
$ pkg_add sbt
```

## Installing clang and runtime dependencies

Scala Native requires Clang, which is part of the
Expand Down Expand Up @@ -103,6 +109,15 @@ $ pkg install boehm-gc # optional
*Note 3:* Using the boehm GC with multi-threaded binaries doesn\'t work
out-of-the-box yet.

**OpenBSD 7.5 and later**

*Note 1:* OpenBSD support is experimental and limited to only AMD64
architecture.

``` shell
$ pkg_add boehm-gc # optional
```

**Nix/NixOS**

``` shell
Expand Down
4 changes: 2 additions & 2 deletions javalib/src/main/resources/scala-native/net/if_dl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
// Does not exist on Linux, so no check
#else // macOS, FreeBSD, etc.

#if defined(__FreeBSD__)
// Make u_* types required/used by FreeBSD net/if_dl.h available
#if defined(__FreeBSD__) || defined(__OpenBSD__)
// Make u_* types required/used by FreeBSD / OpenBSD net/if_dl.h available
#undef __BSD_VISIBLE
#define __BSD_VISIBLE 1
#include <sys/types.h> // size_t
Expand Down
4 changes: 3 additions & 1 deletion javalib/src/main/resources/scala-native/time_nano.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ long long scalanative_nano_time() {
#else
#if defined(__FreeBSD__)
int clock = CLOCK_MONOTONIC_PRECISE; // OS has no CLOCK_MONOTONIC_RAW
#elif defined(__OpenBSD__)
int clock = CLOCK_MONOTONIC; // OpenBSD has only CLOCK_MONOTONIC
#else // Linux, macOS
int clock = CLOCK_MONOTONIC_RAW;
#endif // !FreeBSD
#endif // !FreeBSD || !OpenBSD

// return value of 0 is success
struct timespec ts;
Expand Down
33 changes: 28 additions & 5 deletions javalib/src/main/scala/java/net/NetworkInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,20 @@ object NetworkInterface {
): Option[InterfaceAddress] = {

def decodePrefixLength(sa: Ptr[sockaddr]): Short = {
val af =
// When interface has IPv4 and IPv6 OpenBSD sets AF_UNSPEC as
// sa_family on IPv4's netmask's sockaddr, recover to AF_INET.
if (LinktimeInfo.isOpenBSD) {
val af = sa.sa_family
if (af == AF_UNSPEC) AF_INET else af
} else sa.sa_family

val result =
if (sa.sa_family.toInt == AF_INET) {
if (af == AF_INET) {
val sin4 = sa.asInstanceOf[Ptr[sockaddr_in]]
val mask = sin4.sin_addr.s_addr.toInt
Integer.bitCount(mask)
} else if (sa.sa_family.toInt == AF_INET6) {
} else if (af == AF_INET6) {
val sin6 = sa.asInstanceOf[Ptr[sockaddr_in6]]
val longs =
sin6.sin6_addr.at1.at(0).asInstanceOf[Ptr[scala.Long]]
Expand Down Expand Up @@ -979,15 +987,30 @@ private object macOsIf {
* u_int32_t ifi_mtu; // maximum transmission unit
*/

/* Reference: OpenBSD 7.5
* /usr/include/net/if.h
*
* struct if_data {
* // generic interface information
* u_char ifi_type; // ethernet, tokenring, etc.
* u_char ifi_addrlen; // media address length
* u_char ifi_hdrlen; // media header length
* u_char ifi_link_state; // current link state
* u_int32_t ifi_mtu; // maximum transmission unit
*/

// Incomplete
type if_data = CStruct2[
CLongLong, // Placeholder, consolidate & skip fields of no interest.
type if_data = CStruct3[
CUnsignedInt, // Placeholder, consolidate & skip fields of no interest.
CUnsignedInt, // ifi_mtu or placeholder
CUnsignedInt // ifi_mtu
]

// Incomplete, corresponding to incomplete if_data just above.
implicit class ifDataOps(val ptr: Ptr[if_data]) extends AnyVal {
def ifi_mtu: CUnsignedInt = ptr._2
def ifi_mtu: CUnsignedInt =
if (LinktimeInfo.isOpenBSD) ptr._2
else ptr._3
}
// ifi fields read-only fields in use, so no Ops here to set them.
}
Expand Down
4 changes: 2 additions & 2 deletions nativelib/src/main/resources/scala-native/delimcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#if defined(__aarch64__) // ARM64
#define ASM_JMPBUF_SIZE 192
#define JMPBUF_STACK_POINTER_OFFSET (104 / 8)
#elif defined(__x86_64__) && \
(defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
#elif defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__) || \
defined(__FreeBSD__) || defined(__OpenBSD__))
#define ASM_JMPBUF_SIZE 72
#define JMPBUF_STACK_POINTER_OFFSET (16 / 8)
#elif defined(__i386__) && \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
#if defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__))

/* ----------------------------------------------------------------------------
Copyright (c) 2016, Microsoft Research, Daan Leijen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ long long Time_current_nanos() {
#else
#if defined(__FreeBSD__)
int clock = CLOCK_MONOTONIC_PRECISE; // OS has no CLOCK_MONOTONIC_RAW
#elif defined(__OpenBSD__)
int clock = CLOCK_MONOTONIC; // OpenBSD has only CLOCK_MONOTONIC
#else // Linux, macOS
int clock = CLOCK_MONOTONIC_RAW;
#endif // !FreeBSD
#endif // !FreeBSD || !OpenBSD

// return value of 0 is success
struct timespec ts;
Expand Down
8 changes: 8 additions & 0 deletions nativelib/src/main/resources/scala-native/platform/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ int scalanative_platform_is_freebsd() {
#endif
}

int scalanative_platform_is_openbsd() {
#if defined(__OpenBSD__)
return 1;
#else
return 0;
#endif
}

int scalanative_platform_is_linux() {
#ifdef __linux__
return 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ object LinktimeInfo {
@resolvedAtLinktime
def isFreeBSD: Boolean = target.os == "freebsd"

@resolvedAtLinktime
def isOpenBSD: Boolean = target.os == "openbsd"

@resolvedAtLinktime("scala.scalanative.meta.linktimeinfo.is32BitPlatform")
def is32BitPlatform: Boolean = resolved

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ object Platform {
@name("scalanative_platform_is_freebsd")
def isFreeBSD(): Boolean = extern

@name("scalanative_platform_is_openbsd")
def isOpenBSD(): Boolean = extern

@name("scalanative_platform_is_linux")
def isLinux(): Boolean = extern

Expand Down
8 changes: 7 additions & 1 deletion posixlib/src/main/resources/scala-native/dirent.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ int scalanative_dt_blk() { return DT_BLK; }
int scalanative_dt_reg() { return DT_REG; }
int scalanative_dt_lnk() { return DT_LNK; }
int scalanative_dt_sock() { return DT_SOCK; }
int scalanative_dt_wht() { return DT_WHT; }
int scalanative_dt_wht() {
#ifdef DW_WHT
return DT_WHT;
#else
return 0;
#endif
}

DIR *scalanative_opendir(const char *name) { return opendir(name); }

Expand Down
8 changes: 7 additions & 1 deletion posixlib/src/main/resources/scala-native/errno.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,13 @@ int scalanative_enoexec() { return ENOEXEC; }

int scalanative_enolck() { return ENOLCK; }

int scalanative_enolink() { return ENOLINK; }
int scalanative_enolink() {
#ifdef ENOLINK
return ENOLINK;
#else
return 0;
#endif
}

int scalanative_enomem() { return ENOMEM; }

Expand Down
8 changes: 8 additions & 0 deletions posixlib/src/main/resources/scala-native/langinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@
#define CRNCYSTR -1
#endif // _WIN32

#if defined(__OpenBSD__)
#define ERA -1
#define ERA_D_FMT -1
#define ERA_D_T_FMT -1
#define ERA_T_FMT -1
#define ALT_DIGITS -1
#endif // OpenBSD

int scalanative_codeset() { return CODESET; };

int scalanative_d_t_fmt() { return D_T_FMT; };
Expand Down
16 changes: 14 additions & 2 deletions posixlib/src/main/resources/scala-native/netdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,21 @@ int scalanative_ai_numerichost() { return AI_NUMERICHOST; }

int scalanative_ai_numericserv() { return AI_NUMERICSERV; }

int scalanative_ai_v4mapped() { return AI_V4MAPPED; }
int scalanative_ai_v4mapped() {
#ifdef AI_V4MAPPED
return AI_V4MAPPED;
#else
return 0;
#endif
}

int scalanative_ai_all() { return AI_ALL; }
int scalanative_ai_all() {
#ifdef AI_ALL
return AI_ALL;
#else
return 0;
#endif
}

int scalanative_ai_addrconfig() { return AI_ADDRCONFIG; }

Expand Down
3 changes: 3 additions & 0 deletions posixlib/src/main/resources/scala-native/netinet/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#define WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#else
#ifdef __OpenBSD__
#include <sys/types.h>
#endif
#include <netinet/tcp.h>
#endif

Expand Down
25 changes: 25 additions & 0 deletions posixlib/src/main/resources/scala-native/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@
(defined(__APPLE__) && defined(__MACH__))
#include <signal.h>

#ifdef __OpenBSD__

// OpenBSD doesn't implenent SIGEB_ signals, use 0 instead
#define SIGEV_NONE 0
#define SIGEV_SIGNAL 0
#define SIGEV_THREAD 0

// nor SIGPOLL
#define POLL_IN 0
#define POLL_OUT 0
#define POLL_MSG 0
#define POLL_ERR 0
#define POLL_PRI 0
#define POLL_HUP 0
#define NSIGPOLL 0

// nor SIGPROF
#define PROF_SIG 0
#define NSIGPROF 0

// SI_ASYNCIO and SI_MESGQ are missed as well
#define SI_ASYNCIO 0
#define SI_MESGQ 0
#endif

// symbolic constants - see signal.scala
// some missing are deprecated or not supported
// others missing can be found in clib
Expand Down
8 changes: 7 additions & 1 deletion posixlib/src/main/resources/scala-native/sys/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ rlim_t scalanative_rlim_saved_cur() { return RLIM_SAVED_CUR; };

rlim_t scalanative_rlim_saved_max() { return RLIM_SAVED_MAX; };

int scalanative_rlimit_as() { return RLIMIT_AS; };
int scalanative_rlimit_as() {
#ifdef RLIMIT_AS
return RLIMIT_AS;
#else
return 0;
#endif
};

int scalanative_rlimit_core() { return RLIMIT_CORE; };

Expand Down
7 changes: 6 additions & 1 deletion posixlib/src/main/resources/scala-native/sys/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct scalanative_sockaddr_storage {
scalanative_sa_family_t ss_family;
unsigned short __opaquePadTo32;
unsigned int __opaquePadTo64;
unsigned long long __opaqueAlignStructure[15];
unsigned long long __opaqueAlignStructure[31];
};

// Also verifies that Scala Native sa_family field has the traditional size.
Expand All @@ -67,8 +67,13 @@ _Static_assert(offsetof(struct scalanative_sockaddr, sa_data) ==
offsetof(struct sockaddr, sa_data),
"offset mismatch: sockaddr sa_data");

#if defined(__OpenBSD__)
_Static_assert(sizeof(struct sockaddr_storage) == 256,
"unexpected size for sockaddr_storage");
#else
_Static_assert(sizeof(struct sockaddr_storage) == 128,
"unexpected size for sockaddr_storage");
#endif

// struct msghdr - POSIX 48 byte (padding) on 64 bit machines, 28 on 32 bit.
struct scalanative_msghdr {
Expand Down
8 changes: 7 additions & 1 deletion posixlib/src/main/resources/scala-native/syslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ int scalanative_log_debug() { return LOG_DEBUG; }
int scalanative_log_primask() { return LOG_PRIMASK; }

int scalanative_log_pri(int p) { return LOG_PRI(p); }
int scalanative_log_makepri(int fac, int pri) { return LOG_MAKEPRI(fac, pri); }
int scalanative_log_makepri(int fac, int pri) {
#ifdef LOG_MAKEPRI
return LOG_MAKEPRI(fac, pri);
#else
return fac | pri;
#endif
}

int scalanative_log_kern() { return LOG_KERN; }
int scalanative_log_user() { return LOG_USER; }
Expand Down
20 changes: 20 additions & 0 deletions posixlib/src/main/resources/scala-native/termios.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@
#define VTDLY VTDELAY
#endif

#if defined(__OpenBSD__)
// OpenBSD has missed some constatn, use 0 instead
#define NLDLY 0
#define CRDLY 0
#define BSDLY 0
#define VTDLY 0
#define BS0 0
#define BS1 0
#define CR0 0
#define CR1 0
#define CR2 0
#define CR3 0
#define FF0 0
#define FF1 0
#define NL0 0
#define NL1 0
#define TAB1 0
#define TAB2 0
#endif

// symbolic constants for use as subscripts for the array c_cc

int scalanative_termios_veof() { return VEOF; }
Expand Down

0 comments on commit d95b063

Please sign in to comment.