FreeBSD v0.1.0

Source
FreeBSD platform bindings

Installation

Add FreeBSD to the [Dependencies] table of your package's Rux.toml:

[Dependencies]
FreeBSD = { Namespace = "Rux", Version = "0.1.0" }

Standard packages are declared by hand: the registry does not serve them, so rux add Rux/FreeBSD cannot add them.

Dependencies

Guide

FreeBSD platform bindings: the raw syscall interface, with no libc in between.

What it provides

ModuleCovers
Typesthe kernel ABI's own types: ProcessId, FileDescriptor, FileOffset, FileMode, UserId, Timespec
Errorsthe errno numbers, and IsError / Errno for reading a raw result
SyscallSyscall0 through Syscall6 as inline assembly, the call numbers, and SignExtendFd
FileRead, Write, Close, OpenAt, Lseek, Fsync, Ftruncate, UnlinkAt, MkdirAt, RenameAt, Fstat, FstatAt, Dup2, Pipe2, the open flags, and the three standard descriptors
MemoryMmap, Munmap, Brk, Mprotect, Madvise, QueryPageSize, and the protection, mapping and advice flags
ClockClockGetTime, ClockGetResolution, Nanosleep, and the clock identifiers
EntropyGetRandom, the only source here fit for a key or a token
ProcessExit and GetPid
Dynamicdlopen, dlsym, dlclose, dlerror, and the RTLD_* flags
Threadpthread_create, pthread_join, pthread_detach, the pthread_attr_* stack-size calls, sched_yield, sysconf and SC_NPROCESSORS_ONLN, and pthread_getthreadid_np, linked from libthr and libc
UmtxUmtxWait and UmtxWake, the private _umtx_op(2) word operations every lock in Rux/Sync sleeps on
Spawnposix_spawnp, the posix_spawn_file_actions_* calls, waitpid, kill, fcntl and __error, linked from libc
SocketSocket, Connect, Bind, Listen, Accept4, SendTo, ReceiveFrom, Shutdown, SetSocketOption, GetSocketName and GetPeerName as system calls, with the address families, socket options and MSG_NOSIGNAL
Resolvegetaddrinfo, freeaddrinfo and AddressInfo, linked from libc
PollKqueue and KeventCall as system calls, Kevent, the EVFILT_* and EV_* flags, and FcntlInt with F_GETFL, F_SETFL and O_NONBLOCK

The module names describe where each declaration comes from; they are not part of an import path.

FreeBSD reports an error by setting the carry flag and leaving a positive errno in the result register, so a raw instruction result cannot be tested for sign. The assembly wrappers normalize that to a small negative number, which is Linux's convention, so everything above them reads the same on both systems and IsError and Errno are the same two functions.

Nothing here is interchangeable with Rux/Linux, and the resemblance is the hazard. The clock identifiers differ — monotonic is 4 here and 1 there — the open flags are the BSD ones, MADV_DONTNEED does not discard where Linux's does, and only the errno numbers below thirty-five agree. A value taken from one package and passed to the other compiles and means something else.

QueryPageSize reads the hw.pagesize sysctl, which is how FreeBSD publishes the value; there is no dedicated call and no auxiliary vector to read without libc.

The shared POSIX contract

Nothing here is interchangeable with the other POSIX packages, but the three are spelled the same, which is a different claim and a deliberate one. An equivalent call has the same wrapper name, the same parameter names and the same parameter shapes on all three systems, so a consumer such as Rux/FileSystem or Rux/Time writes one call site instead of a when #target.os ladder around three names for one idea. Tests/Unit/PlatformBindingContractTests.cpp compares the three packages' parsed sources and fails when they drift apart.

The values are the opposite: every constant is this system's own, and the same file asserts that the ones a reader might carry across really do differ.

What is tested

Tests/Packages/FreeBSD/Descriptors covers descriptor numbering, short reads and writes, end of file, size boundaries and the native error for each way of misusing a descriptor or a name. Tests/Packages/FreeBSD/Mapping covers anonymous mappings, protection changes, advice, the requests the kernel refuses, and both edges of the reserved error-result window. Tests/Packages/FreeBSD/Syscall covers the wrapper surface and the shared POSIX contract.

