Implement new sys/unix package

This commit is contained in:
flysand7
2023-10-18 01:57:26 +11:00
parent 8e4bdcfb98
commit 4d65b1ab9c
25 changed files with 6683 additions and 755 deletions

View File

@@ -1,8 +1,8 @@
package crypto
import "core:fmt"
import "core:os"
import "core:sys/unix"
import "core:sys/linux"
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
@@ -12,26 +12,25 @@ _rand_bytes :: proc (dst: []byte) {
for l > 0 {
to_read := min(l, _MAX_PER_CALL_BYTES)
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
if ret < 0 {
switch os.Errno(-ret) {
case os.EINTR:
// Call interupted by a signal handler, just retry the
// request.
continue
case os.ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("crypto: getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic(fmt.tprintf("crypto: getrandom failed: %d", ret))
}
n_read, errno := linux.getrandom(dst[:to_read], {})
#partial switch errno {
case .NONE:
// Do nothing
case .EINTR:
// Call interupted by a signal handler, just retry the
// request.
continue
case .ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("crypto: getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic(fmt.tprintf("crypto: getrandom failed: %v", errno))
}
l -= ret
dst = dst[ret:]
l -= n_read
dst = dst[n_read:]
}
}

View File

@@ -1,27 +1,28 @@
package rand
import "core:sys/unix"
import "core:sys/linux"
@(require_results)
_system_random :: proc() -> u64 {
for {
value: u64
ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0)
if ret < 0 {
switch ret {
case -4: // EINTR
// Call interupted by a signal handler, just retry the request.
continue
case -38: // ENOSYS
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic("getrandom failed")
}
value_buf := (cast([^]u8)&value)[:size_of(u64)]
_, errno := linux.getrandom(value_buf, {})
#partial switch errno {
case .NONE:
// Do nothing
case .EINTR:
// Call interupted by a signal handler, just retry the request.
continue
case .ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic("getrandom failed")
}
return value
}

View File

@@ -2,100 +2,49 @@
//+private
package mem_virtual
import "core:c"
import "core:intrinsics"
import "core:sys/unix"
PROT_NONE :: 0x0
PROT_READ :: 0x1
PROT_WRITE :: 0x2
PROT_EXEC :: 0x4
PROT_GROWSDOWN :: 0x01000000
PROT_GROWSUP :: 0x02000000
MAP_FIXED :: 0x1
MAP_PRIVATE :: 0x2
MAP_SHARED :: 0x4
MAP_ANONYMOUS :: 0x20
MADV_NORMAL :: 0
MADV_RANDOM :: 1
MADV_SEQUENTIAL :: 2
MADV_WILLNEED :: 3
MADV_DONTNEED :: 4
MADV_FREE :: 8
MADV_REMOVE :: 9
MADV_DONTFORK :: 10
MADV_DOFORK :: 11
MADV_MERGEABLE :: 12
MADV_UNMERGEABLE :: 13
MADV_HUGEPAGE :: 14
MADV_NOHUGEPAGE :: 15
MADV_DONTDUMP :: 16
MADV_DODUMP :: 17
MADV_WIPEONFORK :: 18
MADV_KEEPONFORK :: 19
MADV_HWPOISON :: 100
mmap :: proc "contextless" (addr: rawptr, length: uint, prot: c.int, flags: c.int, fd: c.int, offset: uintptr) -> int {
res := intrinsics.syscall(unix.SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
return int(res)
}
munmap :: proc "contextless" (addr: rawptr, length: uint) -> c.int {
res := intrinsics.syscall(unix.SYS_munmap, uintptr(addr), uintptr(length))
return c.int(res)
}
mprotect :: proc "contextless" (addr: rawptr, length: uint, prot: c.int) -> c.int {
res := intrinsics.syscall(unix.SYS_mprotect, uintptr(addr), uintptr(length), uintptr(prot))
return c.int(res)
}
madvise :: proc "contextless" (addr: rawptr, length: uint, advice: c.int) -> c.int {
res := intrinsics.syscall(unix.SYS_madvise, uintptr(addr), uintptr(length), uintptr(advice))
return c.int(res)
}
import "core:sys/linux"
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
if result < 0 && result > -4096 {
addr, errno := linux.mmap(0, size, {}, {.PRIVATE, .ANONYMOUS})
if errno == .ENOMEM {
return nil, .Out_Of_Memory
} else if errno == .EINVAL {
return nil, .Invalid_Argument
}
return ([^]byte)(uintptr(result))[:size], nil
return (cast([^]byte)addr)[:size], nil
}
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
result := mprotect(data, size, PROT_READ|PROT_WRITE)
if result != 0 {
// TODO(bill): Handle error value correctly
errno := linux.mprotect(data, size, {.READ, .WRITE})
if errno == .EINVAL {
return .Invalid_Pointer
} else if errno == .ENOMEM {
return .Out_Of_Memory
}
return nil
}
_decommit :: proc "contextless" (data: rawptr, size: uint) {
mprotect(data, size, PROT_NONE)
madvise(data, size, MADV_FREE)
_ = linux.mprotect(data, size, {})
_ = linux.madvise(data, size, .FREE)
}
_release :: proc "contextless" (data: rawptr, size: uint) {
munmap(data, size)
_ = linux.munmap(data, size)
}
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
pflags: c.int
pflags = PROT_NONE
if .Read in flags { pflags |= PROT_READ }
if .Write in flags { pflags |= PROT_WRITE }
if .Execute in flags { pflags |= PROT_EXEC }
err := mprotect(data, size, pflags)
return err != 0
pflags: linux.Mem_Protection
pflags = {}
if .Read in flags { pflags |= {.READ} }
if .Write in flags { pflags |= {.WRITE} }
if .Execute in flags { pflags |= {.EXEC} }
errno := linux.mprotect(data, size, pflags)
return errno != .NONE
}
_platform_memory_init :: proc() {
DEFAULT_PAGE_SIZE = 4096
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}

View File

@@ -16,182 +16,184 @@ package net
Tetralux: Initial implementation
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
Jeroen van Rijn: Cross platform unification, code style, documentation
flysand: Move dependency from core:linux.Errno to core:sys/linux
*/
import "core:c"
import "core:os"
import "core:sys/linux"
Create_Socket_Error :: enum c.int {
None = 0,
Family_Not_Supported_For_This_Socket = c.int(os.EAFNOSUPPORT),
No_Socket_Descriptors_Available = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
No_Memory_Available_Available = c.int(os.ENOMEM),
Protocol_Unsupported_By_System = c.int(os.EPROTONOSUPPORT),
Wrong_Protocol_For_Socket = c.int(os.EPROTONOSUPPORT),
Family_And_Socket_Type_Mismatch = c.int(os.EPROTONOSUPPORT),
Family_Not_Supported_For_This_Socket = c.int(linux.Errno.EAFNOSUPPORT),
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
No_Memory_Available_Available = c.int(linux.Errno.ENOMEM),
Protocol_Unsupported_By_System = c.int(linux.Errno.EPROTONOSUPPORT),
Wrong_Protocol_For_Socket = c.int(linux.Errno.EPROTONOSUPPORT),
Family_And_Socket_Type_Mismatch = c.int(linux.Errno.EPROTONOSUPPORT),
}
Dial_Error :: enum c.int {
None = 0,
Port_Required = -1,
Address_In_Use = c.int(os.EADDRINUSE),
In_Progress = c.int(os.EINPROGRESS),
Cannot_Use_Any_Address = c.int(os.EADDRNOTAVAIL),
Wrong_Family_For_Socket = c.int(os.EAFNOSUPPORT),
Refused = c.int(os.ECONNREFUSED),
Is_Listening_Socket = c.int(os.EACCES),
Already_Connected = c.int(os.EISCONN),
Network_Unreachable = c.int(os.ENETUNREACH), // Device is offline
Host_Unreachable = c.int(os.EHOSTUNREACH), // Remote host cannot be reached
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Not_Socket = c.int(os.ENOTSOCK),
Timeout = c.int(os.ETIMEDOUT),
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
In_Progress = c.int(linux.Errno.EINPROGRESS),
Cannot_Use_Any_Address = c.int(linux.Errno.EADDRNOTAVAIL),
Wrong_Family_For_Socket = c.int(linux.Errno.EAFNOSUPPORT),
Refused = c.int(linux.Errno.ECONNREFUSED),
Is_Listening_Socket = c.int(linux.Errno.EACCES),
Already_Connected = c.int(linux.Errno.EISCONN),
Network_Unreachable = c.int(linux.Errno.ENETUNREACH), // Device is offline
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH), // Remote host cannot be reached
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Timeout = c.int(linux.Errno.ETIMEDOUT),
// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
Would_Block = c.int(os.EWOULDBLOCK),
Would_Block = c.int(linux.Errno.EWOULDBLOCK),
}
Bind_Error :: enum c.int {
None = 0,
Address_In_Use = c.int(os.EADDRINUSE), // Another application is currently bound to this endpoint.
Given_Nonlocal_Address = c.int(os.EADDRNOTAVAIL), // The address is not a local address on this machine.
Broadcast_Disabled = c.int(os.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
Address_Family_Mismatch = c.int(os.EFAULT), // The address family of the address does not match that of the socket.
Already_Bound = c.int(os.EINVAL), // The socket is already bound to an address.
No_Ports_Available = c.int(os.ENOBUFS), // There are not enough ephemeral ports available.
Address_In_Use = c.int(linux.Errno.EADDRINUSE), // Another application is currently bound to this endpoint.
Given_Nonlocal_Address = c.int(linux.Errno.EADDRNOTAVAIL), // The address is not a local address on this machine.
Broadcast_Disabled = c.int(linux.Errno.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
Address_Family_Mismatch = c.int(linux.Errno.EFAULT), // The address family of the address does not match that of the socket.
Already_Bound = c.int(linux.Errno.EINVAL), // The socket is already bound to an address.
No_Ports_Available = c.int(linux.Errno.ENOBUFS), // There are not enough ephemeral ports available.
}
Listen_Error :: enum c.int {
None = 0,
Address_In_Use = c.int(os.EADDRINUSE),
Already_Connected = c.int(os.EISCONN),
No_Socket_Descriptors_Available = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Nonlocal_Address = c.int(os.EADDRNOTAVAIL),
Not_Socket = c.int(os.ENOTSOCK),
Listening_Not_Supported_For_This_Socket = c.int(os.EOPNOTSUPP),
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
Already_Connected = c.int(linux.Errno.EISCONN),
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Nonlocal_Address = c.int(linux.Errno.EADDRNOTAVAIL),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Listening_Not_Supported_For_This_Socket = c.int(linux.Errno.EOPNOTSUPP),
}
Accept_Error :: enum c.int {
None = 0,
Not_Listening = c.int(os.EINVAL),
No_Socket_Descriptors_Available_For_Client_Socket = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Not_Socket = c.int(os.ENOTSOCK),
Not_Connection_Oriented_Socket = c.int(os.EOPNOTSUPP),
Not_Listening = c.int(linux.Errno.EINVAL),
No_Socket_Descriptors_Available_For_Client_Socket = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Not_Connection_Oriented_Socket = c.int(linux.Errno.EOPNOTSUPP),
// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
Would_Block = c.int(os.EWOULDBLOCK),
Would_Block = c.int(linux.Errno.EWOULDBLOCK),
}
TCP_Recv_Error :: enum c.int {
None = 0,
Shutdown = c.int(os.ESHUTDOWN),
Not_Connected = c.int(os.ENOTCONN),
Connection_Broken = c.int(os.ENETRESET),
Not_Socket = c.int(os.ENOTSOCK),
Aborted = c.int(os.ECONNABORTED),
Shutdown = c.int(linux.Errno.ESHUTDOWN),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Connection_Broken = c.int(linux.Errno.ENETRESET),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Aborted = c.int(linux.Errno.ECONNABORTED),
// TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them?
Connection_Closed = c.int(os.ECONNRESET),
Offline = c.int(os.ENETDOWN),
Host_Unreachable = c.int(os.EHOSTUNREACH),
Interrupted = c.int(os.EINTR),
Timeout = c.int(os.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
Connection_Closed = c.int(linux.Errno.ECONNRESET),
Offline = c.int(linux.Errno.ENETDOWN),
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
Interrupted = c.int(linux.Errno.EINTR),
Timeout = c.int(linux.Errno.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
}
UDP_Recv_Error :: enum c.int {
None = 0,
Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Buffer_Too_Small = c.int(linux.Errno.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(linux.Errno.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(linux.Errno.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
// The send timeout duration passed before all data was received. See Socket_Option.Receive_Timeout.
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
Timeout = c.int(os.EWOULDBLOCK),
Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
Timeout = c.int(linux.Errno.EWOULDBLOCK),
Socket_Not_Bound = c.int(linux.Errno.EINVAL), // The socket must be bound for this operation, but isn't.
}
TCP_Send_Error :: enum c.int {
None = 0,
Aborted = c.int(os.ECONNABORTED),
Connection_Closed = c.int(os.ECONNRESET),
Not_Connected = c.int(os.ENOTCONN),
Shutdown = c.int(os.ESHUTDOWN),
Aborted = c.int(linux.Errno.ECONNABORTED),
Connection_Closed = c.int(linux.Errno.ECONNRESET),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Shutdown = c.int(linux.Errno.ESHUTDOWN),
// The send queue was full.
// This is usually a transient issue.
//
// This also shouldn't normally happen on Linux, as data is dropped if it
// doesn't fit in the send queue.
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Offline = c.int(os.ENETDOWN),
Host_Unreachable = c.int(os.EHOSTUNREACH),
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(os.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Offline = c.int(linux.Errno.ENETDOWN),
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(linux.Errno.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
}
// TODO
UDP_Send_Error :: enum c.int {
None = 0,
Message_Too_Long = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
Message_Too_Long = c.int(linux.Errno.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
// TODO: not sure what the exact circumstances for this is yet
Network_Unreachable = c.int(os.ENETUNREACH),
No_Outbound_Ports_Available = c.int(os.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send.
Network_Unreachable = c.int(linux.Errno.ENETUNREACH),
No_Outbound_Ports_Available = c.int(linux.Errno.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send.
// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
Timeout = c.int(os.EWOULDBLOCK),
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(linux.Errno.EWOULDBLOCK),
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(linux.Errno.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(linux.Errno.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
// The send queue was full.
// This is usually a transient issue.
//
// This also shouldn't normally happen on Linux, as data is dropped if it
// doesn't fit in the send queue.
No_Buffer_Space_Available = c.int(os.ENOBUFS),
No_Memory_Available = c.int(os.ENOMEM), // No memory was available to properly manage the send queue.
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
No_Memory_Available = c.int(linux.Errno.ENOMEM), // No memory was available to properly manage the send queue.
}
// TODO(flysand): slight regression
Shutdown_Manner :: enum c.int {
Receive = c.int(os.SHUT_RD),
Send = c.int(os.SHUT_WR),
Both = c.int(os.SHUT_RDWR),
Receive = c.int(linux.Shutdown_How.RD),
Send = c.int(linux.Shutdown_How.WR),
Both = c.int(linux.Shutdown_How.RDWR),
}
Shutdown_Error :: enum c.int {
None = 0,
Aborted = c.int(os.ECONNABORTED),
Reset = c.int(os.ECONNRESET),
Offline = c.int(os.ENETDOWN),
Not_Connected = c.int(os.ENOTCONN),
Not_Socket = c.int(os.ENOTSOCK),
Invalid_Manner = c.int(os.EINVAL),
Aborted = c.int(linux.Errno.ECONNABORTED),
Reset = c.int(linux.Errno.ECONNRESET),
Offline = c.int(linux.Errno.ENETDOWN),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Invalid_Manner = c.int(linux.Errno.EINVAL),
}
Socket_Option_Error :: enum c.int {
None = 0,
Offline = c.int(os.ENETDOWN),
Timeout_When_Keepalive_Set = c.int(os.ENETRESET),
Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT),
Reset_When_Keepalive_Set = c.int(os.ENOTCONN),
Not_Socket = c.int(os.ENOTSOCK),
Offline = c.int(linux.Errno.ENETDOWN),
Timeout_When_Keepalive_Set = c.int(linux.Errno.ENETRESET),
Invalid_Option_For_Socket = c.int(linux.Errno.ENOPROTOOPT),
Reset_When_Keepalive_Set = c.int(linux.Errno.ENOTCONN),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
}
Set_Blocking_Error :: enum c.int {
None = 0,
// TODO: add errors occuring on followig calls:
// flags, _ := os.fcntl(sd, os.F_GETFL, 0)
// os.fcntl(sd, os.F_SETFL, flags | int(os.O_NONBLOCK))
// flags, _ := linux.Errno.fcntl(sd, linux.Errno.F_GETFL, 0)
// linux.Errno.fcntl(sd, linux.Errno.F_SETFL, flags | int(linux.Errno.O_NONBLOCK))
}

View File

@@ -21,120 +21,124 @@ package net
TODO: When we have raw sockets, split off into its own file for Linux so we can use the NETLINK protocol and bypass libc.
*/
import "core:os"
import "core:strings"
//import "core:strings"
// TODO(flysand): regression
// NOTE(flysand): https://man7.org/linux/man-pages/man7/netlink.7.html
// apparently musl libc uses this to enumerate network interfaces
@(private)
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
context.allocator = allocator
head: ^os.ifaddrs
// head: ^os.ifaddrs
if res := os._getifaddrs(&head); res < 0 {
return {}, .Unable_To_Enumerate_Network_Interfaces
}
// if res := os._getifaddrs(&head); res < 0 {
// return {}, .Unable_To_Enumerate_Network_Interfaces
// }
/*
Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
We're going to have to iterate over a list and coalesce information as we go.
*/
ifaces: map[string]^Network_Interface
defer delete(ifaces)
// /*
// Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
// We're going to have to iterate over a list and coalesce information as we go.
// */
// ifaces: map[string]^Network_Interface
// defer delete(ifaces)
for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
adapter_name := string(ifaddr.name)
// for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
// adapter_name := string(ifaddr.name)
/*
Check if we have seen this interface name before so we can reuse the `Network_Interface`.
Else, create a new one.
*/
if adapter_name not_in ifaces {
ifaces[adapter_name] = new(Network_Interface)
ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
}
iface := ifaces[adapter_name]
// /*
// Check if we have seen this interface name before so we can reuse the `Network_Interface`.
// Else, create a new one.
// */
// if adapter_name not_in ifaces {
// ifaces[adapter_name] = new(Network_Interface)
// ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
// }
// iface := ifaces[adapter_name]
address: Address
netmask: Netmask
// address: Address
// netmask: Netmask
if ifaddr.address != nil {
switch int(ifaddr.address.sa_family) {
case os.AF_INET, os.AF_INET6:
address = _sockaddr_basic_to_endpoint(ifaddr.address).address
// if ifaddr.address != nil {
// switch int(ifaddr.address.sa_family) {
// case os.AF_INET, os.AF_INET6:
// address = _sockaddr_basic_to_endpoint(ifaddr.address).address
case os.AF_PACKET:
/*
For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
is truncated beyond usefulness.
// case os.AF_PACKET:
// /*
// For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
// 32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
// is truncated beyond usefulness.
We're not going to retrieve stats now. Instead this serves as a reminder to use
the NETLINK protocol for this purpose.
// We're not going to retrieve stats now. Instead this serves as a reminder to use
// the NETLINK protocol for this purpose.
But in case you were curious:
stats := transmute(^os.rtnl_link_stats)ifaddr.data
fmt.println(stats)
*/
case:
}
}
// But in case you were curious:
// stats := transmute(^os.rtnl_link_stats)ifaddr.data
// fmt.println(stats)
// */
// case:
// }
// }
if ifaddr.netmask != nil {
switch int(ifaddr.netmask.sa_family) {
case os.AF_INET, os.AF_INET6:
netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
case:
}
}
// if ifaddr.netmask != nil {
// switch int(ifaddr.netmask.sa_family) {
// case os.AF_INET, os.AF_INET6:
// netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
// case:
// }
// }
if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
switch int(ifaddr.broadcast_or_dest.sa_family) {
case os.AF_INET, os.AF_INET6:
broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
append(&iface.multicast, broadcast)
case:
}
}
// if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
// switch int(ifaddr.broadcast_or_dest.sa_family) {
// case os.AF_INET, os.AF_INET6:
// broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
// append(&iface.multicast, broadcast)
// case:
// }
// }
if address != nil {
lease := Lease{
address = address,
netmask = netmask,
}
append(&iface.unicast, lease)
}
// if address != nil {
// lease := Lease{
// address = address,
// netmask = netmask,
// }
// append(&iface.unicast, lease)
// }
/*
TODO: Refine this based on the type of adapter.
*/
state := Link_State{}
// /*
// TODO: Refine this based on the type of adapter.
// */
// state := Link_State{}
if .UP in ifaddr.flags {
state |= {.Up}
}
// if .UP in ifaddr.flags {
// state |= {.Up}
// }
if .DORMANT in ifaddr.flags {
state |= {.Dormant}
}
// if .DORMANT in ifaddr.flags {
// state |= {.Dormant}
// }
if .LOOPBACK in ifaddr.flags {
state |= {.Loopback}
}
iface.link.state = state
}
// if .LOOPBACK in ifaddr.flags {
// state |= {.Loopback}
// }
// iface.link.state = state
// }
/*
Free the OS structures.
*/
os._freeifaddrs(head)
// /*
// Free the OS structures.
// */
// os._freeifaddrs(head)
/*
Turn the map into a slice to return.
*/
_interfaces := make([dynamic]Network_Interface, 0, allocator)
for _, iface in ifaces {
append(&_interfaces, iface^)
free(iface)
}
return _interfaces[:], {}
// /*
// Turn the map into a slice to return.
// */
// _interfaces := make([dynamic]Network_Interface, 0, allocator)
// for _, iface in ifaces {
// append(&_interfaces, iface^)
// free(iface)
// }
// return _interfaces[:], {}
return nil, {}
}

View File

@@ -18,7 +18,7 @@ package net
Jeroen van Rijn: Cross platform unification, code style, documentation
*/
any_socket_to_socket :: proc(socket: Any_Socket) -> Socket {
any_socket_to_socket :: proc "contextless" (socket: Any_Socket) -> Socket {
switch s in socket {
case TCP_Socket: return Socket(s)
case UDP_Socket: return Socket(s)

View File

@@ -16,241 +16,294 @@ package net
Tetralux: Initial implementation
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
Jeroen van Rijn: Cross platform unification, code style, documentation
flysand: Move dependency from core:os to core:sys/linux
*/
import "core:c"
import "core:os"
import "core:time"
import "core:sys/linux"
Socket_Option :: enum c.int {
Reuse_Address = c.int(os.SO_REUSEADDR),
Keep_Alive = c.int(os.SO_KEEPALIVE),
Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE),
TCP_Nodelay = c.int(os.TCP_NODELAY),
Linger = c.int(os.SO_LINGER),
Receive_Buffer_Size = c.int(os.SO_RCVBUF),
Send_Buffer_Size = c.int(os.SO_SNDBUF),
Receive_Timeout = c.int(os.SO_RCVTIMEO_NEW),
Send_Timeout = c.int(os.SO_SNDTIMEO_NEW),
Reuse_Address = c.int(linux.Socket_Option.REUSEADDR),
Keep_Alive = c.int(linux.Socket_Option.KEEPALIVE),
Out_Of_Bounds_Data_Inline = c.int(linux.Socket_Option.OOBINLINE),
TCP_Nodelay = c.int(linux.Socket_TCP_Option.NODELAY),
Linger = c.int(linux.Socket_Option.LINGER),
Receive_Buffer_Size = c.int(linux.Socket_Option.RCVBUF),
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO_NEW),
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO_NEW),
}
@(private)
_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Network_Error) {
c_type, c_protocol, c_family: int
// Wrappers and unwrappers for system-native types
@(private="file")
_unwrap_os_socket :: proc "contextless" (sock: Any_Socket)->linux.Fd {
return linux.Fd(any_socket_to_socket(sock))
}
@(private="file")
_wrap_os_socket :: proc "contextless" (sock: linux.Fd, protocol: Socket_Protocol)->Any_Socket {
switch protocol {
case .TCP: return TCP_Socket(Socket(sock))
case .UDP: return UDP_Socket(Socket(sock))
case:
unreachable()
}
}
@(private="file")
_unwrap_os_family :: proc "contextless" (family: Address_Family)->linux.Address_Family {
switch family {
case .IP4: c_family = os.AF_INET
case .IP6: c_family = os.AF_INET6
case:
unreachable()
}
switch protocol {
case .TCP: c_type = os.SOCK_STREAM; c_protocol = os.IPPROTO_TCP
case .UDP: c_type = os.SOCK_DGRAM; c_protocol = os.IPPROTO_UDP
case:
unreachable()
}
sock, ok := os.socket(c_family, c_type, c_protocol)
if ok != os.ERROR_NONE {
err = Create_Socket_Error(ok)
return
}
switch protocol {
case .TCP: return TCP_Socket(sock), nil
case .UDP: return UDP_Socket(sock), nil
case .IP4: return .INET
case .IP6: return .INET6
case:
unreachable()
}
}
@(private="file")
_unwrap_os_proto_socktype :: proc "contextless" (protocol: Socket_Protocol)->(linux.Protocol, linux.Socket_Type) {
switch protocol {
case .TCP: return .TCP, .STREAM
case .UDP: return .UDP, .DGRAM
case:
unreachable()
}
}
@(private="file")
_unwrap_os_addr :: proc "contextless" (endpoint: Endpoint)->(linux.Sock_Addr_Any) {
switch address in endpoint.address {
case IP4_Address:
return {
ipv4 = {
sin_family = .INET,
sin_port = u16be(endpoint.port),
sin_addr = transmute([4]u8) endpoint.address.(IP4_Address),
},
}
case IP6_Address:
return {
ipv6 = {
sin6_port = u16be(endpoint.port),
sin6_addr = transmute([16]u8) endpoint.address.(IP6_Address),
sin6_family = .INET6,
},
}
case:
unreachable()
}
}
@(private="file")
_wrap_os_addr :: proc "contextless" (addr: linux.Sock_Addr_Any)->(Endpoint) {
#partial switch addr.family {
case .INET:
return {
address = cast(IP4_Address) addr.sin_addr,
port = cast(int) addr.sin_port,
}
case .INET6:
return {
port = cast(int) addr.sin6_port,
address = transmute(IP6_Address) addr.sin6_addr,
}
case:
unreachable()
}
}
_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (Any_Socket, Network_Error) {
family := _unwrap_os_family(family)
proto, socktype := _unwrap_os_proto_socktype(protocol)
sock, errno := linux.socket(family, socktype, {}, proto)
if errno != .NONE {
return {}, Create_Socket_Error(errno)
}
return _wrap_os_socket(sock, protocol), nil
}
@(private)
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (skt: TCP_Socket, err: Network_Error) {
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (tcp_sock: TCP_Socket, err: Network_Error) {
errno: linux.Errno
if endpoint.port == 0 {
return 0, .Port_Required
}
family := family_from_endpoint(endpoint)
sock := create_socket(family, .TCP) or_return
skt = sock.(TCP_Socket)
// Create new TCP socket
os_sock: linux.Fd
os_sock, errno = linux.socket(_unwrap_os_family(family_from_endpoint(endpoint)), .STREAM, {}, .TCP)
if errno != .NONE {
// TODO(flysand): should return invalid file descriptor here casted as TCP_Socket
return {}, Create_Socket_Error(errno)
}
// NOTE(tetra): This is so that if we crash while the socket is open, we can
// bypass the cooldown period, and allow the next run of the program to
// use the same address immediately.
_ = set_option(skt, .Reuse_Address, true)
sockaddr := _endpoint_to_sockaddr(endpoint)
res := os.connect(os.Socket(skt), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
if res != os.ERROR_NONE {
err = Dial_Error(res)
return
reuse_addr: b32 = true
_ = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &reuse_addr)
addr := _unwrap_os_addr(endpoint)
errno = linux.connect(linux.Fd(tcp_sock), &addr)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Dial_Error(errno)
}
if options.no_delay {
_ = _set_option(sock, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
}
return
// NOTE(tetra): Not vital to succeed; error ignored
no_delay: b32 = cast(b32) options.no_delay
_ = linux.setsockopt(os_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &no_delay)
return cast(TCP_Socket) os_sock, nil
}
@(private)
_bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) {
sockaddr := _endpoint_to_sockaddr(ep)
s := any_socket_to_socket(skt)
res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
if res != os.ERROR_NONE {
err = Bind_Error(res)
_bind :: proc(sock: Any_Socket, endpoint: Endpoint) -> (Network_Error) {
addr := _unwrap_os_addr(endpoint)
errno := linux.bind(_unwrap_os_socket(sock), &addr)
if errno != .NONE {
return Bind_Error(errno)
}
return
return nil
}
@(private)
_listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_Socket, err: Network_Error) {
_listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (TCP_Socket, Network_Error) {
errno: linux.Errno
assert(backlog > 0 && i32(backlog) < max(i32))
family := family_from_endpoint(interface_endpoint)
sock := create_socket(family, .TCP) or_return
skt = sock.(TCP_Socket)
// Figure out the address family and address of the endpoint
ep_family := _unwrap_os_family(family_from_endpoint(endpoint))
ep_address := _unwrap_os_addr(endpoint)
// Create TCP socket
os_sock: linux.Fd
os_sock, errno = linux.socket(ep_family, .STREAM, {}, .TCP)
if errno != .NONE {
// TODO(flysand): should return invalid file descriptor here casted as TCP_Socket
return {}, Create_Socket_Error(errno)
}
// NOTE(tetra): This is so that if we crash while the socket is open, we can
// bypass the cooldown period, and allow the next run of the program to
// use the same address immediately.
//
// TODO(tetra, 2022-02-15): Confirm that this doesn't mean other processes can hijack the address!
set_option(sock, .Reuse_Address, true) or_return
bind(sock, interface_endpoint) or_return
res := os.listen(os.Socket(skt), backlog)
if res != os.ERROR_NONE {
err = Listen_Error(res)
return
do_reuse_addr: b32 = true
errno = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &do_reuse_addr)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Listen_Error(errno)
}
return
// Bind the socket to endpoint address
errno = linux.bind(os_sock, &ep_address)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Bind_Error(errno)
}
// Listen on bound socket
errno = linux.listen(os_sock, cast(i32) backlog)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Listen_Error(errno)
}
return cast(TCP_Socket) os_sock, nil
}
@(private)
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_Error) {
sockaddr: os.SOCKADDR_STORAGE_LH
sockaddrlen := c.int(size_of(sockaddr))
client_sock, ok := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen)
if ok != os.ERROR_NONE {
err = Accept_Error(ok)
return
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (tcp_client: TCP_Socket, endpoint: Endpoint, err: Network_Error) {
addr: linux.Sock_Addr_Any
client_sock, errno := linux.accept(linux.Fd(sock), &addr)
if errno != .NONE {
return {}, {}, Accept_Error(errno)
}
client = TCP_Socket(client_sock)
source = _sockaddr_storage_to_endpoint(&sockaddr)
if options.no_delay {
_ = _set_option(client, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
}
return
// NOTE(tetra): Not vital to succeed; error ignored
val: b32 = cast(b32) options.no_delay
_ = linux.setsockopt(client_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &val)
return TCP_Socket(client_sock), _wrap_os_addr(addr), nil
}
@(private)
_close :: proc(skt: Any_Socket) {
s := any_socket_to_socket(skt)
os.close(os.Handle(os.Socket(s)))
_close :: proc(sock: Any_Socket) {
linux.close(_unwrap_os_socket(sock))
}
@(private)
_recv_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_read: int, err: Network_Error) {
_recv_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) {
if len(buf) <= 0 {
return
return 0, nil
}
res, ok := os.recv(os.Socket(skt), buf, 0)
if ok != os.ERROR_NONE {
err = TCP_Recv_Error(ok)
return
bytes_read, errno := linux.recv(linux.Fd(tcp_sock), buf, {})
if errno != .NONE {
return 0, TCP_Recv_Error(errno)
}
return int(res), nil
return int(bytes_read), nil
}
@(private)
_recv_udp :: proc(skt: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endpoint: Endpoint, err: Network_Error) {
_recv_udp :: proc(udp_sock: UDP_Socket, buf: []byte) -> (int, Endpoint, Network_Error) {
if len(buf) <= 0 {
return
// NOTE(flysand): It was returning no error, I didn't change anything
return 0, {}, {}
}
from: os.SOCKADDR_STORAGE_LH = ---
fromsize := c.int(size_of(from))
// NOTE(tetra): On Linux, if the buffer is too small to fit the entire datagram payload, the rest is silently discarded,
// and no error is returned.
// However, if you pass MSG_TRUNC here, 'res' will be the size of the incoming message, rather than how much was read.
// We can use this fact to detect this condition and return .Buffer_Too_Small.
res, ok := os.recvfrom(os.Socket(skt), buf, os.MSG_TRUNC, cast(^os.SOCKADDR) &from, &fromsize)
if ok != os.ERROR_NONE {
err = UDP_Recv_Error(ok)
return
from_addr: linux.Sock_Addr_Any
bytes_read, errno := linux.recvfrom(linux.Fd(udp_sock), buf, {.TRUNC}, &from_addr)
if errno != .NONE {
return 0, {}, UDP_Recv_Error(errno)
}
bytes_read = int(res)
remote_endpoint = _sockaddr_storage_to_endpoint(&from)
if bytes_read > len(buf) {
// NOTE(tetra): The buffer has been filled, with a partial message.
bytes_read = len(buf)
err = .Buffer_Too_Small
return len(buf), {}, .Buffer_Too_Small
}
return
return bytes_read, _wrap_os_addr(from_addr), nil
}
@(private)
_send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Network_Error) {
for bytes_written < len(buf) {
limit := min(int(max(i32)), len(buf) - bytes_written)
remaining := buf[bytes_written:][:limit]
res, ok := os.send(os.Socket(skt), remaining, 0)
if ok != os.ERROR_NONE {
err = TCP_Send_Error(ok)
return
_send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) {
total_written := 0
for total_written < len(buf) {
limit := min(int(max(i32)), len(buf) - total_written)
remaining := buf[total_written:][:limit]
res, errno := linux.send(linux.Fd(tcp_sock), remaining, {})
if errno != .NONE {
return total_written, TCP_Send_Error(errno)
}
bytes_written += int(res)
total_written += int(res)
}
return
return total_written, nil
}
@(private)
_send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: int, err: Network_Error) {
toaddr := _endpoint_to_sockaddr(to)
res, os_err := os.sendto(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &toaddr, size_of(toaddr))
if os_err != os.ERROR_NONE {
err = UDP_Send_Error(os_err)
return
_send_udp :: proc(udp_sock: UDP_Socket, buf: []byte, to: Endpoint) -> (int, Network_Error) {
to_addr := _unwrap_os_addr(to)
bytes_written, errno := linux.sendto(linux.Fd(udp_sock), buf, {}, &to_addr)
if errno != .NONE {
return bytes_written, UDP_Send_Error(errno)
}
bytes_written = int(res)
return
return int(bytes_written), nil
}
@(private)
_shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
s := any_socket_to_socket(skt)
res := os.shutdown(os.Socket(s), int(manner))
if res != os.ERROR_NONE {
return Shutdown_Error(res)
_shutdown :: proc(sock: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
os_sock := _unwrap_os_socket(sock)
errno := linux.shutdown(os_sock, cast(linux.Shutdown_How) manner)
if errno != .NONE {
return Shutdown_Error(errno)
}
return
return nil
}
// TODO(flysand): Figure out what we want to do with this on core:sys/ level.
@(private)
_set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
level := os.SOL_SOCKET if option != .TCP_Nodelay else os.IPPROTO_TCP
_set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
level: int
if option == .TCP_Nodelay {
level = int(linux.SOL_TCP)
} else {
level = int(linux.SOL_SOCKET)
}
os_sock := _unwrap_os_socket(sock)
// NOTE(tetra, 2022-02-15): On Linux, you cannot merely give a single byte for a bool;
// it _has_ to be a b32.
// I haven't tested if you can give more than that.
// I haven't tested if you can give more than that. <-- (flysand) probably not, posix explicitly specifies an int
bool_value: b32
int_value: i32
timeval_value: os.Timeval
ptr: rawptr
len: os.socklen_t
timeval_value: linux.Time_Val
errno: linux.Errno
switch option {
case
.Reuse_Address,
@@ -258,7 +311,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
.Out_Of_Bounds_Data_Inline,
.TCP_Nodelay:
// TODO: verify whether these are options or not on Linux
// .Broadcast,
// .Broadcast, <-- yes
// .Conditional_Accept,
// .Dont_Linger:
switch x in value {
@@ -274,8 +327,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
case:
panic("set_option() value must be a boolean here", loc)
}
ptr = &bool_value
len = size_of(bool_value)
errno = linux.setsockopt(os_sock, level, int(option), &bool_value)
case
.Linger,
.Send_Timeout,
@@ -283,125 +335,49 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
t, ok := value.(time.Duration)
if !ok do panic("set_option() value must be a time.Duration here", loc)
micros := i64(time.duration_microseconds(t))
timeval_value.microseconds = int(micros % 1e6)
timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
ptr = &timeval_value
len = size_of(timeval_value)
micros := cast(i64) (time.duration_microseconds(t))
timeval_value.microseconds = cast(int) (micros % 1e6)
timeval_value.seconds = cast(int) ((micros - i64(timeval_value.microseconds)) / 1e6)
errno = linux.setsockopt(os_sock, level, int(option), &timeval_value)
case
.Receive_Buffer_Size,
.Send_Buffer_Size:
// TODO: check for out of range values and return .Value_Out_Of_Range?
switch i in value {
case i8, u8: i2 := i; int_value = os.socklen_t((^u8)(&i2)^)
case i16, u16: i2 := i; int_value = os.socklen_t((^u16)(&i2)^)
case i32, u32: i2 := i; int_value = os.socklen_t((^u32)(&i2)^)
case i64, u64: i2 := i; int_value = os.socklen_t((^u64)(&i2)^)
case i128, u128: i2 := i; int_value = os.socklen_t((^u128)(&i2)^)
case int, uint: i2 := i; int_value = os.socklen_t((^uint)(&i2)^)
case i8, u8: i2 := i; int_value = i32((^u8)(&i2)^)
case i16, u16: i2 := i; int_value = i32((^u16)(&i2)^)
case i32, u32: i2 := i; int_value = i32((^u32)(&i2)^)
case i64, u64: i2 := i; int_value = i32((^u64)(&i2)^)
case i128, u128: i2 := i; int_value = i32((^u128)(&i2)^)
case int, uint: i2 := i; int_value = i32((^uint)(&i2)^)
case:
panic("set_option() value must be an integer here", loc)
}
ptr = &int_value
len = size_of(int_value)
errno = linux.setsockopt(os_sock, level, int(option), &int_value)
}
skt := any_socket_to_socket(s)
res := os.setsockopt(os.Socket(skt), int(level), int(option), ptr, len)
if res != os.ERROR_NONE {
return Socket_Option_Error(res)
if errno != .NONE {
return Socket_Option_Error(errno)
}
return nil
}
@(private)
_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
socket := any_socket_to_socket(socket)
flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0)
if getfl_err != os.ERROR_NONE {
return Set_Blocking_Error(getfl_err)
_set_blocking :: proc(sock: Any_Socket, should_block: bool) -> (err: Network_Error) {
errno: linux.Errno
flags: linux.Open_Flags
os_sock := _unwrap_os_socket(sock)
flags, errno = linux.fcntl(os_sock, linux.F_GETFL)
if errno != .NONE {
return Set_Blocking_Error(errno)
}
if should_block {
flags &= ~int(os.O_NONBLOCK)
flags &= ~{.NONBLOCK}
} else {
flags |= int(os.O_NONBLOCK)
flags |= {.NONBLOCK}
}
_, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags)
if setfl_err != os.ERROR_NONE {
return Set_Blocking_Error(setfl_err)
errno = linux.fcntl(os_sock, linux.F_SETFL, flags)
if errno != .NONE {
return Set_Blocking_Error(errno)
}
return nil
}
@(private)
_endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH) {
switch a in ep.address {
case IP4_Address:
(^os.sockaddr_in)(&sockaddr)^ = os.sockaddr_in {
sin_port = u16be(ep.port),
sin_addr = transmute(os.in_addr) a,
sin_family = u16(os.AF_INET),
}
return
case IP6_Address:
(^os.sockaddr_in6)(&sockaddr)^ = os.sockaddr_in6 {
sin6_port = u16be(ep.port),
sin6_addr = transmute(os.in6_addr) a,
sin6_family = u16(os.AF_INET6),
}
return
}
unreachable()
}
@(private)
_sockaddr_storage_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endpoint) {
switch native_addr.ss_family {
case u16(os.AF_INET):
addr := cast(^os.sockaddr_in) native_addr
port := int(addr.sin_port)
ep = Endpoint {
address = IP4_Address(transmute([4]byte) addr.sin_addr),
port = port,
}
case u16(os.AF_INET6):
addr := cast(^os.sockaddr_in6) native_addr
port := int(addr.sin6_port)
ep = Endpoint {
address = IP6_Address(transmute([8]u16be) addr.sin6_addr),
port = port,
}
case:
panic("native_addr is neither IP4 or IP6 address")
}
return
}
@(private)
_sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint) {
switch native_addr.sa_family {
case u16(os.AF_INET):
addr := cast(^os.sockaddr_in) native_addr
port := int(addr.sin_port)
ep = Endpoint {
address = IP4_Address(transmute([4]byte) addr.sin_addr),
port = port,
}
case u16(os.AF_INET6):
addr := cast(^os.sockaddr_in6) native_addr
port := int(addr.sin6_port)
ep = Endpoint {
address = IP6_Address(transmute([8]u16be) addr.sin6_addr),
port = port,
}
case:
panic("native_addr is neither IP4 or IP6 address")
}
return
}

View File

@@ -8,7 +8,18 @@ import "core:strings"
import "core:c"
import "core:strconv"
import "core:intrinsics"
import "core:sys/unix"
// NOTE(flysand): For compatibility we'll make core:os package
// depend on the old (scheduled for removal) linux package.
// Seeing that there are plans for os2, I'm imagining that *that*
// package should inherit the new sys functionality.
// The reasons for these are as follows:
// 1. It's very hard to update this package without breaking *a lot* of code.
// 2. os2 is not stable anyways, so we can break compatibility all we want
// It might be weird to bring up compatibility when Odin in it's nature isn't
// all that about compatibility. But we don't want to push experimental changes
// and have people's code break while it's still work in progress.
import unix "core:sys/unix"
Handle :: distinct i32
Pid :: distinct i32

View File

@@ -2,95 +2,60 @@
//+build linux
package sync
import "core:c"
import "core:time"
import "core:intrinsics"
import "core:sys/unix"
import "core:sys/linux"
FUTEX_WAIT :: 0
FUTEX_WAKE :: 1
FUTEX_PRIVATE_FLAG :: 128
FUTEX_WAIT_PRIVATE :: (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_PRIVATE :: (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
ESUCCESS :: 0
EINTR :: -4
EAGAIN :: -11
EFAULT :: -14
EINVAL :: -22
ETIMEDOUT :: -110
get_errno :: proc "contextless" (r: int) -> int {
if -4096 < r && r < 0 {
return r
}
return 0
}
internal_futex :: proc "contextless" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> int {
code := int(intrinsics.syscall(unix.SYS_futex, uintptr(f), uintptr(op), uintptr(val), uintptr(timeout), 0, 0))
return get_errno(code)
}
_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, nil)
switch err {
case ESUCCESS, EINTR, EAGAIN, EINVAL:
// okay
case ETIMEDOUT:
_futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected)
if errno == .ETIMEDOUT {
return false
case EFAULT:
fallthrough
}
#partial switch errno {
case .NONE, .EINTR, .EAGAIN:
return true
case:
// TODO(flysand): More descriptive panic messages based on the vlaue of `errno`
_panic("futex_wait failure")
}
return true
}
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {
_futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, duration: time.Duration) -> bool {
if duration <= 0 {
return false
}
timespec_t :: struct {
tv_sec: c.long,
tv_nsec: c.long,
}
err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, &timespec_t{
tv_sec = (c.long)(duration/1e9),
tv_nsec = (c.long)(duration%1e9),
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected, &linux.Time_Spec{
time_sec = cast(uint)(duration/1e9),
time_nsec = cast(uint)(duration%1e9),
})
switch err {
case ESUCCESS, EINTR, EAGAIN, EINVAL:
// okay
case ETIMEDOUT:
if errno == .ETIMEDOUT {
return false
case EFAULT:
fallthrough
}
#partial switch errno {
case .NONE, .EINTR, .EAGAIN:
return true
case:
_panic("futex_wait_with_timeout failure")
}
return true
}
_futex_signal :: proc "contextless" (f: ^Futex) {
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, 1, nil)
switch err {
case ESUCCESS, EINVAL, EFAULT:
// okay
_futex_signal :: proc "contextless" (futex: ^Futex) {
_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, 1)
#partial switch errno {
case .NONE:
return
case:
_panic("futex_wake_single failure")
}
}
_futex_broadcast :: proc "contextless" (f: ^Futex) {
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, u32(max(i32)), nil)
switch err {
case ESUCCESS, EINVAL, EFAULT:
// okay
_futex_broadcast :: proc "contextless" (futex: ^Futex) {
// NOTE(flysand): This code was kinda funny and I don't want to remove it, but here I will
// record history of what has been in here before
// FUTEX_WAKE_PRIVATE | FUTEX_WAKE
_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, max(i32))
#partial switch errno {
case .NONE:
return
case:
_panic("_futex_wake_all failure")
}

View File

@@ -2,8 +2,8 @@
//+private
package sync
import "core:sys/unix"
import "core:sys/linux"
_current_thread_id :: proc "contextless" () -> int {
return unix.sys_gettid()
return cast(int) linux.gettid()
}

View File

@@ -1,40 +1,34 @@
// +build linux
package sysinfo
import "core:c"
import sys "core:sys/unix"
import "core:intrinsics"
import "core:runtime"
import "core:os"
import "core:strings"
import "core:strconv"
import "core:sys/linux"
@(private)
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
os_version.platform = .Linux
// Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
fd, err := os.open("/etc/os-release", os.O_RDONLY, 0)
if err != 0 {
return
fd, errno := linux.open("/etc/os-release", {.RDONLY}, {})
assert(errno == .NONE, "Failed to read /etc/os-release")
defer {
errno := linux.close(fd)
assert(errno == .NONE, "Failed to close the file descriptor")
}
defer os.close(fd)
os_release_buf: [2048]u8
n, read_err := os.read(fd, os_release_buf[:])
if read_err != 0 {
return
}
n, read_errno := linux.read(fd, os_release_buf[:])
assert(read_errno == .NONE, "Failed to read data from /etc/os-release")
release := string(os_release_buf[:n])
// Search the line in the file until we find "PRETTY_NAME="
NEEDLE :: "PRETTY_NAME=\""
pretty_start := strings.index(release, NEEDLE)
b := strings.builder_from_bytes(version_string_buf[:])
if pretty_start > 0 {
for r, i in release[pretty_start + len(NEEDLE):] {
if r == '"' {
@@ -46,94 +40,48 @@ init_os_version :: proc () {
}
}
}
NEW_UTS_LEN :: 64
UTS_Name :: struct {
sys_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
node_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
release: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
version: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
machine: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
domain_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
}
uts: UTS_Name
// Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname
if intrinsics.syscall(sys.SYS_uname, uintptr(&uts)) != 0 {
return
}
uts: linux.UTS_Name
uname_errno := linux.uname(&uts)
assert(uname_errno == .NONE, "This should never happen!")
// Append the system name (typically "Linux") and kernel release (looks like 6.5.2-arch1-1)
strings.write_string(&b, ", ")
strings.write_string(&b, string(cstring(&uts.sys_name[0])))
strings.write_string(&b, string(cstring(&uts.sysname[0])))
strings.write_rune(&b, ' ')
l := strings.builder_len(b)
strings.write_string(&b, string(cstring(&uts.release[0])))
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
// Parse kernel version, as substrings of the version info in `version_string_buf`
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
version_bits := strings.split_n(strings.to_string(b)[l:], "-", 2, context.temp_allocator)
if len(version_bits) > 1 {
os_version.version = version_bits[1]
}
// Parse major, minor, patch from release info
triplet := strings.split(version_bits[0], ".", context.temp_allocator)
if len(triplet) == 3 {
major, major_ok := strconv.parse_int(triplet[0])
minor, minor_ok := strconv.parse_int(triplet[1])
patch, patch_ok := strconv.parse_int(triplet[2])
if major_ok && minor_ok && patch_ok {
os_version.major = major
os_version.minor = minor
os_version.patch = patch
}
}
// Finish the string
os_version.as_string = strings.to_string(b)
}
Sys_Info :: struct {
uptime: c.long, // Seconds since boot
loads: [3]c.long, // 1, 5, 15 minute load averages
totalram: c.ulong, // Total usable main memory size
freeram: c.ulong, // Available memory size
sharedram: c.ulong, // Amount of shared memory
bufferram: c.ulong, // Memory used by buffers
totalswap: c.ulong, // Total swap space size
freeswap: c.ulong, // Swap space still available
procs: c.ushort, // Number of current processes
totalhigh: c.ulong, // Total high memory size
freehigh: c.ulong, // Available high memory size
mem_unit: c.int, // Memory unit size in bytes
_padding: [20 - (2 * size_of(c.long)) - size_of(c.int)]u8,
}
get_sysinfo :: proc "c" () -> (res: Sys_Info, ok: bool) {
si: Sys_Info
err := intrinsics.syscall(sys.SYS_sysinfo, uintptr(rawptr(&si)))
if err != 0 {
// Unable to retrieve sysinfo
return {}, false
}
return si, true
}
@(init)
init_ram :: proc() {
// Retrieve RAM info using `sysinfo`
si, ok := get_sysinfo()
if !ok {
return
}
sys_info: linux.Sys_Info
errno := linux.sysinfo(&sys_info)
assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!")
ram = RAM{
total_ram = int(si.totalram) * int(si.mem_unit),
free_ram = int(si.freeram) * int(si.mem_unit),
total_swap = int(si.totalswap) * int(si.mem_unit),
free_swap = int(si.freeswap) * int(si.mem_unit),
total_ram = int(sys_info.totalram) * int(sys_info.mem_unit),
free_ram = int(sys_info.freeram) * int(sys_info.mem_unit),
total_swap = int(sys_info.totalswap) * int(sys_info.mem_unit),
free_swap = int(sys_info.freeswap) * int(sys_info.mem_unit),
}
}

1400
core/sys/linux/bits.odin Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
package linux
/// Special file descriptor to pass to `*at` functions to specify
/// that relative paths are relative to current directory
AT_FDCWD :: Fd(-100)
/// Special value to put into timespec for utimensat() to set timestamp to the current time
UTIME_NOW :: uint((1 << 30) - 1)
/// Special value to put into the timespec for utimensat() to leave the corresponding field of the timestamp unchanged
UTIME_OMIT :: uint((1 << 30) - 2)
/// For wait4: Pass this pid to wait for any process
WAIT_ANY :: Pid(-1)
/// For wait4: Pass this pid to wait for any process in current process group
WAIT_MYPGRP :: Pid(0)
/// Maximum priority (aka nice value) for the process
PRIO_MAX :: 20
/// Minimum priority (aka nice value) for the process
PRIO_MIN :: -20
SIGRTMIN :: Signal(32)
SIGRTMAX :: Signal(64)
S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFFIFO}
S_IFSOCK :: Mode{.IFREG, .IFDIR}
S_IFLNK :: Mode{.IFREG, .IFCHR}
S_IFBLK :: Mode{.IFDIR, .IFCHR}
S_IFFIFO :: Mode{.IFFIFO}
S_IFCHR :: Mode{.IFCHR}
S_IFDIR :: Mode{.IFDIR}
S_IFREG :: Mode{.IFREG}
/// Checks the Mode bits to see if the file is a named pipe (FIFO)
S_ISFIFO :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFFIFO == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a character device
S_ISCHR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFCHR == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a directory
S_ISDIR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFDIR == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a register
S_ISREG :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFREG == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a socket
S_ISSOCK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFSOCK == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a symlink
S_ISLNK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFLNK == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a block device
S_ISBLK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFBLK == (m & S_IFMT))}
/// For access.2 syscall family: instruct to check if the file exists
F_OK :: Mode{}
/// For access.2 syscall family: instruct to check if the file is executable
X_OK :: Mode{.IXOTH}
/// For access.2 syscall family: instruct to check if the file is writeable
W_OK :: Mode{.IWOTH}
/// For access.2 syscall family: instruct to check if the file is readable
R_OK :: Mode{.IROTH}
/// The stats you get by calling `stat`
STATX_BASIC_STATS :: Statx_Mask {
.TYPE,
.MODE,
.NLINK,
.UID,
.GID,
.ATIME,
.MTIME,
.CTIME,
.INO,
.SIZE,
.BLOCKS,
}
FCntl_Command_DUPFD :: distinct FCntl_Command
FCntl_Command_GETFD :: distinct FCntl_Command
FCntl_Command_SETFD :: distinct FCntl_Command
FCntl_Command_GETFL :: distinct FCntl_Command
FCntl_Command_SETFL :: distinct FCntl_Command
FCntl_Command_GETLK :: distinct FCntl_Command
FCntl_Command_SETLK :: distinct FCntl_Command
FCntl_Command_SETLKW :: distinct FCntl_Command
FCntl_Command_DUPFD_CLOEXEC :: distinct FCntl_Command
FCntl_Command_SETOWN :: distinct FCntl_Command
FCntl_Command_GETOWN :: distinct FCntl_Command
FCntl_Command_SETSIG :: distinct FCntl_Command
FCntl_Command_GETSIG :: distinct FCntl_Command
FCntl_Command_SETOWN_EX :: distinct FCntl_Command
FCntl_Command_GETOWN_EX :: distinct FCntl_Command
FCntl_Command_SETLEASE :: distinct FCntl_Command
FCntl_Command_GETLEASE :: distinct FCntl_Command
FCntl_Command_NOTIFY :: distinct FCntl_Command
FCntl_Command_SETPIPE_SZ :: distinct FCntl_Command
FCntl_Command_GETPIPE_SZ :: distinct FCntl_Command
FCntl_Command_ADD_SEALS :: distinct FCntl_Command
FCntl_Command_GET_SEALS :: distinct FCntl_Command
FCntl_Command_GET_RW_HINT :: distinct FCntl_Command
FCntl_Command_SET_RW_HINT :: distinct FCntl_Command
FCntl_Command_GET_FILE_RW_HINT :: distinct FCntl_Command
FCntl_Command_SET_FILE_RW_HINT :: distinct FCntl_Command
F_DUPFD :: FCntl_Command_DUPFD(.DUPFD)
F_GETFD :: FCntl_Command_GETFD(.GETFD)
F_SETFD :: FCntl_Command_SETFD(.SETFD)
F_GETFL :: FCntl_Command_GETFL(.GETFL)
F_SETFL :: FCntl_Command_SETFL(.SETFL)
// F_GETLK64 :: FCntl_Command_GETLK64(.GETLK64)
// F_SETLK64 :: FCntl_Command_SETLK64(.SETLK64)
// F_SETLKW64 :: FCntl_Command_SETLKW64(.SETLKW64)
F_GETLK :: FCntl_Command_GETLK(.GETLK)
F_SETLK :: FCntl_Command_SETLK(.SETLK)
F_SETLKW :: FCntl_Command_SETLKW(.SETLKW)
F_DUPFD_CLOEXEC :: FCntl_Command_DUPFD_CLOEXEC(.DUPFD_CLOEXEC)
F_SETOWN :: FCntl_Command_SETOWN(.SETOWN)
F_GETOWN :: FCntl_Command_GETOWN(.GETOWN)
F_SETSIG :: FCntl_Command_SETSIG(.SETSIG)
F_GETSIG :: FCntl_Command_GETSIG(.GETSIG)
F_SETOWN_EX :: FCntl_Command_SETOWN_EX(.SETOWN_EX)
F_GETOWN_EX :: FCntl_Command_GETOWN_EX(.GETOWN_EX)
F_SETLEASE :: FCntl_Command_SETLEASE(.SETLEASE)
F_GETLEASE :: FCntl_Command_GETLEASE(.GETLEASE)
F_NOTIFY :: FCntl_Command_NOTIFY(.NOTIFY)
F_SETPIPE_SZ :: FCntl_Command_SETPIPE_SZ(.SETPIPE_SZ)
F_GETPIPE_SZ :: FCntl_Command_GETPIPE_SZ(.GETPIPE_SZ)
F_ADD_SEALS :: FCntl_Command_ADD_SEALS(.ADD_SEALS)
F_GET_SEALS :: FCntl_Command_GET_SEALS(.GET_SEALS)
F_GET_RW_HINT :: FCntl_Command_GET_RW_HINT(.GET_RW_HINT)
F_SET_RW_HINT :: FCntl_Command_SET_RW_HINT(.SET_RW_HINT)
F_GET_FILE_RW_HINT :: FCntl_Command_GET_FILE_RW_HINT(.GET_FILE_RW_HINT)
F_SET_FILE_RW_HINT :: FCntl_Command_SET_FILE_RW_HINT(.SET_FILE_RW_HINT)
Socket_API_Level_Sock :: distinct Socket_API_Level
Socket_API_Level_TCP :: distinct Socket_API_Level
Socket_API_Level_UDP :: distinct Socket_API_Level
Socket_API_Level_Raw :: distinct Socket_API_Level
SOL_SOCKET :: Socket_API_Level_Sock(.SOCKET)
SOL_TCP :: Socket_API_Level_TCP(.TCP)
SOL_UDP :: Socket_API_Level_UDP(.UDP)
SOL_RAW :: Socket_API_Level_Raw(.RAW)
Futex_Wait_Type :: distinct Futex_Op
Futex_Wake_Type :: distinct Futex_Op
Futex_Fd_Type :: distinct Futex_Op
Futex_Requeue_Type :: distinct Futex_Op
Futex_Cmp_Requeue_Type :: distinct Futex_Op
Futex_Wake_Op_Type :: distinct Futex_Op
Futex_Lock_Pi_Type :: distinct Futex_Op
Futex_Unlock_Pi_Type :: distinct Futex_Op
Futex_Trylock_Pi_Type :: distinct Futex_Op
Futex_Wait_Bitset_Type :: distinct Futex_Op
Futex_Wake_Bitset_Type :: distinct Futex_Op
Futex_Wait_requeue_Pi_Type :: distinct Futex_Op
Futex_Cmp_requeue_Pi_Type :: distinct Futex_Op
Futex_Lock_Pi2_Type :: distinct Futex_Op
/// Wait on futex wakeup signal
FUTEX_WAIT :: Futex_Wait_Type(.WAIT)
/// Wake up other processes waiting on the futex
FUTEX_WAKE :: Futex_Wake_Type(.WAKE)
/// Not implemented. Basically, since
FUTEX_FD :: Futex_Fd_Type(.FD)
/// Requeue waiters from one futex to another
FUTEX_REQUEUE :: Futex_Requeue_Type(.REQUEUE)
/// Requeue waiters from one futex to another if the value at mutex matches
FUTEX_CMP_REQUEUE :: Futex_Cmp_Requeue_Type(.CMP_REQUEUE)
/// See man pages, I'm not describing it here
FUTEX_WAKE_OP :: Futex_Wake_Op_Type(.WAKE_OP)
/// Wait on a futex, but the value is a bitset
FUTEX_WAIT_BITSET :: Futex_Wait_Bitset_Type(.WAIT_BITSET)
/// Wait on a futex, but the value is a bitset
FUTEX_WAKE_BITSET :: Futex_Wake_Bitset_Type(.WAKE_BITSET)
// TODO(flysand): Priority inversion futexes
FUTEX_LOCK_PI :: Futex_Lock_Pi_Type(.LOCK_PI)
FUTEX_UNLOCK_PI :: Futex_Unlock_Pi_Type(.UNLOCK_PI)
FUTEX_TRYLOCK_PI :: Futex_Trylock_Pi_Type(.TRYLOCK_PI)
FUTEX_WAIT_REQUEUE_PI :: Futex_Wait_requeue_Pi_Type(.WAIT_REQUEUE_PI)
FUTEX_CMP_REQUEUE_PI :: Futex_Cmp_requeue_Pi_Type(.CMP_REQUEUE_PI)
FUTEX_LOCK_PI2 :: Futex_Lock_Pi2_Type(.LOCK_PI2)

150
core/sys/linux/helpers.odin Normal file
View File

@@ -0,0 +1,150 @@
//+build linux
package linux
import "core:intrinsics"
// Note(flysand): In the case of syscall let's get rid of extra
// casting. First of all, let these syscalls return int, because
// we'll need to check for Errno anyway. Second of all
// most parameters are going to be trivially-castable to
// uintptr, so we'll have that.
@(private)
syscall0 :: #force_inline proc "contextless" (nr: uintptr) -> int {
return cast(int) intrinsics.syscall(nr)
}
@(private)
syscall1 :: #force_inline proc "contextless" (nr: uintptr, p1: $T) -> int
where
size_of(p1) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr, cast(uintptr) p1)
}
@(private)
syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1, cast(uintptr) p2)
}
@(private)
syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3)
}
@(private)
syscall4 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4)
}
@(private)
syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr) &&
size_of(p5) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4,
cast(uintptr) p5)
}
@(private)
syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr) &&
size_of(p5) <= size_of(uintptr) &&
size_of(p6) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4,
cast(uintptr) p5,
cast(uintptr) p6)
}
syscall :: proc {syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}
// Note(bumbread): This should shrug off a few lines from every syscall.
// Since not any type can be trivially casted to another type, we take two arguments:
// the final type to cast to, and the type to transmute to before casting.
// One transmute + one cast should allow us to get to any type we might want
// to return from a syscall wrapper.
@(private)
errno_unwrap3 :: #force_inline proc "contextless" (ret: $P, $T: typeid, $U: typeid) -> (T, Errno)
where
intrinsics.type_is_ordered_numeric(P)
{
if ret < 0 {
default_value: T
return default_value, Errno(-ret)
} else {
return cast(T) transmute(U) ret, Errno(.NONE)
}
}
@(private)
errno_unwrap2 :: #force_inline proc "contextless" (ret: $P, $T: typeid) -> (T, Errno) {
if ret < 0 {
default_value: T
return default_value, Errno(-ret)
} else {
return cast(T) ret, Errno(.NONE)
}
}
@(private)
errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
// Note(flysand): 32-bit architectures sometimes take in a 64-bit argument in a
// register pair. This function should help me avoid typing the same code a few times..
when size_of(int) == 4 {
// xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
@(private)
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
no_sign := uint(a)
hi = uint(no_sign >> 32)
lo = uint(no_sign & 0xffff_ffff)
return
}
} else {
// ... and on 64-bit architectures it's just a long
@(private)
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (uint) {
return uint(a)
}
}

