This commit is contained in:
flysand7
2023-11-02 08:51:33 +11:00
parent 62d0b0ae72
commit 7faa146004
4 changed files with 1149 additions and 61 deletions

View File

@@ -1398,3 +1398,173 @@ PER_OSF4 :: 0x000f
PER_HPUX :: 0x0010
PER_MASK :: 0x00ff
/*
Bits for access modes for shared memory
*/
IPC_Mode_Bits :: enum {
WROTH = 1,
RDOTH = 2,
WRGRP = 4,
RDGRP = 5,
WRUSR = 7,
RDUSR = 8,
DEST = 9,
LOCKED = 10,
}
/*
Shared memory flags bits
*/
IPC_Flags_Bits :: enum {
IPC_CREAT = 9,
IPC_EXCL = 10,
IPC_NOWAIT = 11,
// Semaphore
SEM_UNDO = 9,
// Shared memory
SHM_HUGETLB = 11,
SHM_NORESERVE = 12,
SHM_RDONLY = 12,
SHM_RND = 13,
SHM_REMAP = 14,
SHM_EXEC = 15,
// Message queue
MSG_NOERROR = 12,
MSG_EXCEPT = 13,
MSG_COPY = 14,
}
/*
IPC memory commands
*/
IPC_Cmd :: enum i16 {
// IPC common
IPC_RMID = 0,
IPC_SET = 1,
IPC_STAT = 2,
// Shared memory
SHM_LOCK = 11,
SHM_UNLOCK = 12,
SHM_STAT = 13,
SHM_INFO = 14,
SHM_STAT_ANY = 15,
// Semaphore
GETPID = 11,
GETVAL = 12,
GETALL = 13,
GETNCNT = 14,
GETZCNT = 15,
SETVAL = 16,
SETALL = 17,
SEM_STAT = 18,
SEM_INFO = 19,
SEM_STAT_ANY = 20,
// Message queue
MSG_STAT = 11,
MSG_INFO = 12,
MSG_STAT_ANY = 13,
}
/*
File locking operation bits
*/
FLock_Op_Bits :: enum {
SH = 1,
EX = 2,
NB = 4,
UN = 8,
}
/*
ptrace requests
*/
PTrace_Request :: enum {
TRACEME = 0,
PEEKTEXT = 1,
PEEKDATA = 2,
PEEKUSER = 3,
POKETEXT = 4,
POKEDATA = 5,
POKEUSER = 6,
CONT = 7,
KILL = 8,
SINGLESTEP = 9,
GETREGS = 12,
SETREGS = 13,
GETFPREGS = 14,
SETFPREGS = 15,
ATTACH = 16,
DETACH = 17,
GETFPXREGS = 18,
SETFPXREGS = 19,
SYSCALL = 24,
GET_THREAD_AREA = 25,
SET_THREAD_AREA = 26,
ARCH_PRCTL = 30,
SYSEMU = 31,
SYSEMU_SINGLESTEP = 32,
SINGLEBLOCK = 33,
SETOPTIONS = 0x4200,
GETEVENTMSG = 0x4201,
GETSIGINFO = 0x4202,
SETSIGINFO = 0x4203,
GETREGSET = 0x4204,
SETREGSET = 0x4205,
SEIZE = 0x4206,
INTERRUPT = 0x4207,
LISTEN = 0x4208,
PEEKSIGINFO = 0x4209,
GETSIGMASK = 0x420a,
SETSIGMASK = 0x420b,
SECCOMP_GET_FILTER = 0x420c,
SECCOMP_GET_METADATA = 0x420d,
GET_SYSCALL_INFO = 0x420e,
GET_RSEQ_CONFIGURATION = 0x420f,
};
/*
ptrace options
*/
PTrace_Options_Bits :: enum {
TRACESYSGOOD = 0,
TRACEFORK = 1,
TRACEVFORK = 2,
TRACECLONE = 3,
TRACEEXEC = 4,
TRACEVFORKDONE = 5,
TRACEEXIT = 6,
TRACESECCOMP = 7,
EXITKILL = 20,
SUSPEND_SECCOMP = 21,
}
/*
ptrace event codes.
*/
PTrace_Event_Code :: enum {
EVENT_FORK = 1,
EVENT_VFORK = 2,
EVENT_CLONE = 3,
EVENT_EXEC = 4,
EVENT_VFORK_DONE = 5,
EVENT_EXIT = 6,
EVENT_SECCOMP = 7,
EVENT_STOP = 128,
}
/*
ptrace's get syscall info operation.
*/
PTrace_Get_Syscall_Info_Op :: enum u8 {
NONE = 0,
ENTRY = 1,
EXIT = 2,
SECCOMP = 3,
};
/*
ptrace's PEEKSIGINFO flags bits
*/
PTrace_Peek_Sig_Info_Flags_Bits :: enum {
SHARED = 0,
}

View File