All of it compiles for both architectures, and none of it has ever run on a host that is not FreeBSD. Until it does, the syscall numbers, flag values and errno constants here rest on published documentation rather than on a passing test.

Values and pointers

Kernel records such as Timespec are structural values and copy by value. Syscall wrappers deliberately retain raw pointers because the kernel consumes untyped integer addresses, buffers carry separate lengths, and optional outputs may be null. Pass addresses explicitly, for example ClockGetTime(ClockMonotonic, @time), and uphold each function's safety contract. The package does not own raw addresses or descriptors; release them explicitly or use the higher-level Rux/Memory and Rux/Io packages.

Platform

FreeBSD only. Guard use behind a compile-time check, so a build for another target never resolves these declarations:

import Core::{ #target };

when #target.os {
    .FreeBSD => import FreeBSD::{ StdOut, Write }
}

Higher-level packages such as Rux/Io and Rux/Memory already do this, and are the interface to prefer unless you need the syscall itself.

AArch64 ABI

The AArch64 wrappers follow the FreeBSD syscall convention: the call number is placed in x8, up to six wrapper arguments are shifted into x0 through x5, and svc #0 enters the kernel. A carry-set return is converted from a positive errno to the negative result used by the package API.

Descriptor and clock identifiers are sign-extended before entering the generic uint64 syscall interface. Mmap likewise preserves a signed descriptor while passing the FreeBSD 15.1 mapping constants and all six arguments directly. The same source keeps a separate set of x86-64 wrappers, which reach the kernel through syscall and normalize the carry flag the same way.

Index

Types

NameSummary
KeventOne struct kevent as FreeBSD 12 and later lay it out: a change to register or an event to report.
AddressInfoThe C library's addrinfo: one result of getaddrinfo, linked to the next.
SpawnFileActionsRoom for a posix_spawn_file_actions_t, which each C library sizes its own way and none larger than this.
PThreadA thread as the C library names it, pthread_t.
PThreadAttributesRoom for a pthread_attr_t, which each C library sizes its own way and none larger than this.
ProcessIdA process identifier, as getpid and its relatives report one.
FileDescriptorA file descriptor, as the kernel numbers one.
FileOffsetA byte offset within a file, 64 bits on every supported target.
FileModeA file's type and permission bits.
UserIdA user identifier.
GroupIdA group identifier.
TimespecA duration or an instant, as seconds and nanoseconds.

Functions