2038
core/sys/linux/sys.odin Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,373 @@
//+build amd64
package linux
// AMD64 uses the new way to define syscalls, i.e. one that
// is different from the other architectures. Instead of using
// a .tbl file, they define constants to tell which syscalls they
// want and then include a generic unistd.h file.
SYS_read :: uintptr(0)
SYS_write :: uintptr(1)
SYS_open :: uintptr(2)
SYS_close :: uintptr(3)
SYS_stat :: uintptr(4)
SYS_fstat :: uintptr(5)
SYS_lstat :: uintptr(6)
SYS_poll :: uintptr(7)
SYS_lseek :: uintptr(8)
SYS_mmap :: uintptr(9)
SYS_mprotect :: uintptr(10)
SYS_munmap :: uintptr(11)
SYS_brk :: uintptr(12)
SYS_rt_sigaction :: uintptr(13)
SYS_rt_sigprocmask :: uintptr(14)
SYS_rt_sigreturn :: uintptr(15)
SYS_ioctl :: uintptr(16)
SYS_pread64 :: uintptr(17)
SYS_pwrite64 :: uintptr(18)
SYS_readv :: uintptr(19)
SYS_writev :: uintptr(20)
SYS_access :: uintptr(21)
SYS_pipe :: uintptr(22)
SYS_select :: uintptr(23)
SYS_sched_yield :: uintptr(24)
SYS_mremap :: uintptr(25)
SYS_msync :: uintptr(26)
SYS_mincore :: uintptr(27)
SYS_madvise :: uintptr(28)
SYS_shmget :: uintptr(29)
SYS_shmat :: uintptr(30)
SYS_shmctl :: uintptr(31)
SYS_dup :: uintptr(32)
SYS_dup2 :: uintptr(33)
SYS_pause :: uintptr(34)
SYS_nanosleep :: uintptr(35)
SYS_getitimer :: uintptr(36)
SYS_alarm :: uintptr(37)
SYS_setitimer :: uintptr(38)
SYS_getpid :: uintptr(39)
SYS_sendfile :: uintptr(40)
SYS_socket :: uintptr(41)
SYS_connect :: uintptr(42)
SYS_accept :: uintptr(43)
SYS_sendto :: uintptr(44)
SYS_recvfrom :: uintptr(45)
SYS_sendmsg :: uintptr(46)
SYS_recvmsg :: uintptr(47)
SYS_shutdown :: uintptr(48)
SYS_bind :: uintptr(49)
SYS_listen :: uintptr(50)
SYS_getsockname :: uintptr(51)
SYS_getpeername :: uintptr(52)
SYS_socketpair :: uintptr(53)
SYS_setsockopt :: uintptr(54)
SYS_getsockopt :: uintptr(55)
SYS_clone :: uintptr(56)
SYS_fork :: uintptr(57)
SYS_vfork :: uintptr(58)
SYS_execve :: uintptr(59)
SYS_exit :: uintptr(60)
SYS_wait4 :: uintptr(61)
SYS_kill :: uintptr(62)
SYS_uname :: uintptr(63)
SYS_semget :: uintptr(64)
SYS_semop :: uintptr(65)
SYS_semctl :: uintptr(66)
SYS_shmdt :: uintptr(67)
SYS_msgget :: uintptr(68)
SYS_msgsnd :: uintptr(69)
SYS_msgrcv :: uintptr(70)
SYS_msgctl :: uintptr(71)
SYS_fcntl :: uintptr(72)
SYS_flock :: uintptr(73)
SYS_fsync :: uintptr(74)
SYS_fdatasync :: uintptr(75)
SYS_truncate :: uintptr(76)
SYS_ftruncate :: uintptr(77)
SYS_getdents :: uintptr(78)
SYS_getcwd :: uintptr(79)
SYS_chdir :: uintptr(80)
SYS_fchdir :: uintptr(81)
SYS_rename :: uintptr(82)
SYS_mkdir :: uintptr(83)
SYS_rmdir :: uintptr(84)
SYS_creat :: uintptr(85)
SYS_link :: uintptr(86)
SYS_unlink :: uintptr(87)
SYS_symlink :: uintptr(88)
SYS_readlink :: uintptr(89)
SYS_chmod :: uintptr(90)
SYS_fchmod :: uintptr(91)
SYS_chown :: uintptr(92)
SYS_fchown :: uintptr(93)
SYS_lchown :: uintptr(94)
SYS_umask :: uintptr(95)
SYS_gettimeofday :: uintptr(96)
SYS_getrlimit :: uintptr(97)
SYS_getrusage :: uintptr(98)
SYS_sysinfo :: uintptr(99)
SYS_times :: uintptr(100)
SYS_ptrace :: uintptr(101)
SYS_getuid :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_getgid :: uintptr(104)
SYS_setuid :: uintptr(105)
SYS_setgid :: uintptr(106)
SYS_geteuid :: uintptr(107)
SYS_getegid :: uintptr(108)
SYS_setpgid :: uintptr(109)
SYS_getppid :: uintptr(110)
SYS_getpgrp :: uintptr(111)
SYS_setsid :: uintptr(112)
SYS_setreuid :: uintptr(113)
SYS_setregid :: uintptr(114)
SYS_getgroups :: uintptr(115)
SYS_setgroups :: uintptr(116)
SYS_setresuid :: uintptr(117)
SYS_getresuid :: uintptr(118)
SYS_setresgid :: uintptr(119)
SYS_getresgid :: uintptr(120)
SYS_getpgid :: uintptr(121)
SYS_setfsuid :: uintptr(122)
SYS_setfsgid :: uintptr(123)
SYS_getsid :: uintptr(124)
SYS_capget :: uintptr(125)
SYS_capset :: uintptr(126)
SYS_rt_sigpending :: uintptr(127)
SYS_rt_sigtimedwait :: uintptr(128)
SYS_rt_sigqueueinfo :: uintptr(129)
SYS_rt_sigsuspend :: uintptr(130)
SYS_sigaltstack :: uintptr(131)
SYS_utime :: uintptr(132)
SYS_mknod :: uintptr(133)
SYS_uselib :: uintptr(134)
SYS_personality :: uintptr(135)
SYS_ustat :: uintptr(136)
SYS_statfs :: uintptr(137)
SYS_fstatfs :: uintptr(138)
SYS_sysfs :: uintptr(139)
SYS_getpriority :: uintptr(140)
SYS_setpriority :: uintptr(141)
SYS_sched_setparam :: uintptr(142)
SYS_sched_getparam :: uintptr(143)
SYS_sched_setscheduler :: uintptr(144)
SYS_sched_getscheduler :: uintptr(145)
SYS_sched_get_priority_max :: uintptr(146)
SYS_sched_get_priority_min :: uintptr(147)
SYS_sched_rr_get_interval :: uintptr(148)
SYS_mlock :: uintptr(149)
SYS_munlock :: uintptr(150)
SYS_mlockall :: uintptr(151)
SYS_munlockall :: uintptr(152)
SYS_vhangup :: uintptr(153)
SYS_modify_ldt :: uintptr(154)
SYS_pivot_root :: uintptr(155)
SYS__sysctl :: uintptr(156)
SYS_prctl :: uintptr(157)
SYS_arch_prctl :: uintptr(158)
SYS_adjtimex :: uintptr(159)
SYS_setrlimit :: uintptr(160)
SYS_chroot :: uintptr(161)
SYS_sync :: uintptr(162)
SYS_acct :: uintptr(163)
SYS_settimeofday :: uintptr(164)
SYS_mount :: uintptr(165)
SYS_umount2 :: uintptr(166)
SYS_swapon :: uintptr(167)
SYS_swapoff :: uintptr(168)
SYS_reboot :: uintptr(169)
SYS_sethostname :: uintptr(170)
SYS_setdomainname :: uintptr(171)
SYS_iopl :: uintptr(172)
SYS_ioperm :: uintptr(173)
SYS_create_module :: uintptr(174)
SYS_init_module :: uintptr(175)
SYS_delete_module :: uintptr(176)
SYS_get_kernel_syms :: uintptr(177)
SYS_query_module :: uintptr(178)
SYS_quotactl :: uintptr(179)
SYS_nfsservctl :: uintptr(180)
SYS_getpmsg :: uintptr(181)
SYS_putpmsg :: uintptr(182)
SYS_afs_syscall :: uintptr(183)
SYS_tuxcall :: uintptr(184)
SYS_security :: uintptr(185)
SYS_gettid :: uintptr(186)
SYS_readahead :: uintptr(187)
SYS_setxattr :: uintptr(188)
SYS_lsetxattr :: uintptr(189)
SYS_fsetxattr :: uintptr(190)
SYS_getxattr :: uintptr(191)
SYS_lgetxattr :: uintptr(192)
SYS_fgetxattr :: uintptr(193)
SYS_listxattr :: uintptr(194)
SYS_llistxattr :: uintptr(195)
SYS_flistxattr :: uintptr(196)
SYS_removexattr :: uintptr(197)
SYS_lremovexattr :: uintptr(198)
SYS_fremovexattr :: uintptr(199)
SYS_tkill :: uintptr(200)
SYS_time :: uintptr(201)
SYS_futex :: uintptr(202)
SYS_sched_setaffinity :: uintptr(203)
SYS_sched_getaffinity :: uintptr(204)
SYS_set_thread_area :: uintptr(205)
SYS_io_setup :: uintptr(206)
SYS_io_destroy :: uintptr(207)
SYS_io_getevents :: uintptr(208)
SYS_io_submit :: uintptr(209)
SYS_io_cancel :: uintptr(210)
SYS_get_thread_area :: uintptr(211)
SYS_lookup_dcookie :: uintptr(212)
SYS_epoll_create :: uintptr(213)
SYS_epoll_ctl_old :: uintptr(214)
SYS_epoll_wait_old :: uintptr(215)
SYS_remap_file_pages :: uintptr(216)
SYS_getdents64 :: uintptr(217)
SYS_set_tid_address :: uintptr(218)
SYS_restart_syscall :: uintptr(219)
SYS_semtimedop :: uintptr(220)
SYS_fadvise64 :: uintptr(221)
SYS_timer_create :: uintptr(222)
SYS_timer_settime :: uintptr(223)
SYS_timer_gettime :: uintptr(224)
SYS_timer_getoverrun :: uintptr(225)
SYS_timer_delete :: uintptr(226)
SYS_clock_settime :: uintptr(227)
SYS_clock_gettime :: uintptr(228)
SYS_clock_getres :: uintptr(229)
SYS_clock_nanosleep :: uintptr(230)
SYS_exit_group :: uintptr(231)
SYS_epoll_wait :: uintptr(232)
SYS_epoll_ctl :: uintptr(233)
SYS_tgkill :: uintptr(234)
SYS_utimes :: uintptr(235)
SYS_vserver :: uintptr(236)
SYS_mbind :: uintptr(237)
SYS_set_mempolicy :: uintptr(238)
SYS_get_mempolicy :: uintptr(239)
SYS_mq_open :: uintptr(240)
SYS_mq_unlink :: uintptr(241)
SYS_mq_timedsend :: uintptr(242)
SYS_mq_timedreceive :: uintptr(243)
SYS_mq_notify :: uintptr(244)
SYS_mq_getsetattr :: uintptr(245)
SYS_kexec_load :: uintptr(246)
SYS_waitid :: uintptr(247)
SYS_add_key :: uintptr(248)
SYS_request_key :: uintptr(249)
SYS_keyctl :: uintptr(250)
SYS_ioprio_set :: uintptr(251)
SYS_ioprio_get :: uintptr(252)
SYS_inotify_init :: uintptr(253)
SYS_inotify_add_watch :: uintptr(254)
SYS_inotify_rm_watch :: uintptr(255)
SYS_migrate_pages :: uintptr(256)
SYS_openat :: uintptr(257)
SYS_mkdirat :: uintptr(258)
SYS_mknodat :: uintptr(259)
SYS_fchownat :: uintptr(260)
SYS_futimesat :: uintptr(261)
SYS_newfstatat :: uintptr(262)
SYS_unlinkat :: uintptr(263)
SYS_renameat :: uintptr(264)
SYS_linkat :: uintptr(265)
SYS_symlinkat :: uintptr(266)
SYS_readlinkat :: uintptr(267)
SYS_fchmodat :: uintptr(268)
SYS_faccessat :: uintptr(269)
SYS_pselect6 :: uintptr(270)
SYS_ppoll :: uintptr(271)
SYS_unshare :: uintptr(272)
SYS_set_robust_list :: uintptr(273)
SYS_get_robust_list :: uintptr(274)
SYS_splice :: uintptr(275)
SYS_tee :: uintptr(276)
SYS_sync_file_range :: uintptr(277)
SYS_vmsplice :: uintptr(278)
SYS_move_pages :: uintptr(279)
SYS_utimensat :: uintptr(280)
SYS_epoll_pwait :: uintptr(281)
SYS_signalfd :: uintptr(282)
SYS_timerfd_create :: uintptr(283)
SYS_eventfd :: uintptr(284)
SYS_fallocate :: uintptr(285)
SYS_timerfd_settime :: uintptr(286)
SYS_timerfd_gettime :: uintptr(287)
SYS_accept4 :: uintptr(288)
SYS_signalfd4 :: uintptr(289)
SYS_eventfd2 :: uintptr(290)
SYS_epoll_create1 :: uintptr(291)
SYS_dup3 :: uintptr(292)
SYS_pipe2 :: uintptr(293)
SYS_inotify_init1 :: uintptr(294)
SYS_preadv :: uintptr(295)
SYS_pwritev :: uintptr(296)
SYS_rt_tgsigqueueinfo :: uintptr(297)
SYS_perf_event_open :: uintptr(298)
SYS_recvmmsg :: uintptr(299)
SYS_fanotify_init :: uintptr(300)
SYS_fanotify_mark :: uintptr(301)
SYS_prlimit64 :: uintptr(302)
SYS_name_to_handle_at :: uintptr(303)
SYS_open_by_handle_at :: uintptr(304)
SYS_clock_adjtime :: uintptr(305)
SYS_syncfs :: uintptr(306)
SYS_sendmmsg :: uintptr(307)
SYS_setns :: uintptr(308)
SYS_getcpu :: uintptr(309)
SYS_process_vm_readv :: uintptr(310)
SYS_process_vm_writev :: uintptr(311)
SYS_kcmp :: uintptr(312)
SYS_finit_module :: uintptr(313)
SYS_sched_setattr :: uintptr(314)
SYS_sched_getattr :: uintptr(315)
SYS_renameat2 :: uintptr(316)
SYS_seccomp :: uintptr(317)
SYS_getrandom :: uintptr(318)
SYS_memfd_create :: uintptr(319)
SYS_kexec_file_load :: uintptr(320)
SYS_bpf :: uintptr(321)
SYS_execveat :: uintptr(322)
SYS_userfaultfd :: uintptr(323)
SYS_membarrier :: uintptr(324)
SYS_mlock2 :: uintptr(325)
SYS_copy_file_range :: uintptr(326)
SYS_preadv2 :: uintptr(327)
SYS_pwritev2 :: uintptr(328)
SYS_pkey_mprotect :: uintptr(329)
SYS_pkey_alloc :: uintptr(330)
SYS_pkey_free :: uintptr(331)
SYS_statx :: uintptr(332)
SYS_io_pgetevents :: uintptr(333)
SYS_rseq :: uintptr(334)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)
SYS_map_shadow_stack :: uintptr(453)

