From 4d65b1ab9cb86bcbbfb0e5b26e3552f6f3582004 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Wed, 18 Oct 2023 01:57:26 +1100 Subject: Implement new sys/unix package --- core/sys/linux/bits.odin | 1400 +++++++++++++++++++++++++ core/sys/linux/constants.odin | 199 ++++ core/sys/linux/helpers.odin | 150 +++ core/sys/linux/sys.odin | 2038 +++++++++++++++++++++++++++++++++++++ core/sys/linux/syscall_amd64.odin | 373 +++++++ core/sys/linux/syscall_arm32.odin | 470 +++++++++ core/sys/linux/syscall_arm64.odin | 321 ++++++ core/sys/linux/syscall_i386.odin | 458 +++++++++ core/sys/linux/types.odin | 566 ++++++++++ core/sys/linux/wrappers.odin | 121 +++ 10 files changed, 6096 insertions(+) create mode 100644 core/sys/linux/bits.odin create mode 100644 core/sys/linux/constants.odin create mode 100644 core/sys/linux/helpers.odin create mode 100644 core/sys/linux/sys.odin create mode 100644 core/sys/linux/syscall_amd64.odin create mode 100644 core/sys/linux/syscall_arm32.odin create mode 100644 core/sys/linux/syscall_arm64.odin create mode 100644 core/sys/linux/syscall_i386.odin create mode 100644 core/sys/linux/types.odin create mode 100644 core/sys/linux/wrappers.odin (limited to 'core/sys/linux') diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin new file mode 100644 index 000000000..b6b22dfdb --- /dev/null +++ b/core/sys/linux/bits.odin @@ -0,0 +1,1400 @@ +package linux + + +/// Represents an error returned by most of syscalls +Errno :: enum i32 { + NONE = 0, + // Errno-base + EPERM = 1, + ENOENT = 2, + ESRCH = 3, + EINTR = 4, + EIO = 5, + ENXIO = 6, + E2BIG = 7, + ENOEXEC = 8, + EBADF = 9, + ECHILD = 10, + EAGAIN = 11, + ENOMEM = 12, + EACCES = 13, + EFAULT = 14, + ENOTBLK = 15, + EBUSY = 16, + EEXIST = 17, + EXDEV = 18, + ENODEV = 19, + ENOTDIR = 20, + EISDIR = 21, + EINVAL = 22, + ENFILE = 23, + EMFILE = 24, + ENOTTY = 25, + ETXTBSY = 26, + EFBIG = 27, + ENOSPC = 28, + ESPIPE = 29, + EROFS = 30, + EMLINK = 31, + EPIPE = 32, + EDOM = 33, + ERANGE = 34, + // Linux + EDEADLK = 35, + ENAMETOOLONG = 36, + ENOLCK = 37, + ENOSYS = 38, + ENOTEMPTY = 39, + ELOOP = 40, + ENOMSG = 42, + EIDRM = 43, + ECHRNG = 44, + EL2NSYNC = 45, + EL3HLT = 46, + EL3RST = 47, + ELNRNG = 48, + EUNATCH = 49, + ENOCSI = 50, + EL2HLT = 51, + EBADE = 52, + EBADR = 53, + EXFULL = 54, + ENOANO = 55, + EBADRQC = 56, + EBADSLT = 57, + EBFONT = 59, + ENOSTR = 60, + ENODATA = 61, + ETIME = 62, + ENOSR = 63, + ENONET = 64, + ENOPKG = 65, + EREMOTE = 66, + ENOLINK = 67, + EADV = 68, + ESRMNT = 69, + ECOMM = 70, + EPROTO = 71, + EMULTIHOP = 72, + EDOTDOT = 73, + EBADMSG = 74, + EOVERFLOW = 75, + ENOTUNIQ = 76, + EBADFD = 77, + EREMCHG = 78, + ELIBACC = 79, + ELIBBAD = 80, + ELIBSCN = 81, + ELIBMAX = 82, + ELIBEXEC = 83, + EILSEQ = 84, + ERESTART = 85, + ESTRPIPE = 86, + EUSERS = 87, + ENOTSOCK = 88, + EDESTADDRREQ = 89, + EMSGSIZE = 90, + EPROTOTYPE = 91, + ENOPROTOOPT = 92, + EPROTONOSUPPORT = 93, + ESOCKTNOSUPPORT = 94, + EOPNOTSUPP = 95, + EPFNOSUPPORT = 96, + EAFNOSUPPORT = 97, + EADDRINUSE = 98, + EADDRNOTAVAIL = 99, + ENETDOWN = 100, + ENETUNREACH = 101, + ENETRESET = 102, + ECONNABORTED = 103, + ECONNRESET = 104, + ENOBUFS = 105, + EISCONN = 106, + ENOTCONN = 107, + ESHUTDOWN = 108, + ETOOMANYREFS = 109, + ETIMEDOUT = 110, + ECONNREFUSED = 111, + EHOSTDOWN = 112, + EHOSTUNREACH = 113, + EALREADY = 114, + EINPROGRESS = 115, + ESTALE = 116, + EUCLEAN = 117, + ENOTNAM = 118, + ENAVAIL = 119, + EISNAM = 120, + EREMOTEIO = 121, + EDQUOT = 122, + ENOMEDIUM = 123, + EMEDIUMTYPE = 124, + ECANCELED = 125, + ENOKEY = 126, + EKEYEXPIRED = 127, + EKEYREVOKED = 128, + EKEYREJECTED = 129, + EOWNERDEAD = 130, + ENOTRECOVERABLE = 131, + ERFKILL = 132, + EHWPOISON = 133, + // Errno aliases + EWOULDBLOCK = EAGAIN, + EDEADLOCK = EDEADLK, +} + + +/// Bits for Open_Flags +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, +} + +/// Bits for FD_Flags bitset +FD_Flags_Bits :: enum { + SYMLINK_NOFOLLOW = 8, + REMOVEDIR = 9, + EACCESS = 9, + SYMLINK_FOLLOW = 10, + NO_AUTOMOUNT = 11, + EMPTY_PATH = 12, + STATX_FORCE_SYNC = 13, + STATX_DONT_SYNC = 14, + RECURSIVE = 15, +} + +/// The bits for the Mode bitset. +Mode_Bits :: enum { + IXOTH = 0, // 0o0000001 + IWOTH = 1, // 0o0000002 + IROTH = 2, // 0o0000004 + IXGRP = 3, // 0o0000010 + IWGRP = 4, // 0o0000020 + IRGRP = 5, // 0o0000040 + IXUSR = 6, // 0o0000100 + IWUSR = 7, // 0o0000200 + IRUSR = 8, // 0o0000400 + ISVTX = 9, // 0o0001000 + ISGID = 10, // 0o0002000 + ISUID = 11, // 0o0004000 + IFFIFO = 12, // 0o0010000 + IFCHR = 13, // 0o0020000 + IFDIR = 14, // 0o0040000 + IFREG = 15, // 0o0100000 +} + +/// The bits used by the Statx_Mask bitset +Statx_Mask_Bits :: enum { + TYPE = 0, + MODE = 1, + NLINK = 2, + UID = 3, + GID = 4, + ATIME = 5, + MTIME = 6, + CTIME = 7, + INO = 8, + SIZE = 9, + BLOCKS = 10, + BTIME = 11, + MNT_ID = 12, + DIOALIGN = 13, +} + +/// Bits found in Statx_Attr bitset +/// You should not use these directly +Statx_Attr_Bits :: enum { + COMPRESSED = 2, // 0x00000004 + IMMUTABLE = 4, // 0x00000010 + APPEND = 5, // 0x00000020 + NODUMP = 6, // 0x00000040 + ENCRYPTED = 11, // 0x00000800 + AUTOMOUNT = 12, // 0x00001000 + MOUNT_ROOT = 13, // 0x00002000 + VERITY = 20, // 0x00100000 + DAX = 21, // 0x00200000 +} + +/// Magic bits for filesystems returned by Stat_FS +FS_Magic :: enum u32 { + ADFS_SUPER_MAGIC = 0xadf5, + AFFS_SUPER_MAGIC = 0xadff, + AFS_SUPER_MAGIC = 0x5346414f, + ANON_INODE_FS_MAGIC = 0x09041934, + AUTOFS_SUPER_MAGIC = 0x0187, + BDEVFS_MAGIC = 0x62646576, + BEFS_SUPER_MAGIC = 0x42465331, + BFS_MAGIC = 0x1badface, + BINFMTFS_MAGIC = 0x42494e4d, + BPF_FS_MAGIC = 0xcafe4a11, + BTRFS_SUPER_MAGIC = 0x9123683e, + BTRFS_TEST_MAGIC = 0x73727279, + CGROUP_SUPER_MAGIC = 0x27e0eb, + CGROUP2_SUPER_MAGIC = 0x63677270, + CIFS_MAGIC_NUMBER = 0xff534d42, + CODA_SUPER_MAGIC = 0x73757245, + COH_SUPER_MAGIC = 0x012ff7b7, + CRAMFS_MAGIC = 0x28cd3d45, + DEBUGFS_MAGIC = 0x64626720, + DEVFS_SUPER_MAGIC = 0x1373, + DEVPTS_SUPER_MAGIC = 0x1cd1, + ECRYPTFS_SUPER_MAGIC = 0xf15f, + EFIVARFS_MAGIC = 0xde5e81e4, + EFS_SUPER_MAGIC = 0x00414a53, + EXT_SUPER_MAGIC = 0x137d, + EXT2_OLD_SUPER_MAGIC = 0xef51, + EXT2_SUPER_MAGIC = 0xef53, + EXT3_SUPER_MAGIC = 0xef53, + EXT4_SUPER_MAGIC = 0xef53, + F2FS_SUPER_MAGIC = 0xf2f52010, + FUSE_SUPER_MAGIC = 0x65735546, + FUTEXFS_SUPER_MAGIC = 0xbad1dea, + HFS_SUPER_MAGIC = 0x4244, + HOSTFS_SUPER_MAGIC = 0x00c0ffee, + HPFS_SUPER_MAGIC = 0xf995e849, + HUGETLBFS_MAGIC = 0x958458f6, + ISOFS_SUPER_MAGIC = 0x9660, + JFFS2_SUPER_MAGIC = 0x72b6, + JFS_SUPER_MAGIC = 0x3153464a, + MINIX_SUPER_MAGIC = 0x137f, + MINIX_SUPER_MAGIC2 = 0x138f, + MINIX2_SUPER_MAGIC = 0x2468, + MINIX2_SUPER_MAGIC2 = 0x2478, + MINIX3_SUPER_MAGIC = 0x4d5a, + MQUEUE_MAGIC = 0x19800202, + MSDOS_SUPER_MAGIC = 0x4d44, + MTD_INODE_FS_MAGIC = 0x11307854, + NCP_SUPER_MAGIC = 0x564c, + NFS_SUPER_MAGIC = 0x6969, + NILFS_SUPER_MAGIC = 0x3434, + NSFS_MAGIC = 0x6e736673, + NTFS_SB_MAGIC = 0x5346544e, + OCFS2_SUPER_MAGIC = 0x7461636f, + OPENPROM_SUPER_MAGIC = 0x9fa1, + OVERLAYFS_SUPER_MAGIC = 0x794c7630, + PIPEFS_MAGIC = 0x50495045, + PROC_SUPER_MAGIC = 0x9fa0, + PSTOREFS_MAGIC = 0x6165676c, + QNX4_SUPER_MAGIC = 0x002f, + QNX6_SUPER_MAGIC = 0x68191122, + RAMFS_MAGIC = 0x858458f6, + REISERFS_SUPER_MAGIC = 0x52654973, + ROMFS_MAGIC = 0x7275, + SECURITYFS_MAGIC = 0x73636673, + SELINUX_MAGIC = 0xf97cff8c, + SMACK_MAGIC = 0x43415d53, + SMB_SUPER_MAGIC = 0x517b, + SMB2_MAGIC_NUMBER = 0xfe534d42, + SOCKFS_MAGIC = 0x534f434b, + SQUASHFS_MAGIC = 0x73717368, + SYSFS_MAGIC = 0x62656572, + SYSV2_SUPER_MAGIC = 0x012ff7b6, + SYSV4_SUPER_MAGIC = 0x012ff7b5, + TMPFS_MAGIC = 0x01021994, + TRACEFS_MAGIC = 0x74726163, + UDF_SUPER_MAGIC = 0x15013346, + UFS_MAGIC = 0x00011954, + USBDEVICE_SUPER_MAGIC = 0x9fa2, + V9FS_MAGIC = 0x01021997, + VXFS_SUPER_MAGIC = 0xa501fcf5, + XENFS_SUPER_MAGIC = 0xabba1974, + XENIX_SUPER_MAGIC = 0x012ff7b4, + XFS_SUPER_MAGIC = 0x58465342, + _XIAFS_SUPER_MAGIC = 0x012fd16d, +} + +/// Bits for FS_Flags bitset +FS_Flags_Bits :: enum { + RDONLY = 0, + NOSUID = 1, + NODEV = 2, + NOEXEC = 3, + SYNCHRONOUS = 4, + VALID = 5, + MANDLOCK = 6, + NOATIME = 10, + NODIRATIME = 11, + RELATIME = 12, + NOSYMFOLLOW = 13, +} + +Seek_Whence :: enum i16 { + SET = 0, + CUR = 1, + END = 2, + DATA = 3, + HOLE = 4, +} + +/// Bits for Close_Range_Flags +Close_Range_Flags_Bits :: enum { + CLOEXEC = 2, + UNSHARE = 1, +} + +/// Bits for Rename_Flags +Rename_Flags_Bits :: enum { + EXCHANGE = 1, + NOREPLACE = 0, + WHITEOUT = 2, +} + +/// Type of the file in a directory entry +Dirent_Type :: enum u8 { + UNKNOWN = 0, + FIFO = 1, + CHR = 2, + DIR = 4, + BLK = 6, + REG = 8, + LNK = 10, + SOCK = 12, + WHT = 14, +} + +/// Type of a lock for fcntl.2 +FLock_Type :: enum i16 { + RDLCK = 0, + WRLCK = 1, + UNLCK = 2, +} + +/// Bits for FD_Notifications +FD_Notifications_Bits :: enum { + ACCESS = 0, + MODIFY = 1, + CREATE = 2, + DELETE = 3, + RENAME = 4, + ATTRIB = 5, + MULTISHOT = 31, +} + +/// Bits for seal +Seal_Bits :: enum { + SEAL = 0, + SHRINK = 1, + GROW = 2, + WRITE = 3, + FUTURE_WRITE = 4, +} + +RW_Hint :: enum u64 { + WRITE_LIFE_NOT_SET = 0, + WRITE_LIFE_NONE = 1, + WRITE_LIFE_SHORT = 2, + WRITE_LIFE_MEDIUM = 3, + WRITE_LIFE_LONG = 4, + WRITE_LIFE_EXTREME = 5, +} + +FD_Lease :: enum { + RDLCK = 0, + WRLCK = 1, + UNLCK = 2, +} + +/// Kind of owner for FD_Owner +F_Owner_Type :: enum i32 { + OWNER_TID = 0, + OWNER_PID = 1, + OWNER_PGRP = 2, +} + +/// Command for fcntl.2 +FCntl_Command :: enum { + DUPFD = 0, + GETFD = 1, + SETFD = 2, + GETFL = 3, + SETFL = 4, + GETLK = 5, + SETLK = 6, + SETLKW = 7, + SETOWN = 8, + GETOWN = 9, + SETSIG = 10, + GETSIG = 11, + SETOWN_EX = 15, + GETOWN_EX = 16, + // OFD_GETLK = 36, + // OFD_SETLK = 37, + // OFD_SETLKW = 38, + SETLEASE = 1024, + GETLEASE = 1025, + NOTIFY = 1026, + DUPFD_CLOEXEC = 1030, + SETPIPE_SZ = 1031, + GETPIPE_SZ = 1032, + ADD_SEALS = 1033, + GET_SEALS = 1034, + GET_RW_HINT = 1035, + SET_RW_HINT = 1036, + GET_FILE_RW_HINT = 1037, + SET_FILE_RW_HINT = 1038, + // F_OK = 0, +} + +Fd_Poll_Events_Bits :: enum { + IN = 0, + PRI = 1, + OUT = 2, + ERR = 3, + HUP = 4, + NVAL = 5, + RDNORM = 6, + RDBAND = 7, + WRNORM = 8, + WRBAND = 9, + MSG = 10, + REMOVE = 12, + RDHUP = 13, +} + +/// Bits for Mem_Protection bitfield +Mem_Protection_Bits :: enum{ + READ = 0, + WRITE = 1, + EXEC = 2, + SEM = 3, + // platform-specific section start + ARM64_BTI = 4, + ARM64_MTE = 5, + // platform-specific section end + GROWSDOWN = 24, + GROWSUP = 25, +} + +/// Bits for Map_Flags +Map_Flags_Bits :: enum { + SHARED = 0, + PRIVATE = 1, + SHARED_VALIDATE = 2, + FIXED = 4, + ANONYMOUS = 5, + // platform-dependent section start + X86_32BIT = 6, + X86_ABOVE4G = 7, + // platform-dependent section end + GROWSDOWN = 8, + DENYWRITE = 11, + EXECUTABLE = 12, + LOCKED = 13, + NORESERVE = 14, + POPULATE = 15, + NONBLOCK = 16, + STACK = 17, + HUGETLB = 18, + SYNC = 19, + FIXED_NOREPLACE = 20, + UNINITIALIZED = 26, +} + +/// Bits for MLock_Flags +MLock_Flags_Bits :: enum { + ONFAULT = 0, +} + +/// Bits for MSync_Flags +MSync_Flags_Bits :: enum { + ASYNC = 0, + INVALIDATE = 1, + SYNC = 2, +} + +/// Argument for madvice.2 +MAdvice :: enum { + NORMAL = 0, + RANDOM = 1, + SEQUENTIAL = 2, + WILLNEED = 3, + DONTNEED = 4, + FREE = 8, + REMOVE = 9, + DONTFORK = 10, + DOFORK = 11, + MERGEABLE = 12, + UNMERGEABLE = 13, + HUGEPAGE = 14, + NOHUGEPAGE = 15, + DONTDUMP = 16, + DODUMP = 17, + WIPEONFORK = 18, + KEEPONFORK = 19, + COLD = 20, + PAGEOUT = 21, + POPULATE_READ = 22, + POPULATE_WRITE = 23, + DONTNEED_LOCKED = 24, + COLLAPSE = 25, + HWPOISON = 100, + SOFT_OFFLINE = 101, +} + +/// Bits for PKey_Access_Rights +PKey_Access_Bits :: enum { + DISABLE_ACCESS = 0, + DISABLE_WRITE = 2, +} + +/// Bits for MRemap_Flags +MRemap_Flags_Bits :: enum { + MAYMOVE = 0, + FIXED = 1, + DONTUNMAP = 2, +} + +/// Bits for Get_Random_Flags +Get_Random_Flags_Bits :: enum { + RANDOM = 0, + NONBLOCK = 1, + INSECURE = 2, +} + +/// Bits for Perf_Flags +Perf_Flags_Bits :: enum { + FD_NO_GROUP = 0, + FD_OUTPUT = 1, + PID_CGROUP = 2, + FD_CLOEXEC = 3, +} + +/// Union tag for Perf_Event_Attr struct +Perf_Event_Type :: enum u32 { + HARDWARE = 0, + SOFTWARE = 1, + TRACEPOINT = 2, + HW_CACHE = 3, + RAW = 4, + BREAKPOINT = 5, +} + +Perf_Event_Flags_Bits :: enum u64 { + Disabled = 0, + Inherit = 1, + Pinned = 2, + Exclusive = 3, + Exclude_User = 4, + Exclude_Kernel = 5, + Exclude_HV = 6, + Exclude_Idle = 7, + Mmap = 8, + Comm = 9, + Freq = 10, + Inherit_Stat = 11, + Enable_On_Exec = 12, + Task = 13, + Watermark = 14, + Precise_IP_0 = 15, + Precise_IP_1 = 16, + Mmap_Data = 17, + Sample_Id_All = 18, + Exclude_Host = 19, + Exclude_Guest = 20, + Exclude_Callchain_Kernel = 21, + Exclude_Callchain_User = 22, + Mmap2 = 23, + Comm_Exec = 24, + Use_Clockid = 25, + Context_Switch = 26, + Write_Backward = 27, + Namespaces = 28, + KSymbol = 29, + BPF_Event = 30, + Aux_Output = 31, + CGroup = 32, + Text_Poke = 33, + Build_Id = 34, + Inherit_Thread = 35, + Remove_On_Exec = 36, + Sigtrap = 37, +} + +Perf_Cap_Flags_Bits :: enum u64 { + Bit0 = 0, + Bit0_Is_Deprecated = 1, + User_Rdpmc = 2, + User_Time = 3, + User_Time_Zero = 4, + User_Time_Short = 5, +} + +/// Specifies the type of the hardware event that you want to get info about +Perf_Hardware_Id :: enum u64 { + CPU_CYCLES = 0, + INSTRUCTIONS = 1, + CACHE_REFERENCES = 2, + CACHE_MISSES = 3, + BRANCH_INSTRUCTIONS = 4, + BRANCH_MISSES = 5, + BUS_CYCLES = 6, + STALLED_CYCLES_FRONTEND = 7, + STALLED_CYCLES_BACKEND = 8, + REF_CPU_CYCLES = 9, +} + +/// Specifies the cache for the particular cache event that you want to get info about +Perf_Hardware_Cache_Id :: enum u64 { + L1D = 0, + L1I = 1, + LL = 2, + DTLB = 3, + ITLB = 4, + BPU = 5, + NODE = 6, +} + +/// Specifies the cache op that you want to get info about +Perf_Hardware_Cache_Op_Id :: enum u64 { + READ = 0, + WRITE = 1, + PREFETCH = 2, +} + +/// Specifies the cache operation result that you want to get info about +Perf_Hardware_Cache_Result_Id :: enum u64 { + ACCESS = 0, + MISS = 1, +} + +/// Specifies the particular software event that you want to get info about +Perf_Software_Id :: enum u64 { + CPU_CLOCK = 0, + TASK_CLOCK = 1, + PAGE_FAULTS = 2, + CONTEXT_SWITCHES = 3, + CPU_MIGRATIONS = 4, + PAGE_FAULTS_MIN = 5, + PAGE_FAULTS_MAJ = 6, + ALIGNMENT_FAULTS = 7, + EMULATION_FAULTS = 8, + DUMMY = 9, + BPF_OUTPUT = 10, + CGROUP_SWITCHES = 11, + +} + +/// Specifies which values to include in the sample +Perf_Event_Sample_Type_Bits :: enum { + IP = 0, + TID = 1, + TIME = 2, + ADDR = 3, + READ = 4, + CALLCHAIN = 5, + ID = 6, + CPU = 7, + PERIOD = 8, + STREAM_ID = 9, + RAW = 10, + BRANCH_STACK = 11, + REGS_USER = 12, + STACK_USER = 13, + WEIGHT = 14, + DATA_SRC = 15, + IDENTIFIER = 16, + TRANSACTION = 17, + REGS_INTR = 18, + PHYS_ADDR = 19, + AUX = 20, + CGROUP = 21, + DATA_PAGE_SIZE = 22, + CODE_PAGE_SIZE = 23, + WEIGHT_STRUCT = 24, +} + +/// Describes field sets to include in mmaped page +Perf_Read_Format :: enum { + TOTAL_TIME_ENABLED = 0, + TOTAL_TIME_RUNNING = 1, + ID = 2, + GROUP = 3, + LOST = 4, +} + +/// Chooses the breakpoint type +Hardware_Breakpoint_Type :: enum u32 { + EMPTY = 0, + R = 1, + W = 2, + X = 4, + RW = R | W, + INVALID = RW | X, +} + +/// Bits for Branch_Sample_Type +Branch_Sample_Type_Bits :: enum { + USER = 0, + KERNEL = 1, + HV = 2, + ANY = 3, + ANY_CALL = 4, + ANY_RETURN = 5, + IND_CALL = 6, + ABORT_TX = 7, + IN_TX = 8, + NO_TX = 9, + COND = 10, + CALL_STACK = 11, + IND_JUMP = 12, + CALL = 13, + NO_FLAGS = 14, + NO_CYCLES = 15, + TYPE_SAVE = 16, + HW_INDEX = 17, + PRIV_SAVE = 18, +} + +/// Represent the type of Id +Id_Type :: enum uint { + ALL = 0, + PID = 1, + PGID = 2, + PIDFD = 3, +} + +/// Options for wait syscalls +Wait_Option :: enum { + WNOHANG = 0, + WUNTRACED = 1, + WSTOPPED = 1, + WEXITED = 2, + WCONTINUED = 3, + WNOWAIT = 24, + // // For processes created using clone + __WNOTHREAD = 29, + __WALL = 30, + __WCLONE = 31, +} + +/// Bits for flags for pidfd +Pid_FD_Flags_Bits :: enum { + NONBLOCK = 11, +} + +/// Priority for process, process group, user +Priority_Which :: enum i32 { + PROCESS = 0, + PGRP = 1, + USER = 2, +} + +Signal :: enum i32 { + // POSIX-defined signals + SIGINT = 2, // Interactive attention signal. + SIGILL = 4, // Illegal instruction. + SIGABRT = 6, // Abnormal termination. + SIGFPE = 8, // Erroneous arithmetic operation. + SIGSEGV = 11, // Invalid access to storage. + SIGTERM = 15, // Termination request. + // Other POSIX signals + SIGHUP = 1, // Hangup. + SIGQUIT = 3, // Quit. + SIGTRAP = 5, // Trace/breakpoint trap. + SIGKILL = 9, // Killed. + SIGPIPE = 13, // Broken pipe. + SIGALRM = 14, // Alarm clock. + // Adjustments needed for most linux systems + SIGSTKFLT = 16, // Stack fault (obsolete). + SIGPWR = 30, // Power failure imminent. + // Historical signals specified by POSIX. + SIGBUS = 7, // Bus error. + SIGSYS = 31, // Bad system call. + // New(er) POSIX signals (1003.1-2008, 1003.1-2013). + SIGURG = 23, // Urgent data is available at a socket. + SIGSTOP = 19, // Stop, unblockable. + SIGTSTP = 20, // Keyboard stop. + SIGCONT = 18, // Continue. + SIGCHLD = 17, // Child terminated or stopped. + SIGTTIN = 21, // Background read from control terminal. + SIGTTOU = 22, // Background write to control terminal. + SIGPOLL = 29, // Pollable event occurred (System V). + SIGXFSZ = 25, // File size limit exceeded. + SIGXCPU = 24, // CPU time limit exceeded. + SIGVTALRM = 26, // Virtual timer expired. + SIGPROF = 27, // Profiling timer expired. + SIGUSR1 = 10, // User-defined signal 1. + SIGUSR2 = 12, // User-defined signal 2. + // Nonstandard signals found in all modern POSIX systems (including both BSD and Linux). + SIGWINCH = 28, // Window size change (4.3 BSD, Sun). + // Archaic names for compatibility. + SIGIO = SIGPOLL, // I/O now possible (4.2 BSD). + SIGIOT = SIGABRT, // IOT instruction, abort() on a PDP-11. + SIGCLD = SIGCHLD, // Old System V name +} + +Sig_Mask_Kind :: enum i32 { + SIG_BLOCK = 0, + SIG_UNBLOCK = 1, + SIG_SETMASK = 2, +} + +Sig_Stack_Flag :: enum i32 { + DISABLE = 0, + ONSTACK = 1, + AUTODISARM = 31, +} + +/// Type of socket to create +/// For TCP you want to use SOCK_STREAM +/// For UDP you want to use SOCK_DGRAM +/// Also see Protocol +Socket_Type :: enum { + STREAM = 1, + DGRAM = 2, + RAW = 3, + RDM = 4, + SEQPACKET = 5, + DCCP = 6, + PACKET = 10, +} + +/// Bits for Socket_FD_Flags +Socket_FD_Flags_Bits :: enum { + NONBLOCK = 14, + CLOEXEC = 25, +} + +/// Protocol family +Protocol_Family :: enum u16 { + UNSPEC = 0, + LOCAL = 1, + UNIX = LOCAL, + FILE = LOCAL, + INET = 2, + AX25 = 3, + IPX = 4, + APPLETALK = 5, + NETROM = 6, + BRIDGE = 7, + ATMPVC = 8, + X25 = 9, + INET6 = 10, + ROSE = 11, + DECnet = 12, + NETBEUI = 13, + SECURITY = 14, + KEY = 15, + NETLINK = 16, + ROUTE = NETLINK, + PACKET = 17, + ASH = 18, + ECONET = 19, + ATMSVC = 20, + RDS = 21, + SNA = 22, + IRDA = 23, + PPPOX = 24, + WANPIPE = 25, + LLC = 26, + IB = 27, + MPLS = 28, + CAN = 29, + TIPC = 30, + BLUETOOTH = 31, + IUCV = 32, + RXRPC = 33, + ISDN = 34, + PHONET = 35, + IEEE802154 = 36, + CAIF = 37, + ALG = 38, + NFC = 39, + VSOCK = 40, + KCM = 41, + QIPCRTR = 42, + SMC = 43, + XDP = 44, + MCTP = 45, +} + +/// The protocol number according to IANA protocol number list +/// Full list of protocol numbers: +/// https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml +/// Supported by the OS protocols can be queried by reading: +/// /etc/protocols +Protocol :: enum { + HOPOPT = 0, + ICMP = 1, + IGMP = 2, + GGP = 3, + IPv4 = 4, + ST = 5, + TCP = 6, + CBT = 7, + EGP = 8, + IGP = 9, + BBN_RCC_MON = 10, + NVP_II = 11, + PUP = 12, + EMCON = 14, + XNET = 15, + CHAOS = 16, + UDP = 17, + MUX = 18, + DCN_MEAS = 19, + HMP = 20, + PRM = 21, + XNS_IDP = 22, + TRUNK_1 = 23, + TRUNK_2 = 24, + LEAF_1 = 25, + LEAF_2 = 26, + RDP = 27, + IRTP = 28, + ISO_TP4 = 29, + NETBLT = 30, + MFE_NSP = 31, + MERIT_INP = 32, + DCCP = 33, + THREE_PC = 34, + IDPR = 35, + XTP = 36, + DDP = 37, + IDPR_CMTP = 38, + TP_PlusPlus = 39, + IL = 40, + IPv6 = 41, + SDRP = 42, + IPv6_Route = 43, + IPv6_Frag = 44, + IDRP = 45, + RSVP = 46, + GRE = 47, + DSR = 48, + BNA = 49, + ESP = 50, + AH = 51, + I_NLSP = 52, + NARP = 54, + MOBILE = 55, + TLSP = 56, + SKIP = 57, + IPv6_ICMP = 58, + IPv6_NoNxt = 59, + IPv6_Opts = 60, + CFTP = 62, + SAT_EXPAK = 64, + KRYPTOLAN = 65, + RVD = 66, + IPPC = 67, + SAT_MON = 69, + VISA = 70, + IPCV = 71, + CPNX = 72, + CPHB = 73, + WSN = 74, + PVP = 75, + BR_SAT_MON = 76, + SUN_ND = 77, + WB_MON = 78, + WB_EXPAK = 79, + ISO_IP = 80, + VMTP = 81, + SECURE_VMTP = 82, + VINES = 83, + IPTM = 84, + NSFNET_IGP = 85, + DGP = 86, + TCF = 87, + EIGRP = 88, + OSPFIGP = 89, + Sprite_RPC = 90, + LARP = 91, + MTP = 92, + AX_25 = 93, + IPIP = 94, + SCC_SP = 96, + ETHERIP = 97, + ENCAP = 98, + GMTP = 100, + IFMP = 101, + PNNI = 102, + PIM = 103, + ARIS = 104, + SCPS = 105, + QNX = 106, + A_N = 107, + IPComp = 108, + SNP = 109, + Compaq_Peer = 110, + IPX_in_IP = 111, + VRRP = 112, + PGM = 113, + L2TP = 115, + DDX = 116, + IATP = 117, + STP = 118, + SRP = 119, + UTI = 120, + SMP = 121, + PTP = 123, + FIRE = 125, + CRTP = 126, + CRUDP = 127, + SSCOPMCE = 128, + IPLT = 129, + SPS = 130, + PIPE = 131, + SCTP = 132, + FC = 133, + RSVP_E2E_IGNORE = 134, + UDPLite = 136, + MPLS_in_IP = 137, + manet = 138, + HIP = 139, + Shim6 = 140, + WESP = 141, + ROHC = 142, + Ethernet = 143, + AGGFRAG = 144, + NSH = 145, + Reserved = 255, +} + +/// API Level for get/setsockopt.2 +Socket_API_Level :: enum { + // Comes from + SOCKET = 1, + // Copy-pasted from protocol numbers + TCP = 6, + UDP = 17, + // Comes from + RAW = 255, + DECNET = 261, + X25 = 262, + PACKET = 263, + ATM = 264, + AAL = 265, + IRDA = 266, + NETBEUI = 267, + LLC = 268, + DCCP = 269, + NETLINK = 270, + TIPC = 271, + RXRPC = 272, + PPPOL2TP = 273, + BLUETOOTH = 274, + PNPIPE = 275, + RDS = 276, + IUCV = 277, + CAIF = 278, + ALG = 279, + NFC = 280, + KCM = 281, + TLS = 282, + XDP = 283, + MPTCP = 284, + MCTP = 285, + SMC = 286, +} + +/// If Socket_API_Level == .SOCKET, these are the options +/// you can specify in get/setsockopt.2 +Socket_Option :: enum { + DEBUG = 1, + REUSEADDR = 2, + TYPE = 3, + ERROR = 4, + DONTROUTE = 5, + BROADCAST = 6, + SNDBUF = 7, + RCVBUF = 8, + SNDBUFFORCE = 32, + RCVBUFFORCE = 33, + KEEPALIVE = 9, + OOBINLINE = 10, + NO_CHECK = 11, + PRIORITY = 12, + LINGER = 13, + BSDCOMPAT = 14, + REUSEPORT = 15, + PASSCRED = 16, + PEERCRED = 17, + RCVLOWAT = 18, + SNDLOWAT = 19, + RCVTIMEO_OLD = 20, + SNDTIMEO_OLD = 21, + SECURITY_AUTHENTICATION = 22, + SECURITY_ENCRYPTION_TRANSPORT = 23, + SECURITY_ENCRYPTION_NETWORK = 24, + BINDTODEVICE = 25, + ATTACH_FILTER = 26, + DETACH_FILTER = 27, + GET_FILTER = ATTACH_FILTER, + PEERNAME = 28, + ACCEPTCONN = 30, + PEERSEC = 31, + PASSSEC = 34, + MARK = 36, + PROTOCOL = 38, + DOMAIN = 39, + RXQ_OVFL = 40, + WIFI_STATUS = 41, + PEEK_OFF = 42, + NOFCS = 43, + LOCK_FILTER = 44, + SELECT_ERR_QUEUE = 45, + BUSY_POLL = 46, + MAX_PACING_RATE = 47, + BPF_EXTENSIONS = 48, + INCOMING_CPU = 49, + ATTACH_BPF = 50, + DETACH_BPF = DETACH_FILTER, + ATTACH_REUSEPORT_CBPF = 51, + ATTACH_REUSEPORT_EBPF = 52, + CNX_ADVICE = 53, + TIMESTAMPING_OPT_STATS = 54, + MEMINFO = 55, + INCOMING_NAPI_ID = 56, + COOKIE = 57, + TIMESTAMPING_PKTINFO = 58, + PEERGROUPS = 59, + ZEROCOPY = 60, + TXTIME = 61, + BINDTOIFINDEX = 62, + TIMESTAMP_OLD = 29, + TIMESTAMPNS_OLD = 35, + TIMESTAMPING_OLD = 37, + TIMESTAMP_NEW = 63, + TIMESTAMPNS_NEW = 64, + TIMESTAMPING_NEW = 65, + RCVTIMEO_NEW = 66, + SNDTIMEO_NEW = 67, + DETACH_REUSEPORT_BPF = 68, + PREFER_BUSY_POLL = 69, + BUSY_POLL_BUDGET = 70, + NETNS_COOKIE = 71, + BUF_LOCK = 72, + RESERVE_MEM = 73, + TXREHASH = 74, + RCVMARK = 75, + // Hardcoded 64-bit Time. It's time to move on. + TIMESTAMP = TIMESTAMP_NEW, + TIMESTAMPNS = TIMESTAMPNS_NEW, + TIMESTAMPING = TIMESTAMPING_NEW, + RCVTIMEO = RCVTIMEO_NEW, + SNDTIMEO = SNDTIMEO_NEW, +} + +Socket_UDP_Option :: enum { + CORK = 1, + ENCAP = 100, + NO_CHECK6_TX = 101, + NO_CHECK6_RX = 102, + SEGMENT = 103, + GRO = 104, +} + +UPD_Encapsulation :: enum { + ENCAP_ESPINUDP_NON_IKE = 1, + ENCAP_ESPINUDP = 2, + ENCAP_L2TPINUDP = 3, + ENCAP_GTP0 = 4, + ENCAP_GTP1U = 5, +} + +Socket_TCP_Option :: enum { + NODELAY = 1, + MAXSEG = 2, + CORK = 3, + KEEPIDLE = 4, + KEEPINTVL = 5, + KEEPCNT = 6, + SYNCNT = 7, + LINGER2 = 8, + DEFER_ACCEPT = 9, + WINDOW_CLAMP = 10, + INFO = 11, + QUICKACK = 12, + CONGESTION = 13, + MD5SIG = 14, + COOKIE_TRANSACTIONS = 15, + THIN_LINEAR_TIMEOUTS = 16, + THIN_DUPACK = 17, + USER_TIMEOUT = 18, + REPAIR = 19, + REPAIR_QUEUE = 20, + QUEUE_SEQ = 21, + REPAIR_OPTIONS = 22, + FASTOPEN = 23, + TIMESTAMP = 24, + NOTSENT_LOWAT = 25, + CC_INFO = 26, + SAVE_SYN = 27, + SAVED_SYN = 28, + REPAIR_WINDOW = 29, + FASTOPEN_CONNECT = 30, + ULP = 31, + MD5SIG_EXT = 32, + FASTOPEN_KEY = 33, + FASTOPEN_NO_COOKIE = 34, + ZEROCOPY_RECEIVE = 35, + INQ = 36, + CM_INQ = INQ, + TX_DELAY = 37, +} + +/// Bits for Socket_Msg +Socket_Msg_Bits :: enum { + OOB = 0, + PEEK = 1, + DONTROUTE = 2, + TRYHARD = DONTROUTE, + CTRUNC = 3, + PROXY = 4, + TRUNC = 5, + DONTWAIT = 6, + EOR = 7, + WAITALL = 8, + FIN = 9, + SYN = 10, + CONFIRM = 11, + RST = 12, + ERRQUEUE = 13, + NOSIGNAL = 14, + MORE = 15, + WAITFORONE = 16, + BATCH = 18, + ZEROCOPY = 22, + FASTOPEN = 29, + CMSG_CLOEXEC = 30, +} + +/// Argument to shutdown.2 +Shutdown_How :: enum i32 { + RD = 0, + WR = 1, + RDWR = 2, +} + +/// Second argument to futex.2 syscall +Futex_Op :: enum u32 { + WAIT = 0, + WAKE = 1, + FD = 2, + REQUEUE = 3, + CMP_REQUEUE = 4, + WAKE_OP = 5, + LOCK_PI = 6, + UNLOCK_PI = 7, + TRYLOCK_PI = 8, + WAIT_BITSET = 9, + WAKE_BITSET = 10, + WAIT_REQUEUE_PI = 11, + CMP_REQUEUE_PI = 12, + LOCK_PI2 = 13, +} + +/// Bits for Futex_Flags +Futex_Flags_Bits :: enum { + PRIVATE = 7, + REALTIME = 8, +} + +/// 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< cmparg) wake */ + GE = 5, /* if (oldval >= cmparg) wake */ +} + +/// The kind of resource limits +RLimit_Kind :: enum i32 { + CPU = 0, + FSIZE = 1, + DATA = 2, + STACK = 3, + CORE = 4, + RSS = 5, + NOFILE = 7, + AS = 9, + NPROC = 6, + MEMLOCK = 8, + LOCKS = 10, + SIGPENDING = 11, + MSGQUEUE = 12, + NICE = 13, + RTPRIO = 14, + RTTIME = 15, + NLIMITS = 16, +} + +/// Represents the user of resources +RUsage_Who :: enum i32 { + CHILDREN = -1, + SELF = 0, + THREAD = 1, + LWP = THREAD, +} + +/// Bits for Personality_Flags +UNAME26 :: 17 +ADDR_NO_RANDOMIZE :: 18 +FDPIC_FUNCPTRS :: 19 +MMAP_PAGE_ZERO :: 20 +ADDR_COMPAT_LAYOUT :: 21 +READ_IMPLIES_EXEC :: 22 +ADDR_LIMIT_32BIT :: 23 +SHORT_INODE :: 24 +WHOLE_SECONDS :: 25 +STICKY_TIMEOUTS :: 26 +ADDR_LIMIT_3GB :: 27 + +/// Personality type +/// These go into the bottom 8 bits of the personality value +PER_LINUX :: 0x0000 +PER_LINUX_32BIT :: 0x0000 | ADDR_LIMIT_32BIT +PER_LINUX_FDPIC :: 0x0000 | FDPIC_FUNCPTRS +PER_SVR4 :: 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO +PER_SVR3 :: 0x0002 | STICKY_TIMEOUTS | SHORT_INODE +PER_SCOSVR3 :: 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE +PER_OSR5 :: 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS +PER_WYSEV386 :: 0x0004 | STICKY_TIMEOUTS | SHORT_INODE +PER_ISCR4 :: 0x0005 | STICKY_TIMEOUTS +PER_BSD :: 0x0006 +PER_SUNOS :: 0x0006 | STICKY_TIMEOUTS +PER_XENIX :: 0x0007 | STICKY_TIMEOUTS | SHORT_INODE +PER_LINUX32 :: 0x0008 +PER_LINUX32_3GB :: 0x0008 | ADDR_LIMIT_3GB +PER_IRIX32 :: 0x0009 | STICKY_TIMEOUTS +PER_IRIXN32 :: 0x000a | STICKY_TIMEOUTS +PER_IRIX64 :: 0x000b | STICKY_TIMEOUTS +PER_RISCOS :: 0x000c +PER_SOLARIS :: 0x000d | STICKY_TIMEOUTS +PER_UW7 :: 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO +PER_OSF4 :: 0x000f +PER_HPUX :: 0x0010 +PER_MASK :: 0x00ff + diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin new file mode 100644 index 000000000..f826a556d --- /dev/null +++ b/core/sys/linux/constants.odin @@ -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) + diff --git a/core/sys/linux/helpers.odin b/core/sys/linux/helpers.odin new file mode 100644 index 000000000..8fe4de6d2 --- /dev/null +++ b/core/sys/linux/helpers.odin @@ -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) + } +} + diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin new file mode 100644 index 000000000..fa7b7186a --- /dev/null +++ b/core/sys/linux/sys.odin @@ -0,0 +1,2038 @@ +//+build linux +package linux + +import "core:intrinsics" + + +/// Read data from file into the buffer +/// Returns the number of bytes successfully read, which may be less than the size +/// of the buffer even if the termination is successfull +/// +/// Available since Linux 1.0 +/// Before Linux 3.14, this operation is not atomic (i.e. not thread safe). +read :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) { + ret := syscall(SYS_read, fd, raw_data(buf), len(buf) * size_of(T)) + return errno_unwrap(ret, int) +} + +/// Write the data from a buffer into the file +/// Returns the number of bytes successfully written, which may be less than the size +/// of the buffer, even if the termination is successfull +/// When using direct I/O, error doesn't mean the write has failed. Partial data may +/// have been written. +/// If .Eintr is returned, the write operation has failed due to interrupt. You'll probably +/// need to restart this syscall +/// +/// Available since Linux 1.0 +/// Before Linux 3.14 this operation is not atomic (i.e. not thread safe) +write :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) { + ret := syscall(SYS_write, fd, raw_data(buf), len(buf)*size_of(T)) + return errno_unwrap(ret, int) +} + +/// Open file, get the file descriptor +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +open :: proc "contextless" (name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_openat, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode) + return errno_unwrap(ret, Fd) + } else { + ret := syscall(SYS_open, transmute(uintptr) name, transmute(u32) mode) + return errno_unwrap(ret, Fd) + } +} + +/// Close the file +/// Available since Linux 1.0 +close :: proc "contextless" (fd: Fd) -> (Errno) { + ret := syscall(SYS_close, fd) + return Errno(-ret) +} + +/// Get file status +/// +/// Returns information about the file in struct pointed to by `stat` parameter. +/// +/// Available since Linux 1.0 +/// For 32-bit systems a different syscall is used that became available since 2.4 +/// Not available on arm64 +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) + return Errno(-ret) + } else { + ret := syscall(SYS_stat, cast(rawptr) filename, stat) + return Errno(-ret) + } + } else { + ret := syscall(SYS_stat64, cast(rawptr) filename, stat) + return Errno(-ret) + } +} + +/// Get file status from file descriptor +/// +/// Returns information about the file in struct pointed to by `stat` parameter. +/// +/// Available since Linux 1.0 +/// For 32-bit systems a different syscall is used that became available since 2.4 +fstat :: proc "contextless" (fd: Fd, stat: ^Stat) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_fstat, stat) + return Errno(-ret) + } else { + ret := syscall(SYS_fstat64, stat) + return Errno(-ret) + } +} + +/// Get information about the file that's potentially a symbolic link +/// The information is returned in a struct pointed to by `stat` parameter. +/// The difference with stat, fstat is that if the file is a symbolic link, +/// stat and fstat will dereference the link. lstat doesn't dereference symlinks +/// +/// Available since Linux 1.0 +/// For 32-bit systems a different syscall is used that became available since 2.4 +/// Not available on arm64 +lstat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { + when size_of(int) == 8 { + when ODIN_ARCH == .arm64 { + return fstatat(AT_FDCWD, filename, stat, {.SYMLINK_NOFOLLOW}) + } else { + ret := syscall(SYS_lstat, cast(rawptr) filename, stat) + return Errno(-ret) + } + } else { + ret := syscall(SYS_lstat64, cast(rawptr) filename, stat) + return Errno(-ret) + } +} + +/// Wait on event on a file descriptor +/// Available since Linux 2.2 +poll :: proc "contextless" (fds: []Poll_Fd, timeout: i32) -> (i32, Errno) { + when ODIN_ARCH == .arm64 { + seconds := cast(uint) timeout / 1000 + nanoseconds := cast(uint) (timeout % 1000) * 1_000_000 + timeout_spec := Time_Spec{seconds, nanoseconds} + ret := syscall(SYS_ppoll, raw_data(fds), len(fds), &timeout_spec, 0, 0) + return errno_unwrap(ret, i32) + } else { + ret := syscall(SYS_poll, raw_data(fds), len(fds), timeout) + return errno_unwrap(ret, i32) + } +} + + +/// Seek the file stream to specified offset +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 1.2 +lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_lseek, fd, off, whence) + return Errno(-ret) + } else { + ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), whence) + return Errno(-ret) + } +} + +/// Map files into memory +/// Available since Linux 1.0 +/// On 32-bit platforms since Linux 1.0 +mmap :: proc "contextless" (addr: uintptr, size: uint, prot: Mem_Protection, flags: Map_Flags, fd: Fd = Fd(-1), offset: i64 = 0) -> (rawptr, Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_mmap, addr, size, transmute(i32) prot, transmute(i32) flags, fd, offset) + return errno_unwrap(ret, rawptr, uintptr) + } else { + ret := syscall(SYS_mmap2, addr, size, transmute(i32) prot, transmute(i32) flags, fd, cast(uintptr)(offset/4096)) + return errno_unwrap(ret, rawptr, uintptr) + } +} + +/// Protect memory region +mprotect :: proc "contextless" (addr: rawptr, size: uint, prot: Mem_Protection) -> (Errno) { + ret := syscall(SYS_mprotect, addr, size, transmute(i32) prot) + return Errno(-ret) +} + +/// Unmap memory +/// Available since Linux 1.0 +munmap :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_mmap, addr, size) + return Errno(-ret) +} + +// TODO(flysand): brk + +/// Alter an action taken by a process +rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno { + ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set)) + return Errno(-ret) +} + +/// Examime and alter blocked signals +/// Available since Linux 2.2 +rt_sigprocmask :: proc "contextless" (mask_kind: Sig_Mask_Kind, new_set: ^Sig_Set, old_set: ^Sig_Set) -> Errno { + ret := syscall(SYS_rt_sigprocmask, mask_kind, new_set, old_set, size_of(Sig_Set)) + return Errno(-ret) +} + +// TODO(flysand): rt_sigreturn + +// TODO(flysand): ioctl + +/// Read the file at a specified offset +/// Note, it is not an error to return less bytes than requested +/// Available since Linux 2.2 +pread :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) { + ret := syscall(SYS_pread64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T))) + return errno_unwrap(ret, int) +} + +/// Read the file at a specified offset +/// Note, it is not an error to return less bytes than requested +/// Available since Linux 2.2 +pwrite :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) { + ret := syscall(SYS_pwrite64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T))) + return errno_unwrap(ret, int) +} + +// TODO(flysand): readv + +// TODO(flysand): writev + +/// Check user permissions for a file +/// If Mode is F_OK, checks whether the file exists +/// Similarly, X_OK, W_OK, R_OK check if the file is executable, writeable, readable respectively +/// Available since Linux 1.0 +/// For ARM64 available since Linux 2.6.16 +access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (bool, Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_faccessat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode) + return errno_unwrap(ret, bool) + } else { + ret := syscall(SYS_access, cast(rawptr) name, transmute(u32) mode) + return errno_unwrap(ret, bool) + } +} + +/// Create a pipe +/// Available since Linux 2.6.27 +pipe2 :: proc "contextless" (pipes: ^[2]Fd, flags: Open_Flags) -> (Errno) { + ret := syscall(SYS_pipe2, pipes, transmute(u32) flags) + return Errno(-ret) +} + +// TODO(flysand): select + +// TODO(flysand): sched_yield + +// TODO(flysand): add docs here +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) + return errno_unwrap(ret, rawptr, rawptr) + } else { + ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags) + return errno_unwrap(ret, rawptr, rawptr) + } +} + +/// Sync file with memory map +/// Available since Linux 2.0 +msync :: proc "contextless" (addr: rawptr, size: uint, flags: MSync_Flags) -> (Errno) { + ret := syscall(SYS_msync, addr, size, transmute(i32) flags) + return Errno(-ret) +} + +// TODO(flysand): mincore + +/// Give advice about use of memory +/// Available since Linux 2.4 +madvise :: proc "contextless" (addr: rawptr, size: uint, advice: MAdvice) -> (Errno) { + ret := syscall(SYS_madvise, addr, size, advice) + return Errno(-ret) +} + +// TODO(flysand): shmget + +// TODO(flysand): shmat + +// TODO(flysand): shmctl + +/// Allocate a new file descriptor that refers to the same file as the one provided +/// Available since Linux 1.0 +dup :: proc "contextless" (fd: Fd) -> (Fd, Errno) { + ret := syscall(SYS_dup, fd) + return errno_unwrap(ret, Fd) +} + +/// Adjust an existing file descriptor to point to the same file as `old` +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.27 +dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_dup3, old, new, 0) + return errno_unwrap(ret, Fd) + } else { + ret := syscall(SYS_dup2, old, new) + return errno_unwrap(ret, Fd) + } +} + +// TODO(flysand): pause + +// TODO(flysand): nanosleep + +// TODO(flysand): getitimer + +// TODO(flysand): alarm + +// TODO(flysand): setitimer + +/// Returns the thread group ID of the current process +/// Note that it doesn't return the pid, despite it's name. +/// Available since Linux 1.0 +getpid :: proc "contextless" () -> Pid { + return cast(Pid) syscall(SYS_getpid) +} + +// TODO(flysand): sendfile + +/// Create a socket file descriptor +/// Available since Linux 2.0 +socket :: proc "contextless" (domain: Address_Family, socktype: Socket_Type, sockflags: Socket_FD_Flags, protocol: Protocol) -> (Fd, Errno) { + sock_type_flags: int = cast(int) socktype | transmute(int) sockflags + ret := syscall(SYS_socket, domain, sock_type_flags, protocol) + return errno_unwrap(ret, Fd) +} + +/// Connect the socket to the address +/// Available since Linux 2.0 +connect :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno) +where + T == Sock_Addr_In || + T == Sock_Addr_In6 || + T == Sock_Addr_Any +{ + ret := syscall(SYS_connect, sock, addr, size_of(T)) + return Errno(-ret) +} + +/// Accept a pending connection or block until new connection appears +/// Depends on Sock_FD_Flags of the `sock` parameter. +/// Available since Linux 2.0 +accept :: proc "contextless" (sock: Fd, addr: ^$T, sockflags: Socket_FD_Flags = {}) -> (Fd, Errno) +where + T == Sock_Addr_In || + T == Sock_Addr_In6 || + T == Sock_Addr_Any +{ + ret := syscall(SYS_accept4, sock, addr, size_of(T), transmute(int) sockflags) + return errno_unwrap(ret, Fd) +} + +// TODO(flysand): Rewrite recvfrom and sendto to use default parameters +recvfrom :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$T) -> (int, Errno) +where + T == Sock_Addr_In || + T == Sock_Addr_In6 || + T == Sock_Addr_Any +{ + ret := syscall(SYS_recvfrom, sock, raw_data(buf), len(buf), transmute(i32) flags, addr, size_of(T)) + return errno_unwrap(ret, int) +} + +@private +recv_noaddr :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_recvfrom, sock, raw_data(buf), len(buf), transmute(i32) flags, cast(rawptr) nil, cast(uintptr) 0) + return errno_unwrap(ret, int) +} + +sendto :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$T) -> (int, Errno) +where + T == Sock_Addr_In || + T == Sock_Addr_In6 || + T == Sock_Addr_Any +{ + ret := syscall(SYS_sendto, sock, raw_data(buf), len(buf), transmute(i32) flags, addr, size_of(T)) + return errno_unwrap(ret, int) +} + +@private +send_noaddr :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_sendto, sock, raw_data(buf), len(buf), transmute(i32) flags, cast(rawptr) nil, cast(uintptr) 0) + return errno_unwrap(ret, int) +} + +/// Receive a message from a socket +/// Available since Linux 2.0 +recv :: proc {recvfrom, recv_noaddr} + +/// Send a message through a socket +/// Available since Linux 2.0 +send :: proc {sendto, send_noaddr} + +// TODO(flysand): sendmsg + +// TODO(flysand): recvmsg + +shutdown :: proc "contextless" (sock: Fd, how: Shutdown_How) -> (Errno) { + ret := syscall(SYS_shutdown, sock, how) + return Errno(-ret) +} + +/// Bind a socket to the given local address +/// Available since Linux 2.0 +bind :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno) +where + T == Sock_Addr_In || + T == Sock_Addr_In6 || + T == Sock_Addr_Any +{ + ret := syscall(SYS_bind, sock, addr, size_of(T)) + return Errno(-ret) +} + +/// Marks the socket as a socket that listen to connections using accept.2 +/// Available since Linux 2.0 +listen :: proc "contextless" (sock: Fd, queue_len: i32) -> (Errno) { + ret := syscall(SYS_listen, sock, queue_len) + return Errno(-ret) +} + +// TODO(flysand): getsockname + +// TODO(flysand): getpeername + +// TODO(flysand): socketpair + +// TODO(flysand): the parameters are the same, maybe there's a way to make it into a single proc, sacrificing type +// safety slightly +// TODO(flysand): add ability to specify slices +setsockopt_base :: proc "contextless" (sock: Fd, level: int, opt: int, val: $T) -> (Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + val_data := val + val_size := size_of(intrinsics.type_elem_type(T)) + ret := syscall(SYS_setsockopt, sock, level, opt, val_data, val_size) + return Errno(-ret) +} + +setsockopt_sock :: proc "contextless" (sock: Fd, level: Socket_API_Level_Sock, opt: Socket_Option, val: $T) -> (Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return setsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +setsockopt_tcp :: proc "contextless" (sock: Fd, level: Socket_API_Level_TCP, opt: Socket_TCP_Option, val: $T) -> (Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return setsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +setsockopt_udp :: proc "contextless" (sock: Fd, level: Socket_API_Level_UDP, opt: Socket_UDP_Option, val: $T) -> (Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return setsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +/// Set socket option for a given socket API level +/// Available since Linux 2.0 +setsockopt :: proc { + setsockopt_sock, + setsockopt_tcp, + setsockopt_udp, + setsockopt_base, +} + +getsockopt_base :: proc "contextless" (sock: Fd, level: int, opt: Socket_Option, val: $T) -> (int, Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + val_data := val + val_size := size_of(T) + ret := syscall(SYS_getsockopt, sock, level, opt, val_data, cast(rawptr) &val_size) + return val_size, Errno(-ret) +} + +getsockopt_sock :: proc "contextless" (sock: Fd, level: Socket_API_Level_Sock, opt: Socket_Option, val: ^$T) -> (int, Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return getsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +getsockopt_tcp :: proc "contextless" (sock: Fd, level: Socket_API_Level_TCP, opt: Socket_TCP_Option, val: ^$T) -> (int, Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return getsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +getsockopt_udp :: proc "contextless" (sock: Fd, level: Socket_API_Level_UDP, opt: Socket_UDP_Option, val: ^$T) -> (int, Errno) +where + intrinsics.type_is_pointer(T) || + intrinsics.type_is_multi_pointer(T) +{ + return getsockopt_base(sock, cast(int) level, cast(int) opt, val) +} + +/// Get socket option for a given socket API level +/// Available since Linux 2.0 +getsockopt :: proc { + getsockopt_sock, + getsockopt_tcp, + getsockopt_udp, + getsockopt_base, +} + +// TODO(flysand): clone (probably not in this PR, maybe not ever) + +/// Creates a copy of the running process +/// Available since Linux 1.0 +fork :: proc "contextless" () -> (Pid, Errno) { + when ODIN_ARCH == .arm64 { + // Note(flysand): this syscall is not documented, but the bottom 8 bits of flags + // are for exit signal + ret := syscall(SYS_clone, Signal.SIGCHLD) + return errno_unwrap(ret, Pid) + } else { + ret := syscall(SYS_fork) + return errno_unwrap(ret, Pid) + } +} + +// TODO(flysand): vfork + +// TODO(flysand): execve + +/// Exit the thread with a given exit code +/// Available since Linux 1.0 +exit :: proc "contextless" (code: i32) -> ! { + syscall(SYS_exit, code) + unreachable() +} + +/// Wait for the process to change state +/// Available since Linux 1.0 +wait4 :: proc "contextless" (pid: Pid, status: ^u32, options: Wait_Options) -> (Pid, Errno) { + ret := syscall(SYS_wait4, pid, status, transmute(u32) options) + return errno_unwrap(ret, Pid) +} + +/// See wait4 +waitpid :: wait4 + +// TODO(flysand): kill + +/// Get system information +/// Available since Linux 1.0 +uname :: proc "contextless" (uts_name: ^UTS_Name) -> (Errno) { + ret := syscall(SYS_uname, uts_name) + return Errno(-ret) +} + +// TODO(flysand): semget + +// TODO(flysand): semop + +// TODO(flysand): semctl + +// TODO(flysand): shmdt + +// TODO(flysand): msgget + +// TODO(flysand): msgsnd + +// TODO(flysand): msgrcv + +// TODO(flysand): msgctl + +fcntl_dupfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD, newfd: Fd) -> (Fd, Errno) { + ret := syscall(SYS_fcntl, fd, cmd, newfd) + return errno_unwrap(ret, Fd) +} + +fcntl_dupfd_cloexec :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD_CLOEXEC, newfd: Fd) -> (Fd, Errno) { + ret := syscall(SYS_fcntl, fd, cmd, newfd) + return errno_unwrap(ret, Fd) +} + +fcntl_getfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETFD) -> (Fd, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(ret, Fd) +} + +fcntl_setfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETFD, newfd: Fd) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, newfd) + return Errno(-ret) +} + +fcntl_getfl :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETFL) -> (Open_Flags, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(u32(ret), Open_Flags, Open_Flags) +} + +fcntl_setfl :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETFL, flags: Open_Flags) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, transmute(u32) flags) + return Errno(-ret) +} + +fcntl_setlk :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLK, lock: ^FLock) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_fcntl64, fd, cmd, lock) + return Errno(-ret) + } else { + ret := syscall(SYS_fcntl, fd, cmd, lock) + return Errno(-ret) + } +} + +fcntl_setlkw :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLKW, lock: ^FLock) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_fcntl64, fd, cmd, lock) + return Errno(-ret) + } else { + ret := syscall(SYS_fcntl, fd, cmd, lock) + return Errno(-ret) + } +} + +fcntl_getlk :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETLK, lock: ^FLock) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_fcntl64, fd, cmd, lock) + return Errno(-ret) + } else { + ret := syscall(SYS_fcntl, fd, cmd, lock) + return Errno(-ret) + } +} + +fcntl_getown_ex :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETOWN_EX, owner: ^F_Owner) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, owner) + return Errno(-ret) +} + +fcntl_setown_ex :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETOWN_EX, owner: ^F_Owner) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, owner) + return Errno(-ret) +} + +fcntl_getsig :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETSIG) -> (Signal, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(ret, Signal) +} + +fcntl_setsig :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETSIG, sig: Signal) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, sig) + return Errno(-ret) +} + +fcntl_setlease :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLEASE, lease: FD_Lease) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, lease) + return Errno(-ret) +} + +fcntl_getlease :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETLEASE) -> (FD_Lease, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(ret, FD_Lease) +} + +fcntl_notify :: proc "contextless" (fd: Fd, cmd: FCntl_Command_NOTIFY, notifications: FD_Notifications) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return Errno(-ret) +} + +fcntl_setpipe_sz :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETPIPE_SZ, sz: i32) -> (i32, Errno) { + ret := syscall(SYS_fcntl, fd, cmd, sz) + return errno_unwrap(ret, i32) +} + +fcntl_getpipe_sz :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETPIPE_SZ) -> (i32, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(ret, i32) +} + +fcntl_add_seals :: proc "contextless" (fd: Fd, cmd: FCntl_Command_ADD_SEALS, seal: Seal) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, transmute(i32) seal) + return Errno(-ret) +} + +fcntl_get_seals :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_SEALS) -> (Seal, Errno) { + ret := syscall(SYS_fcntl, fd, cmd) + return errno_unwrap(i32(ret), Seal, Seal) +} + +fcntl_get_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_RW_HINT, hint: ^RW_Hint) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, hint) + return Errno(-ret) +} + +fcntl_set_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SET_RW_HINT, hint: ^RW_Hint) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, hint) + return Errno(-ret) +} + +fcntl_get_file_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_FILE_RW_HINT, hint: ^RW_Hint) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, hint) + return Errno(-ret) +} + +fcntl_set_file_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SET_FILE_RW_HINT, hint: ^RW_Hint) -> (Errno) { + ret := syscall(SYS_fcntl, fd, cmd, hint) + return Errno(-ret) +} + +fcntl :: proc { + fcntl_dupfd, + fcntl_dupfd_cloexec, + fcntl_getfd, + fcntl_setfd, + fcntl_getfl, + fcntl_setfl, + fcntl_setlk, + fcntl_setlkw, + fcntl_getlk, + fcntl_getown_ex, + fcntl_setown_ex, + fcntl_getsig, + fcntl_setsig, + fcntl_setlease, + fcntl_getlease, + fcntl_notify, + fcntl_setpipe_sz, + fcntl_getpipe_sz, + fcntl_add_seals, + fcntl_get_seals, + fcntl_get_rw_hint, + fcntl_set_rw_hint, + fcntl_get_file_rw_hint, + fcntl_set_file_rw_hint, +} + +// TODO(flysand): flock + +/// Sync state of the file with the storage device +fsync :: proc "contextless" (fd: Fd) -> (Errno) { + ret := syscall(SYS_fsync, fd) + return Errno(-ret) +} + +// TODO(flysand): fdatasync + +/// Truncate a file to specified length +/// On 32-bit architectures available since Linux 2.4 +truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_truncate64, cast(rawptr) name, compat64_arg_pair(length)) + return Errno(-ret) + } else { + ret := syscall(SYS_truncate, cast(rawptr) name, compat64_arg_pair(length)) + return Errno(-ret) + } +} + +/// Truncate a file specified by file descriptor to specified length +/// On 32-bit architectures available since 2.4 +ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length)) + return Errno(-ret) + } else { + ret := syscall(SYS_truncate, fd, compat64_arg_pair(length)) + return Errno(-ret) + } +} + +/// Retrieve the contents of the directory specified by dirfd +/// Returns the number of bytes written +/// Available since Linux 2.4 +getdents :: proc "contextless" (dirfd: Fd, buf: []u8) -> (int, Errno) { + ret := syscall(SYS_getdents64, dirfd, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) +} + +/// Get current working directory +/// Available since Linux 1.0 +getcwd :: proc "contextless" (buf: []u8) -> (int, Errno) { + ret := syscall(SYS_getcwd, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) +} + +/// Change working directory to the directory specified by path +/// Available since Linux 1.0 +chdir :: proc "contextless" (path: cstring) -> (Errno) { + ret := syscall(SYS_chdir, cast(rawptr) path) + return Errno(-ret) +} + +/// Change working directory to the directory specified by dirfd +/// Available since Linux 1.0 +fchdir :: proc "contextless" (fd: Fd) -> (Errno) { + ret := syscall(SYS_fchdir, fd) + return Errno(-ret) +} + +/// Rename (move) the file +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +rename :: proc "contextless" (old: cstring, new: cstring) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_renameat, AT_FDCWD, cast(rawptr) old, AT_FDCWD, cast(rawptr) new) + return Errno(-ret) + } else { + ret := syscall(SYS_rename, cast(rawptr) old, cast(rawptr) new) + return Errno(-ret) + } +} + +/// Creates a directory +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +mkdir :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_mkdirat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode) + return Errno(-ret) + } else { + ret := syscall(SYS_mkdir, cast(rawptr) name, transmute(u32) mode) + return Errno(-ret) + } +} + +/// Remove a directory specified by name +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +rmdir :: proc "contextless" (name: cstring) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, transmute(i32) FD_Flags{.REMOVEDIR}) + return Errno(-ret) + } else { + ret := syscall(SYS_rmdir, cast(rawptr) name) + return Errno(-ret) + } +} + +// TODO(flysand): creat + +/// Create a hard link on a file +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +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) + return Errno(-ret) + } else { + ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath) + return Errno(-ret) + } +} + +/// Delete a name, and possible a file it refers to +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +unlink :: proc "contextless" (name: cstring) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, 0) + return Errno(-ret) + } else { + ret := syscall(SYS_unlink, cast(rawptr) name) + return Errno(-ret) + } +} + +/// Create a symbolic link +/// Available since Linux 1.0 +/// On arm64 available since Linux 2.6.16 +symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath) + return Errno(-ret) + } else { + ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath) + return Errno(-ret) + } +} + +/// Read the value of a symbolic link +/// Available since Linux 1.0 +/// On arm64 available since Linux 2.6.16 +readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_readlinkat, AT_FDCWD, cast(rawptr) name, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) + } else { + ret := syscall(SYS_readlink, cast(rawptr) name, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) + } +} + +/// Change file permissions +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0) + return Errno(-ret) + } else { + ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode) + return Errno(-ret) + } +} + +/// Change file permissions through a file descriptor +/// Available since Linux 1.0 +fchmod :: proc "contextless" (fd: Fd, mode: Mode) -> (Errno) { + ret := syscall(SYS_fchmod, fd, transmute(u32) mode) + return Errno(-ret) +} + +/// Change ownership of a file +/// Available since Linux 2.2 +/// On 32-bit architectures available since Linux 2.4 +/// On ARM64 available since Linux 2.6.16 +chown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_chown32, cast(rawptr) name, uid, gid) + return Errno(-ret) + } else when ODIN_ARCH == .arm64 { + ret := syscall(SYS_fchownat, AT_FDCWD, cast(rawptr) name, uid, gid, 0) + return Errno(-ret) + } else { + ret := syscall(SYS_chown, cast(rawptr) name, uid, gid) + return Errno(-ret) + } +} + +/// Change ownership of a file by file descriptor +/// Available since Linux 1.0 +/// On 32-bit architecvtures available since Linux 2.4 +fchown :: proc "contextless" (fd: Fd, uid: Uid, gid: Gid) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_fchown32, fd, uid, gid) + return Errno(-ret) + } else { + ret := syscall(SYS_fchown, fd, uid, gid) + return Errno(-ret) + } +} + +/// Change ownership of a file. Unlike chown, if a file is a symlink dooesn't dereference it +/// Available since Linux 1.0 +/// On 32-bit architectures available since Linux 2.4 +/// On ARM64 available since Linux 2.6.16 +lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_lchown32, cast(rawptr) name, uid, gid) + return Errno(-ret) + } else when ODIN_ARCH == .arm64 { + ret := syscall(SYS_fchownat, AT_FDCWD, cast(rawptr) name, uid, gid, transmute(i32) FD_Flags{.SYMLINK_NOFOLLOW}) + return Errno(-ret) + } else { + ret := syscall(SYS_lchown, cast(rawptr) name, uid, gid) + return Errno(-ret) + } +} + +// TODO(flysand): umask + +// TODO(flysand): gettimeofday + +/// Get limits on resources +/// Available since Linux 1.0 +getrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) { + ret := syscall(SYS_getrlimit, kind, resource) + return Errno(-ret) +} + +/// Get resource usage +/// Available since Linux 1.0 +getrusage :: proc "contextless" (who: RUsage_Who, rusage: ^RUsage) -> (Errno) { + ret := syscall(SYS_getrusage, who, rusage) + return Errno(-ret) +} + +/// Get information about the system +sysinfo :: proc "contextless" (sysinfo: ^Sys_Info) -> (Errno) { + ret := syscall(SYS_sysinfo, sysinfo) + return Errno(-ret) +} + +/// Get current process times +/// Available since Linux 1.0 +times :: proc "contextless" (tms: ^Tms) -> (Errno) { + ret := syscall(SYS_times, cast(rawptr) tms) + return Errno(-ret) +} + +// TODO(flysand): ptrace + +/// Get real user ID +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +getuid :: proc "contextless" () -> Uid { + when size_of(int) == 8 { + return cast(Uid) syscall(SYS_getuid) + } else { + return cast(Uid) syscall(SYS_getuid32) + } +} + +// TODO(flysand): syslog + +/// Get real group ID +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +getgid :: proc "contextless" () -> Gid { + when size_of(int) == 8 { + return cast(Gid) syscall(SYS_getgid) + } else { + return cast(Gid) syscall(SYS_getgid32) + } +} + +/// Set effective user id +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setuid :: proc "contextless" (uid: Uid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setuid, uid) + return Errno(-ret) + } else { + ret := syscall(SYS_setuid32, uid) + return Errno(-ret) + } +} + +/// Set effective group id +/// If the process is privileged also sets real group id +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setgid :: proc "contextless" (gid: Gid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setgid, gid) + return Errno(-ret) + } else { + ret := syscall(SYS_setgid32, gid) + return Errno(-ret) + } +} + +/// Get effective user ID +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +geteuid :: proc "contextless" () -> Uid { + when size_of(int) == 8 { + return cast(Uid) syscall(SYS_geteuid) + } else { + return cast(Uid) syscall(SYS_geteuid32) + } +} + +/// Get effective group ID +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +getegid :: proc "contextless" () -> Gid { + when size_of(int) == 8 { + return cast(Gid) syscall(SYS_getegid) + } else { + return cast(Gid) syscall(SYS_getegid32) + } +} + +/// Set process group +/// Available since Linux 1.0 +setpgid :: proc "contextless" (pid: Pid, pgid: Pid) -> (Errno) { + ret := syscall(SYS_setpgid, pid, pgid) + return Errno(-ret) +} + +/// Get the parent process ID +/// Available since Linux 1.0 +getppid :: proc "contextless" () -> Pid { + return cast(Pid) syscall(SYS_getppid) +} + +/// Get process group +/// Available since Linux 1.0 +getpgrp :: proc "contextless" () -> (Pid, Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_getpgid, 0) + return errno_unwrap(ret, Pid) + } else { + ret := syscall(SYS_getpgrp) + return errno_unwrap(ret, Pid) + } +} + +/// Create a session and set the process group ID +/// Available since Linux 2.0 +setsid :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_setsid) + return Errno(-ret) +} + +/// Set real and/or effective user id +/// If any of the arguments is -1, the corresponding id is not changed +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setreuid :: proc "contextless" (real: Uid, effective: Uid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setreuid, real, effective) + return Errno(-ret) + } else { + ret := syscall(SYS_setreuid32, real, effective) + return Errno(-ret) + } +} + +/// Set real and/or effective group id +/// If any of the arguments is -1, the corresponding id is not changed +/// Available since Linux 1.0 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setregid :: proc "contextless" (real: Gid, effective: Gid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setregid, real, effective) + return Errno(-ret) + } else { + ret := syscall(SYS_setregid32, real, effective) + return Errno(-ret) + } +} + +// TODO(flysand): getgroups + +// TODO(flysand): setgroups + +/// Set real, effective and/or saved user id +/// If any of the arguments is -1, the corresponding id is not changed +/// Available since Linux 2.2 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setresuid :: proc "contextless" (real: Uid, effective: Uid, saved: Uid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setresuid, real, effective, saved) + return Errno(-ret) + } else { + ret := syscall(SYS_setresuid32, real, effective, saved) + return Errno(-ret) + } +} + +/// Get real, effective and saved user id +/// Available since Linux 2.2 +/// On 32-bit platforms available since Linux 2.4 +getresuid :: proc "contextless" (real: ^Uid, effective: ^Uid, saved: ^Uid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_getresuid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) + return Errno(-ret) + } else { + ret := syscall(SYS_getresuid32, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) + return Errno(-ret) + } +} + +/// Set real, effective and/or saved group id +/// If any of the arguments is -1, the corresponding id is not changed +/// Available since Linux 2.2 +/// On 32-bit platforms available since Linux 2.4 +@(require_results) +setresgid :: proc "contextless" (real: Gid, effective: Gid, saved: Uid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setresgid, real, effective, saved) + return Errno(-ret) + } else { + ret := syscall(SYS_setresgid32, real, effective, saved) + return Errno(-ret) + } +} + +/// Get real, effective and saved group id +/// Available since Linux 2.2 +/// On 32-bit platforms available since Linux 2.4 +getresgid :: proc "contextless" (real: ^Gid, effective: ^Gid, saved: ^Gid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_getresgid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) + return Errno(-ret) + } else { + ret := syscall(SYS_getresgid32, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) + return Errno(-ret) + } +} + +/// Get process group +/// Available since Linux 1.0 +getpgid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { + ret := syscall(SYS_getpgid, pid) + 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) { + ret := syscall(SYS_getsid, pid) + return errno_unwrap(ret, Pid) +} + +// TODO(flysand): capget + +// TODO(flysand): capset + +/// Examine pending signals +/// Available since Linux 2.2 +rt_sigpending :: proc "contextless" (sigs: ^Sig_Set) -> Errno { + ret := syscall(SYS_rt_sigpending, sigs, size_of(Sig_Set)) + return Errno(-ret) +} + +/// Synchronously wait for queued signals +/// Available since Linux 2.2 +rt_sigtimedwait :: proc "contextless" (sigs: ^Sig_Set, info: ^Sig_Info, time_sus: ^Time_Spec) -> (Signal, Errno) { + ret := syscall(SYS_rt_sigtimedwait, sigs, info, time_sus, size_of(Sig_Set)) + return errno_unwrap(ret, Signal) +} + +/// Send signal information to a process +/// Available since Linux 2.2 +rt_sigqueueinfo :: proc "contextless" (pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) { + ret := syscall(SYS_rt_sigqueueinfo, pid, sig, si) + return Errno(-ret) +} + +/// Replace the signal mask for a value with the new mask until a signal is received +/// Available since Linux 2.2 +rt_sigsuspend :: proc "contextless" (sigset: ^Sig_Set) -> Errno { + ret := syscall(SYS_rt_sigsuspend, sigset, size_of(Sig_Set)) + return Errno(-ret) +} + +/// Set or get signal stack context +/// Available since Linux 2.2 +sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) -> (Errno) { + ret := syscall(SYS_sigaltstack, stack, old_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 +/// Available since Linux 1.0 +/// On ARM64 available since Linux 2.6.16 +mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) { + when ODIN_ARCH == .arm64 { + ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, dev) + return Errno(-ret) + } else { + ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, dev) + return Errno(-ret) + } +} + +// TODO(flysand): uselib + +/// Set the process execution domain +/// Available since Linux 1.2 +personality :: proc "contextless" (personality: uint) -> (uint, Errno) { + ret := syscall(SYS_personality, personality) + return errno_unwrap(ret, uint) +} + +// TODO(flysand): ustat + +/// Query information about filesystem +/// +/// Available since Linux 1.0 +/// For 32-bit systems a different syscall is used that became available since 2.6 +statfs :: proc "contextless" (path: cstring, statfs: ^Stat_FS) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_statfs, transmute(uintptr) path, statfs) + return Errno(-ret) + } else { + ret := syscall(SYS_statfs64, cast(rawptr) path, size_of(Stat_FS), statfs) + return Errno(-ret) + } +} + +/// Query information about filesystem by file descriptor +/// +/// Available since Linux 1.0 +/// For 32-bit systems a different syscall is used that became available since 2.6 +fstatfs :: proc "contextless" (fd: Fd, statfs: ^Stat_FS) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_statfs, fd, statfs) + return Errno(-ret) + } else { + ret := syscall(SYS_statfs64, fd, size_of(Stat_FS), statfs) + return Errno(-ret) + } +} + +// TODO(flysand): sysfs + +/// Get priority on user, process group or process +/// Available since Linux 1.0 +getpriority :: proc "contextless" (which: Priority_Which, who: i32) -> (i32, Errno) { + ret := syscall(SYS_getpriority, which, who) + prio, err := errno_unwrap(ret, i32) + // NOTE(flysand): getpriority will return `20 - priority` to avoid returning + // negative priorities as errors + prio = 20 - prio + return prio, err +} + +/// Set priority on user, process group or process +/// Available since Linux 1.0 +setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) -> (Errno) { + ret := syscall(SYS_setpriority, which, who, prio) + return Errno(-ret) +} + +// TODO(flysand): sched_setparam + +// TODO(flysand): sched_getparam + +// TODO(flysand): sched_setscheduler + +// TODO(flysand): sched_getscheduler + +// TODO(flysand): sched_get_priority_max + +// TODO(flysand): sched_get_priority_min + +// TODO(flysand): sched_rr_get_interval + +/// Lock and memory +/// Available since Linux 2.0 +/// If flags specified, available since Linux 4.4 +mlock :: proc "contextless" (addr: rawptr, size: uint, flags: MLock_Flags = {}) -> (Errno) { + // Pretty darn recent syscall, better call simpler version if we can + if flags > {} { + ret := syscall(SYS_mlock2, addr, size, transmute(i32) flags) + return Errno(-ret) + } else { + ret := syscall(SYS_mlock, addr, size) + return Errno(-ret) + } +} + +/// Unlock memory +/// Available since Linux 2.0 +munlock :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_munlock, addr, size) + return Errno(-ret) +} + +/// Lock all memory +mlockall :: proc "contextless" (flags: MLock_Flags = {}) -> (Errno) { + ret := syscall(SYS_mlockall, transmute(i32) flags) + return Errno(-ret) +} + +/// Unlock all memory +munlockall :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_munlockall) + return Errno(-ret) +} + +// TODO(flysand): vhangup + +// TODO(flysand): modify_ldt + +// TODO(flysand): pivot_root + +// TODO(flysand): _sysctl + +// TODO(flysand): prctl + +// TODO(flysand): arch_prctl + +// TODO(flysand): adj_timex + +/// Set limits on resources +/// Available since Linux 1.0 +setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) { + ret := syscall(SYS_setrlimit, kind, resource) + return Errno(-ret) +} + +// TODO(flysand): sync + +// TODO(flysand): acct + +// TODO(flysand): settimeofday + +// TODO(flysand): mount + +// TODO(flysand): umount2 + +// TODO(flysand): swapon + +// TODO(flysand): swapoff + +// TODO(flysand): reboot + +/// Set hostname +/// Note: to get the host name, use `uname` syscall +/// Available since Linux 1.0 +sethostname :: proc "contextless" (hostname: string) -> (Errno) { + ret := syscall(SYS_sethostname, raw_data(hostname), len(hostname)) + return Errno(-ret) +} + +/// Set domain name +/// Note: to get the domain name, use `uname` syscall +/// Available since Linux 2.2 +setdomainname :: proc "contextless" (name: string) -> (Errno) { + ret := syscall(SYS_setdomainname, raw_data(name), len(name)) + return Errno(-ret) +} + +// TODO(flysand): iopl + +// 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 + +// TODO(flysand): getpmsg + +// TODO(flysand): putpmsg + +// TODO(flysand): afs_syscall + +// TODO(flysand): tuxcall + +// TODO(flysand): security + +/// Returns the thread ID of the current process +/// This is what the kernel calls "pid" +/// Let me insert a tiny rant here, this terminology is confusing: +/// sometimes pid refers to a thread, and other times it refers +/// to a thread group (process group?) +/// Anyway, this syscall is available since Linux 1.0 +gettid :: proc "contextless" () -> Pid { + return cast(Pid) syscall(SYS_gettid) +} + +// TODO(flysand): readahead + +// TODO(flysand): setxattr + +// TODO(flysand): lsetxattr + +// TODO(flysand): fsetxattr + +// TODO(flysand): getxattr + +// TODO(flysand): lgetxattr + +// TODO(flysand): fgetxattr + +// TODO(flysand): listxattr + +// TODO(flysand): llistxattr + +// TODO(flysand): flistxattr + +// TODO(flysand): removexattr + +// TODO(flysand): lremovexattr + +// TODO(flysand): fremovexattr + +// TODO(flysand): tkill + +// TODO(flysand): time + +/// 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) { + futex_flags := cast(u32) op + transmute(u32) flags + ret := syscall(SYS_futex, futex, futex_flags, val, timeout) + return Errno(-ret) +} + +/// Wake up other threads on a futex +/// n_wakeup specifies the number of processes to wakeup. Specify max(i32) to wake up all processes waiting +futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Futex_Flags, n_wakeup: i32) -> (int, Errno) { + futex_flags := cast(u32) op + transmute(u32) flags + ret := syscall(SYS_futex, futex, futex_flags, n_wakeup) + return errno_unwrap(ret, int) +} + +// NOTE(flysand): futex_fd is racy, so not implemented + +/// Requeues processes waiting on futex `futex` to wait on futex `requeue_futex` +/// `requeue_threshold` specifies the maximum amount of waiters to wake up, the rest of the waiters will be requeued +/// `requeue_max` specifies the maximum amount of waiters that are required at `requeue_futex` +/// The operation blocks until the `requeue_max` requirement is satisfied +/// If the value of the mutex is not equal to `val`, fails with EAGAIN before any further checks +/// 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) +{ + 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) +} + +/// See `futex_cmp_requeue`, this function does the same thing but doesn't check the value of the futex +/// 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) +{ + 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) +} + +/// Okay, for this one, see the man pages, the description for it is pretty long and very specific. It's sole +/// 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) +{ + 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) +} + +/// 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) +{ + futex_flags := cast(u32) op + transmute(u32) flags + ret := syscall(SYS_futex, futex, futex_flags, val, timeout, 0, mask) + return errno_unwrap(ret, int) +} + +/// 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_flags := cast(u32) op + transmute(u32) flags + ret := syscall(SYS_futex, futex, futex_flags, n_wakeup, 0, 0, mask) + return errno_unwrap(ret, int) +} + +// TODO(flysand): Priority inheritance (PI) futicees + +futex :: proc { + futex_wait, + futex_wake, + futex_cmp_requeue, + futex_requeue, + futex_wake_op, + futex_wait_bitset, + futex_wake_bitset, +} + +// TODO(flysand): sched_setaffinity + +// TODO(flysand): sched_getaffinity + +// TODO(flysand): set_thread_area + +// TODO(flysand): io_setup + +// TODO(flysand): io_destroy + +// TODO(flysand): io_getevents + +// TODO(flysand): io_submit + +// TODO(flysand): io_cancel + +// TODO(flysand): get_thread_area + +// TODO(flysand): lookup_dcookie + +// TODO(flysand): epoll_create + +// TODO(flysand): epoll_ctl_old + +// TODO(flysand): epoll_wait_old + +// TODO(flysand): remap_file_pages + +/// Set the address of the futex that's gonna be waken when +/// current thread terminates +/// Available since Linux 2.6 +set_tid_address :: proc "contextless" (tidptr: ^u32) { + syscall(SYS_set_tid_address, tidptr) +} + +// TODO(flysand): restart_syscall + +// TODO(flysand): semtimedop + +// TODO(flysand): fadvise64 + +// TODO(flysand): timer_create + +// TODO(flysand): timer_settime + +// TODO(flysand): timer_gettime + +// TODO(flysand): timer_getoverrun + +// TODO(flysand): timer_delete + +// TODO(flysand): clock_settime + +// TODO(flysand): clock_gettime + +// TODO(flysand): clock_getres + +// TODO(flysand): clock_nanosleep + +/// Exit the thread group +/// Available since Linux 2.6 +exit_group :: proc "contextless" (code: i32) -> ! { + syscall(SYS_exit_group, code) + unreachable() +} + +// TODO(flysand): epoll_wait + +// TODO(flysand): epoll_ctl + +// TODO(flysand): tgkill + +// TODO(flysand): utimes + +// TODO(flysand): vserver + +// TODO(flysand): mbind + +// TODO(flysand): set_mempolicy + +// TODO(flysand): get_mempolicy + +// TODO(flysand): mq_open + +// TODO(flysand): mq_unlink + +// TODO(flysand): mq_timedsend + +// TODO(flysand): mq_timedreceive + +// TODO(flysand): mq_notify + +// TODO(flysand): mq_getsetattr + +// TODO(flysand): kexec_load + + +/// 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) + return Errno(-ret) +} + +// TODO(flysand): add_key + +// TODO(flysand): request_key + +// TODO(flysand): keyctl + +// TODO(flysand): ioprio_set + +// TODO(flysand): ioprio_get + +// TODO(flysand): inotify_init + +// TODO(flysand): inotify_add_watch + +// TODO(flysand): inotify_rm_watch + +// TODO(flysand): migrate_pages + +/// Open file at the specified file descriptor +/// 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) + return errno_unwrap(ret, Fd) +} + +/// Create a directory relative to specified dirfd +/// Available since Linux 2.6.16 +mkdirat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode) -> (Errno) { + ret := syscall(SYS_mkdirat, dirfd, cast(rawptr) name, transmute(u32) mode) + return Errno(-ret) +} + +/// Create a special or ordinary file wrt given directory specified by dirfd +/// Available since Linux 2.6.16 +mknodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, dev: Dev) -> (Errno) { + ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, dev) + return Errno(-ret) +} + +/// Change the ownership of the file specified relative to directory +/// Available since Linux 2.6.16 +fchownat :: proc "contextless" (dirfd: Fd, name: cstring, uid: Uid, gid: Gid) -> (Errno) { + ret := syscall(SYS_fchownat, dirfd, cast(rawptr) name, uid, gid) + return Errno(-ret) +} + +// TODO(flysand): futimesat + +/// Get information about a file at a specific directory +/// Available since Linux 2.6.16 +fstatat :: proc "contextless" (dirfd: Fd, name: cstring, stat: ^Stat, flags: FD_Flags) -> (Errno) { + when size_of(int) == 4 { + ret := syscall(SYS_fstatat64, dirfd, cast(rawptr) name, stat, transmute(i32) flags) + return Errno(-ret) + } else when ODIN_ARCH == .amd64 { + ret := syscall(SYS_newfstatat, dirfd, cast(rawptr) name, stat, transmute(i32) flags) + return Errno(-ret) + } else { + ret := syscall(SYS_fstatat, dirfd, cast(rawptr) name, stat, transmute(i32) flags) + return Errno(-ret) + } +} + +/// Remove a directory entry relative to a directory file descriptor +/// Available since Linux 2.6.16 +unlinkat :: proc "contextless" (dirfd: Fd, name: cstring, flags: FD_Flags) -> (Errno) { + ret := syscall(SYS_unlinkat, dirfd, cast(rawptr) name, transmute(i32) flags) + return Errno(-ret) +} + +/// Rename the file with names relative to the specified dirfd's +/// Available since Linux 2.6.16 +renameat :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring) -> (Errno) { + ret := syscall(SYS_renameat, oldfd, cast(rawptr) old, newfd, cast(rawptr) new) + return Errno(-ret) +} + +/// Creates a hard link on a file relative to specified dirfd +/// Available since Linux 2.6.16 +linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd, link: cstring, flags: FD_Flags) -> (Errno) { + ret := syscall(SYS_linkat, target_dirfd, cast(rawptr) oldpath, link_dirfd, cast(rawptr) link, transmute(i32) flags) + return Errno(-ret) +} + +/// 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) + return Errno(-ret) +} + +/// Read the value of a symbolic link at given dirfd +/// Available since Linux 2.6.16 +readlinkat :: proc "contextless" (dirfd: Fd, name: cstring, buf: []u8) -> (int, Errno) { + ret := syscall(SYS_readlinkat, dirfd, cast(rawptr) name, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) +} + +/// Change the file mode at a specified file descriptor +/// Available since Linux 2.6.16 +fchmodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, flags: FD_Flags) -> (Errno) { + ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags) + return Errno(-ret) +} + +/// Checks the user permissions for a file at specified dirfd +/// Available since Linux 2.6.16 +faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) -> (bool, Errno) { + ret := syscall(SYS_faccessat, dirfd, cast(rawptr) name, transmute(u32) mode) + return errno_unwrap(ret, bool) +} + +// TODO(flysand): pselect6 + +/// 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) { + when size_of(int) == 8 { + ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) + return Errno(-ret) + } else { + ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) + return Errno(-ret) + } +} + +// TODO(flysand): unshare + +// TODO(flysand): set_robust_list + +// TODO(flysand): get_robust_list + +// TODO(flysand): splice + +// TODO(flysand): tee + +// TODO(flysand): sync_file_range + +// TODO(flysand): vmsplice + +// TODO(flysand): move_pages + +/// Change file timestamps with nanosecond precision +/// Available since Linux 2.6.22 +utimensat :: proc "contextless" (dirfd: Fd, name: cstring, timespec: ^Time_Spec, flags: FD_Flags) -> (Errno) { + ret := syscall(SYS_utimensat, dirfd, cast(rawptr) name, timespec, transmute(i32) flags) + return Errno(-ret) +} + +// TODO(flysand): epoll_pwait + +// TODO(flysand): signalfd + +// TODO(flysand): timerfd_create + +// TODO(flysand): eventfd + +// TODO(flysand): fallocate + +// TODO(flysand): timerfd_settime + +// TODO(flysand): timerfd_gettime + +// TODO(flysand): accept4 + +// TODO(flysand): signalfd4 + +// TODO(flysand): eventfd2 + +// TODO(flysand): epoll_create1 + +/// Adjust an existing file descriptor to point to the same file as `old` +/// In addition to dup2 allows to pass O_CLOEXEC flag +/// Available since Linux 2.6.27 +dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno) { + ret := syscall(SYS_dup3, old, new, transmute(i32) flags) + return errno_unwrap(ret, Fd) +} + +// TODO(flysand): inotify_init1 + +// TODO(flysand): preadv + +// 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) { + ret := syscall(SYS_rt_tgsigqueueinfo, tgid, pid, sig, si) + return Errno(-ret) +} + +/// Set up performance monitoring +/// Available since Linux 2.6.31 +perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: int, group_fd: Fd, flags: Perf_Flags = {}) -> (Fd, Errno) { + ret := syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, transmute(uint) flags) + return errno_unwrap(ret, Fd) +} + +// TODO(flysand): recvmmsg + +// TODO(flysand): fanotify_init + +// TODO(flysand): fanotify_mark + +// TODO(flysand): prlimit64 + +// TODO(flysand): name_to_handle_at + +// TODO(flysand): open_by_handle_at + +// TODO(flysand): clock_adjtime + +// TODO(flysand): syncfs + +// TODO(flysand): sendmmsg + +// TODO(flysand): setns + +// TODO(flysand): getcpu + +// TODO(flysand): process_vm_readv + +// TODO(flysand): process_vm_writev + +// TODO(flysand): kcmp + +// TODO(flysand): finit_module + +// TODO(flysand): sched_setattr + +// TODO(flysand): sched_getattr + +/// Rename the file with names relative to the specified dirfd's with other options +/// Available since Linux 3.15 +renameat2 :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring, flags: Rename_Flags) -> (Errno) { + ret := syscall(SYS_renameat2, oldfd, cast(rawptr) old, newfd, cast(rawptr) new, transmute(u32) flags) + return Errno(-ret) +} + +// TODO(flysand): seccomp + +getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Errno) { + ret := syscall(SYS_getrandom, raw_data(buf), len(buf), transmute(i32) flags) + return errno_unwrap(ret, int) +} + +// TODO(flysand): memfd_create + +// TODO(flysand): kexec_file_load + +// TODO(flysand): bpf + +// TODO(flysand): execveat + +// TODO(flysand): userfaultfd + +// TODO(flysand): membarrier + +// TODO(flysand): mlock2 + +// TODO(flysand): copy_file_range + +// TODO(flysand): preadv2 + +// TODO(flysand): pwritev2 + +// TODO(flysand): pkey_mprotect + +// TODO(flysand): pkey_alloc + +// TODO(flysand): pkey_free + +/// Query extended information about the file +/// +/// The file can be specified as: +/// absolute pathname: `dir` parameter is ignored +/// relatvie pathname: `dir` parameter specifies the base directory's fd +/// file descriptor: `AT_EMPTY_PATH` is passed in flags, pathname is empty, `dir` specifies the file descriptor +/// +/// Available since Linux 4.11 +statx :: proc "contextless" (dir: Fd, pathname: cstring, flags: FD_Flags, mask: Statx_Mask, statx: ^Statx) -> (Errno) { + ret := syscall(SYS_statx, dir, transmute(uintptr) pathname, transmute(i32) flags, transmute(u32) mask, statx) + return Errno(-ret) +} + +// TODO(flysand): io_pgetevents + +// TODO(flysand): rseq + +// TODO(flysand): pidfd_send_signal + +// TODO(flysand): io_uring_setup + +// TODO(flysand): io_uring_enter + +// TODO(flysand): io_uring_register + +// TODO(flysand): open_tree + +// TODO(flysand): move_mount + +// TODO(flysand): fsopen + +// TODO(flysand): fsconfig + +// TODO(flysand): fsmount + +// TODO(flysand): fspick + +/// Creates a new PID file descriptor +/// The process identified by `pid` must be a pid group leader +/// The returned `pidfd` has `CLOEXEC` semantics +/// Available since Linux 5.3 +pidfd_open :: proc "contextless" (pid: Pid, flags: Pid_FD_Flags) -> (Pid_FD, Errno) { + ret := syscall(SYS_pidfd_open, pid, transmute(i32) flags) + return errno_unwrap(ret, Pid_FD) +} + +// TODO(flysand): clone3 (probably not this PR) + +/// Close the range of files as an atomic operation +/// The range of file descriptors is inclusive, and may contain invalid file descriptors +/// Available since Linux 5.9 +close_range :: proc "contextless" (lo: Fd, hi: Fd, flags: Close_Range_Flags) -> (Errno) { + ret := syscall(SYS_close_range, lo, hi, transmute(u32) flags) + return Errno(-ret) +} + +// TODO(flysand): openat2 + +/// Get a file descriptor from another process +/// `fd` refers to a file descriptor number to get +/// `flags` must be zero +/// Available since Linux 5.3 +pidfd_getfd :: proc "contextless" (pidfd: Pid_FD, fd: Fd, flags: i32 = 0) -> (Fd, Errno) { + ret := syscall(SYS_pidfd_getfd, pidfd, fd, flags) + return errno_unwrap(ret, Fd) +} + +/// Checks the user permissions for a file at specified dirfd (with flags) +/// Available since Linux 5.8 +faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, flags: FD_Flags = FD_Flags{}) -> (bool, Errno) { + ret := syscall(SYS_faccessat2, dirfd, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags) + return errno_unwrap(ret, bool) +} + +// TODO(flysand): process_madvise + +// TODO(flysand): epoll_pwait2 + +// TODO(flysand): mount_setattr + +// TODO(flysand): quotactl_fd + +// TODO(flysand): landlock_create_ruleset + +// TODO(flysand): landlock_add_rule + +// TODO(flysand): landlock_restrict_self + +// TODO(flysand): memfd_secret + +// TODO(flysand): process_mrelease + +// TODO(flysand): futex_waitv + +// TODO(flysand): set_mempolicy_home_node + +// TODO(flysand): cachestat + +// TODO(flysand): fchmodat2 + +// TODO(flysand): map_shadow_stack diff --git a/core/sys/linux/syscall_amd64.odin b/core/sys/linux/syscall_amd64.odin new file mode 100644 index 000000000..ee4e16280 --- /dev/null +++ b/core/sys/linux/syscall_amd64.odin @@ -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) diff --git a/core/sys/linux/syscall_arm32.odin b/core/sys/linux/syscall_arm32.odin new file mode 100644 index 000000000..74640a1a3 --- /dev/null +++ b/core/sys/linux/syscall_arm32.odin @@ -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) diff --git a/core/sys/linux/syscall_arm64.odin b/core/sys/linux/syscall_arm64.odin new file mode 100644 index 000000000..61b5a31b7 --- /dev/null +++ b/core/sys/linux/syscall_arm64.odin @@ -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) + + diff --git a/core/sys/linux/syscall_i386.odin b/core/sys/linux/syscall_i386.odin new file mode 100644 index 000000000..4609fc99c --- /dev/null +++ b/core/sys/linux/syscall_i386.odin @@ -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) diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin new file mode 100644 index 000000000..214aff9cf --- /dev/null +++ b/core/sys/linux/types.odin @@ -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, +} diff --git a/core/sys/linux/wrappers.odin b/core/sys/linux/wrappers.odin new file mode 100644 index 000000000..a4c4aac32 --- /dev/null +++ b/core/sys/linux/wrappers.odin @@ -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) +} \ No newline at end of file -- cgit v1.2.3