@@ -83,6 +83,10 @@ STATX_BASIC_STATS :: Statx_Mask {
.BLOCKS,
}
/*
Tell `shmget` to create a new key
*/
IPC_PRIVATE :: Key(0)
FCntl_Command_DUPFD :: distinct FCntl_Command
FCntl_Command_GETFD :: distinct FCntl_Command
@@ -197,3 +201,82 @@ 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)
PTrace_Traceme_Type :: distinct PTrace_Request
PTrace_Peek_Type :: distinct PTrace_Request
PTrace_Poke_Type :: distinct PTrace_Request
PTrace_Cont_Type :: distinct PTrace_Request
PTrace_Kill_Type :: distinct PTrace_Request
PTrace_Singlestep_Type :: distinct PTrace_Request
PTrace_Getregs_Type :: distinct PTrace_Request
PTrace_Setregs_Type :: distinct PTrace_Request
PTrace_Getfpregs_Type :: distinct PTrace_Request
PTrace_Setfpregs_Type :: distinct PTrace_Request
PTrace_Attach_Type :: distinct PTrace_Request
PTrace_Detach_Type :: distinct PTrace_Request
PTrace_Getfpxregs_Type :: distinct PTrace_Request
PTrace_Setfpxregs_Type :: distinct PTrace_Request
PTrace_Syscall_Type :: distinct PTrace_Request
PTrace_Get_Thread_Area_Type :: distinct PTrace_Request
PTrace_Set_Thread_Area_Type :: distinct PTrace_Request
PTrace_Arch_Prctl_Type :: distinct PTrace_Request
PTrace_Sysemu_Type :: distinct PTrace_Request
PTrace_Sysemu_Singlestep_Type :: distinct PTrace_Request
PTrace_Singleblock_Type :: distinct PTrace_Request
PTrace_Setoptions_Type :: distinct PTrace_Request
PTrace_Geteventmsg_Type :: distinct PTrace_Request
PTrace_Getsiginfo_Type :: distinct PTrace_Request
PTrace_Setsiginfo_Type :: distinct PTrace_Request
PTrace_Getregset_Type :: distinct PTrace_Request
PTrace_Setregset_Type :: distinct PTrace_Request
PTrace_Seize_Type :: distinct PTrace_Request
PTrace_Interrupt_Type :: distinct PTrace_Request
PTrace_Listen_Type :: distinct PTrace_Request
PTrace_Peeksiginfo_Type :: distinct PTrace_Request
PTrace_Getsigmask_Type :: distinct PTrace_Request
PTrace_Setsigmask_Type :: distinct PTrace_Request
PTrace_Seccomp_Get_Filter_Type :: distinct PTrace_Request
PTrace_Seccomp_Get_Metadata_Type :: distinct PTrace_Request
PTrace_Get_Syscall_Info_Type :: distinct PTrace_Request
PTrace_Get_RSeq_Configuration_Type :: distinct PTrace_Request
PTRACE_TRACEME :: PTrace_Traceme_Type(.TRACEME)
PTRACE_PEEKTEXT :: PTrace_Peek_Type(.PEEKTEXT)
PTRACE_PEEKDATA :: PTrace_Peek_Type(.PEEKDATA)
PTRACE_PEEKUSER :: PTrace_Peek_Type(.PEEKUSER)
PTRACE_POKETEXT :: PTrace_Poke_Type(.POKETEXT)
PTRACE_POKEDATA :: PTrace_Poke_Type(.POKEDATA)
PTRACE_POKEUSER :: PTrace_Poke_Type(.POKEUSER)
PTRACE_CONT :: PTrace_Cont_Type(.CONT)
PTRACE_KILL :: PTrace_Kill_Type(.KILL)
PTRACE_SINGLESTEP :: PTrace_Singlestep_Type(.SINGLESTEP)
PTRACE_GETREGS :: PTrace_Getregs_Type(.GETREGS)
PTRACE_SETREGS :: PTrace_Setregs_Type(.SETREGS)
PTRACE_GETFPREGS :: PTrace_Getfpregs_Type(.GETFPREGS)
PTRACE_SETFPREGS :: PTrace_Setfpregs_Type(.SETFPREGS)
PTRACE_ATTACH :: PTrace_Attach_Type(.ATTACH)
PTRACE_DETACH :: PTrace_Detach_Type(.DETACH)
PTRACE_GETFPXREGS :: PTrace_Getfpxregs_Type(.GETFPXREGS)
PTRACE_SETFPXREGS :: PTrace_Setfpxregs_Type(.SETFPXREGS)
PTRACE_SYSCALL :: PTrace_Syscall_Type(.SYSCALL)
PTRACE_GET_THREAD_AREA :: PTrace_Get_Thread_Area_Type(.GET_THREAD_AREA)
PTRACE_SET_THREAD_AREA :: PTrace_Set_Thread_Area_Type(.SET_THREAD_AREA)
PTRACE_ARCH_PRCTL :: PTrace_Arch_Prctl_Type(.ARCH_PRCTL)
PTRACE_SYSEMU :: PTrace_Sysemu_Type(.SYSEMU)
PTRACE_SYSEMU_SINGLESTEP :: PTrace_Sysemu_Singlestep_Type(.SYSEMU_SINGLESTEP)
PTRACE_SINGLEBLOCK :: PTrace_Singleblock_Type(.SINGLEBLOCK)
PTRACE_SETOPTIONS :: PTrace_Setoptions_Type(.SETOPTIONS)
PTRACE_GETEVENTMSG :: PTrace_Geteventmsg_Type(.GETEVENTMSG)
PTRACE_GETSIGINFO :: PTrace_Getsiginfo_Type(.GETSIGINFO)
PTRACE_SETSIGINFO :: PTrace_Setsiginfo_Type(.SETSIGINFO)
PTRACE_GETREGSET :: PTrace_Getregset_Type(.GETREGSET)
PTRACE_SETREGSET :: PTrace_Setregset_Type(.SETREGSET)
PTRACE_SEIZE :: PTrace_Seize_Type(.SEIZE)
PTRACE_INTERRUPT :: PTrace_Interrupt_Type(.INTERRUPT)
PTRACE_LISTEN :: PTrace_Listen_Type(.LISTEN)
PTRACE_PEEKSIGINFO :: PTrace_Peeksiginfo_Type(.PEEKSIGINFO)
PTRACE_GETSIGMASK :: PTrace_Getsigmask_Type(.GETSIGMASK)
PTRACE_SETSIGMASK :: PTrace_Setsigmask_Type(.SETSIGMASK)
PTRACE_SECCOMP_GET_FILTER :: PTrace_Seccomp_Get_Filter_Type(.SECCOMP_GET_FILTER)
PTRACE_SECCOMP_GET_METADATA :: PTrace_Seccomp_Get_Metadata_Type(.SECCOMP_GET_METADATA)
PTRACE_GET_SYSCALL_INFO :: PTrace_Get_Syscall_Info_Type(.GET_SYSCALL_INFO)
PTRACE_GET_RSEQ_CONFIGURATION :: PTrace_Get_RSeq_Configuration_Type(.GET_RSEQ_CONFIGURATION)