View File

@@ -0,0 +1,470 @@
//+build arm32
package linux
// This file was taken and transformed from
// /arch/arm/tools/syscall.tbl
// in linux headers. OABI and EABI syscalls
// are included.
// TODO(bumbread, 2023-10-13): I'm not sure whether I have used
// the right syscall table. ARM64 stuff seems to be also compatible
// with ARM32, I'm not sure whether ARM32 also uses the new way of
// defining the syscall table, and this one is just for compatibility..?
// This syscall is not meant to be used by userspace
SYS_restart_syscall :: uintptr(0)
SYS_exit :: uintptr(1)
SYS_fork :: uintptr(2)
SYS_read :: uintptr(3)
SYS_write :: uintptr(4)
SYS_open :: uintptr(5)
SYS_close :: uintptr(6)
// 7 was sys_waitpid
SYS_creat :: uintptr(8)
SYS_link :: uintptr(9)
SYS_unlink :: uintptr(10)
SYS_execve :: uintptr(11)
SYS_chdir :: uintptr(12)
SYS_time :: uintptr(13)
SYS_mknod :: uintptr(14)
SYS_chmod :: uintptr(15)
SYS_lchown :: uintptr(16)
// 17 was sys_break
// 18 was sys_stat
SYS_lseek :: uintptr(19)
SYS_getpid :: uintptr(20)
SYS_mount :: uintptr(21)
SYS_umount :: uintptr(22)
SYS_setuid :: uintptr(23)
SYS_getuid :: uintptr(24)
SYS_stime :: uintptr(25)
SYS_ptrace :: uintptr(26)
SYS_alarm :: uintptr(27)
// 28 was sys_fstat
SYS_pause :: uintptr(29)
SYS_utime :: uintptr(30)
// 31 was sys_stty
// 32 was sys_gtty
SYS_access :: uintptr(33)
SYS_nice :: uintptr(34)
// 35 was sys_ftime
SYS_sync :: uintptr(36)
SYS_kill :: uintptr(37)
SYS_rename :: uintptr(38)
SYS_mkdir :: uintptr(39)
SYS_rmdir :: uintptr(40)
SYS_dup :: uintptr(41)
SYS_pipe :: uintptr(42)
SYS_times :: uintptr(43)
// 44 was sys_prof
SYS_brk :: uintptr(45)
SYS_setgid :: uintptr(46)
SYS_getgid :: uintptr(47)
// 48 was sys_signal
SYS_geteuid :: uintptr(49)
SYS_getegid :: uintptr(50)
SYS_acct :: uintptr(51)
SYS_umount2 :: uintptr(52)
// 53 was sys_lock
SYS_ioctl :: uintptr(54)
SYS_fcntl :: uintptr(55)
// 56 was sys_mpx
SYS_setpgid :: uintptr(57)
// 58 was sys_ulimit
// 59 was sys_olduname
SYS_umask :: uintptr(60)
SYS_chroot :: uintptr(61)
SYS_ustat :: uintptr(62)
SYS_dup2 :: uintptr(63)
SYS_getppid :: uintptr(64)
SYS_getpgrp :: uintptr(65)
SYS_setsid :: uintptr(66)
SYS_sigaction :: uintptr(67)
// 68 was sys_sgetmask
// 69 was sys_ssetmask
SYS_setreuid :: uintptr(70)
SYS_setregid :: uintptr(71)
SYS_sigsuspend :: uintptr(72)
SYS_sigpending :: uintptr(73)
SYS_sethostname :: uintptr(74)
SYS_setrlimit :: uintptr(75)
// Back compat 2GB limited rlimit
SYS_getrlimit :: uintptr(76)
SYS_getrusage :: uintptr(77)
SYS_gettimeofday :: uintptr(78)
SYS_settimeofday :: uintptr(79)
SYS_getgroups :: uintptr(80)
SYS_setgroups :: uintptr(81)
SYS_select :: uintptr(82)
SYS_symlink :: uintptr(83)
// 84 was sys_lstat
SYS_readlink :: uintptr(85)
SYS_uselib :: uintptr(86)
SYS_swapon :: uintptr(87)
SYS_reboot :: uintptr(88)
SYS_readdir :: uintptr(89)
SYS_mmap :: uintptr(90)
SYS_munmap :: uintptr(91)
SYS_truncate :: uintptr(92)
SYS_ftruncate :: uintptr(93)
SYS_fchmod :: uintptr(94)
SYS_fchown :: uintptr(95)
SYS_getpriority :: uintptr(96)
SYS_setpriority :: uintptr(97)
// 98 was sys_profil
SYS_statfs :: uintptr(99)
SYS_fstatfs :: uintptr(100)
// 101 was sys_ioperm
SYS_socketcall :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_setitimer :: uintptr(104)
SYS_getitimer :: uintptr(105)
SYS_stat :: uintptr(106)
SYS_lstat :: uintptr(107)
SYS_fstat :: uintptr(108)
// 109 was sys_uname
// 110 was sys_iopl
SYS_vhangup :: uintptr(111)
// 112 was sys_idle
// syscall to call a syscall!
SYS_syscall :: uintptr(113)
SYS_wait4 :: uintptr(114)
SYS_swapoff :: uintptr(115)
SYS_sysinfo :: uintptr(116)
SYS_ipc :: uintptr(117)
SYS_fsync :: uintptr(118)
SYS_sigreturn :: uintptr(119)
SYS_clone :: uintptr(120)
SYS_setdomainname :: uintptr(121)
SYS_uname :: uintptr(122)
// 123 was sys_modify_ldt
SYS_adjtimex :: uintptr(124)
SYS_mprotect :: uintptr(125)
SYS_sigprocmask :: uintptr(126)
// 127 was sys_create_module
SYS_init_module :: uintptr(128)
SYS_delete_module :: uintptr(129)
// 130 was sys_get_kernel_syms
SYS_quotactl :: uintptr(131)
SYS_getpgid :: uintptr(132)
SYS_fchdir :: uintptr(133)
SYS_bdflush :: uintptr(134)
SYS_sysfs :: uintptr(135)
SYS_personality :: uintptr(136)
// 137 was sys_afs_syscall
SYS_setfsuid :: uintptr(138)
SYS_setfsgid :: uintptr(139)
SYS__llseek :: uintptr(140)
SYS_getdents :: uintptr(141)
SYS__newselect :: uintptr(142)
SYS_flock :: uintptr(143)
SYS_msync :: uintptr(144)
SYS_readv :: uintptr(145)
SYS_writev :: uintptr(146)
SYS_getsid :: uintptr(147)
SYS_fdatasync :: uintptr(148)
SYS__sysctl :: uintptr(149)
SYS_mlock :: uintptr(150)
SYS_munlock :: uintptr(151)
SYS_mlockall :: uintptr(152)
SYS_munlockall :: uintptr(153)
SYS_sched_setparam :: uintptr(154)
SYS_sched_getparam :: uintptr(155)
SYS_sched_setscheduler :: uintptr(156)
SYS_sched_getscheduler :: uintptr(157)
SYS_sched_yield :: uintptr(158)
SYS_sched_get_priority_max :: uintptr(159)
SYS_sched_get_priority_min :: uintptr(160)
SYS_sched_rr_get_interval :: uintptr(161)
SYS_nanosleep :: uintptr(162)
SYS_mremap :: uintptr(163)
SYS_setresuid :: uintptr(164)
SYS_getresuid :: uintptr(165)
// 166 was sys_vm86
// 167 was sys_query_module
SYS_poll :: uintptr(168)
SYS_nfsservctl :: uintptr(169)
SYS_setresgid :: uintptr(170)
SYS_getresgid :: uintptr(171)
SYS_prctl :: uintptr(172)
SYS_rt_sigreturn :: uintptr(173)
SYS_rt_sigaction :: uintptr(174)
SYS_rt_sigprocmask :: uintptr(175)
SYS_rt_sigpending :: uintptr(176)
SYS_rt_sigtimedwait :: uintptr(177)
SYS_rt_sigqueueinfo :: uintptr(178)
SYS_rt_sigsuspend :: uintptr(179)
SYS_pread64 :: uintptr(180)
SYS_pwrite64 :: uintptr(181)
SYS_chown :: uintptr(182)
SYS_getcwd :: uintptr(183)
SYS_capget :: uintptr(184)
SYS_capset :: uintptr(185)
SYS_sigaltstack :: uintptr(186)
SYS_sendfile :: uintptr(187)
// 188 reserved
// 189 reserved
SYS_vfork :: uintptr(190)
// SuS compliant getrlimit
SYS_ugetrlimit :: uintptr(191)
SYS_mmap2 :: uintptr(192)
SYS_truncate64 :: uintptr(193)
SYS_ftruncate64 :: uintptr(194)
SYS_stat64 :: uintptr(195)
SYS_lstat64 :: uintptr(196)
SYS_fstat64 :: uintptr(197)
SYS_lchown32 :: uintptr(198)
SYS_getuid32 :: uintptr(199)
SYS_getgid32 :: uintptr(200)
SYS_geteuid32 :: uintptr(201)
SYS_getegid32 :: uintptr(202)
SYS_setreuid32 :: uintptr(203)
SYS_setregid32 :: uintptr(204)
SYS_getgroups32 :: uintptr(205)
SYS_setgroups32 :: uintptr(206)
SYS_fchown32 :: uintptr(207)
SYS_setresuid32 :: uintptr(208)
SYS_getresuid32 :: uintptr(209)
SYS_setresgid32 :: uintptr(210)
SYS_getresgid32 :: uintptr(211)
SYS_chown32 :: uintptr(212)
SYS_setuid32 :: uintptr(213)
SYS_setgid32 :: uintptr(214)
SYS_setfsuid32 :: uintptr(215)
SYS_setfsgid32 :: uintptr(216)
SYS_getdents64 :: uintptr(217)
SYS_pivot_root :: uintptr(218)
SYS_mincore :: uintptr(219)
SYS_madvise :: uintptr(220)
SYS_fcntl64 :: uintptr(221)
// 222 for tux
// 223 is unused
SYS_gettid :: uintptr(224)
SYS_readahead :: uintptr(225)
SYS_setxattr :: uintptr(226)
SYS_lsetxattr :: uintptr(227)
SYS_fsetxattr :: uintptr(228)
SYS_getxattr :: uintptr(229)
SYS_lgetxattr :: uintptr(230)
SYS_fgetxattr :: uintptr(231)
SYS_listxattr :: uintptr(232)
SYS_llistxattr :: uintptr(233)
SYS_flistxattr :: uintptr(234)
SYS_removexattr :: uintptr(235)
SYS_lremovexattr :: uintptr(236)
SYS_fremovexattr :: uintptr(237)
SYS_tkill :: uintptr(238)
SYS_sendfile64 :: uintptr(239)
SYS_futex :: uintptr(240)
SYS_sched_setaffinity :: uintptr(241)
SYS_sched_getaffinity :: uintptr(242)
SYS_io_setup :: uintptr(243)
SYS_io_destroy :: uintptr(244)
SYS_io_getevents :: uintptr(245)
SYS_io_submit :: uintptr(246)
SYS_io_cancel :: uintptr(247)
SYS_exit_group :: uintptr(248)
SYS_lookup_dcookie :: uintptr(249)
SYS_epoll_create :: uintptr(250)
SYS_epoll_ctl :: uintptr(251)
SYS_epoll_wait :: uintptr(252)
SYS_remap_file_pages :: uintptr(253)
// 254 for set_thread_area
// 255 for get_thread_area
SYS_set_tid_address :: uintptr(256)
SYS_timer_create :: uintptr(257)
SYS_timer_settime :: uintptr(258)
SYS_timer_gettime :: uintptr(259)
SYS_timer_getoverrun :: uintptr(260)
SYS_timer_delete :: uintptr(261)
SYS_clock_settime :: uintptr(262)
SYS_clock_gettime :: uintptr(263)
SYS_clock_getres :: uintptr(264)
SYS_clock_nanosleep :: uintptr(265)
SYS_statfs64 :: uintptr(266)
SYS_fstatfs64 :: uintptr(267)
SYS_tgkill :: uintptr(268)
SYS_utimes :: uintptr(269)
SYS_arm_fadvise64_64 :: uintptr(270)
SYS_pciconfig_iobase :: uintptr(271)
SYS_pciconfig_read :: uintptr(272)
SYS_pciconfig_write :: uintptr(273)
SYS_mq_open :: uintptr(274)
SYS_mq_unlink :: uintptr(275)
SYS_mq_timedsend :: uintptr(276)
SYS_mq_timedreceive :: uintptr(277)
SYS_mq_notify :: uintptr(278)
SYS_mq_getsetattr :: uintptr(279)
SYS_waitid :: uintptr(280)
SYS_socket :: uintptr(281)
SYS_bind :: uintptr(282)
SYS_connect :: uintptr(283)
SYS_listen :: uintptr(284)
SYS_accept :: uintptr(285)
SYS_getsockname :: uintptr(286)
SYS_getpeername :: uintptr(287)
SYS_socketpair :: uintptr(288)
SYS_send :: uintptr(289)
SYS_sendto :: uintptr(290)
SYS_recv :: uintptr(291)
SYS_recvfrom :: uintptr(292)
SYS_shutdown :: uintptr(293)
SYS_setsockopt :: uintptr(294)
SYS_getsockopt :: uintptr(295)
SYS_sendmsg :: uintptr(296)
SYS_recvmsg :: uintptr(297)
SYS_semop :: uintptr(298)
SYS_semget :: uintptr(299)
SYS_semctl :: uintptr(300)
SYS_msgsnd :: uintptr(301)
SYS_msgrcv :: uintptr(302)
SYS_msgget :: uintptr(303)
SYS_msgctl :: uintptr(304)
SYS_shmat :: uintptr(305)
SYS_shmdt :: uintptr(306)
SYS_shmget :: uintptr(307)
SYS_shmctl :: uintptr(308)
SYS_add_key :: uintptr(309)
SYS_request_key :: uintptr(310)
SYS_keyctl :: uintptr(311)
SYS_semtimedop :: uintptr(312)
SYS_vserver :: uintptr(313)
SYS_ioprio_set :: uintptr(314)
SYS_ioprio_get :: uintptr(315)
SYS_inotify_init :: uintptr(316)
SYS_inotify_add_watch :: uintptr(317)
SYS_inotify_rm_watch :: uintptr(318)
SYS_mbind :: uintptr(319)
SYS_get_mempolicy :: uintptr(320)
SYS_set_mempolicy :: uintptr(321)
SYS_openat :: uintptr(322)
SYS_mkdirat :: uintptr(323)
SYS_mknodat :: uintptr(324)
SYS_fchownat :: uintptr(325)
SYS_futimesat :: uintptr(326)
SYS_fstatat64 :: uintptr(327)
SYS_unlinkat :: uintptr(328)
SYS_renameat :: uintptr(329)
SYS_linkat :: uintptr(330)
SYS_symlinkat :: uintptr(331)
SYS_readlinkat :: uintptr(332)
SYS_fchmodat :: uintptr(333)
SYS_faccessat :: uintptr(334)
SYS_pselect6 :: uintptr(335)
SYS_ppoll :: uintptr(336)
SYS_unshare :: uintptr(337)
SYS_set_robust_list :: uintptr(338)
SYS_get_robust_list :: uintptr(339)
SYS_splice :: uintptr(340)
SYS_arm_sync_file_range :: uintptr(341)
SYS_tee :: uintptr(342)
SYS_vmsplice :: uintptr(343)
SYS_move_pages :: uintptr(344)
SYS_getcpu :: uintptr(345)
SYS_epoll_pwait :: uintptr(346)
SYS_kexec_load :: uintptr(347)
SYS_utimensat :: uintptr(348)
SYS_signalfd :: uintptr(349)
SYS_timerfd_create :: uintptr(350)
SYS_eventfd :: uintptr(351)
SYS_fallocate :: uintptr(352)
SYS_timerfd_settime :: uintptr(353)
SYS_timerfd_gettime :: uintptr(354)
SYS_signalfd4 :: uintptr(355)
SYS_eventfd2 :: uintptr(356)
SYS_epoll_create1 :: uintptr(357)
SYS_dup3 :: uintptr(358)
SYS_pipe2 :: uintptr(359)
SYS_inotify_init1 :: uintptr(360)
SYS_preadv :: uintptr(361)
SYS_pwritev :: uintptr(362)
SYS_rt_tgsigqueueinfo :: uintptr(363)
SYS_perf_event_open :: uintptr(364)
SYS_recvmmsg :: uintptr(365)
SYS_accept4 :: uintptr(366)
SYS_fanotify_init :: uintptr(367)
SYS_fanotify_mark :: uintptr(368)
SYS_prlimit64 :: uintptr(369)
SYS_name_to_handle_at :: uintptr(370)
SYS_open_by_handle_at :: uintptr(371)
SYS_clock_adjtime :: uintptr(372)
SYS_syncfs :: uintptr(373)
SYS_sendmmsg :: uintptr(374)
SYS_setns :: uintptr(375)
SYS_process_vm_readv :: uintptr(376)
SYS_process_vm_writev :: uintptr(377)
SYS_kcmp :: uintptr(378)
SYS_finit_module :: uintptr(379)
SYS_sched_setattr :: uintptr(380)
SYS_sched_getattr :: uintptr(381)
SYS_renameat2 :: uintptr(382)
SYS_seccomp :: uintptr(383)
SYS_getrandom :: uintptr(384)
SYS_memfd_create :: uintptr(385)
SYS_bpf :: uintptr(386)
SYS_execveat :: uintptr(387)
SYS_userfaultfd :: uintptr(388)
SYS_membarrier :: uintptr(389)
SYS_mlock2 :: uintptr(390)
SYS_copy_file_range :: uintptr(391)
SYS_preadv2 :: uintptr(392)
SYS_pwritev2 :: uintptr(393)
SYS_pkey_mprotect :: uintptr(394)
SYS_pkey_alloc :: uintptr(395)
SYS_pkey_free :: uintptr(396)
SYS_statx :: uintptr(397)
SYS_rseq :: uintptr(398)
SYS_io_pgetevents :: uintptr(399)
SYS_migrate_pages :: uintptr(400)
SYS_kexec_file_load :: uintptr(401)
// 402 is unused
SYS_clock_gettime64 :: uintptr(403)
SYS_clock_settime64 :: uintptr(404)
SYS_clock_adjtime64 :: uintptr(405)
SYS_clock_getres_time64 :: uintptr(406)
SYS_clock_nanosleep_time64 :: uintptr(407)
SYS_timer_gettime64 :: uintptr(408)
SYS_timer_settime64 :: uintptr(409)
SYS_timerfd_gettime64 :: uintptr(410)
SYS_timerfd_settime64 :: uintptr(411)
SYS_utimensat_time64 :: uintptr(412)
SYS_pselect6_time64 :: uintptr(413)
SYS_ppoll_time64 :: uintptr(414)
SYS_io_pgetevents_time64 :: uintptr(416)
SYS_recvmmsg_time64 :: uintptr(417)
SYS_mq_timedsend_time64 :: uintptr(418)
SYS_mq_timedreceive_time64 :: uintptr(419)
SYS_semtimedop_time64 :: uintptr(420)
SYS_rt_sigtimedwait_time64 :: uintptr(421)
SYS_futex_time64 :: uintptr(422)
SYS_sched_rr_get_interval_time64:: uintptr(423)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
// 447 reserved for memfd_secret
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)

