Add core:sys/freebsd

This commit is contained in:
Feoramund
2024-06-26 01:11:37 -04:00
parent 8d1827838f
commit c61f5bbfe7
2 changed files with 2083 additions and 0 deletions

View File

@@ -0,0 +1,504 @@
package sys_freebsd
import "base:intrinsics"
import "core:c"
// FreeBSD 15 syscall numbers
// See: https://alfonsosiciliano.gitlab.io/posts/2023-08-28-freebsd-15-system-calls.html
SYS_open : uintptr : 5
SYS_close : uintptr : 6
SYS_getpid : uintptr : 20
SYS_recvfrom : uintptr : 29
SYS_accept : uintptr : 30
SYS_fcntl : uintptr : 92
SYS_socket : uintptr : 97
SYS_connect : uintptr : 98
SYS_bind : uintptr : 104
SYS_listen : uintptr : 106
SYS_sendto : uintptr : 133
SYS_shutdown : uintptr : 134
SYS_setsockopt : uintptr : 105
SYS_sysctl : uintptr : 202
SYS__umtx_op : uintptr : 454
SYS_accept4 : uintptr : 541
//
// Odin syscall wrappers
//
// Open or create a file for reading, writing or executing.
//
// The open() function appeared in Version 1 AT&T UNIX.
// The openat() function was introduced in FreeBSD 8.0.
open :: proc "contextless" (path: string, flags: File_Status_Flags, mode: int = 0o000) -> (Fd, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_open,
cast(uintptr)raw_data(path),
cast(uintptr)transmute(c.int)flags,
cast(uintptr)mode)
if !ok {
return 0, cast(Errno)result
}
return cast(Fd)result, nil
}
// Delete a descriptor.
//
// The open() function appeared in Version 1 AT&T UNIX.
close :: proc "contextless" (fd: Fd) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_close,
cast(uintptr)fd)
return cast(Errno)result
}
// Get parent or calling process identification.
//
// The getpid() function appeared in Version 7 AT&T UNIX.
getpid :: proc "contextless" () -> pid_t {
// always succeeds
result, _ := intrinsics.syscall_bsd(SYS_getpid)
return cast(pid_t)result
}
// Receive message(s) from a socket.
//
// The recv() function appeared in 4.2BSD.
// The recvmmsg() function appeared in FreeBSD 11.0.
recvfrom :: proc "contextless" (s: Fd, buf: []u8, flags: Recv_Flags, from: ^$T) -> (int, Errno)
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
fromlen: socklen_t = size_of(T)
result, ok := intrinsics.syscall_bsd(SYS_recvfrom,
cast(uintptr)s,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf),
cast(uintptr)flags,
cast(uintptr)from,
cast(uintptr)fromlen)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Receive message(s) from a socket.
//
// The recv() function appeared in 4.2BSD.
// The recvmmsg() function appeared in FreeBSD 11.0.
recv :: proc "contextless" (s: Fd, buf: []u8, flags: Recv_Flags) -> (int, Errno) {
// This is a wrapper over recvfrom().
result, ok := intrinsics.syscall_bsd(SYS_recvfrom,
cast(uintptr)s,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf),
cast(uintptr)flags,
0,
0)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Accept a connection on a socket.
//
// The accept() system call appeared in 4.2BSD.
accept_T :: proc "contextless" (s: Fd, sockaddr: ^$T) -> (Fd, Errno)
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
// sockaddr must contain a valid pointer, or this will segfault because
// we're telling the syscall that there's memory available to write to.
addrlen: socklen_t = size_of(T)
result, ok := intrinsics.syscall_bsd(SYS_accept,
cast(uintptr)s,
cast(uintptr)sockaddr,
cast(uintptr)&addrlen)
if !ok {
return 0, cast(Errno)result
}
sockaddr.len = cast(u8)addrlen
return cast(Fd)result, nil
}
// Accept a connection on a socket.
//
// The accept() system call appeared in 4.2BSD.
accept_nil :: proc "contextless" (s: Fd) -> (Fd, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_accept,
cast(uintptr)s,
cast(uintptr)0,
cast(uintptr)0)
if !ok {
return 0, cast(Errno)result
}
return cast(Fd)result, nil
}
accept :: proc { accept_T, accept_nil }
// File control.
//
// The fcntl() system call appeared in 4.2BSD.
// The F_DUP2FD constant first appeared in FreeBSD 7.1.
//
// NOTE: If you know at compile-time what command you're calling, use one of the
// `fcntl_*` procedures instead to preserve type safety.
fcntl :: proc "contextless" (fd: Fd, cmd: File_Control_Command, arg: c.int) -> (int, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)cmd,
cast(uintptr)arg)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// TODO: Implement more type-safe fcntl commands.
fcntl_dupfd :: proc "contextless" (fd: Fd, newfd: Fd) -> (Fd, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.DUPFD,
cast(uintptr)newfd)
if !ok {
return 0, cast(Errno)result
}
return cast(Fd)result, nil
}
fcntl_getfd :: proc "contextless" (fd: Fd) -> (bool, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.GETFD)
if !ok {
return false, cast(Errno)result
}
return result & FD_CLOEXEC > 0, nil
}
fcntl_setfd :: proc "contextless" (fd: Fd, close_on_exec: bool) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.SETFD,
cast(uintptr)(close_on_exec ? FD_CLOEXEC : 0))
return cast(Errno)result
}
fcntl_getfl :: proc "contextless" (fd: Fd) -> (File_Status_Flags, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.GETFL)
if !ok {
return nil, cast(Errno)result
}
return transmute(File_Status_Flags)cast(c.int)result, nil
}
fcntl_setfl :: proc "contextless" (fd: Fd, flags: File_Status_Flags) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.SETFL,
cast(uintptr)transmute(c.int)flags)
return cast(Errno)result
}
fcntl_getown :: proc "contextless" (fd: Fd) -> (pid_t, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.GETOWN)
if !ok {
return 0, cast(Errno)result
}
return cast(pid_t)result, nil
}
fcntl_setown :: proc "contextless" (fd: Fd, pid: pid_t) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.SETOWN,
cast(uintptr)pid)
return cast(Errno)result
}
fcntl_getlk :: proc "contextless" (fd: Fd, flock: ^File_Lock) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.GETLK,
cast(uintptr)flock)
return cast(Errno)result
}
fcntl_setlk :: proc "contextless" (fd: Fd, flock: ^File_Lock) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.SETLK,
cast(uintptr)flock)
return cast(Errno)result
}
fcntl_add_seals :: proc "contextless" (fd: Fd, seals: File_Seals) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.ADD_SEALS,
cast(uintptr)transmute(c.int)seals)
return cast(Errno)result
}
fcntl_get_seals :: proc "contextless" (fd: Fd) -> (File_Seals, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_fcntl,
cast(uintptr)fd,
cast(uintptr)File_Control_Command.GET_SEALS)
if !ok {
return nil, cast(Errno)result
}
return transmute(File_Seals)cast(c.int)result, nil
}
//
// End type-safe fcntl commands.
//
// Create an endpoint for communication.
//
// The socket() system call appeared in 4.2BSD.
socket :: proc "contextless" (domain: Protocol_Family, type: Socket_Type, protocol: Protocol) -> (Fd, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_socket,
cast(uintptr)domain,
cast(uintptr)type,
cast(uintptr)protocol)
if !ok {
return 0, cast(Errno)result
}
return cast(Fd)result, nil
}
// Initiate a connection on a socket.
//
// The connect() system call appeared in 4.2BSD.
connect :: proc "contextless" (fd: Fd, sockaddr: ^$T, addrlen: socklen_t) -> Errno
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
result, _ := intrinsics.syscall_bsd(SYS_connect,
cast(uintptr)fd,
cast(uintptr)sockaddr,
cast(uintptr)addrlen)
return cast(Errno)result
}
// Assign a local protocol address to a socket.
//
// The bind() system call appeared in 4.2BSD.
bind :: proc "contextless" (s: Fd, sockaddr: ^$T, addrlen: socklen_t) -> Errno
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
result, _ := intrinsics.syscall_bsd(SYS_bind,
cast(uintptr)s,
cast(uintptr)sockaddr,
cast(uintptr)addrlen)
return cast(Errno)result
}
// Listen for connections on a socket.
//
// The listen() system call appeared in 4.2BSD.
listen :: proc "contextless" (s: Fd, backlog: int) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_listen,
cast(uintptr)s,
cast(uintptr)backlog)
return cast(Errno)result
}
// Send message(s) from a socket.
//
// The send() function appeared in 4.2BSD.
// The sendmmsg() function appeared in FreeBSD 11.0.
sendto :: proc "contextless" (s: Fd, msg: []u8, flags: Send_Flags, to: ^$T) -> (int, Errno)
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
result, ok := intrinsics.syscall_bsd(SYS_sendto,
cast(uintptr)s,
cast(uintptr)raw_data(msg),
cast(uintptr)len(msg),
cast(uintptr)flags,
cast(uintptr)to,
cast(uintptr)to.len)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Send message(s) from a socket.
//
// The send() function appeared in 4.2BSD.
// The sendmmsg() function appeared in FreeBSD 11.0.
send :: proc "contextless" (s: Fd, msg: []u8, flags: Send_Flags) -> (int, Errno) {
// This is a wrapper over sendto().
result, ok := intrinsics.syscall_bsd(SYS_sendto,
cast(uintptr)s,
cast(uintptr)raw_data(msg),
cast(uintptr)len(msg),
cast(uintptr)flags,
0,
0)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Disable sends and/or receives on a socket.
//
// The shutdown() system call appeared in 4.2BSD.
shutdown :: proc "contextless" (s: Fd, how: Shutdown_Method) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_shutdown,
cast(uintptr)s,
cast(uintptr)how)
return cast(Errno)result
}
// Get and set options on sockets.
//
// The getsockopt() and setsockopt() system calls appeared in 4.2BSD.
setsockopt :: proc "contextless" (s: Fd, level: Valid_Socket_Option_Level, optname: Socket_Option, optval: rawptr, optlen: socklen_t) -> Errno {
real_level: uintptr
switch which in level {
case Protocol_Family: real_level = cast(uintptr)which
case Socket_Option_Level: real_level = cast(uintptr)which
}
result, _ := intrinsics.syscall_bsd(SYS_setsockopt,
cast(uintptr)s,
real_level,
cast(uintptr)optname,
cast(uintptr)optval,
cast(uintptr)optlen)
return cast(Errno)result
}
// Get or set system information.
//
// The sysctl() function first appeared in 4.4BSD.
sysctl :: proc "contextless" (mib: []MIB_Identifier, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS_sysctl,
cast(uintptr)raw_data(mib),
cast(uintptr)len(mib),
cast(uintptr)oldp,
cast(uintptr)oldlenp,
cast(uintptr)newp,
cast(uintptr)newlen)
return cast(Errno)result
}
// Interface for implementation of userspace threading synchronization primitives.
//
// The _umtx_op() system call is non-standard and is used by the 1:1 Threading
// Library (libthr, -lthr) to implement IEEE Std 1003.1-2001 (“POSIX.1”)
// pthread(3) functionality.
_umtx_op :: proc "contextless" (obj: rawptr, op: Mutex_Operation, val: c.ulong, uaddr, uaddr2: rawptr) -> Errno {
result, _ := intrinsics.syscall_bsd(SYS__umtx_op,
cast(uintptr)obj,
cast(uintptr)op,
cast(uintptr)val,
cast(uintptr)uaddr,
cast(uintptr)uaddr2)
return cast(Errno)result
}
// Accept a connection on a socket.
//
// The accept4() system call appeared in FreeBSD 10.0.
accept4_T :: proc "contextless" (s: Fd, sockaddr: ^$T, flags: Socket_Flags = {}) -> (Fd, Errno)
where
intrinsics.type_is_subtype_of(T, Socket_Address_Header)
{
// sockaddr must contain a valid pointer, or this will segfault because
// we're telling the syscall that there's memory available to write to.
addrlen: u32 = size_of(T)
result, ok := intrinsics.syscall_bsd(SYS_accept4,
cast(uintptr)s,
cast(uintptr)sockaddr,
cast(uintptr)&addrlen,
cast(uintptr)transmute(c.int)flags)
if !ok {
return 0, cast(Errno)result
}
sockaddr.len = cast(u8)addrlen
return cast(Fd)result, nil
}
// Accept a connection on a socket.
//
// The accept4() system call appeared in FreeBSD 10.0.
accept4_nil :: proc "contextless" (s: Fd, flags: Socket_Flags = {}) -> (Fd, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_accept4,
cast(uintptr)s,
cast(uintptr)0,
cast(uintptr)0,
cast(uintptr)transmute(c.int)flags)
if !ok {
return 0, cast(Errno)result
}
return cast(Fd)result, nil
}
accept4 :: proc { accept4_nil, accept4_T }

1579
core/sys/freebsd/types.odin Normal file

File diff suppressed because it is too large Load Diff