View File

@@ -165,7 +165,16 @@ munmap :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): brk
/*
Extend the data segment size until the address `addr`. Note: you may be
familiar with sbrk(), which is not actually a syscall, so is not
implemented here.
Available since Linux 1.0.
*/
brk :: proc "contextless" (addr: uintptr) -> (Errno) {
ret := syscall(SYS_brk, addr)
return Errno(-ret)
}
/// Alter an action taken by a process
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno {
@@ -180,8 +189,6 @@ rt_sigprocmask :: proc "contextless" (mask_kind: Sig_Mask_Kind, new_set: ^Sig_Se
return Errno(-ret)
}
// TODO(flysand): rt_sigreturn
// TODO(flysand): ioctl
/// Read the file at a specified offset
@@ -200,9 +207,23 @@ pwrite :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) {
return errno_unwrap(ret, int)
}
// TODO(flysand): readv
/*
Read the data from file into multiple buffers.
Available since Linux 2.0.
*/
readv :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) {
ret := syscall(SYS_readv, fd, raw_data(iov), len(iov))
return errno_unwrap(ret, int)
}
// TODO(flysand): writev
/*
Write the data from multiple buffers into a file.
Available since Linux 2.0.
*/
writev :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) {
ret := syscall(SYS_writev, fd, raw_data(iov), len(iov))
return errno_unwrap(ret, int)
}
/// Check user permissions for a file
/// If Mode is F_OK, checks whether the file exists
@@ -226,11 +247,18 @@ pipe2 :: proc "contextless" (pipes: ^[2]Fd, flags: Open_Flags) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): select
/*
Yield the processor.
Available since Linux 2.0.
*/
sched_yield :: proc "contextless" () {
syscall(SYS_sched_yield)
}
// TODO(flysand): sched_yield
// TODO(flysand): add docs here
/*
Remap a virtual memory address.
Available since Linux 2.0.
*/
mremap :: proc "contextless" (old_addr: rawptr, old_size: uint, new_size: uint, flags: MRemap_Flags, new_addr: uintptr = 0) -> (rawptr, Errno) {
if .FIXED in flags {
ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags, new_addr)
@@ -248,7 +276,14 @@ msync :: proc "contextless" (addr: rawptr, size: uint, flags: MSync_Flags) -> (E
return Errno(-ret)
}
// TODO(flysand): mincore
/*
Determine if pages are resident in memory.
Available since Linux 2.4.
*/
mincore :: proc "contextless" (addr: rawptr, size: uint, vec: []b8) -> (Errno) {
ret := syscall(SYS_mincore, addr, size, raw_data(vec))
return Errno(-ret)
}
/// Give advice about use of memory
/// Available since Linux 2.4
@@ -257,11 +292,44 @@ madvise :: proc "contextless" (addr: rawptr, size: uint, advice: MAdvice) -> (Er
return Errno(-ret)
}
// TODO(flysand): shmget
/*
Allocate a SystemV shared memory segment.
Available since Linux 2.0.
*/
shmget :: proc "contextless" (key: Key, size: uint, flags: IPC_Flags) -> (Key, Errno) {
ret := syscall(SYS_shmget, key, size, transmute(i16) flags)
return errno_unwrap(ret, Key)
}
// TODO(flysand): shmat
/*
SystemV shared memory segment operations.
Available since Linux 2.0.
*/
shmat :: proc "contextless" (key: Key, addr: rawptr, flags: IPC_Flags) -> (rawptr, Errno) {
ret := syscall(SYS_shmat, key, addr, transmute(i16) flags)
return errno_unwrap(ret, Key)
}
// TODO(flysand): shmctl
shmctl_ds :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shmid_DS) -> (Errno) {
ret := syscall(SYS_shmctl, key, cmd, buf)
return Errno(-ret)
}
shmctl_info :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shmid_Info) -> (int, Errno) {
ret := syscall(SYS_shmctl, key, cmd, buf)
return errno_unwrap(ret, int)
}
shmctl_stat :: proc "contextless" (index: int, cmd: IPC_Cmd, buf: ^Shmid_DS) -> (Key, Errno) {
ret := syscall(SYS_shmctl, key, cmd, buf)
return errno_unwrap(ret, Key)
}
/*
SystemV shared memory control.
Available since Linux 2.0.
*/
shmctl :: proc {shmctl_ds, shmctl_info, shmctl_stat}
/// Allocate a new file descriptor that refers to the same file as the one provided
/// Available since Linux 1.0
@@ -283,15 +351,48 @@ dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) {
}
}
// TODO(flysand): pause
/*
Wait until the next signal is delivered.
Available since Linux 1.0.
*/
pause :: proc "contextless" () {
syscall(SYS_pause)
}
// TODO(flysand): nanosleep
/*
High-resolution sleep.
Available since Linux 2.0.
*/
nanosleep :: proc "contextless" (req: ^Time_Spec, rem: ^Time_Spec) -> (Errno) {
ret := syscall(SYS_nanosleep, req, rem)
return Errno(-ret)
}
// TODO(flysand): getitimer
/*
Get the value of an internal timer.
Available since Linux 1.0.
*/
getitimer :: proc "contextless" (which: ITimer_Which, cur: ^ITimer_Val) -> (Errno) {
ret := syscall(SYS_getitimer, cur)
return Errno(-ret)
}
// TODO(flysand): alarm
/*
Set an alarm clock for delivery of a signal.
Available since Linux 1.0.
*/
alarm :: proc "contextless" (seconds: u32) -> u32 {
return cast(u32) syscall(SYS_alarm, seconds)
}
// TODO(flysand): setitimer
/*
Set the value of an internal timer.
Available since Linux 1.0.
*/
getitimer :: proc "contextless" (which: ITimer_Which, new: ^ITimer_Val, old: ^ITimer_Val) -> (Errno) {
ret := syscall(SYS_getitimer, new, old)
return Errno(-ret)
}
/// Returns the thread group ID of the current process
/// Note that it doesn't return the pid, despite it's name.
@@ -300,7 +401,20 @@ getpid :: proc "contextless" () -> Pid {
return cast(Pid) syscall(SYS_getpid)
}
// TODO(flysand): sendfile
/*
Transfer the data between file descriptors.
Available since Linux 2.2.
On 32-bit platforms available since Linux 2.6.
*/
sendfile :: proc "contextless" (out: Fd, in: Fd, offset: ^i64, count: uint) -> (int, Errno) {
when size_of(int) == 8 {
ret := syscall(SYS_sendfile, out, in, offset, count)
return errno_unwrap(ret, Errno)
} else {
ret := syscall(SYS_sendfile64, out, in, offset, count)
return errno_unwrap(ret, Errno)
}
}
/// Create a socket file descriptor
/// Available since Linux 2.0
@@ -377,10 +491,28 @@ recv :: proc {recvfrom, recv_noaddr}
/// Available since Linux 2.0
send :: proc {sendto, send_noaddr}
// TODO(flysand): sendmsg
/*
Send a message on a socket.
Available since Linux 2.0.
*/
sendmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) {
ret := syscall(SYS_sendmsg, sock, msghdr, transmute(i32) flags)
return errno_unwrap(ret, int)
}
// TODO(flysand): recvmsg
/*
Receive a message on a socket.
Available since Linux 2.0.
*/
recvmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) {
ret := syscall(SYS_recvmsg, sock, msghdr, transmute(i32) flags)
return errno_unwrap(ret, int)
}
/*
Shutdown a socket.
Available since Linux 2.0.
*/
shutdown :: proc "contextless" (sock: Fd, how: Shutdown_How) -> (Errno) {
ret := syscall(SYS_shutdown, sock, how)
return Errno(-ret)
@@ -405,11 +537,34 @@ listen :: proc "contextless" (sock: Fd, queue_len: i32) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): getsockname
/*
Get socket name (aka it's bound address).
Available since Linux 2.0.
*/
getsockname :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) {
addr_len := size_of(Sock_Addr_Any)
ret := syscall(SYS_getsockname, sock, addr, &addr_len)
return Errno(-ret)
}
// TODO(flysand): getpeername
/*
Get the name of the connected peer socket.
Available since Linux 2.0.
*/
getpeername :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) {
addr_len := size_of(Sock_Addr_Any)
ret := syscall(SYS_getpeername, sock, addr, &addr_len)
return Errno(-ret)
}
// TODO(flysand): socketpair
/*
Create a pair of connected sockets.
Available since Linux 2.0.
*/
socketpair :: proc "contextless" (domain: Protocol_Family, type: Socket_Type, proto: Protocol, pair: ^[2]Fd) -> (Errno) {
ret := syscall(SYS_socketpair, domain, type, proto, pair)
return Errno(-ret)
}
// TODO(flysand): the parameters are the same, maybe there's a way to make it into a single proc, sacrificing type
// safety slightly
@@ -518,9 +673,32 @@ fork :: proc "contextless" () -> (Pid, Errno) {
}
}
// TODO(flysand): vfork
/*
Create a child process and block parent.
Available since Linux 2.2.
*/
vfork :: proc "contextless" () -> Pid {
when ODIN_ARCH != .arm64 {
return Pid(syscall(SYS_vfork))
} else {
return Pid(syscall(SYS_fork))
}
}
// TODO(flysand): execve
/*
Replace the current process with another program.
Available since Linux 1.0.
On ARM64 available since Linux 3.19.
*/
execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) {
when ODIN_ARCH != .arm64 {
ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp)
return Errno(-ret)
} else {
ret := syscall(SYS_execveat, AT_FDCWD, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp)
return Errno(-ret)
}
}
/// Exit the thread with a given exit code
/// Available since Linux 1.0
@@ -539,7 +717,14 @@ wait4 :: proc "contextless" (pid: Pid, status: ^u32, options: Wait_Options) -> (
/// See wait4
waitpid :: wait4
// TODO(flysand): kill
/*
Send signal to a process.
Available since Linux 1.0.
*/
kill :: proc "contextless" (pid: Pid, signal: Signal) -> (Errno) {
ret := syscall(SYS_kill, pid, signal)
return Errno(-ret)
}
/// Get system information
/// Available since Linux 1.0
@@ -548,21 +733,84 @@ uname :: proc "contextless" (uts_name: ^UTS_Name) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): semget
/*
Get a SystemV semaphore set identifier.
Available since Linux 2.0.
*/
semget :: proc "contextless" (key: Key, n: i32, flags: IPC_Flags) -> (Key, Errno) {
ret := syscall(SYS_semget, key, n, transmute(i16) flags)
return errno_unwrap(ret, Key)
}
// TODO(flysand): semop
/*
SystemV semaphore operations.
Available since Linux 2.0.
*/
semop :: proc "contextless" (key: Key, ops: []Sem_Buf) -> (Errno) {
ret := syscall(SYS_semop, key, raw_data(ops), len(ops))
return Errno(-ret)
}
// TODO(flysand): semctl
semctl3 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd) -> (int, Errno) {
ret := syscall(SYS_semctl, key, semnum, cmd)
return errno_unwrap(ret, int)
}
// TODO(flysand): shmdt
semctl4 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd, semun: Sem_Un) -> (int, Errno) {
ret := syscall(SYS_semctl, key, semnum, cmd, semun)
return errno_unwrap(ret, int)
}
// TODO(flysand): msgget
/*
SystemV semaphore control operations.
Available since Linux 2.0.
*/
semctl :: proc {semctl3, semctl4}
// TODO(flysand): msgsnd
/*
SystemV shared memory operations.
Available since Linux 2.0.
*/
shmdt :: proc "contextless" (shmaddr: rawptr) -> (Errno) {
ret := syscall(SYS_shmdt, shmaddr)
return Errno(-ret)
}
// TODO(flysand): msgrcv
/*
Get SystemV message queue identifier.
Available since Linux 2.0.
*/
msgget :: proc "contextless" (key: Key, flags: IPC_Flags) -> (Key, Errno) {
ret := syscall(SYS_msgget, key, transmute(i16) flags)
return errno_unwrap(ret, Key)
}
// TODO(flysand): msgctl
/*
Send message to a SystemV message queue.
Available since Linux 2.0.
*/
msgsnd :: proc "contextless" (key: Key, buf: rawptr, size: int, flags: IPC_Flags) -> (Errno) {
ret := syscall(SYS_msgsnd, key, buf, size, transmute(i16) flags)
return Errno(-ret)
}
/*
Receive a message from a SystemV message queue.
Available since Linux 2.0.
*/
msgrcv :: proc "contextless" (key: Key, buf: rawptr, size: int, type: uint, flags: IPC_Flags) -> (int, Errno) {
ret := syscall(SYS_msgrcv, key, buf, size, type, transmute(i16) flags)
return errno_unwrap(ret, int)
}
/*
SystemV message control operations.
Available since Linux 2.0.
*/
msgctl :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Msqid_DS) -> (int, Errno) {
ret := syscall(SYS_msgctl, key, cmd, buf)
return errno_unwrap(ret, int)
}
fcntl_dupfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD, newfd: Fd) -> (Fd, Errno) {
ret := syscall(SYS_fcntl, fd, cmd, newfd)
@@ -726,7 +974,14 @@ fcntl :: proc {
fcntl_set_file_rw_hint,
}
// TODO(flysand): flock
/*
Apply or remove advisory lock on an open file.
Available since Linux 2.0.
*/
flock :: proc "contextless" (fd: Fd, operation: FLock_Op) -> (Errno) {
ret := syscall(SYS_flock, fd, transmute(i32) operation)
return Errno(-ret)
}
/// Sync state of the file with the storage device
fsync :: proc "contextless" (fd: Fd) -> (Errno) {
@@ -734,7 +989,15 @@ fsync :: proc "contextless" (fd: Fd) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): fdatasync
/*
Synchronize the state of the file with the storage device. Similar to `fsync`,
except does not flush the metadata.
Available since Linux 2.0.
*/
fdatasync :: proc "contextless" (fd: Fd) -> (Errno) {
ret := syscall(SYS_fdatasync, fd)
return Errno(-ret)
}
/// Truncate a file to specified length
/// On 32-bit architectures available since Linux 2.4
@@ -828,7 +1091,19 @@ rmdir :: proc "contextless" (name: cstring) -> (Errno) {
}
}
// TODO(flysand): creat
/*
Create a file.
Available since Linux 1.0.
On ARM64 available since Linux 2.6.16.
*/
creat :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
when ODIN_ARCH == .arm64 {
return openat(AT_FDCWD, name, {.CREAT, .WRONLY,.TRUNC}, mode)
} else {
ret := syscall(SYS_creat, cast(rawptr) name, transmute(u32) mode)
return Errno(-ret)
}
}
/// Create a hard link on a file
/// Available since Linux 1.0
@@ -949,9 +1224,23 @@ lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) {
}
}
// TODO(flysand): umask
/*
Set file mode creation mask.
Available since Linux 1.0.
*/
umask :: proc "contextless" (mask: Mask) -> Mask {
ret := syscall(SYS_umask, transmute(u32) mask)
return transmute(u32) cast(u32) ret
}
// TODO(flysand): gettimeofday
/*
Get current time.
Available since Linux 1.0.
*/
gettimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) {
ret := syscall(SYS_gettimeofday, tv)
return Errno(-ret)
}
/// Get limits on resources
/// Available since Linux 1.0
@@ -980,7 +1269,97 @@ times :: proc "contextless" (tms: ^Tms) -> (Errno) {
return Errno(-ret)
}
// TODO(flysand): ptrace
ptrace_traceme :: proc "contextless" (rq: PTrace_Traceme_Type) -> (Errno) {
ret := syscall(SYS_ptrace, rq)
return Errno(-ret)
}
ptrace_peek :: proc "contextless" (rq: PTrace_Peek_Type, addr: uintptr) -> (uint, Errno) {
ret := syscall(SYS_ptrace, rq, addr)
return errno_unwrap(rq, uint)
}
ptrace_poke :: proc "contextless" (rq: PTrace_Poke_Type, addr: uintptr, data: uint) -> (Errno) {
ret := syscall(SYS_ptrace, rq, addr, data)
return Errno(-ret)
}
ptrace_getregs :: proc "contextless" (rq: PTrace_Getregs_Type, buf: ^User_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
ptrace_getfpregs :: proc "contextless" (rq: PTrace_Getfpregs_Type, buf: ^User_FP_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
ptrace_getfpxregs :: proc "contextless" (rq: PTrace_Getfpxregs_Type, buf: ^User_FPX_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
ptrace_setregs :: proc "contextless" (rq: PTrace_Setregs_Type, buf: ^User_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
ptrace_setfpregs :: proc "contextless" (rq: PTrace_Setfpregs_Type, buf: ^User_FP_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
ptrace_setfpxregs :: proc "contextless" (rq: PTrace_Setfpxregs_Type, buf: ^User_FPX_Regs) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, buf)
return Errno(-ret)
}
// TODO(flysand): ptrace_getregset
// TODO(flysand): ptrace_setregset
// TODO(flysand): ptrace_setsiginfo
// TODO(flysand): ptrace_peeksiginfo
// TODO(flysand): ptrace_getsigmask
// TODO(flysand): ptrace_setsigmask
ptrace_setoptions :: proc "contextless" (rq: PTrace_Setoptions_Type, options: PTrace_Options) -> (Errno) {
ret := syscall(SYS_ptrace, rq, 0, transmute(u32) options)
return Errno(-ret)
}
// TODO(flysand): ptrace_geteventmsg
// TODO(flysand): ptrace_cont
// TODO(flysand): ptrace_syscall
// TODO(flysand): ptrace_singlestep
// TODO(flysand): ptrace_set_syscall
// TODO(flysand): ptrace_sysemu
// TODO(flysand): ptrace_sysemu_singlestep
// TODO(flysand): ptrace_listen
// TODO(flysand): ptrace_kill
// TODO(flysand): ptrace_interrupt
// TODO(flysand): ptrace_attach
// TODO(flysand): ptrace_seize
// TODO(flysand): ptrace_seccomp_get_filter
// TODO(flysand): ptrace_detach
// TODO(flysand): ptrace_get_thread_area
// TODO(flysand): ptrace_set_thread_area
// TODO(flysand): ptrace_get_syscall_info
// TODO(flysand): ptrace_setsigmask
/*
Trace process
*/
ptrace :: proc {
ptrace_traceme,
peek,
ptrace_poke,
ptrace_getregs,
ptrace_getfpregs,
ptrace_getfpxregs,
ptrace_setregs,
ptrace_setfpregs,
ptrace_setfpxregs,
ptrace_setoptions,
}
/// Get real user ID
/// Available since Linux 1.0
@@ -1186,8 +1565,6 @@ getpgid :: proc "contextless" (pid: Pid) -> (Pid, Errno) {
return errno_unwrap(ret, Pid)
}
// NOTE(flysand): setfsuid and setfsgid are deprecated
/// Get session ID of the calling process
/// Available since Linux 2.0
getsid :: proc "contextless" (pid: Pid) -> (Pid, Errno) {
@@ -1234,8 +1611,6 @@ sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) ->
return Errno(-ret)
}
// TODO(flysand): utime
/// Create a special or ordinary file
/// `mode` parameter contains both the the file mode and the type of the node to create
/// -> Add one of S_IFSOCK, S_IFBLK, S_IFFIFO, S_IFCHR to mode
@@ -1251,8 +1626,6 @@ mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) {
}
}
// TODO(flysand): uselib
/// Set the process execution domain
/// Available since Linux 1.2
personality :: proc "contextless" (personality: uint) -> (uint, Errno) {
@@ -1414,16 +1787,10 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) {
// TODO(flysand): ioperm
// TODO(flysand): create_module
// TODO(flysand): init_module
// TODO(flysand): delete_module
// TODO(flysand): get_kernel_syms
// TODO(flysand): query_module
// TODO(flysand): quotactl
// TODO(flysand): nfsservctl
@@ -1474,9 +1841,14 @@ gettid :: proc "contextless" () -> Pid {
// TODO(flysand): fremovexattr
// TODO(flysand): tkill
// TODO(flysand): time
/*
Get current time in seconds.
Available since Linux 1.0.
*/
time :: proc "contextless" (tloc: ^uint) -> (Errno) {
ret := syscall(SYS_time, tloc)
return Errno(-ret)
}
/// Wait on a futex until it's signaled
futex_wait :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Type, flags: Futex_Flags, val: u32, timeout: ^Time_Spec = nil) -> (Errno) {
@@ -1593,8 +1965,6 @@ set_tid_address :: proc "contextless" (tidptr: ^u32) {
syscall(SYS_set_tid_address, tidptr)
}
// TODO(flysand): restart_syscall
// TODO(flysand): semtimedop
// TODO(flysand): fadvise64
@@ -1847,7 +2217,6 @@ dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno)
// TODO(flysand): pwritev
/// Send signal information to a thread
/// Available since Linux 2.2
rt_tgsigqueueinfo :: proc "contextless" (tgid: Pid, pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) {
@@ -1862,7 +2231,14 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in
return errno_unwrap(ret, Fd)
}
// TODO(flysand): recvmmsg
/*
Receive multiple messages from a socket.
Available since Linux 2.6.33.
*/
recvmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) {
ret := syscall(SYS_recvmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags)
return errno_unwrap(ret, int)
}
// TODO(flysand): fanotify_init
@@ -1878,7 +2254,14 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in
// TODO(flysand): syncfs
// TODO(flysand): sendmmsg
/*
Send multiple messages on a socket.
Available since Linux 3.0.
*/
sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) {
ret := syscall(SYS_sendmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags)
return errno_unwrap(ret, int)
}
// TODO(flysand): setns