View File

@@ -0,0 +1,321 @@
//+build arm64
package linux
// Syscalls for arm64 are defined using the new way, i.e. differently from
// the other platforms. It defines a few constants representing which optional
// syscalls it wants and includes the generic unistd.h file.
SYS_io_setup :: uintptr(0)
SYS_io_destroy :: uintptr(1)
SYS_io_submit :: uintptr(2)
SYS_io_cancel :: uintptr(3)
// time32 syscall
SYS_io_getevents :: uintptr(4)
SYS_setxattr :: uintptr(5)
SYS_lsetxattr :: uintptr(6)
SYS_fsetxattr :: uintptr(7)
SYS_getxattr :: uintptr(8)
SYS_lgetxattr :: uintptr(9)
SYS_fgetxattr :: uintptr(10)
SYS_listxattr :: uintptr(11)
SYS_llistxattr :: uintptr(12)
SYS_flistxattr :: uintptr(13)
SYS_removexattr :: uintptr(14)
SYS_lremovexattr :: uintptr(15)
SYS_fremovexattr :: uintptr(16)
SYS_getcwd :: uintptr(17)
SYS_lookup_dcookie :: uintptr(18)
SYS_eventfd2 :: uintptr(19)
SYS_epoll_create1 :: uintptr(20)
SYS_epoll_ctl :: uintptr(21)
SYS_epoll_pwait :: uintptr(22)
SYS_dup :: uintptr(23)
SYS_dup3 :: uintptr(24)
SYS_fcntl :: uintptr(25)
SYS_inotify_init1 :: uintptr(26)
SYS_inotify_add_watch :: uintptr(27)
SYS_inotify_rm_watch :: uintptr(28)
SYS_ioctl :: uintptr(29)
SYS_ioprio_set :: uintptr(30)
SYS_ioprio_get :: uintptr(31)
SYS_flock :: uintptr(32)
SYS_mknodat :: uintptr(33)
SYS_mkdirat :: uintptr(34)
SYS_unlinkat :: uintptr(35)
SYS_symlinkat :: uintptr(36)
SYS_linkat :: uintptr(37)
SYS_renameat :: uintptr(38)
SYS_umount2 :: uintptr(39)
SYS_mount :: uintptr(40)
SYS_pivot_root :: uintptr(41)
SYS_nfsservctl :: uintptr(42)
SYS_statfs :: uintptr(43)
SYS_fstatfs :: uintptr(44)
SYS_truncate :: uintptr(45)
SYS_ftruncate :: uintptr(46)
SYS_fallocate :: uintptr(47)
SYS_faccessat :: uintptr(48)
SYS_chdir :: uintptr(49)
SYS_fchdir :: uintptr(50)
SYS_chroot :: uintptr(51)
SYS_fchmod :: uintptr(52)
SYS_fchmodat :: uintptr(53)
SYS_fchownat :: uintptr(54)
SYS_fchown :: uintptr(55)
SYS_openat :: uintptr(56)
SYS_close :: uintptr(57)
SYS_vhangup :: uintptr(58)
SYS_pipe2 :: uintptr(59)
SYS_quotactl :: uintptr(60)
SYS_getdents64 :: uintptr(61)
SYS_lseek :: uintptr(62)
SYS_read :: uintptr(63)
SYS_write :: uintptr(64)
SYS_readv :: uintptr(65)
SYS_writev :: uintptr(66)
SYS_pread64 :: uintptr(67)
SYS_pwrite64 :: uintptr(68)
SYS_preadv :: uintptr(69)
SYS_pwritev :: uintptr(70)
SYS_sendfile :: uintptr(71)
SYS_pselect6 :: uintptr(72)
SYS_ppoll :: uintptr(73)
SYS_signalfd4 :: uintptr(74)
SYS_vmsplice :: uintptr(75)
SYS_splice :: uintptr(76)
SYS_tee :: uintptr(77)
SYS_readlinkat :: uintptr(78)
SYS_fstatat :: uintptr(79)
SYS_fstat :: uintptr(80)
SYS_sync :: uintptr(81)
SYS_fsync :: uintptr(82)
SYS_fdatasync :: uintptr(83)
SYS_sync_file_range :: uintptr(84)
SYS_timerfd_create :: uintptr(85)
SYS_timerfd_settime :: uintptr(86)
SYS_timerfd_gettime :: uintptr(87)
SYS_utimensat :: uintptr(88)
SYS_acct :: uintptr(89)
SYS_capget :: uintptr(90)
SYS_capset :: uintptr(91)
SYS_personality :: uintptr(92)
SYS_exit :: uintptr(93)
SYS_exit_group :: uintptr(94)
SYS_waitid :: uintptr(95)
SYS_set_tid_address :: uintptr(96)
SYS_unshare :: uintptr(97)
SYS_futex :: uintptr(98)
SYS_set_robust_list :: uintptr(99)
SYS_get_robust_list :: uintptr(100)
SYS_nanosleep :: uintptr(101)
SYS_getitimer :: uintptr(102)
SYS_setitimer :: uintptr(103)
SYS_kexec_load :: uintptr(104)
SYS_init_module :: uintptr(105)
SYS_delete_module :: uintptr(106)
SYS_timer_create :: uintptr(107)
SYS_timer_gettime :: uintptr(108)
SYS_timer_getoverrun :: uintptr(109)
SYS_timer_settime :: uintptr(110)
SYS_timer_delete :: uintptr(111)
SYS_clock_settime :: uintptr(112)
SYS_clock_gettime :: uintptr(113)
SYS_clock_getres :: uintptr(114)
SYS_clock_nanosleep :: uintptr(115)
SYS_syslog :: uintptr(116)
SYS_ptrace :: uintptr(117)
SYS_sched_setparam :: uintptr(118)
SYS_sched_setscheduler :: uintptr(119)
SYS_sched_getscheduler :: uintptr(120)
SYS_sched_getparam :: uintptr(121)
SYS_sched_setaffinity :: uintptr(122)
SYS_sched_getaffinity :: uintptr(123)
SYS_sched_yield :: uintptr(124)
SYS_sched_get_priority_max :: uintptr(125)
SYS_sched_get_priority_min :: uintptr(126)
SYS_sched_rr_get_interval :: uintptr(127)
SYS_restart_syscall :: uintptr(128)
SYS_kill :: uintptr(129)
SYS_tkill :: uintptr(130)
SYS_tgkill :: uintptr(131)
SYS_sigaltstack :: uintptr(132)
SYS_rt_sigsuspend :: uintptr(133)
SYS_rt_sigaction :: uintptr(134)
SYS_rt_sigprocmask :: uintptr(135)
SYS_rt_sigpending :: uintptr(136)
SYS_rt_sigtimedwait :: uintptr(137)
SYS_rt_sigqueueinfo :: uintptr(138)
SYS_rt_sigreturn :: uintptr(139)
SYS_setpriority :: uintptr(140)
SYS_getpriority :: uintptr(141)
SYS_reboot :: uintptr(142)
SYS_setregid :: uintptr(143)
SYS_setgid :: uintptr(144)
SYS_setreuid :: uintptr(145)
SYS_setuid :: uintptr(146)
SYS_setresuid :: uintptr(147)
SYS_getresuid :: uintptr(148)
SYS_setresgid :: uintptr(149)
SYS_getresgid :: uintptr(150)
SYS_setfsuid :: uintptr(151)
SYS_setfsgid :: uintptr(152)
SYS_times :: uintptr(153)
SYS_setpgid :: uintptr(154)
SYS_getpgid :: uintptr(155)
SYS_getsid :: uintptr(156)
SYS_setsid :: uintptr(157)
SYS_getgroups :: uintptr(158)
SYS_setgroups :: uintptr(159)
SYS_uname :: uintptr(160)
SYS_sethostname :: uintptr(161)
SYS_setdomainname :: uintptr(162)
SYS_getrlimit :: uintptr(163)
SYS_setrlimit :: uintptr(164)
SYS_getrusage :: uintptr(165)
SYS_umask :: uintptr(166)
SYS_prctl :: uintptr(167)
SYS_getcpu :: uintptr(168)
SYS_gettimeofday :: uintptr(169)
SYS_settimeofday :: uintptr(170)
SYS_adjtimex :: uintptr(171)
SYS_getpid :: uintptr(172)
SYS_getppid :: uintptr(173)
SYS_getuid :: uintptr(174)
SYS_geteuid :: uintptr(175)
SYS_getgid :: uintptr(176)
SYS_getegid :: uintptr(177)
SYS_gettid :: uintptr(178)
SYS_sysinfo :: uintptr(179)
SYS_mq_open :: uintptr(180)
SYS_mq_unlink :: uintptr(181)
SYS_mq_timedsend :: uintptr(182)
SYS_mq_timedreceive :: uintptr(183)
SYS_mq_notify :: uintptr(184)
SYS_mq_getsetattr :: uintptr(185)
SYS_msgget :: uintptr(186)
SYS_msgctl :: uintptr(187)
SYS_msgrcv :: uintptr(188)
SYS_msgsnd :: uintptr(189)
SYS_semget :: uintptr(190)
SYS_semctl :: uintptr(191)
SYS_semtimedop :: uintptr(192)
SYS_semop :: uintptr(193)
SYS_shmget :: uintptr(194)
SYS_shmctl :: uintptr(195)
SYS_shmat :: uintptr(196)
SYS_shmdt :: uintptr(197)
SYS_socket :: uintptr(198)
SYS_socketpair :: uintptr(199)
SYS_bind :: uintptr(200)
SYS_listen :: uintptr(201)
SYS_accept :: uintptr(202)
SYS_connect :: uintptr(203)
SYS_getsockname :: uintptr(204)
SYS_getpeername :: uintptr(205)
SYS_sendto :: uintptr(206)
SYS_recvfrom :: uintptr(207)
SYS_setsockopt :: uintptr(208)
SYS_getsockopt :: uintptr(209)
SYS_shutdown :: uintptr(210)
SYS_sendmsg :: uintptr(211)
SYS_recvmsg :: uintptr(212)
SYS_readahead :: uintptr(213)
SYS_brk :: uintptr(214)
SYS_munmap :: uintptr(215)
SYS_mremap :: uintptr(216)
SYS_add_key :: uintptr(217)
SYS_request_key :: uintptr(218)
SYS_keyctl :: uintptr(219)
SYS_clone :: uintptr(220)
SYS_execve :: uintptr(221)
SYS_mmap :: uintptr(222)
SYS_fadvise64 :: uintptr(223)
/* CONFIG_MMU only */
SYS_swapon :: uintptr(224)
SYS_swapoff :: uintptr(225)
SYS_mprotect :: uintptr(226)
SYS_msync :: uintptr(227)
SYS_mlock :: uintptr(228)
SYS_munlock :: uintptr(229)
SYS_mlockall :: uintptr(230)
SYS_munlockall :: uintptr(231)
SYS_mincore :: uintptr(232)
SYS_madvise :: uintptr(233)
SYS_remap_file_pages :: uintptr(234)
SYS_mbind :: uintptr(235)
SYS_get_mempolicy :: uintptr(236)
SYS_set_mempolicy :: uintptr(237)
SYS_migrate_pages :: uintptr(238)
SYS_move_pages :: uintptr(239)
SYS_rt_tgsigqueueinfo :: uintptr(240)
SYS_perf_event_open :: uintptr(241)
SYS_accept4 :: uintptr(242)
SYS_recvmmsg :: uintptr(243)
SYS_wait4 :: uintptr(260)
SYS_prlimit64 :: uintptr(261)
SYS_fanotify_init :: uintptr(262)
SYS_fanotify_mark :: uintptr(263)
SYS_name_to_handle_at :: uintptr(264)
SYS_open_by_handle_at :: uintptr(265)
SYS_clock_adjtime :: uintptr(266)
SYS_syncfs :: uintptr(267)
SYS_setns :: uintptr(268)
SYS_sendmmsg :: uintptr(269)
SYS_process_vm_readv :: uintptr(270)
SYS_process_vm_writev :: uintptr(271)
SYS_kcmp :: uintptr(272)
SYS_finit_module :: uintptr(273)
SYS_sched_setattr :: uintptr(274)
SYS_sched_getattr :: uintptr(275)
SYS_renameat2 :: uintptr(276)
SYS_seccomp :: uintptr(277)
SYS_getrandom :: uintptr(278)
SYS_memfd_create :: uintptr(279)
SYS_bpf :: uintptr(280)
SYS_execveat :: uintptr(281)
SYS_userfaultfd :: uintptr(282)
SYS_membarrier :: uintptr(283)
SYS_mlock2 :: uintptr(284)
SYS_copy_file_range :: uintptr(285)
SYS_preadv2 :: uintptr(286)
SYS_pwritev2 :: uintptr(287)
SYS_pkey_mprotect :: uintptr(288)
SYS_pkey_alloc :: uintptr(289)
SYS_pkey_free :: uintptr(290)
SYS_statx :: uintptr(291)
SYS_io_pgetevents :: uintptr(292)
SYS_rseq :: uintptr(293)
SYS_kexec_file_load :: uintptr(294)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)

