mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-31 10:22:08 +00:00
Add core/hyperthread count to `core:sys/info` for Windows and Linux. TODO: Linux RISCV, Linux ARM, Darwin, and the BSDs.
637 lines
16 KiB
Odin
637 lines
16 KiB
Odin
package sys_freebsd
|
|
|
|
/*
|
|
(c) Copyright 2024 Feoramund <rune@swevencraft.org>.
|
|
Made available under Odin's BSD-3 license.
|
|
|
|
List of contributors:
|
|
Feoramund: Initial implementation.
|
|
*/
|
|
|
|
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_read : uintptr : 3
|
|
SYS_write : uintptr : 4
|
|
SYS_open : uintptr : 5
|
|
SYS_close : uintptr : 6
|
|
SYS_getpid : uintptr : 20
|
|
SYS_recvfrom : uintptr : 29
|
|
SYS_accept : uintptr : 30
|
|
SYS_getpeername: uintptr : 31
|
|
SYS_getsockname: uintptr : 32
|
|
SYS_fcntl : uintptr : 92
|
|
SYS_fsync : uintptr : 95
|
|
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_pread : uintptr : 475
|
|
SYS_pwrite : uintptr : 476
|
|
SYS_accept4 : uintptr : 541
|
|
|
|
//
|
|
// Odin syscall wrappers
|
|
//
|
|
|
|
// Read input.
|
|
//
|
|
// The read() function appeared in Version 1 AT&T UNIX.
|
|
read :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) {
|
|
result, ok := intrinsics.syscall_bsd(SYS_read,
|
|
cast(uintptr)fd,
|
|
cast(uintptr)raw_data(buf),
|
|
cast(uintptr)len(buf))
|
|
|
|
if !ok {
|
|
return 0, cast(Errno)result
|
|
}
|
|
|
|
return cast(int)result, nil
|
|
}
|
|
|
|
// Write output.
|
|
//
|
|
// The write() function appeared in Version 1 AT&T UNIX.
|
|
write :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) {
|
|
result, ok := intrinsics.syscall_bsd(SYS_pwrite,
|
|
cast(uintptr)fd,
|
|
cast(uintptr)raw_data(buf),
|
|
cast(uintptr)len(buf))
|
|
|
|
if !ok {
|
|
return 0, cast(Errno)result
|
|
}
|
|
|
|
return cast(int)result, nil
|
|
}
|
|
|
|
// 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 {
|
|
// This 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)
|
|
|
|
// `from.len` will be modified by the syscall, so we shouldn't need to pass
|
|
// `fromlen` back from this API.
|
|
|
|
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 }
|
|
|
|
getsockname_or_peername :: proc "contextless" (s: Fd, sockaddr: ^$T, is_peer: bool) -> Errno {
|
|
// 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(
|
|
is_peer ? SYS_getpeername : SYS_getsockname,
|
|
cast(uintptr)s,
|
|
cast(uintptr)sockaddr,
|
|
cast(uintptr)&addrlen)
|
|
|
|
if !ok {
|
|
return cast(Errno)result
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Get name of connected peer
|
|
//
|
|
// The getpeername() system call appeared in 4.2BSD.
|
|
getpeername :: proc "contextless" (s: Fd, sockaddr: ^$T) -> Errno {
|
|
return getsockname_or_peername(s, sockaddr, true)
|
|
}
|
|
|
|
// Get socket name.
|
|
//
|
|
// The getsockname() system call appeared in 4.2BSD.
|
|
getsockname :: proc "contextless" (s: Fd, sockaddr: ^$T) -> Errno {
|
|
return getsockname_or_peername(s, sockaddr, false)
|
|
}
|
|
|
|
// Synchronize changes to a file.
|
|
//
|
|
// The fsync() system call appeared in 4.2BSD.
|
|
fsync :: proc "contextless" (fd: Fd) -> Errno {
|
|
result, _ := intrinsics.syscall_bsd(SYS_fsync,
|
|
cast(uintptr)fd)
|
|
|
|
return cast(Errno)result
|
|
}
|
|
|
|
// 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,
|
|
(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: Userland_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
|
|
}
|
|
|
|
// Read input without modifying the file pointer.
|
|
//
|
|
// The pread() function appeared in AT&T System V Release 4 UNIX.
|
|
pread :: proc "contextless" (fd: Fd, buf: []u8, offset: off_t) -> (int, Errno) {
|
|
result, ok := intrinsics.syscall_bsd(SYS_pread,
|
|
cast(uintptr)fd,
|
|
cast(uintptr)raw_data(buf),
|
|
cast(uintptr)len(buf),
|
|
cast(uintptr)offset)
|
|
|
|
if !ok {
|
|
return 0, cast(Errno)result
|
|
}
|
|
|
|
return cast(int)result, nil
|
|
}
|
|
|
|
// Write output without modifying the file pointer.
|
|
//
|
|
// The pwrite() function appeared in AT&T System V Release 4 UNIX.
|
|
//
|
|
// BUGS
|
|
//
|
|
// The pwrite() system call appends the file without changing the file
|
|
// offset if O_APPEND is set, contrary to IEEE Std 1003.1-2008 (“POSIX.1”)
|
|
// where pwrite() writes into offset regardless of whether O_APPEND is set.
|
|
pwrite :: proc "contextless" (fd: Fd, buf: []u8, offset: off_t) -> (int, Errno) {
|
|
result, ok := intrinsics.syscall_bsd(SYS_pwrite,
|
|
cast(uintptr)fd,
|
|
cast(uintptr)raw_data(buf),
|
|
cast(uintptr)len(buf),
|
|
cast(uintptr)offset)
|
|
|
|
if !ok {
|
|
return 0, cast(Errno)result
|
|
}
|
|
|
|
return cast(int)result, nil
|
|
}
|
|
|
|
// 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 }
|