View File

@@ -26,6 +26,9 @@ Pid_FD :: distinct i32
/// Used pretty much only in struct Stat64 for 32-bit platforms
Inode :: distinct u64
/// Shared memory identifiers used by `shm*` calls
Key :: distinct i32
/// Represents time with nanosecond precision
Time_Spec :: struct {
time_sec: uint,
@@ -38,6 +41,15 @@ Time_Val :: struct {
microseconds: int,
}
/*
Access and modification times for files
*/
UTim_Buf :: struct {
actime: uint,
modtime: uint,
};
/// open.2 flags
Open_Flags :: bit_set[Open_Flags_Bits; u32]
@@ -235,6 +247,13 @@ FLock :: struct {
pid: Pid,
}
/*
File locking operations.
Use one of `EX`, `RW` or `UN` to specify the operation, and add `UN` if
you need a non-blocking operation.
*/
FLock_Op :: bit_set[FLock_Op_Bits; i32]
/// Flags for fcntl_notify
FD_Notifications :: bit_set[FD_Notifications_Bits; i32]
@@ -496,6 +515,25 @@ Sock_Addr_Any :: struct #raw_union {
using ipv6: Sock_Addr_In6,
}
/*
Message header for sendmsg/recvmsg
*/
Msg_Hdr :: struct {
name: rawptr,
namelen: i32,
iov: []IO_Vec, // ptr followed by length, abi matches
control: []u8,
flags: Socket_Msg,
};
/*
Multiple message header for sendmmsg/recvmmsg
*/
MMsg_Hdr :: struct {
hdr: Msg_Hdr,
len: u32,
}
/// Just an alias to make futex-values more visible
Futex :: u32
@@ -564,3 +602,417 @@ RUsage :: struct {
nvcsw_word: int,
nivcsw_word: int,
}
/*
Struct used for IO operations
*/
IO_Vec :: struct {
base: rawptr,
len: uint,
}
/*
Access mode for shared memory
*/
IPC_Mode :: bit_set[IPC_Mode; u32]
/*
Flags used by IPC objects
*/
IPC_Flags :: bit_set[IPC_Flags_Bits; i16]
/*
Permissions for IPC objects
*/
IPC_Perm :: struct {
key: Key,
uid: u32,
gid: u32,
cuid: u32,
cgid: u32,
mode: IPC_Mode,
seq: u16,
_: [2 + 2*size_of(int)],
}
when size_of(int) == 8 || ODIN_ARCH == .i386 {
// 32-bit and 64-bit x86, 64-bit arm
_Arch_Shmid_DS :: struct {
perm: IPC_Perm,
segsz: uint,
atime: int,
dtime: int,
ctime: int,
cpid: Pid,
lpid: Pid,
nattch: uint,
_: [2]uint,
}
} else {
// Other 32-bit platforms
// NOTE(flysand): I'm not risking assuming it's little endian...
_Arch_Shmid_DS :: struct {
perm: IPC_Perm,
segsz: uint,
atime: uint,
atime_high: uint,
dtime: uint,
dtime_high: uint,
ctime: uint,
ctime_high: uint,
cpid: Pid,
lpid: Pid,
nattach: uint,
_: [2]uint,
}
}
/*
SystemV shared memory data.
*/
Shmid_DS :: _Arch_Shmid_DS
/*
SystemV shared memory info.
*/
Shm_Info :: struct {
used_ids: i32
shm_tot: uint,
shm_rss: uint,
shm_swp: uint,
swap_attempts: uint,
swap_successes: uint,
}
/*
SystemV semaphore operation.
*/
Sem_Buf :: struct {
num: u16,
op: IPC_Cmd,
flg: IPC_Flags,
}
when ODIN_ARCH == .i386 {
_Arch_Semid_DS :: struct {
perm: IPC_Perm,
otime: uint,
otime_high: uint,
ctime: uint,
ctime_high: uint,
nsems: uint,
_: [2]uint,
}
else when ODIN_ARCH == .amd64 {
_Arch_Semid_DS :: struct {
perm: IPC_Perm,
otime: int,
ctime: int,
nsems: uint,
_: [2]uint,
}
} else when ODIN_ARCH == .amd32 {
_Arch_Semid_DS :: struct {
perm: IPC_Perm,
otime: uint,
otime_high: uint,
ctime: uint,
ctime_high: uint,
nsems: uint,
_: [2]uint,
}
} else when ODIN_ARCH == .amd64 {
_Arch_Semid_DS :: struct {
perm: IPC_Perm,
otime: int,
ctime: int,
sem_nsems: uint,
__unused3: uint,
__unused4: uint,
}
}
/*
Architecture-specific semaphore data.
*/
Semid_DS :: _Arch_Semid_DS
/*
Argument for semctl functions
*/
Sem_Un :: struct #raw_union {
val: i32,
buf: rawptr,
array: u16,
__buf: Sem_Info,
_: uintptr,
}
/*
SystenV semaphore info.
*/
Sem_Info {
map: i32,
mni: i32,
mns: i32,
mnu: i32,
msl: i32,
opm: i32,
ume: i32,
usz: i32,
vmx: i32,
aem: i32,
}
/*
Template for the struct used for sending and receiving messages
*/
Msg_Buf :: struct {
type: int,
text: [0]u8,
}
/*
SystemV message queue data.
*/
struct Msqid_DS {
perm: IPC_Perm,
stime: uint,
rtime: uint,
ctime: uint,
cbytes: uint,
qnum: uint,
qbytes: uint,
lspid: Pid,
lrpid: Pid,
_: [2]uint
};
/*
Interval timer types
*/
ITimer_Which :: enum {
REAL = 0,
VIRTUAL = 1,
PROF = 2,
}
/*
Interval timer value
*/
ITimer_Val :: struct {
interval: Time_Val,
value: Time_Val,
}
when ODIN_ARCH == .arm32 {
_Arch_User_Regs :: struct {
cpsr: uint,
pc: uint,
lr: uint,
sp: uint,
ip: uint,
fp: uint,
r10: uint,
r9: uint,
r8: uint,
r7: uint,
r6: uint,
r5: uint,
r4: uint,
r3: uint,
r2: uint,
r1: uint,
r0: uint,
ORIG_r0: uint,
}
// TODO(flysand): Idk what to do about these, couldn't find their
// definitions
_Arch_User_FP_Regs :: struct {}
_Arch_User_FPX_Regs :: struct {}
} else when ODIN_ARCH == .arm64 {
_Arch_User_Regs :: struct {
regs: [31]uint,
sp: uint,
pc: uint,
pstate: uint,
}
_Arch_User_FP_Regs :: struct {
vregs: [32]u128,
fpsr: u32,
fpcr: u32,
_: [2]u32
}
_Arch_User_FPX_Regs :: struct {}
} else when ODIN_ARCH == .i386 {
_Arch_User_Regs :: struct {
ebx: uint,
ecx: uint,
edx: uint,
esi: uint,
edi: uint,
ebp: uint,
eax: uint,
xds: uint,
xes: uint,
xfs: uint,
xgs: uint,
orig_eax: uint,
eip: uint,
xcs: uint,
eflags: uint,
esp: uint,
xss: uint,
}
// x87 FPU state
_Arch_User_FP_Regs :: struct {
cwd: uint,
swd: uint,
twd: uint,
fip: uint,
fcs: uint,
foo: uint,
fos: uint,
st_space: [20]uint,
}
// FXSR instruction set state
_Arch_User_FPX_Regs :: struct {
cwd: u16,
swd: u16,
twd: u16,
fop: u16,
fip: uint,
fcs: uint,
foo: uint,
fos: uint,
mxcsr: uint,
_: uint,
st_space: [32]uint,
xmm_space: [32]uint,
padding: [56]uint,
}
} else when ODIN_ARCH == .amd64 {
_Arch_User_Regs {
// Callee-preserved, may not be correct if the syscall doesn't need
// these registers
r15: uint,
r14: uint,
r13: uint,
r12: uint,
rbp: uint,
rbx: uint,
// Always saved
r11: uint,
r10: uint,
r9: uint,
r8: uint,
rax: uint,
rcx: uint,
rdx: uint,
rsi: uint,
rdi: uint,
// On syscall entry this is the syscall number, on CPU exception this
// is the error code, on hardware interrupt this is its IRQ number
orig_rax: uint,
// Return frame for iretq
rip: uint,
cs: uint,
eflags: uint,
rsp: uint,
ss: uint,
}
// All floating point state
_Arch_User_FP_Regs :: struct {
cwd: u16,
swd: u16,
twd: u16,
fop: u16,
rip: uint,
rdp: uint,
mxcsr: u32,
mxcsr_mask: u32,
st_space: [32]u32,
xmm_space: [64]u32,
_: [24]u32;
}
}
/*
Architecture-specific registers struct.
*/
User_Regs :: _Arch_User_Regs
/*
Architecture-specific floating-point registers
*/
User_FP_Regs :: _Arch_User_FP_Regs
/*
Architecture-specific extended floating-point registers.
Currently only used for x86 CPU's.
*/
User_FPX_Regs :: _Arch_User_FPX_Regs
/*
ptrace options.
*/
PTrace_Options :: bit_set[PTrace_Options_Bits; u32]
/*
ptrace's PEEKSIGINFO argument.
*/
PTrace_Peek_Sig_Info_Args :: struct {
off: u64,
flags: PTrace_Peek_Sig_Info_Flags,
nr: i32,
}
/*
ptrace's PEEKSIGINFO flags.
*/
PTrace_Peek_Sig_Info_Flags :: bit_set[PTrace_Peek_Sig_Info_Flags_Bits, u32]
/*
ptrace's SECCOMP metadata.
*/
PTrace_Seccomp_Metadata
{
filter_off: u64,
flags: u64,
}
/*
ptrace's results of GET_SYSCALL_INFO.
*/
PTrace_Syscall_Info :: struct {
op: PTrace_Get_Syscall_Info_Op,
arch: u32, // TODO: AUDIT_ARCH*
instruction_pointer: u64,
stack_pointer: u64,
using _: struct #raw_union {
entry: struct {
nr: u64,
args: [6]u64,
},
exit: struct {
rval: i64,
is_error: b8,
},
seccomp: struct {
nr: u64,
args: [6]u64,
ret_data: u32,
},
};
};
/*
ptrace's results of GET_RSEQ_CONFIGURATION.
*/
PTrace_RSeq_Configuration {
rseq_abi_pointer: u64,
rseq_abi_size: u32,
signature: u32,
flags: u32,
_: u32,
};