View File

@@ -0,0 +1,458 @@
//+build i386
package linux
// The numbers are taken from
// /arch/x86/entry/syscalls/syscall_32.tbl
// in Linux headers. Only x64 and common ABI
// syscalls were taken, for x32 is not
// supported by Odin
// This syscall is only used by the kernel internally
// userspace has no reason to use it.
SYS_restart_syscall :: uintptr(0)
SYS_exit :: uintptr(1)
SYS_fork :: uintptr(2)
SYS_read :: uintptr(3)
SYS_write :: uintptr(4)
SYS_open :: uintptr(5)
SYS_close :: uintptr(6)
SYS_waitpid :: uintptr(7)
SYS_creat :: uintptr(8)
SYS_link :: uintptr(9)
SYS_unlink :: uintptr(10)
SYS_execve :: uintptr(11)
SYS_chdir :: uintptr(12)
SYS_time :: uintptr(13)
SYS_mknod :: uintptr(14)
SYS_chmod :: uintptr(15)
SYS_lchown :: uintptr(16)
SYS_break :: uintptr(17)
SYS_oldstat :: uintptr(18)
SYS_lseek :: uintptr(19)
SYS_getpid :: uintptr(20)
SYS_mount :: uintptr(21)
SYS_umount :: uintptr(22)
SYS_setuid :: uintptr(23)
SYS_getuid :: uintptr(24)
SYS_stime :: uintptr(25)
SYS_ptrace :: uintptr(26)
SYS_alarm :: uintptr(27)
SYS_oldfstat :: uintptr(28)
SYS_pause :: uintptr(29)
SYS_utime :: uintptr(30)
SYS_stty :: uintptr(31)
SYS_gtty :: uintptr(32)
SYS_access :: uintptr(33)
SYS_nice :: uintptr(34)
SYS_ftime :: uintptr(35)
SYS_sync :: uintptr(36)
SYS_kill :: uintptr(37)
SYS_rename :: uintptr(38)
SYS_mkdir :: uintptr(39)
SYS_rmdir :: uintptr(40)
SYS_dup :: uintptr(41)
SYS_pipe :: uintptr(42)
SYS_times :: uintptr(43)
SYS_prof :: uintptr(44)
SYS_brk :: uintptr(45)
SYS_setgid :: uintptr(46)
SYS_getgid :: uintptr(47)
SYS_signal :: uintptr(48)
SYS_geteuid :: uintptr(49)
SYS_getegid :: uintptr(50)
SYS_acct :: uintptr(51)
SYS_umount2 :: uintptr(52)
SYS_lock :: uintptr(53)
SYS_ioctl :: uintptr(54)
SYS_fcntl :: uintptr(55)
SYS_mpx :: uintptr(56)
SYS_setpgid :: uintptr(57)
SYS_ulimit :: uintptr(58)
SYS_oldolduname :: uintptr(59)
SYS_umask :: uintptr(60)
SYS_chroot :: uintptr(61)
SYS_ustat :: uintptr(62)
SYS_dup2 :: uintptr(63)
SYS_getppid :: uintptr(64)
SYS_getpgrp :: uintptr(65)
SYS_setsid :: uintptr(66)
SYS_sigaction :: uintptr(67)
SYS_sgetmask :: uintptr(68)
SYS_ssetmask :: uintptr(69)
SYS_setreuid :: uintptr(70)
SYS_setregid :: uintptr(71)
SYS_sigsuspend :: uintptr(72)
SYS_sigpending :: uintptr(73)
SYS_sethostname :: uintptr(74)
SYS_setrlimit :: uintptr(75)
SYS_getrlimit :: uintptr(76)
SYS_getrusage :: uintptr(77)
SYS_gettimeofday :: uintptr(78)
SYS_settimeofday :: uintptr(79)
SYS_getgroups :: uintptr(80)
SYS_setgroups :: uintptr(81)
SYS_select :: uintptr(82)
SYS_symlink :: uintptr(83)
SYS_oldlstat :: uintptr(84)
SYS_readlink :: uintptr(85)
SYS_uselib :: uintptr(86)
SYS_swapon :: uintptr(87)
SYS_reboot :: uintptr(88)
SYS_readdir :: uintptr(89)
SYS_mmap :: uintptr(90)
SYS_munmap :: uintptr(91)
SYS_truncate :: uintptr(92)
SYS_ftruncate :: uintptr(93)
SYS_fchmod :: uintptr(94)
SYS_fchown :: uintptr(95)
SYS_getpriority :: uintptr(96)
SYS_setpriority :: uintptr(97)
SYS_profil :: uintptr(98)
SYS_statfs :: uintptr(99)
SYS_fstatfs :: uintptr(100)
SYS_ioperm :: uintptr(101)
SYS_socketcall :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_setitimer :: uintptr(104)
SYS_getitimer :: uintptr(105)
SYS_stat :: uintptr(106)
SYS_lstat :: uintptr(107)
SYS_fstat :: uintptr(108)
SYS_olduname :: uintptr(109)
SYS_iopl :: uintptr(110)
SYS_vhangup :: uintptr(111)
SYS_idle :: uintptr(112)
SYS_vm86old :: uintptr(113)
SYS_wait4 :: uintptr(114)
SYS_swapoff :: uintptr(115)
SYS_sysinfo :: uintptr(116)
SYS_ipc :: uintptr(117)
SYS_fsync :: uintptr(118)
SYS_sigreturn :: uintptr(119)
SYS_clone :: uintptr(120)
SYS_setdomainname :: uintptr(121)
SYS_uname :: uintptr(122)
SYS_modify_ldt :: uintptr(123)
SYS_adjtimex :: uintptr(124)
SYS_mprotect :: uintptr(125)
SYS_sigprocmask :: uintptr(126)
SYS_create_module :: uintptr(127)
SYS_init_module :: uintptr(128)
SYS_delete_module :: uintptr(129)
SYS_get_kernel_syms :: uintptr(130)
SYS_quotactl :: uintptr(131)
SYS_getpgid :: uintptr(132)
SYS_fchdir :: uintptr(133)
SYS_bdflush :: uintptr(134)
SYS_sysfs :: uintptr(135)
SYS_personality :: uintptr(136)
SYS_afs_syscall :: uintptr(137)
SYS_setfsuid :: uintptr(138)
SYS_setfsgid :: uintptr(139)
SYS__llseek :: uintptr(140)
SYS_getdents :: uintptr(141)
SYS__newselect :: uintptr(142)
SYS_flock :: uintptr(143)
SYS_msync :: uintptr(144)
SYS_readv :: uintptr(145)
SYS_writev :: uintptr(146)
SYS_getsid :: uintptr(147)
SYS_fdatasync :: uintptr(148)
SYS__sysctl :: uintptr(149)
SYS_mlock :: uintptr(150)
SYS_munlock :: uintptr(151)
SYS_mlockall :: uintptr(152)
SYS_munlockall :: uintptr(153)
SYS_sched_setparam :: uintptr(154)
SYS_sched_getparam :: uintptr(155)
SYS_sched_setscheduler :: uintptr(156)
SYS_sched_getscheduler :: uintptr(157)
SYS_sched_yield :: uintptr(158)
SYS_sched_get_priority_max :: uintptr(159)
SYS_sched_get_priority_min :: uintptr(160)
SYS_sched_rr_get_interval :: uintptr(161)
SYS_nanosleep :: uintptr(162)
SYS_mremap :: uintptr(163)
SYS_setresuid :: uintptr(164)
SYS_getresuid :: uintptr(165)
SYS_vm86 :: uintptr(166)
SYS_query_module :: uintptr(167)
SYS_poll :: uintptr(168)
SYS_nfsservctl :: uintptr(169)
SYS_setresgid :: uintptr(170)
SYS_getresgid :: uintptr(171)
SYS_prctl :: uintptr(172)
SYS_rt_sigreturn :: uintptr(173)
SYS_rt_sigaction :: uintptr(174)
SYS_rt_sigprocmask :: uintptr(175)
SYS_rt_sigpending :: uintptr(176)
SYS_rt_sigtimedwait :: uintptr(177)
SYS_rt_sigqueueinfo :: uintptr(178)
SYS_rt_sigsuspend :: uintptr(179)
SYS_pread64 :: uintptr(180)
SYS_pwrite64 :: uintptr(181)
SYS_chown :: uintptr(182)
SYS_getcwd :: uintptr(183)
SYS_capget :: uintptr(184)
SYS_capset :: uintptr(185)
SYS_sigaltstack :: uintptr(186)
SYS_sendfile :: uintptr(187)
SYS_getpmsg :: uintptr(188)
SYS_putpmsg :: uintptr(189)
SYS_vfork :: uintptr(190)
SYS_ugetrlimit :: uintptr(191)
SYS_mmap2 :: uintptr(192)
SYS_truncate64 :: uintptr(193)
SYS_ftruncate64 :: uintptr(194)
SYS_stat64 :: uintptr(195)
SYS_lstat64 :: uintptr(196)
SYS_fstat64 :: uintptr(197)
SYS_lchown32 :: uintptr(198)
SYS_getuid32 :: uintptr(199)
SYS_getgid32 :: uintptr(200)
SYS_geteuid32 :: uintptr(201)
SYS_getegid32 :: uintptr(202)
SYS_setreuid32 :: uintptr(203)
SYS_setregid32 :: uintptr(204)
SYS_getgroups32 :: uintptr(205)
SYS_setgroups32 :: uintptr(206)
SYS_fchown32 :: uintptr(207)
SYS_setresuid32 :: uintptr(208)
SYS_getresuid32 :: uintptr(209)
SYS_setresgid32 :: uintptr(210)
SYS_getresgid32 :: uintptr(211)
SYS_chown32 :: uintptr(212)
SYS_setuid32 :: uintptr(213)
SYS_setgid32 :: uintptr(214)
SYS_setfsuid32 :: uintptr(215)
SYS_setfsgid32 :: uintptr(216)
SYS_pivot_root :: uintptr(217)
SYS_mincore :: uintptr(218)
SYS_madvise :: uintptr(219)
SYS_getdents64 :: uintptr(220)
SYS_fcntl64 :: uintptr(221)
// 222 is unused
// 223 is unused
SYS_gettid :: uintptr(224)
SYS_readahead :: uintptr(225)
SYS_setxattr :: uintptr(226)
SYS_lsetxattr :: uintptr(227)
SYS_fsetxattr :: uintptr(228)
SYS_getxattr :: uintptr(229)
SYS_lgetxattr :: uintptr(230)
SYS_fgetxattr :: uintptr(231)
SYS_listxattr :: uintptr(232)
SYS_llistxattr :: uintptr(233)
SYS_flistxattr :: uintptr(234)
SYS_removexattr :: uintptr(235)
SYS_lremovexattr :: uintptr(236)
SYS_fremovexattr :: uintptr(237)
SYS_tkill :: uintptr(238)
SYS_sendfile64 :: uintptr(239)
SYS_futex :: uintptr(240)
SYS_sched_setaffinity :: uintptr(241)
SYS_sched_getaffinity :: uintptr(242)
SYS_set_thread_area :: uintptr(243)
SYS_get_thread_area :: uintptr(244)
SYS_io_setup :: uintptr(245)
SYS_io_destroy :: uintptr(246)
SYS_io_getevents :: uintptr(247)
SYS_io_submit :: uintptr(248)
SYS_io_cancel :: uintptr(249)
SYS_fadvise64 :: uintptr(250)
// 251 is available for reuse (was briefly sys_set_zone_reclaim)
SYS_exit_group :: uintptr(252)
SYS_lookup_dcookie :: uintptr(253)
SYS_epoll_create :: uintptr(254)
SYS_epoll_ctl :: uintptr(255)
SYS_epoll_wait :: uintptr(256)
SYS_remap_file_pages :: uintptr(257)
SYS_set_tid_address :: uintptr(258)
SYS_timer_create :: uintptr(259)
SYS_timer_settime :: uintptr(260)
SYS_timer_gettime :: uintptr(261)
SYS_timer_getoverrun :: uintptr(262)
SYS_timer_delete :: uintptr(263)
SYS_clock_settime :: uintptr(264)
SYS_clock_gettime :: uintptr(265)
SYS_clock_getres :: uintptr(266)
SYS_clock_nanosleep :: uintptr(267)
SYS_statfs64 :: uintptr(268)
SYS_fstatfs64 :: uintptr(269)
SYS_tgkill :: uintptr(270)
SYS_utimes :: uintptr(271)
SYS_fadvise64_64 :: uintptr(272)
SYS_vserver :: uintptr(273)
SYS_mbind :: uintptr(274)
SYS_get_mempolicy :: uintptr(275)
SYS_set_mempolicy :: uintptr(276)
SYS_mq_open :: uintptr(277)
SYS_mq_unlink :: uintptr(278)
SYS_mq_timedsend :: uintptr(279)
SYS_mq_timedreceive :: uintptr(280)
SYS_mq_notify :: uintptr(281)
SYS_mq_getsetattr :: uintptr(282)
SYS_kexec_load :: uintptr(283)
SYS_waitid :: uintptr(284)
// 285 sys_setaltroot
SYS_add_key :: uintptr(286)
SYS_request_key :: uintptr(287)
SYS_keyctl :: uintptr(288)
SYS_ioprio_set :: uintptr(289)
SYS_ioprio_get :: uintptr(290)
SYS_inotify_init :: uintptr(291)
SYS_inotify_add_watch :: uintptr(292)
SYS_inotify_rm_watch :: uintptr(293)
SYS_migrate_pages :: uintptr(294)
SYS_openat :: uintptr(295)
SYS_mkdirat :: uintptr(296)
SYS_mknodat :: uintptr(297)
SYS_fchownat :: uintptr(298)
SYS_futimesat :: uintptr(299)
SYS_fstatat64 :: uintptr(300)
SYS_unlinkat :: uintptr(301)
SYS_renameat :: uintptr(302)
SYS_linkat :: uintptr(303)
SYS_symlinkat :: uintptr(304)
SYS_readlinkat :: uintptr(305)
SYS_fchmodat :: uintptr(306)
SYS_faccessat :: uintptr(307)
SYS_pselect6 :: uintptr(308)
SYS_ppoll :: uintptr(309)
SYS_unshare :: uintptr(310)
SYS_set_robust_list :: uintptr(311)
SYS_get_robust_list :: uintptr(312)
SYS_splice :: uintptr(313)
SYS_sync_file_range :: uintptr(314)
SYS_tee :: uintptr(315)
SYS_vmsplice :: uintptr(316)
SYS_move_pages :: uintptr(317)
SYS_getcpu :: uintptr(318)
SYS_epoll_pwait :: uintptr(319)
SYS_utimensat :: uintptr(320)
SYS_signalfd :: uintptr(321)
SYS_timerfd_create :: uintptr(322)
SYS_eventfd :: uintptr(323)
SYS_fallocate :: uintptr(324)
SYS_timerfd_settime :: uintptr(325)
SYS_timerfd_gettime :: uintptr(326)
SYS_signalfd4 :: uintptr(327)
SYS_eventfd2 :: uintptr(328)
SYS_epoll_create1 :: uintptr(329)
SYS_dup3 :: uintptr(330)
SYS_pipe2 :: uintptr(331)
SYS_inotify_init1 :: uintptr(332)
SYS_preadv :: uintptr(333)
SYS_pwritev :: uintptr(334)
SYS_rt_tgsigqueueinfo :: uintptr(335)
SYS_perf_event_open :: uintptr(336)
SYS_recvmmsg :: uintptr(337)
SYS_fanotify_init :: uintptr(338)
SYS_fanotify_mark :: uintptr(339)
SYS_prlimit64 :: uintptr(340)
SYS_name_to_handle_at :: uintptr(341)
SYS_open_by_handle_at :: uintptr(342)
SYS_clock_adjtime :: uintptr(343)
SYS_syncfs :: uintptr(344)
SYS_sendmmsg :: uintptr(345)
SYS_setns :: uintptr(346)
SYS_process_vm_readv :: uintptr(347)
SYS_process_vm_writev :: uintptr(348)
SYS_kcmp :: uintptr(349)
SYS_finit_module :: uintptr(350)
SYS_sched_setattr :: uintptr(351)
SYS_sched_getattr :: uintptr(352)
SYS_renameat2 :: uintptr(353)
SYS_seccomp :: uintptr(354)
SYS_getrandom :: uintptr(355)
SYS_memfd_create :: uintptr(356)
SYS_bpf :: uintptr(357)
SYS_execveat :: uintptr(358)
SYS_socket :: uintptr(359)
SYS_socketpair :: uintptr(360)
SYS_bind :: uintptr(361)
SYS_connect :: uintptr(362)
SYS_listen :: uintptr(363)
SYS_accept4 :: uintptr(364)
SYS_getsockopt :: uintptr(365)
SYS_setsockopt :: uintptr(366)
SYS_getsockname :: uintptr(367)
SYS_getpeername :: uintptr(368)
SYS_sendto :: uintptr(369)
SYS_sendmsg :: uintptr(370)
SYS_recvfrom :: uintptr(371)
SYS_recvmsg :: uintptr(372)
SYS_shutdown :: uintptr(373)
SYS_userfaultfd :: uintptr(374)
SYS_membarrier :: uintptr(375)
SYS_mlock2 :: uintptr(376)
SYS_copy_file_range :: uintptr(377)
SYS_preadv2 :: uintptr(378)
SYS_pwritev2 :: uintptr(379)
SYS_pkey_mprotect :: uintptr(380)
SYS_pkey_alloc :: uintptr(381)
SYS_pkey_free :: uintptr(382)
SYS_statx :: uintptr(383)
SYS_arch_prctl :: uintptr(384)
SYS_io_pgetevents :: uintptr(385)
SYS_rseq :: uintptr(386)
SYS_semget :: uintptr(393)
SYS_semctl :: uintptr(394)
SYS_shmget :: uintptr(395)
SYS_shmctl :: uintptr(396)
SYS_shmat :: uintptr(397)
SYS_shmdt :: uintptr(398)
SYS_msgget :: uintptr(399)
SYS_msgsnd :: uintptr(400)
SYS_msgrcv :: uintptr(401)
SYS_msgctl :: uintptr(402)
SYS_clock_gettime64 :: uintptr(403)
SYS_clock_settime64 :: uintptr(404)
SYS_clock_adjtime64 :: uintptr(405)
SYS_clock_getres_time64 :: uintptr(406)
SYS_clock_nanosleep_time64 :: uintptr(407)
SYS_timer_gettime64 :: uintptr(408)
SYS_timer_settime64 :: uintptr(409)
SYS_timerfd_gettime64 :: uintptr(410)
SYS_timerfd_settime64 :: uintptr(411)
SYS_utimensat_time64 :: uintptr(412)
SYS_pselect6_time64 :: uintptr(413)
SYS_ppoll_time64 :: uintptr(414)
SYS_io_pgetevents_time64 :: uintptr(416)
SYS_recvmmsg_time64 :: uintptr(417)
SYS_mq_timedsend_time64 :: uintptr(418)
SYS_mq_timedreceive_time64 :: uintptr(419)
SYS_semtimedop_time64 :: uintptr(420)
SYS_rt_sigtimedwait_time64 :: uintptr(421)
SYS_futex_time64 :: uintptr(422)
SYS_sched_rr_get_interval_time64 :: uintptr(423)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)

