mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-28 17:04:34 +00:00
Implement new sys/unix package
This commit is contained in:
@@ -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:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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, {}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ×pec_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")
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
1400
core/sys/linux/bits.odin
Normal file
File diff suppressed because it is too large
Load Diff
199
core/sys/linux/constants.odin
Normal file
199
core/sys/linux/constants.odin
Normal 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
150
core/sys/linux/helpers.odin
Normal 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
2038
core/sys/linux/sys.odin
Normal file
File diff suppressed because it is too large
Load Diff
373
core/sys/linux/syscall_amd64.odin
Normal file
373
core/sys/linux/syscall_amd64.odin
Normal 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)
|
||||
470
core/sys/linux/syscall_arm32.odin
Normal file
470
core/sys/linux/syscall_arm32.odin
Normal 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)
|
||||
321
core/sys/linux/syscall_arm64.odin
Normal file
321
core/sys/linux/syscall_arm64.odin
Normal 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)
|
||||
|
||||
|
||||
458
core/sys/linux/syscall_i386.odin
Normal file
458
core/sys/linux/syscall_i386.odin
Normal 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
566
core/sys/linux/types.odin
Normal 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,
|
||||
}
|
||||
121
core/sys/linux/wrappers.odin
Normal file
121
core/sys/linux/wrappers.odin
Normal 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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
6
examples/all/all_linux.odin
Normal file
6
examples/all/all_linux.odin
Normal file
@@ -0,0 +1,6 @@
|
||||
//+build linux
|
||||
package all
|
||||
|
||||
import linux "core:sys/linux"
|
||||
|
||||
_ :: linux
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user