NameSummary
ClockGetTimeReads clockId into time.
NanosleepSuspends the caller for the requested duration.
ClockGetResolutionReads the resolution of clockId into resolution.
dlopenLoads a shared object and returns a handle to it, or null on failure.
dlsymFinds a symbol in a loaded object and returns its address, or null.
dlcloseDrops one reference to a loaded object, unloading it when the last one goes.
dlerrorReports the most recent loader error and clears it, or returns null when there is none.
GetRandomFills up to length bytes of buffer with unpredictable bytes.
IsErrorWhether a raw system-call result is one of the normalized error values.
ErrnoThe error number a raw system-call result carries, or zero when it carries none.
ReadReads up to count bytes from fd into buffer.
WriteWrites up to count bytes from buffer to fd.
CloseCloses fd and releases what the kernel held for it.
OpenAtOpens path relative to directoryFd and returns a descriptor, or a negative error number.
LseekMoves the file offset of fd and returns where it ended up, or a negative error number.
GetcwdWrites the current working directory's absolute path into buffer, NUL-terminated.
ChdirMakes path the process's working directory.
ReadlinkAtReads the text a symbolic link holds into buffer.
FstatAtFills statBuffer with what the kernel knows about the file path names.
FchmodAtSets the permission bits of the file path names.
UtimensAtSets the access and modification times of the file path names.
LinkAtCreates a hard link: newPath becomes a second name for the file oldPath names.
SymlinkAtCreates a symbolic link at linkPath holding target as its text.
GetdirentriesReads directory entries from fd into buffer.
FsyncFlushes everything written to fd through to the storage device.
FtruncateSets the length of the file behind fd to length.
UnlinkAtRemoves the name path from its directory.
MkdirAtCreates a directory named path with permission bits mode.
RenameAtRenames oldPath to newPath, each resolved against its own directory descriptor.
FstatFills statBuffer with what the kernel knows about the file behind fd.
Dup2Makes newFd a copy of oldFd, closing whatever newFd was.
Pipe2Creates a pipe and writes its two descriptors into descriptors.
MmapCreates a mapping and returns its address, or a negative error number.
MunmapReleases the mapping that begins at address and spans length bytes.
BrkSets the program break and returns where it ended up.
MprotectChanges what may be done with the pages covering a range.
MadviseTells the kernel how the pages covering a range are about to be used.
QueryPageSizeThe size of a page, asked of the kernel.
FcntlIntPerforms command on a descriptor with an integer argument.
KqueueOpens a kqueue.
KeventCallApplies changeCount changes, then waits until an event is ready or timeout passes, filling events.
ExitEnds the calling process with code.
GetPidThe calling process's own identifier.
QueryExecutablePathWrites the absolute path of the calling process's executable into buffer, NUL-terminated.
getaddrinfoLooks up the addresses of a host and service.
freeaddrinfoFrees the results of getaddrinfo.
SocketOpens a socket.
ConnectConnects a socket to address, waiting for a stream connection to be made.
BindGives a socket its local address.
ListenMakes a bound stream socket accept connections.
Accept4Accepts a waiting connection as a new socket.
SendToSends bytes on a socket, to address when it is not connected.
ReceiveFromReceives bytes from a socket, and where they came from.
ShutdownEnds one or both directions of a connection.
SetSocketOptionSets a socket option.
GetSocketNameReads a socket's local address.
GetPeerNameReads the address of a connected socket's peer.
posix_spawnpStarts file, found through PATH when it has no slash, as a child process.
posix_spawn_file_actions_initInitializes an empty list of file actions.
posix_spawn_file_actions_destroyReleases what posix_spawn_file_actions_init and the actions added since set up.
posix_spawn_file_actions_adddup2Adds an action duplicating fd onto newFd in the child.
posix_spawn_file_actions_addopenAdds an action opening path as fd in the child.
posix_spawn_file_actions_addchdir_npAdds an action changing the child's working directory to path.
waitpidWaits for a child to change state, and reports how it finished.
killSends a signal to a process.
fcntlPerforms a control operation on a descriptor, such as setting its flags with F_SETFD.
__errorReturns the address of the calling thread's errno, where the C library calls above leave their reason.
Syscall0Executes a raw FreeBSD system call without arguments.
Syscall6Executes a raw FreeBSD system call with six arguments.
SignExtendFdWidens a file descriptor to the register width a system call takes it in.
pthread_createStarts a thread running start(argument).
pthread_joinWaits for a thread to finish and releases it.
pthread_detachLets a thread release itself when it finishes, so nothing has to join it.
pthread_attr_initInitializes thread attributes to the defaults.
pthread_attr_setstacksizeSets the stack size a thread started with these attributes gets.
pthread_attr_destroyReleases what pthread_attr_init set up.
pthread_getthreadid_npReturns the kernel's identifier for the calling thread.
sched_yieldGives up the processor so another ready thread can run.
sysconfReads a system configuration value.
UmtxWaitSleeps while *address equals expected, until a wake, a signal or the timeout.
UmtxWakeWakes up to count threads sleeping on address.

Constants