566
core/sys/linux/types.odin Normal file
View File

@@ -0,0 +1,566 @@
//+build linux
package linux
/// Represents storage device handle
Dev :: distinct int
/// Represents 32-bit user id
Uid :: distinct u32
/// Represents 32-bit group id
Gid :: distinct u32
/// Process id's
Pid :: distinct int
/// Represents pid, pifd, pgid values in general
Id :: distinct uint
/// Represents a file descriptor
Fd :: distinct i32
/// Represents a PID file descriptor
Pid_FD :: distinct i32
/// Represents 64-bit inode number for files
/// Used pretty much only in struct Stat64 for 32-bit platforms
Inode :: distinct u64
/// Represents time with nanosecond precision
Time_Spec :: struct {
time_sec: uint,
time_nsec: uint,
}
/// Represents time with millisecond precision
Time_Val :: struct {
seconds: int,
microseconds: int,
}
/// open.2 flags
Open_Flags :: bit_set[Open_Flags_Bits; u32]
/// Flags for the file descriptor to be passed in some syscalls
FD_Flags :: bit_set[FD_Flags_Bits; i32]
/// Represents file's permission and status bits
/// Example:
/// When you're passing a value of this type the recommended usage is
/// sys.Mode{.S_IXOTH, .S_IROTH} | sys.S_IRWXU | sys.S_IRWXG
/// This would generate a mode that has full permissions for the
/// file's owner and group, and only "read" and "execute" bits
/// for others.
Mode :: bit_set[Mode_Bits; u32]
when ODIN_ARCH == .amd64 {
// x86-64 has mode and nlink swapped for some reason
_Arch_Stat :: struct {
dev: Dev,
ino: Inode,
nlink: uint,
mode: Mode,
uid: Uid,
gid: Gid,
_: u32,
rdev: Dev,
size: uint,
blksize: uint,
blocks: uint,
atime: Time_Spec,
mtime: Time_Spec,
ctime: Time_Spec,
_: [3]uint,
}
} else when ODIN_ARCH == .arm64 {
_Arch_Stat :: struct {
dev: Dev,
ino: Inode,
mode: Mode,
nlink: u32,
uid: Uid,
gid: Gid,
rdev: Dev,
_: u64,
size: int,
blksize: i32,
_: i32,
blocks: int,
atime: Time_Spec,
mtime: Time_Spec,
ctime: Time_Spec,
_: [3]uint,
}
} else {
_Arch_Stat :: struct {
dev: Dev,
_: [4]u8,
_ino: uint, // Old 32-bit inode number, don't use
mode: Mode,
nlink: u32,
uid: Uid,
gid: Gid,
rdev: Dev,
size: i64,
blksize: uint,
blocks: u64,
atim: Time_Spec,
mtim: Time_Spec,
ctim: Time_Spec,
ino: Inode,
}
}
/// Represents the file state.
/// Mirrors struct stat in glibc/linux kernel.
/// If you're on 32-bit platform, consider using Stat64 instead
Stat :: struct {
using _impl_stat: _Arch_Stat,
}
/// Timestamp type used for Statx struct
Statx_Timestamp :: struct {
sec: i64,
nsec: u32,
_: i32,
}
/// Query params/results for `statx()`
Statx_Mask :: bit_set[Statx_Mask_Bits; u32]
/// File attributes, returned by statx. This bitset is also
/// used to specify which attributes are present, not just
/// their value.
Statx_Attr :: bit_set[Statx_Attr_Bits; u64]
/// The extended Stat struct
Statx :: struct {
mask: Statx_Mask,
blksize: u32,
attributes: Statx_Attr,
nlink: u32,
uid: Uid,
gid: Gid,
// Note(flysand): mode is 16-bit on linux + there's
// 16-bit padding following it. Since our mode is 32-bits,
// we're using the padding. This should be fine because
// the placement of that padding suggests it was going to
// be used for the Mode bits anyway.
mode: Mode,
ino: Inode,
size: u64,
blocks: u64,
attributes_mask: Statx_Attr,
atime: Statx_Timestamp,
btime: Statx_Timestamp,
ctime: Statx_Timestamp,
mtime: Statx_Timestamp,
rdev_major: u32,
rdev_minor: u32,
dev_major: u32,
dev_minor: u32,
mnt_id: u64,
dio_mem_align: u32,
dio_offset_align: u32,
_: [12]u64,
}
/// Mount flags for filesystem
FS_Flags :: bit_set[FS_Flags_Bits; u32]
when size_of(int) == 8 {
_Arch_Stat_FS :: struct {
// Note(flysand): The FS_Magic bits are never above
// 32-bits, so it should be fine for now...
type: FS_Magic,
_: u32,
bsize: i64,
blocks: i64,
bfree: i64,
bavail: i64,
files: i64,
ffree: i64,
fsid : [2]i32,
namelen: i64,
frsize: i64,
// Note(flysand): Same story as type
flags: FS_Flags,
_: u32,
spare: [4]i64,
}
} else {
_Arch_Stat_FS :: struct {
type: FS_Magic,
bsize: u32,
blocks: u64,
bfree: u64,
bavail: u64,
files: u64,
ffree: u64,
fsid: [2]i32,
namelen: u32,
frsize: u32,
flags: FS_Flags,
spare: [4]u32,
}
}
Stat_FS :: struct {
using _impl_stat_fs: _Arch_Stat_FS,
}
/// Flags for close_range.2
Close_Range_Flags :: bit_set[Close_Range_Flags_Bits; u32]
/// Flags for rename.2
Rename_Flags :: bit_set[Rename_Flags_Bits; u32]
/// Directory entry
/// Recommended to use this with dirent_iterator()
/// and dirent_name()
Dirent :: struct {
ino: Inode,
off: i64,
reclen: u16,
type: Dirent_Type,
name: [0]u8, // See dirent_name
}
/// Lock record for fcntl.2
FLock :: struct {
type: FLock_Type,
whence: Seek_Whence,
start: i64,
len: i64,
pid: Pid,
}
/// Flags for fcntl_notify
FD_Notifications :: bit_set[FD_Notifications_Bits; i32]
/// Seals for fcntl_add_seals
Seal :: bit_set[Seal_Bits; i32]
/// Represents owner that receives events on file updates
F_Owner :: struct {
type: F_Owner_Type,
pid: Pid,
}
/// Events for ppoll
Fd_Poll_Events :: bit_set[Fd_Poll_Events_Bits; u16]
/// Struct for ppoll
Poll_Fd :: struct {
fd: Fd,
events: Fd_Poll_Events,
revents: Fd_Poll_Events,
}
/// Specifies protection for memory pages
Mem_Protection :: bit_set[Mem_Protection_Bits; i32]
/// Flags for mmap
Map_Flags :: bit_set[Map_Flags_Bits; i32]
/// Flags for mlock.2
MLock_Flags :: bit_set[MLock_Flags_Bits; u32]
/// Flags for msync.2
MSync_Flags :: bit_set[MSync_Flags_Bits; i32]
/// Access rights for pkey_alloc.2
PKey_Access_Rights :: bit_set[PKey_Access_Bits; u32]
/// Flags for mremap.2
MRemap_Flags :: bit_set[MRemap_Flags_Bits; i32]
/// Flags for getrandom syscall
Get_Random_Flags :: bit_set[Get_Random_Flags_Bits; i32]
/// Flags for perf_event_open syscall
Perf_Flags :: bit_set[Perf_Flags_Bits; uint]
Perf_Event_Flags :: distinct bit_set[Perf_Event_Flags_Bits; u64]
Perf_Cap_Flags :: distinct bit_set[Perf_Cap_Flags_Bits; u64]
Perf_Event_Sample_Type :: bit_set[Perf_Event_Sample_Type_Bits; u64]
/// Specifies which branches to include in branch record
Branch_Sample_Type :: bit_set[Branch_Sample_Type_Bits; u64]
/// The struct for perf_event_open
Perf_Event_Attr :: struct #packed {
type: Perf_Event_Type,
size: u32,
config: struct #raw_union {
hw: Perf_Hardware_Id,
sw: Perf_Software_Id,
cache: u64,
other: u64,
},
sample: struct #raw_union {
period: u64,
frequency: u64,
},
sample_type: Perf_Event_Sample_Type,
read_format: Perf_Read_Format,
flags: Perf_Event_Flags,
wakeup: struct #raw_union {
events: u32,
watermark: u32,
},
breakpoint_type: Hardware_Breakpoint_Type,
using _: struct #raw_union {
breakpoint_addr: u64,
kprobe_func: u64,
uprobe_path: u64,
config1: u64,
},
using _: struct #raw_union {
breakpoint_len: u64,
kprobe_addr: u64,
uprobe_offset: u64,
config2: u64,
},
branch_sample_type: Branch_Sample_Type,
sample_regs_user: u64,
sample_stack_user: u32,
clock_id: i32, // TODO(flysand): clock_id
sample_regs_intr: u64,
aux_watermark: u32,
sample_max_stack: u16,
_: u16,
}
/// The ring buffer structure when mmaping Perf_Event_Attr
Perf_Event_Mmap_Page :: struct #packed {
version: u32,
compat_version: u32,
lock: u32,
index: u32,
offset: i64,
time_enabled: u64,
time_running: u64,
cap: struct #raw_union {
capabilities: u64,
flags: Perf_Cap_Flags,
},
pmc_width: u16,
time_shift: u16,
time_mult: u32,
time_offset: u64,
time_zero: u64,
size: u32,
reserved1: u32,
time_cycles: u64,
time_mask: u64,
reserved2: [116*8]u8,
data_head: u64,
data_tail: u64,
data_offset: u64,
data_size: u64,
aux_head: u64,
aux_tail: u64,
aux_offset: u64,
aux_size: u64,
}
// TODO(flysand): Its taking too much effort to bind the other data structures related to perf_event_open
/// Options for wait4() and waitpid()
Wait_Options :: bit_set[Wait_Option; i32]
/// Flags for pidfd_open.2
Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
// Note(flysand): these could, in principle be implemented with bitfields,
// however there are ABI differences between odin's bitfields and linux sigsets.
// Mainly:
// 1. Odin's bitfields start from 0, whereas signals start from 1
// 2. It's unclear how bitfields act in terms of ABI (are they an array of ints or an array of longs?).
// it makes a difference because ARM is big endian.
@private _SIGSET_NWORDS :: (1024 / (8 * size_of(uint)))
Sig_Set :: [_SIGSET_NWORDS]uint
@private SI_MAX_SIZE :: 128
@private SI_ARCH_PREAMBLE :: 3 * size_of(i32)
@private SI_PAD_SIZE :: (SI_MAX_SIZE - SI_ARCH_PREAMBLE) / size_of(i32)
@private SI_TIMER_PAD_SIZE :: size_of(Uid) - size_of(i32)
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
Sig_Restore_Fn :: #type proc "c" ()
Sig_Info :: struct #packed {
signo: Signal,
errno: Errno,
code: i32,
_pad0: i32,
using _union: struct #raw_union {
_pad1: [SI_PAD_SIZE]u8,
using _kill: struct {
pid: Pid, /* sender's pid */
uid: Uid, /* sender's uid */
},
using _timer: struct {
timerid: i32, /* timer id */
overrun: i32, /* overrun count */
},
/* POSIX.1b signals */
using _rt: struct {
_pid0: Pid, /* sender's pid */
_uid0: Uid, /* sender's uid */
},
/* SIGCHLD */
using _sigchld: struct {
_pid1: Pid, /* which child */
_uid1: Uid, /* sender's uid */
status: i32, /* exit code */
utime: uint,
stime: uint, //clock_t
},
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
using _sigfault: struct {
addr: rawptr, /* faulting insn/memory ref. */
addr_lsb: i16, /* LSB of the reported address */
},
/* SIGPOLL */
using _sigpoll: struct {
band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
fd: Fd,
},
/* SIGSYS */
using _sigsys: struct {
call_addr: rawptr, /* calling user insn */
syscall: i32, /* triggering system call number */
arch: u32, /* AUDIT_ARCH_* of syscall */
},
},
}
Sig_Stack_Flags :: bit_set[Sig_Stack_Flag; i32]
Sig_Stack :: struct {
sp: rawptr,
flags: Sig_Stack_Flags,
size: uintptr,
}
Sig_Action :: struct($T: typeid) {
using _u: struct #raw_union {
handler: Sig_Handler_Fn,
sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T),
},
flags: uint,
restorer: Sig_Restore_Fn,
mask: Sig_Set,
}
/// Flags for the socket file descriptor
/// Note, on linux these are technically passed by OR'ing together
/// with Socket_Type, our wrapper does this under the hood.
Socket_FD_Flags :: bit_set[Socket_FD_Flags_Bits; int]
/// Address family for the socket
/// Typically there's one address family for every protocol family
Address_Family :: distinct Protocol_Family
/// Flags for the socket for send/recv calls
Socket_Msg :: bit_set[Socket_Msg_Bits; i32]
/// Struct representing IPv4 socket address
Sock_Addr_In :: struct #packed {
sin_family: Address_Family,
sin_port: u16be,
sin_addr: [4]u8,
}
/// Struct representing IPv6 socket address
Sock_Addr_In6 :: struct #packed {
sin6_family: Address_Family,
sin6_port: u16be,
sin6_flowinfo: u32,
sin6_addr: [16]u8,
sin6_scope_id: u32,
}
/// Struct representing an arbitrary socket address
Sock_Addr_Any :: struct #raw_union {
using _: struct {
family: Address_Family,
port: u16be,
},
using ipv4: Sock_Addr_In,
using ipv6: Sock_Addr_In6,
}
/// Just an alias to make futex-values more visible
Futex :: u32
/// Flags for the futex (they are kept separately)
Futex_Flags :: bit_set[Futex_Flags_Bits; u32]
/// Times
Tms :: struct {
tms_utime: int,
tms_stime: int,
tms_cutime: int,
tms_cstime: int,
}
/// "Unix time-sharing system name", allegedly
/// Basically system info
UTS_Name :: struct {
sysname: [65]u8 `fmt:"s,0"`,
nodename: [65]u8 `fmt:"s,0"`,
release: [65]u8 `fmt:"s,0"`,
version: [65]u8 `fmt:"s,0"`,
machine: [65]u8 `fmt:"s,0"`,
domainname: [65]u8 `fmt:"s,0"`,
}
/// Return buffer for the sysinfo syscall
Sys_Info :: struct {
uptime: int,
loads: [3]int,
totalram: uint,
freeram: uint,
sharedram: uint,
bufferram: uint,
totalswap: uint,
freeswap: uint,
procs: u16,
totalhigh: uint,
freehigh: uint,
mem_unit: i32,
_padding: [20 - (2 * size_of(int)) - size_of(i32)]u8,
}
/// Resource limit
RLimit :: struct {
cur: uint,
max: uint,
}
/// Structure representing how much of each resource
/// got used.
RUsage :: struct {
utime: Time_Val,
stime: Time_Val,
maxrss_word: int,
ixrss_word: int,
idrss_word: int,
isrss_word: int,
minflt_word: int,
majflt_word: int,
nswap_word: int,
inblock_word: int,
oublock_word: int,
msgsnd_word: int,
msgrcv_word: int,
nsignals_word: int,
nvcsw_word: int,
nivcsw_word: int,
}

