mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
Merge branch 'master' into syscall-fix
This commit is contained in:
+91
-32
@@ -48,6 +48,7 @@ Errno :: enum i32 {
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
EUNKNOWN_41 = 41,
|
||||
ENOMSG = 42,
|
||||
EIDRM = 43,
|
||||
ECHRNG = 44,
|
||||
@@ -64,6 +65,7 @@ Errno :: enum i32 {
|
||||
ENOANO = 55,
|
||||
EBADRQC = 56,
|
||||
EBADSLT = 57,
|
||||
EUNKNOWN_58 = 58,
|
||||
EBFONT = 59,
|
||||
ENOSTR = 60,
|
||||
ENODATA = 61,
|
||||
@@ -145,26 +147,70 @@ Errno :: enum i32 {
|
||||
}
|
||||
|
||||
/*
|
||||
Bits for Open_Flags
|
||||
Bits for Open_Flags.
|
||||
|
||||
RDONLY flag is not present, because it has the value of 0, i.e. it is the
|
||||
default, unless WRONLY or RDWR is specified.
|
||||
*/
|
||||
Open_Flags_Bits :: enum {
|
||||
RDONLY = 0,
|
||||
WRONLY = 1,
|
||||
RDWR = 2,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECT = 14,
|
||||
DIRECTORY = 16,
|
||||
NOFOLLOW = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
|
||||
Open_Flags_Bits :: enum {
|
||||
WRONLY = 0,
|
||||
RDWR = 1,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECT = 14,
|
||||
LARGEFILE = 15,
|
||||
DIRECTORY = 16,
|
||||
NOFOLLOW = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
}
|
||||
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
|
||||
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
|
||||
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
|
||||
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
|
||||
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
|
||||
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
|
||||
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
|
||||
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
|
||||
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
|
||||
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
|
||||
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
|
||||
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
|
||||
|
||||
} else {
|
||||
Open_Flags_Bits :: enum {
|
||||
WRONLY = 0,
|
||||
RDWR = 1,
|
||||
CREAT = 6,
|
||||
EXCL = 7,
|
||||
NOCTTY = 8,
|
||||
TRUNC = 9,
|
||||
APPEND = 10,
|
||||
NONBLOCK = 11,
|
||||
DSYNC = 12,
|
||||
ASYNC = 13,
|
||||
DIRECTORY = 14,
|
||||
NOFOLLOW = 15,
|
||||
DIRECT = 16,
|
||||
LARGEFILE = 17,
|
||||
NOATIME = 18,
|
||||
CLOEXEC = 19,
|
||||
PATH = 21,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -198,7 +244,7 @@ Mode_Bits :: enum {
|
||||
ISVTX = 9, // 0o0001000
|
||||
ISGID = 10, // 0o0002000
|
||||
ISUID = 11, // 0o0004000
|
||||
IFFIFO = 12, // 0o0010000
|
||||
IFIFO = 12, // 0o0010000
|
||||
IFCHR = 13, // 0o0020000
|
||||
IFDIR = 14, // 0o0040000
|
||||
IFREG = 15, // 0o0100000
|
||||
@@ -845,7 +891,7 @@ Wait_Option :: enum {
|
||||
WSTOPPED = 1,
|
||||
WEXITED = 2,
|
||||
WCONTINUED = 3,
|
||||
WNOWAIT = 24,
|
||||
WNOWAIT = 24,
|
||||
// // For processes created using clone
|
||||
__WNOTHREAD = 29,
|
||||
__WALL = 30,
|
||||
@@ -924,9 +970,22 @@ Sig_Stack_Flag :: enum i32 {
|
||||
AUTODISARM = 31,
|
||||
}
|
||||
|
||||
Sig_Action_Flag :: enum u32 {
|
||||
NOCLDSTOP = 0,
|
||||
NOCLDWAIT = 1,
|
||||
SIGINFO = 2,
|
||||
UNSUPPORTED = 10,
|
||||
EXPOSE_TAGBITS = 11,
|
||||
RESTORER = 26,
|
||||
ONSTACK = 27,
|
||||
RESTART = 28,
|
||||
NODEFER = 30,
|
||||
RESETHAND = 31,
|
||||
}
|
||||
|
||||
/*
|
||||
Type of socket to create
|
||||
- For TCP you want to use SOCK_STREAM
|
||||
- For TCP you want to use SOCK_STREAM
|
||||
- For UDP you want to use SOCK_DGRAM
|
||||
Also see `Protocol`
|
||||
*/
|
||||
@@ -1405,16 +1464,16 @@ Futex_Flags_Bits :: enum {
|
||||
Kind of operation on futex, see FUTEX_WAKE_OP
|
||||
*/
|
||||
Futex_Arg_Op :: enum {
|
||||
SET = 0, /* uaddr2 = oparg; */
|
||||
ADD = 1, /* uaddr2 += oparg; */
|
||||
OR = 2, /* uaddr2 |= oparg; */
|
||||
ANDN = 3, /* uaddr2 &= ~oparg; */
|
||||
XOR = 4, /* uaddr2 ^= oparg; */
|
||||
PO2_SET = 0, /* uaddr2 = 1<<oparg; */
|
||||
PO2_ADD = 1, /* uaddr2 += 1<<oparg; */
|
||||
PO2_OR = 2, /* uaddr2 |= 1<<oparg; */
|
||||
PO2_ANDN = 3, /* uaddr2 &= ~(1<<oparg); */
|
||||
PO2_XOR = 4, /* uaddr2 ^= 1<<oparg; */
|
||||
SET = 0, /* uaddr2 = oparg */
|
||||
ADD = 1, /* uaddr2 += oparg */
|
||||
OR = 2, /* uaddr2 |= oparg */
|
||||
ANDN = 3, /* uaddr2 &= ~oparg */
|
||||
XOR = 4, /* uaddr2 ^= oparg */
|
||||
PO2_SET = 0, /* uaddr2 = 1<<oparg */
|
||||
PO2_ADD = 1, /* uaddr2 += 1<<oparg */
|
||||
PO2_OR = 2, /* uaddr2 |= 1<<oparg */
|
||||
PO2_ANDN = 3, /* uaddr2 &~= 1<<oparg */
|
||||
PO2_XOR = 4, /* uaddr2 ^= 1<<oparg */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -39,11 +39,11 @@ PRIO_MIN :: -20
|
||||
SIGRTMIN :: Signal(32)
|
||||
SIGRTMAX :: Signal(64)
|
||||
|
||||
S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFFIFO}
|
||||
S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFIFO}
|
||||
S_IFSOCK :: Mode{.IFREG, .IFDIR}
|
||||
S_IFLNK :: Mode{.IFREG, .IFCHR}
|
||||
S_IFBLK :: Mode{.IFDIR, .IFCHR}
|
||||
S_IFFIFO :: Mode{.IFFIFO}
|
||||
S_IFIFO :: Mode{.IFIFO}
|
||||
S_IFCHR :: Mode{.IFCHR}
|
||||
S_IFDIR :: Mode{.IFDIR}
|
||||
S_IFREG :: Mode{.IFREG}
|
||||
@@ -51,7 +51,7 @@ 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))}
|
||||
S_ISFIFO :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFIFO == (m & S_IFMT))}
|
||||
|
||||
/*
|
||||
Check the Mode bits to see if the file is a character device.
|
||||
|
||||
+15
-15
@@ -26,7 +26,7 @@ where
|
||||
@(private)
|
||||
syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int
|
||||
where
|
||||
size_of(p1) <= size_of(uintptr) &&
|
||||
size_of(p1) <= size_of(uintptr),
|
||||
size_of(p2) <= size_of(uintptr)
|
||||
{
|
||||
return cast(int) intrinsics.syscall(nr,
|
||||
@@ -36,8 +36,8 @@ where
|
||||
@(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(p1) <= size_of(uintptr),
|
||||
size_of(p2) <= size_of(uintptr),
|
||||
size_of(p3) <= size_of(uintptr)
|
||||
{
|
||||
return cast(int) intrinsics.syscall(nr,
|
||||
@@ -49,9 +49,9 @@ where
|
||||
@(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(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,
|
||||
@@ -64,10 +64,10 @@ where
|
||||
@(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(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,
|
||||
@@ -81,11 +81,11 @@ where
|
||||
@(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(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,
|
||||
|
||||
+44
-29
@@ -69,7 +69,7 @@ close :: proc "contextless" (fd: Fd) -> (Errno) {
|
||||
stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) {
|
||||
when size_of(int) == 8 {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat)
|
||||
ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat, 0)
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_stat, cast(rawptr) filename, stat)
|
||||
@@ -200,10 +200,25 @@ brk :: proc "contextless" (addr: uintptr) -> (Errno) {
|
||||
return Errno(-ret)
|
||||
}
|
||||
|
||||
/*
|
||||
Returns from signal handlers on some archs.
|
||||
*/
|
||||
rt_sigreturn :: proc "c" () -> ! {
|
||||
intrinsics.syscall(uintptr(SYS_rt_sigreturn))
|
||||
unreachable()
|
||||
}
|
||||
|
||||
/*
|
||||
Alter an action taken by a process.
|
||||
*/
|
||||
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno {
|
||||
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action) -> Errno {
|
||||
// NOTE(jason): It appears that the restorer is required for i386 and amd64
|
||||
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
|
||||
sigaction.flags += {.RESTORER}
|
||||
}
|
||||
if sigaction != nil && sigaction.restorer == nil && .RESTORER in sigaction.flags {
|
||||
sigaction.restorer = rt_sigreturn
|
||||
}
|
||||
ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set))
|
||||
return Errno(-ret)
|
||||
}
|
||||
@@ -487,6 +502,7 @@ connect :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno)
|
||||
where
|
||||
T == Sock_Addr_In ||
|
||||
T == Sock_Addr_In6 ||
|
||||
T == Sock_Addr_Un ||
|
||||
T == Sock_Addr_Any
|
||||
{
|
||||
ret := syscall(SYS_connect, sock, addr, size_of(T))
|
||||
@@ -502,6 +518,7 @@ accept :: proc "contextless" (sock: Fd, addr: ^$T, sockflags: Socket_FD_Flags =
|
||||
where
|
||||
T == Sock_Addr_In ||
|
||||
T == Sock_Addr_In6 ||
|
||||
T == Sock_Addr_Un ||
|
||||
T == Sock_Addr_Any
|
||||
{
|
||||
addr_len: i32 = size_of(T)
|
||||
@@ -514,6 +531,7 @@ recvfrom :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$
|
||||
where
|
||||
T == Sock_Addr_In ||
|
||||
T == Sock_Addr_In6 ||
|
||||
T == Sock_Addr_Un ||
|
||||
T == Sock_Addr_Any
|
||||
{
|
||||
addr_len: i32 = size_of(T)
|
||||
@@ -531,6 +549,7 @@ sendto :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$T)
|
||||
where
|
||||
T == Sock_Addr_In ||
|
||||
T == Sock_Addr_In6 ||
|
||||
T == Sock_Addr_Un ||
|
||||
T == Sock_Addr_Any
|
||||
{
|
||||
ret := syscall(SYS_sendto, sock, raw_data(buf), len(buf), transmute(i32) flags, addr, size_of(T))
|
||||
@@ -590,6 +609,7 @@ bind :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno)
|
||||
where
|
||||
T == Sock_Addr_In ||
|
||||
T == Sock_Addr_In6 ||
|
||||
T == Sock_Addr_Un ||
|
||||
T == Sock_Addr_Any
|
||||
{
|
||||
ret := syscall(SYS_bind, sock, addr, size_of(T))
|
||||
@@ -1114,7 +1134,7 @@ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
|
||||
ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_truncate, fd, compat64_arg_pair(length))
|
||||
ret := syscall(SYS_ftruncate, fd, compat64_arg_pair(length))
|
||||
return Errno(-ret)
|
||||
}
|
||||
}
|
||||
@@ -1222,7 +1242,7 @@ creat :: proc "contextless" (name: cstring, mode: Mode) -> (Fd, Errno) {
|
||||
*/
|
||||
link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
|
||||
ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath, 0)
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath)
|
||||
@@ -1252,7 +1272,7 @@ unlink :: proc "contextless" (name: cstring) -> (Errno) {
|
||||
*/
|
||||
symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath)
|
||||
ret := syscall(SYS_symlinkat, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath)
|
||||
@@ -1282,7 +1302,7 @@ readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) {
|
||||
*/
|
||||
chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0)
|
||||
ret := syscall(SYS_fchmodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
|
||||
return Errno(-ret)
|
||||
} else {
|
||||
ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode)
|
||||
@@ -1709,9 +1729,9 @@ getpgrp :: proc "contextless" () -> (Pid, Errno) {
|
||||
Create a session and set the process group ID.
|
||||
Available since Linux 2.0.
|
||||
*/
|
||||
setsid :: proc "contextless" () -> (Errno) {
|
||||
setsid :: proc "contextless" () -> (Pid, Errno) {
|
||||
ret := syscall(SYS_setsid)
|
||||
return Errno(-ret)
|
||||
return errno_unwrap(ret, Pid)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2217,8 +2237,7 @@ futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Fut
|
||||
Returns the total number of waiters that have been woken up plus the number of waiters requeued.
|
||||
*/
|
||||
futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
|
||||
requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno)
|
||||
{
|
||||
requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno) {
|
||||
futex_flags := cast(u32) op + transmute(u32) flags
|
||||
ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex, val)
|
||||
return errno_unwrap(ret, int)
|
||||
@@ -2229,8 +2248,7 @@ futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Ty
|
||||
Returns the total number of waiters that have been woken up.
|
||||
*/
|
||||
futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
|
||||
requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno)
|
||||
{
|
||||
requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno) {
|
||||
futex_flags := cast(u32) op + transmute(u32) flags
|
||||
ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex)
|
||||
return errno_unwrap(ret, int)
|
||||
@@ -2241,8 +2259,7 @@ futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flag
|
||||
purpose is to allow implementing conditional values sync primitive, it seems like.
|
||||
*/
|
||||
futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flags: Futex_Flags, wakeup: i32,
|
||||
dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno)
|
||||
{
|
||||
dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno) {
|
||||
futex_flags := cast(u32) op + transmute(u32) flags
|
||||
ret := syscall(SYS_futex, futex, futex_flags, wakeup, dst_wakeup, dst, futex_op)
|
||||
return errno_unwrap(ret, int)
|
||||
@@ -2252,8 +2269,7 @@ futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flag
|
||||
Same as wait, but mask specifies bits that must be equal for the mutex to wake up.
|
||||
*/
|
||||
futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Type, flags: Futex_Flags, val: u32,
|
||||
timeout: ^Time_Spec, mask: u32) -> (int, Errno)
|
||||
{
|
||||
timeout: ^Time_Spec, mask: u32) -> (int, Errno) {
|
||||
futex_flags := cast(u32) op + transmute(u32) flags
|
||||
ret := syscall(SYS_futex, futex, futex_flags, val, timeout, 0, mask)
|
||||
return errno_unwrap(ret, int)
|
||||
@@ -2262,8 +2278,7 @@ futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Ty
|
||||
/*
|
||||
Wake up on bitset.
|
||||
*/
|
||||
futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno)
|
||||
{
|
||||
futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno) {
|
||||
futex_flags := cast(u32) op + transmute(u32) flags
|
||||
ret := syscall(SYS_futex, futex, futex_flags, n_wakeup, 0, 0, mask)
|
||||
return errno_unwrap(ret, int)
|
||||
@@ -2271,7 +2286,7 @@ futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Ty
|
||||
|
||||
// TODO(flysand): Priority inheritance (PI) futicees
|
||||
|
||||
futex :: proc {
|
||||
futex :: proc{
|
||||
futex_wait,
|
||||
futex_wake,
|
||||
futex_cmp_requeue,
|
||||
@@ -2310,7 +2325,7 @@ futex :: proc {
|
||||
*/
|
||||
epoll_create :: proc(size: i32 = 1) -> (Fd, Errno) {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
ret := syscall(SYS_epoll_create)
|
||||
ret := syscall(SYS_epoll_create, i32(1))
|
||||
return errno_unwrap(ret, Fd)
|
||||
} else {
|
||||
ret := syscall(SYS_epoll_create1, i32(0))
|
||||
@@ -2467,8 +2482,8 @@ tgkill :: proc "contextless" (tgid, tid: Pid, sig: Signal) -> (Errno) {
|
||||
Wait on process, process group or pid file descriptor.
|
||||
Available since Linux 2.6.10.
|
||||
*/
|
||||
waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) {
|
||||
ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options)
|
||||
waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options, rusage: ^RUsage) -> (Errno) {
|
||||
ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options, rusage)
|
||||
return Errno(-ret)
|
||||
}
|
||||
|
||||
@@ -2495,7 +2510,7 @@ waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, opt
|
||||
Available since Linux 2.6.16.
|
||||
*/
|
||||
openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) {
|
||||
ret := syscall(SYS_openat, fd, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode)
|
||||
ret := syscall(SYS_openat, fd, transmute(uintptr) name, transmute(u32) flags, transmute(u32) mode)
|
||||
return errno_unwrap(ret, Fd)
|
||||
}
|
||||
|
||||
@@ -2574,8 +2589,8 @@ linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd
|
||||
Create a symbolic link at specified dirfd.
|
||||
Available since Linux 2.6.16.
|
||||
*/
|
||||
symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) {
|
||||
ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath)
|
||||
symlinkat :: proc "contextless" (target: cstring, dirfd: Fd, linkpath: cstring) -> (Errno) {
|
||||
ret := syscall(SYS_symlinkat, cast(rawptr) target, dirfd, cast(rawptr) linkpath)
|
||||
return Errno(-ret)
|
||||
}
|
||||
|
||||
@@ -2610,13 +2625,13 @@ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) ->
|
||||
Wait for events on a file descriptor.
|
||||
Available since Linux 2.6.16.
|
||||
*/
|
||||
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (Errno) {
|
||||
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
|
||||
when size_of(int) == 8 {
|
||||
ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
|
||||
return Errno(-ret)
|
||||
return errno_unwrap(ret, i32)
|
||||
} else {
|
||||
ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
|
||||
return Errno(-ret)
|
||||
return errno_unwrap(ret, i32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2799,7 +2814,7 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er
|
||||
Execute program relative to a directory file descriptor.
|
||||
Available since Linux 3.19.
|
||||
*/
|
||||
execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: Execveat_Flags) -> (Errno) {
|
||||
execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: FD_Flags = {}) -> (Errno) {
|
||||
ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, transmute(i32) flags)
|
||||
return Errno(-ret)
|
||||
}
|
||||
|
||||
+85
-20
@@ -18,7 +18,7 @@ Gid :: distinct u32
|
||||
/*
|
||||
Type for Process IDs, Thread IDs, Thread group ID.
|
||||
*/
|
||||
Pid :: distinct int
|
||||
Pid :: distinct i32
|
||||
|
||||
/*
|
||||
Type for any of: pid, pidfd, pgid.
|
||||
@@ -89,11 +89,11 @@ 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:
|
||||
|
||||
|
||||
```
|
||||
linux.Mode{.S_IXOTH, .S_IROTH} | linux.S_IRWXU | linux.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.
|
||||
@@ -151,9 +151,9 @@ when ODIN_ARCH == .amd64 {
|
||||
size: i64,
|
||||
blksize: uint,
|
||||
blocks: u64,
|
||||
atim: Time_Spec,
|
||||
mtim: Time_Spec,
|
||||
ctim: Time_Spec,
|
||||
atime: Time_Spec,
|
||||
mtime: Time_Spec,
|
||||
ctime: Time_Spec,
|
||||
ino: Inode,
|
||||
}
|
||||
}
|
||||
@@ -495,16 +495,15 @@ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
|
||||
// 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)))
|
||||
@private _SIGSET_NWORDS :: (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)
|
||||
@private SI_ARCH_PREAMBLE :: 4 * size_of(i32)
|
||||
@private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE
|
||||
|
||||
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
|
||||
Sig_Restore_Fn :: #type proc "c" ()
|
||||
Sig_Restore_Fn :: #type proc "c" () -> !
|
||||
|
||||
Sig_Info :: struct #packed {
|
||||
signo: Signal,
|
||||
@@ -518,8 +517,9 @@ Sig_Info :: struct #packed {
|
||||
uid: Uid, /* sender's uid */
|
||||
},
|
||||
using _timer: struct {
|
||||
timerid: i32, /* timer id */
|
||||
timerid: i32, /* timer id */
|
||||
overrun: i32, /* overrun count */
|
||||
value: Sig_Val, /* timer value */
|
||||
},
|
||||
/* POSIX.1b signals */
|
||||
using _rt: struct {
|
||||
@@ -528,8 +528,8 @@ Sig_Info :: struct #packed {
|
||||
},
|
||||
/* SIGCHLD */
|
||||
using _sigchld: struct {
|
||||
_pid1: Pid, /* which child */
|
||||
_uid1: Uid, /* sender's uid */
|
||||
_pid1: Pid, /* which child */
|
||||
_uid1: Uid, /* sender's uid */
|
||||
status: i32, /* exit code */
|
||||
utime: uint,
|
||||
stime: uint, //clock_t
|
||||
@@ -537,7 +537,24 @@ Sig_Info :: struct #packed {
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
using _sigfault: struct {
|
||||
addr: rawptr, /* faulting insn/memory ref. */
|
||||
addr_lsb: i16, /* LSB of the reported address */
|
||||
using _: struct #raw_union {
|
||||
trapno: i32, /* Trap number that caused signal */
|
||||
addr_lsb: i16, /* LSB of the reported address */
|
||||
using _addr_bnd: struct {
|
||||
_pad2: u64,
|
||||
lower: rawptr, /* lower bound during fault */
|
||||
upper: rawptr, /* upper bound during fault */
|
||||
},
|
||||
using _addr_pkey: struct {
|
||||
_pad3: u64,
|
||||
pkey: u32, /* protection key on PTE that faulted */
|
||||
},
|
||||
using _perf: struct {
|
||||
perf_data: u64,
|
||||
perf_type: u32,
|
||||
perf_flags: u32,
|
||||
},
|
||||
},
|
||||
},
|
||||
/* SIGPOLL */
|
||||
using _sigpoll: struct {
|
||||
@@ -547,12 +564,43 @@ Sig_Info :: struct #packed {
|
||||
/* SIGSYS */
|
||||
using _sigsys: struct {
|
||||
call_addr: rawptr, /* calling user insn */
|
||||
syscall: i32, /* triggering system call number */
|
||||
arch: u32, /* AUDIT_ARCH_* of syscall */
|
||||
syscall: i32, /* triggering system call number */
|
||||
arch: u32, /* AUDIT_ARCH_* of syscall */
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
#assert(size_of(Sig_Info) == 128)
|
||||
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
|
||||
#assert(offset_of(Sig_Info, signo) == 0x00)
|
||||
#assert(offset_of(Sig_Info, errno) == 0x04)
|
||||
#assert(offset_of(Sig_Info, code) == 0x08)
|
||||
#assert(offset_of(Sig_Info, pid) == 0x10)
|
||||
#assert(offset_of(Sig_Info, uid) == 0x14)
|
||||
#assert(offset_of(Sig_Info, timerid) == 0x10)
|
||||
#assert(offset_of(Sig_Info, overrun) == 0x14)
|
||||
#assert(offset_of(Sig_Info, value) == 0x18)
|
||||
#assert(offset_of(Sig_Info, status) == 0x18)
|
||||
#assert(offset_of(Sig_Info, utime) == 0x20)
|
||||
#assert(offset_of(Sig_Info, stime) == 0x28)
|
||||
#assert(offset_of(Sig_Info, addr) == 0x10)
|
||||
#assert(offset_of(Sig_Info, addr_lsb) == 0x18)
|
||||
#assert(offset_of(Sig_Info, trapno) == 0x18)
|
||||
#assert(offset_of(Sig_Info, lower) == 0x20)
|
||||
#assert(offset_of(Sig_Info, upper) == 0x28)
|
||||
#assert(offset_of(Sig_Info, pkey) == 0x20)
|
||||
#assert(offset_of(Sig_Info, perf_data) == 0x18)
|
||||
#assert(offset_of(Sig_Info, perf_type) == 0x20)
|
||||
#assert(offset_of(Sig_Info, perf_flags) == 0x24)
|
||||
#assert(offset_of(Sig_Info, band) == 0x10)
|
||||
#assert(offset_of(Sig_Info, fd) == 0x18)
|
||||
#assert(offset_of(Sig_Info, call_addr) == 0x10)
|
||||
#assert(offset_of(Sig_Info, syscall) == 0x18)
|
||||
#assert(offset_of(Sig_Info, arch) == 0x1C)
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
|
||||
SIGEV_MAX_SIZE :: 64
|
||||
SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32))
|
||||
|
||||
@@ -583,12 +631,20 @@ Sig_Stack :: struct {
|
||||
size: uintptr,
|
||||
}
|
||||
|
||||
Sig_Action_Special :: enum uint {
|
||||
SIG_DFL = 0,
|
||||
SIG_IGN = 1,
|
||||
SIG_ERR = ~uint(0),
|
||||
}
|
||||
|
||||
Sig_Action_Flags :: bit_set[Sig_Action_Flag; uint]
|
||||
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),
|
||||
special: Sig_Action_Special,
|
||||
},
|
||||
flags: uint,
|
||||
flags: Sig_Action_Flags,
|
||||
restorer: Sig_Restore_Fn,
|
||||
mask: Sig_Set,
|
||||
}
|
||||
@@ -631,6 +687,14 @@ Sock_Addr_In6 :: struct #packed {
|
||||
sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
/*
|
||||
Struct representing Unix Domain Socket address
|
||||
*/
|
||||
Sock_Addr_Un :: struct #packed {
|
||||
sun_family: Address_Family,
|
||||
sun_path: [108]u8,
|
||||
}
|
||||
|
||||
/*
|
||||
Struct representing an arbitrary socket address.
|
||||
*/
|
||||
@@ -641,6 +705,7 @@ Sock_Addr_Any :: struct #raw_union {
|
||||
},
|
||||
using ipv4: Sock_Addr_In,
|
||||
using ipv6: Sock_Addr_In6,
|
||||
using uds: Sock_Addr_Un,
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -724,7 +789,7 @@ RLimit :: struct {
|
||||
|
||||
/*
|
||||
Structure representing how much of each resource got used.
|
||||
*/
|
||||
*/
|
||||
RUsage :: struct {
|
||||
utime: Time_Val,
|
||||
stime: Time_Val,
|
||||
@@ -804,7 +869,7 @@ when size_of(int) == 8 || ODIN_ARCH == .i386 {
|
||||
cpid: Pid,
|
||||
lpid: Pid,
|
||||
nattach: uint,
|
||||
_: [2]uint,
|
||||
_: [2]uint,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ WCOREDUMP :: #force_inline proc "contextless" (s: u32) -> bool {
|
||||
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))
|
||||
return (cast(uint)sig - 1) / (8*size_of(uint))
|
||||
}
|
||||
|
||||
// TODO: sigaddset etc
|
||||
@@ -85,13 +85,13 @@ dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent,
|
||||
/// 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
|
||||
str := ([^]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)
|
||||
str_size := 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 {
|
||||
@@ -115,7 +115,6 @@ futex_op :: proc "contextless" (arg_op: Futex_Arg_Op, cmp_op: Futex_Cmp_Op, op_a
|
||||
/// 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
|
||||
{
|
||||
res: Perf_Hardware_Cache_Result_Id) -> u64 {
|
||||
return u64(id) | (u64(op) << 8) | (u64(res) << 16)
|
||||
}
|
||||
Reference in New Issue
Block a user