NameSummary
ClockRealtimeCLOCK_REALTIME: wall-clock time, which can jump when the system clock is set.
ClockMonotonicCLOCK_MONOTONIC: time since an unspecified point, which never goes backwards.
ClockMonotonicFastCLOCK_MONOTONIC_FAST: like ClockMonotonic, read from a cached value rather than the hardware.
ClockRealtimeFastCLOCK_REALTIME_FAST: like ClockRealtime, read from a cached value.
ClockProcessCpuTimeCLOCK_PROCESS_CPUTIME_ID: processor time this process has used.
RTLD_LAZYRTLD_LAZY: resolve a function symbol the first time it is called rather than at load.
RTLD_NOWRTLD_NOW: resolve every symbol before dlopen returns.
RTLD_GLOBALRTLD_GLOBAL: make this object's symbols available to objects loaded afterwards.
RTLD_LOCALRTLD_LOCAL: keep this object's symbols to itself, which is the default.
RandomNonBlockingGRND_NONBLOCK: report rather than wait.
RandomBlockingPoolGRND_RANDOM: accepted and ignored, which is what FreeBSD does with it.
EPERMEPERM: the operation is not permitted to this caller.
ENOENTENOENT: no such file or directory.
ESRCHESRCH: no such process.
EINTREINTR: the call was interrupted by a signal before it did anything.
EIOEIO: a low-level input or output error.
ENXIOENXIO: no such device or address.
EBADFEBADF: the file descriptor is not open, or is not open for what was asked.
EAGAINEAGAIN: the operation would block, and the descriptor was set not to.
ENOMEMENOMEM: not enough memory to satisfy the request.
EACCESEACCES: permission denied.
EFAULTEFAULT: an address the call was given is outside the caller's address space.
EBUSYEBUSY: the resource is in use.
EEXISTEEXIST: the file already exists.
EXDEVEXDEV: the two paths are on different file systems.
ENOTDIRENOTDIR: a path component that had to be a directory is not one.
EISDIREISDIR: the target is a directory and the operation is not one a directory accepts.
EINVALEINVAL: an argument is not valid.
EMFILEEMFILE: this process has too many descriptors open.
ENOSPCENOSPC: the device has no room left.
ESPIPEESPIPE: the descriptor is a pipe or socket and cannot be seeked.
EROFSEROFS: the file system is mounted read-only.
EPIPEEPIPE: the reading end of the pipe is closed.
ENAMETOOLONGENAMETOOLONG: the path or a component of it is too long.
ELOOPELOOP: too many symbolic links were followed resolving the path.
ENOSYSENOSYS: the kernel does not implement this call.
EOVERFLOWEOVERFLOW: a value is too large for the type the call reports it in.
ETIMEDOUTETIMEDOUT: the operation timed out.
MaximumErrnoThe largest error number the normalized error range holds.
StdInThe descriptor a process reads its input from, unless something reassigned it.
StdOutThe descriptor a process writes its output to.
StdErrThe descriptor a process writes its diagnostics to.
AtFdCwdAT_FDCWD: resolve a relative path against the current directory rather than a descriptor.
OpenReadOnlyO_RDONLY: open for reading only.
OpenWriteOnlyO_WRONLY: open for writing only.
OpenReadWriteO_RDWR: open for both reading and writing.
OpenCreateO_CREAT: create the file when it does not exist, which is when the mode argument is read.
OpenExclusiveO_EXCL: with OpenCreate, fail rather than open a file that already exists.
OpenTruncateO_TRUNC: truncate the file to nothing when opening it for writing.
OpenAppendO_APPEND: every write goes to the end.
OpenNonBlockingO_NONBLOCK: reads and writes report EAGAIN rather than waiting.
OpenCloseOnExecO_CLOEXEC: close this descriptor automatically when the process executes a new program.
OpenDirectoryO_DIRECTORY: fail unless the target is a directory.
SeekSetSEEK_SET: measure the new offset from the start of the file.
SeekCurrentSEEK_CUR: measure the new offset from the current one.
SeekEndSEEK_END: measure the new offset from the end of the file.
RemoveDirectoryAT_REMOVEDIR: make UnlinkAt remove a directory rather than a file.
SymlinkNoFollowAT_SYMLINK_NOFOLLOW: act on a symbolic link itself rather than on what it points at.
FollowSymlinksAT_SYMLINK_FOLLOW: make LinkAt link a symbolic link's target rather than the link.
ProtectionNonePROT_NONE: the pages may not be touched at all.
ProtectionReadPROT_READ: the pages may be read.
ProtectionWritePROT_WRITE: the pages may be written.
ProtectionExecutePROT_EXEC: the pages may be executed.
MapSharedMAP_SHARED: writes are visible to other mappings of the same object and reach it.
MapPrivateMAP_PRIVATE: writes are private to this mapping and never reach the object.
MapFixedMAP_FIXED: place the mapping exactly at the requested address, replacing whatever was there.
MapExclusiveMAP_EXCL: with MapFixed, refuse the address rather than replace what occupies it.
MapAnonymousMAP_ANON: the mapping is backed by zeroed pages rather than by a file.
AdviseNormalMADV_NORMAL: no advice; the default.
AdviseRandomMADV_RANDOM: the pages will be touched in no useful order.
AdviseSequentialMADV_SEQUENTIAL: the pages will be touched in order.
AdviseWillNeedMADV_WILLNEED: the pages will be read soon.
AdviseDontNeedMADV_DONTNEED: the pages are not needed soon.
AdviseFreeMADV_FREE: the pages may be reclaimed, and read back as zero if they are.
CtlHardwareCTL_HW: the sysctl branch describing the machine.
HardwarePageSizeHW_PAGESIZE: the leaf under CtlHardware holding the page size, in bytes.
F_GETFLF_SETFD's companion F_GETFL: the fcntl command that reads a descriptor's status flags.
F_SETFLF_SETFL: the fcntl command that sets a descriptor's status flags.
O_NONBLOCKO_NONBLOCK: the status flag that makes a call fail with EAGAIN rather than wait.
EVFILT_READEVFILT_READ: the filter that reports a descriptor with something to read, or a connection to accept.
EVFILT_WRITEEVFILT_WRITE: the filter that reports a descriptor a write would not wait on.
EV_ADDEV_ADD: add the change's filter, or update it.
EV_DELETEEV_DELETE: remove the change's filter.
EV_RECEIPTEV_RECEIPT: report each change as an event, with its outcome in data, rather than waiting.
EV_ERROREV_ERROR: set on an event that reports a failed change, with the error number in data.
EV_EOFEV_EOF: the peer has closed its side.
CtlKernelCTL_KERN: the sysctl branch describing the kernel and its processes.
KernelProcessKERN_PROC: the leaf under CtlKernel describing processes.
KernelProcessPathnameKERN_PROC_PATHNAME: the leaf under KernelProcess holding a process's executable path.
AF_INETAF_INET: the IPv4 address family.
AF_INET6AF_INET6: the IPv6 address family.
SOCK_STREAMSOCK_STREAM: a connected byte stream.
SOCK_DGRAMSOCK_DGRAM: individual datagrams.
SOCK_CLOEXECSOCK_CLOEXEC: close the socket when the process starts another program.
SOL_SOCKETSOL_SOCKET: the level of the options every socket has.
SO_REUSEADDRSO_REUSEADDR: let a listening address be bound again while old connections to it wind down.
SO_RCVTIMEOSO_RCVTIMEO: how long a receive waits.
SO_SNDTIMEOSO_SNDTIMEO: how long a send waits.
IPPROTO_TCPIPPROTO_TCP: the level of TCP's options.
TCP_NODELAYTCP_NODELAY: send small writes at once rather than gathering them.
IPPROTO_IPV6IPPROTO_IPV6: the level of IPv6's options.
IPV6_V6ONLYIPV6_V6ONLY: accept only IPv6 on an IPv6 socket.
MSG_NOSIGNALMSG_NOSIGNAL: report a closed peer as an error rather than with SIGPIPE.
F_SETFDF_SETFD: the fcntl command that sets a descriptor's flags.
FD_CLOEXECFD_CLOEXEC: close the descriptor when the process starts another program.
WNOHANGWNOHANG: have waitpid return at once when the child has not finished.
SIGKILLSIGKILL: the signal that ends a process at once and cannot be caught.
SysGetPidgetpid(2)'s system-call number.
SysMmapmmap(2)'s system-call number.
SC_NPROCESSORS_ONLN_SC_NPROCESSORS_ONLN: the sysconf name for the number of processors currently online.
UMTX_OP_WAIT_UINT_PRIVATEUMTX_OP_WAIT_UINT_PRIVATE: sleep while a 32-bit word holds the expected value.
UMTX_OP_WAKE_PRIVATEUMTX_OP_WAKE_PRIVATE: wake threads sleeping on the word.