View File

@@ -0,0 +1,121 @@
//+build linux
package linux
/// Low 8 bits of the exit code
/// Only retrieve the exit code if WIFEXITED(s) = true
WEXITSTATUS :: #force_inline proc "contextless" (s: u32) -> u32 {
return (s & 0xff00) >> 8
}
/// Termination signal
/// Only retrieve the code if WIFSIGNALED(s) = true
WTERMSIG :: #force_inline proc "contextless" (s: u32) -> u32 {
return s & 0x7f
}
/// The signal that stopped the child
/// Only retrieve if WIFSTOPPED(s) = true
WSTOPSIG :: #force_inline proc "contextless" (s: u32) -> u32 {
return WEXITSTATUS(s)
}
/// Check if the process terminated normally (via exit.2)
WIFEXITED :: #force_inline proc "contextless" (s: u32) -> bool {
return WTERMSIG(s) == 0
}
/// Check if the process signaled
WIFSIGNALED :: #force_inline proc "contextless" (s: u32) -> bool {
return cast(i8)(((s) & 0x7f) + 1) >> 1 > 0
}
/// Check if the process has stopped
WIFSTOPPED :: #force_inline proc "contextless" (s: u32) -> bool {
return (s & 0xff) == 0x7f
}
/// Check if the process is continued by the tracee
WIFCONTINUED :: #force_inline proc "contextless" (s: u32) -> bool {
return s == 0xffff
}
/// Check if the process dumped core
WCOREDUMP :: #force_inline proc "contextless" (s: u32) -> bool {
return s & 0x80 == 0x80
}
@private _sigmask :: proc "contextless" (sig: Signal) -> (uint) {
return 1 << ((cast(uint)(sig) - 1) % (8*size_of(uint)))
}
@private _sigword :: proc "contextless" (sig: Signal) -> (uint) {
return (cast(uint)sig - 1) / (8*size_of(uint))
}
// TODO: sigaddset etc
/// Iterate the results of getdents
/// Only iterates as much data as loaded in the buffer
/// In case you need to iterate *all* files in a directory
/// consider using dirent_get_iterate
///
/// Example of using dirent_iterate_buf
/// // Get dirents into a buffer
/// buf: [128]u8
/// sys.getdents(dirfd, buf[:])
/// // Print the names of the files
/// for dir in sys.dirent_iterate_buf(buf[:], &offs) {
/// name := sys.dirent_name(dir)
/// fmt.println(name)
/// }
/// This function doesn't automatically make a request
/// for the buffer to be refilled
dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent, cont: bool) {
// Stopped iterating when there's no space left
if offs^ >= len(buf) {
return nil, false
}
// Retrieve dirent form the current offset
dirent := cast(^Dirent) &buf[offs^]
// Add the stride of dirent struct to the current offset
offs^ += cast(int) dirent.reclen
return dirent, true
}
/// Obtain the name of dirent as a string
/// The lifetime of the string is bound to the lifetime of the provided dirent structure
dirent_name :: proc "contextless" (dirent: ^Dirent) -> string #no_bounds_check {
str := transmute([^]u8) &dirent.name
// Note(flysand): The string size calculated above applies only to the ideal case
// we subtract 1 byte from the string size, because a null terminator is guaranteed
// to be present. But! That said, the dirents are aligned to 8 bytes and the padding
// between the null terminator and the start of the next struct may be not initialized
// which means we also have to scan these garbage bytes.
str_size := (cast(int) dirent.reclen) - 1 - cast(int) offset_of(Dirent, name)
// This skips *only* over the garbage, since if we're not garbage we're at nul terminator,
// which skips this loop
for str[str_size] != 0 {
str_size -= 1
}
for str[str_size-1] == 0 {
str_size -= 1
}
// Oh yeah btw i could also just `repne scasb` this thing, but honestly I started doing
// it the painful way, might as well finish doing it that way
return string(str[:str_size])
}
/// Constructor for the `futex_op` argument of a FUTEX_WAKE_OP call
futex_op :: proc "contextless" (arg_op: Futex_Arg_Op, cmp_op: Futex_Cmp_Op, op_arg: u32, cmp_arg: u32) -> u32 {
arg_op := cast(u32) arg_op
cmp_op := cast(u32) cmp_op
return (arg_op << 28) | (cmp_op << 24) | ((op_arg & 0xfff) << 12) | (cmp_arg & 0xfff)
}
/// Helper function for constructing the config for caches
perf_cache_config :: #force_inline proc "contextless" (id: Perf_Hardware_Cache_Id,
op: Perf_Hardware_Cache_Op_Id,
res: Perf_Hardware_Cache_Result_Id) -> u64
{
return u64(id) | (u64(op) << 8) | (u64(res) << 16)
}

View File

@@ -2,34 +2,32 @@
//+build linux
package time
import "core:intrinsics"
import "core:sys/unix"
import linux "core:sys/linux"
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
perf_attr := unix.Perf_Event_Attr{}
perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
// Get the file descriptor for the perf mapping
perf_attr := linux.Perf_Event_Attr{}
perf_attr.size = size_of(perf_attr)
perf_attr.type = .HARDWARE
perf_attr.config.hw = .INSTRUCTIONS
perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
if fd == -1 {
fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {})
if perf_errno != nil {
return 0, false
}
defer unix.sys_close(fd)
defer linux.close(fd)
// Map it into the memory
page_size : uint = 4096
ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
if ret < 0 && ret > -4096 {
addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd)
if mmap_errno != nil {
return 0, false
}
addr := rawptr(uintptr(ret))
defer unix.sys_munmap(addr, page_size)
event_page := (^unix.Perf_Event_mmap_Page)(addr)
defer linux.munmap(addr, page_size)
// Get the frequency from the mapped page
event_page := cast(^linux.Perf_Event_Mmap_Page) addr
if .User_Time not_in event_page.cap.flags {
return 0, false
}
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
return frequency, true
}

View File

@@ -0,0 +1,6 @@
//+build linux
package all
import linux "core:sys/linux"
_ :: linux

View File

@@ -39,10 +39,13 @@ import TTF "vendor:sdl2/ttf"
import vk "vendor:vulkan"
import NS "vendor:darwin/Foundation"
import MTL "vendor:darwin/Metal"
import MTK "vendor:darwin/MetalKit"
import CA "vendor:darwin/QuartzCore"
// NOTE(flysand): Since conditional imports are disabled for now I'll have to just disable these
// when ODIN_OS == "darwin" {
// import NS "vendor:darwin/Foundation"
// import MTL "vendor:darwin/Metal"
// import MTK "vendor:darwin/MetalKit"
// import CA "vendor:darwin/QuartzCore"
// }
// NOTE(bill): only one can be checked at a time
import lua_5_4 "vendor:lua/5.4"
@@ -91,10 +94,10 @@ _ :: TTF
_ :: vk
_ :: NS
_ :: MTL
_ :: MTK
_ :: CA
// _ :: NS
// _ :: MTL
// _ :: MTK
// _ :: CA
_ :: lua_5_4

View File

@@ -1,30 +0,0 @@
package main
import "core:intrinsics"
SUS_exit :: uintptr(60)
SUS_write ::uintptr(1)
STDOUT_FILENO :: int(1)
sus_write :: proc "contextless" (fd: int, buf: cstring, size: uint) -> int {
return int(intrinsics.syscall(
SUS_write,
cast(uintptr) fd,
cast(uintptr) cast(rawptr) buf,
cast(uintptr) size
))
}
@(link_name = "sussy_baka")
sus_exit :: proc "contextless" (code: $T)->! {
intrinsics.syscall(SUS_exit, uintptr(code))
unreachable()
}
sus :: proc {sus_write, sus_exit}
@(link_name="_start", export) _start :: proc "c" ()->! {
str :: cstring("Hello, world!\n")
sus_write(STDOUT_FILENO, str, uint(14));
sus_exit(0)
}