Files
zig/lib/std/os/linux/x86_64.zig
Andrew Kelley 3deda15e21 std.os reorganization, avoiding usingnamespace
The main purpose of this branch is to explore avoiding the
`usingnamespace` feature of the zig language, specifically with regards
to `std.os` and related functionality.

If this experiment is successful, it will provide a data point on
whether or not it would be practical to entirely remove `usingnamespace`
from the language.

In this commit, `usingnamespace` has been completely eliminated from
the Linux x86_64 compilation path, aside from io_uring.

The behavior tests pass, however that's as far as this branch goes. It is
very breaking, and a lot more work is needed before it could be
considered mergeable. I wanted to put a pull requset up early so that
zig programmers have time to provide feedback.

This is progress towards closing #6600 since it clarifies where the
actual "owner" of each declaration is, and reduces the number of
different ways to import the same declarations.

One of the main organizational strategies used here is to do namespacing
with real namespaces (e.g. structs) rather than by having declarations
share a common prefix (the C strategy). It's no coincidence that
`usingnamespace` has similar semantics to `#include` and becomes much
less necessary when using proper namespaces.
2021-09-01 17:54:06 -07:00

790 lines
17 KiB
Zig

const std = @import("../../std.zig");
const linux = std.os.linux;
const pid_t = linux.pid_t;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const clock_t = linux.clock_t;
const stack_t = linux.stack_t;
const sigset_t = linux.sigset_t;
const sockaddr = linux.sockaddr;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
pub fn syscall0(number: SYS) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
: "rcx", "r11", "memory"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
: "rcx", "r11", "memory"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
: "rcx", "r11", "memory"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
: "rcx", "r11", "memory"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4),
: "rcx", "r11", "memory"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5),
: "rcx", "r11", "memory"
);
}
pub fn syscall6(
number: SYS,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
arg6: usize,
) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5),
[arg6] "{r9}" (arg6),
: "rcx", "r11", "memory"
);
}
/// This matches the libc clone function.
pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("syscall"
:
: [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
: "rcx", "r11", "memory"
);
}
pub const mode_t = usize;
pub const time_t = isize;
pub const SYS = enum(usize) {
read = 0,
write = 1,
open = 2,
close = 3,
stat = 4,
fstat = 5,
lstat = 6,
poll = 7,
lseek = 8,
mmap = 9,
mprotect = 10,
munmap = 11,
brk = 12,
rt_sigaction = 13,
rt_sigprocmask = 14,
rt_sigreturn = 15,
ioctl = 16,
pread = 17,
pwrite = 18,
readv = 19,
writev = 20,
access = 21,
pipe = 22,
select = 23,
sched_yield = 24,
mremap = 25,
msync = 26,
mincore = 27,
madvise = 28,
shmget = 29,
shmat = 30,
shmctl = 31,
dup = 32,
dup2 = 33,
pause = 34,
nanosleep = 35,
getitimer = 36,
alarm = 37,
setitimer = 38,
getpid = 39,
sendfile = 40,
socket = 41,
connect = 42,
accept = 43,
sendto = 44,
recvfrom = 45,
sendmsg = 46,
recvmsg = 47,
shutdown = 48,
bind = 49,
listen = 50,
getsockname = 51,
getpeername = 52,
socketpair = 53,
setsockopt = 54,
getsockopt = 55,
clone = 56,
fork = 57,
vfork = 58,
execve = 59,
exit = 60,
wait4 = 61,
kill = 62,
uname = 63,
semget = 64,
semop = 65,
semctl = 66,
shmdt = 67,
msgget = 68,
msgsnd = 69,
msgrcv = 70,
msgctl = 71,
fcntl = 72,
flock = 73,
fsync = 74,
fdatasync = 75,
truncate = 76,
ftruncate = 77,
getdents = 78,
getcwd = 79,
chdir = 80,
fchdir = 81,
rename = 82,
mkdir = 83,
rmdir = 84,
creat = 85,
link = 86,
unlink = 87,
symlink = 88,
readlink = 89,
chmod = 90,
fchmod = 91,
chown = 92,
fchown = 93,
lchown = 94,
umask = 95,
gettimeofday = 96,
getrlimit = 97,
getrusage = 98,
sysinfo = 99,
times = 100,
ptrace = 101,
getuid = 102,
syslog = 103,
getgid = 104,
setuid = 105,
setgid = 106,
geteuid = 107,
getegid = 108,
setpgid = 109,
getppid = 110,
getpgrp = 111,
setsid = 112,
setreuid = 113,
setregid = 114,
getgroups = 115,
setgroups = 116,
setresuid = 117,
getresuid = 118,
setresgid = 119,
getresgid = 120,
getpgid = 121,
setfsuid = 122,
setfsgid = 123,
getsid = 124,
capget = 125,
capset = 126,
rt_sigpending = 127,
rt_sigtimedwait = 128,
rt_sigqueueinfo = 129,
rt_sigsuspend = 130,
sigaltstack = 131,
utime = 132,
mknod = 133,
uselib = 134,
personality = 135,
ustat = 136,
statfs = 137,
fstatfs = 138,
sysfs = 139,
getpriority = 140,
setpriority = 141,
sched_setparam = 142,
sched_getparam = 143,
sched_setscheduler = 144,
sched_getscheduler = 145,
sched_get_priority_max = 146,
sched_get_priority_min = 147,
sched_rr_get_interval = 148,
mlock = 149,
munlock = 150,
mlockall = 151,
munlockall = 152,
vhangup = 153,
modify_ldt = 154,
pivot_root = 155,
_sysctl = 156,
prctl = 157,
arch_prctl = 158,
adjtimex = 159,
setrlimit = 160,
chroot = 161,
sync = 162,
acct = 163,
settimeofday = 164,
mount = 165,
umount2 = 166,
swapon = 167,
swapoff = 168,
reboot = 169,
sethostname = 170,
setdomainname = 171,
iopl = 172,
ioperm = 173,
create_module = 174,
init_module = 175,
delete_module = 176,
get_kernel_syms = 177,
query_module = 178,
quotactl = 179,
nfsservctl = 180,
getpmsg = 181,
putpmsg = 182,
afs_syscall = 183,
tuxcall = 184,
security = 185,
gettid = 186,
readahead = 187,
setxattr = 188,
lsetxattr = 189,
fsetxattr = 190,
getxattr = 191,
lgetxattr = 192,
fgetxattr = 193,
listxattr = 194,
llistxattr = 195,
flistxattr = 196,
removexattr = 197,
lremovexattr = 198,
fremovexattr = 199,
tkill = 200,
time = 201,
futex = 202,
sched_setaffinity = 203,
sched_getaffinity = 204,
set_thread_area = 205,
io_setup = 206,
io_destroy = 207,
io_getevents = 208,
io_submit = 209,
io_cancel = 210,
get_thread_area = 211,
lookup_dcookie = 212,
epoll_create = 213,
epoll_ctl_old = 214,
epoll_wait_old = 215,
remap_file_pages = 216,
getdents64 = 217,
set_tid_address = 218,
restart_syscall = 219,
semtimedop = 220,
fadvise64 = 221,
timer_create = 222,
timer_settime = 223,
timer_gettime = 224,
timer_getoverrun = 225,
timer_delete = 226,
clock_settime = 227,
clock_gettime = 228,
clock_getres = 229,
clock_nanosleep = 230,
exit_group = 231,
epoll_wait = 232,
epoll_ctl = 233,
tgkill = 234,
utimes = 235,
vserver = 236,
mbind = 237,
set_mempolicy = 238,
get_mempolicy = 239,
mq_open = 240,
mq_unlink = 241,
mq_timedsend = 242,
mq_timedreceive = 243,
mq_notify = 244,
mq_getsetattr = 245,
kexec_load = 246,
waitid = 247,
add_key = 248,
request_key = 249,
keyctl = 250,
ioprio_set = 251,
ioprio_get = 252,
inotify_init = 253,
inotify_add_watch = 254,
inotify_rm_watch = 255,
migrate_pages = 256,
openat = 257,
mkdirat = 258,
mknodat = 259,
fchownat = 260,
futimesat = 261,
fstatat = 262,
unlinkat = 263,
renameat = 264,
linkat = 265,
symlinkat = 266,
readlinkat = 267,
fchmodat = 268,
faccessat = 269,
pselect6 = 270,
ppoll = 271,
unshare = 272,
set_robust_list = 273,
get_robust_list = 274,
splice = 275,
tee = 276,
sync_file_range = 277,
vmsplice = 278,
move_pages = 279,
utimensat = 280,
epoll_pwait = 281,
signalfd = 282,
timerfd_create = 283,
eventfd = 284,
fallocate = 285,
timerfd_settime = 286,
timerfd_gettime = 287,
accept4 = 288,
signalfd4 = 289,
eventfd2 = 290,
epoll_create1 = 291,
dup3 = 292,
pipe2 = 293,
inotify_init1 = 294,
preadv = 295,
pwritev = 296,
rt_tgsigqueueinfo = 297,
perf_event_open = 298,
recvmmsg = 299,
fanotify_init = 300,
fanotify_mark = 301,
prlimit64 = 302,
name_to_handle_at = 303,
open_by_handle_at = 304,
clock_adjtime = 305,
syncfs = 306,
sendmmsg = 307,
setns = 308,
getcpu = 309,
process_vm_readv = 310,
process_vm_writev = 311,
kcmp = 312,
finit_module = 313,
sched_setattr = 314,
sched_getattr = 315,
renameat2 = 316,
seccomp = 317,
getrandom = 318,
memfd_create = 319,
kexec_file_load = 320,
bpf = 321,
execveat = 322,
userfaultfd = 323,
membarrier = 324,
mlock2 = 325,
copy_file_range = 326,
preadv2 = 327,
pwritev2 = 328,
pkey_mprotect = 329,
pkey_alloc = 330,
pkey_free = 331,
statx = 332,
io_pgetevents = 333,
rseq = 334,
pidfd_send_signal = 424,
io_uring_setup = 425,
io_uring_enter = 426,
io_uring_register = 427,
open_tree = 428,
move_mount = 429,
fsopen = 430,
fsconfig = 431,
fsmount = 432,
fspick = 433,
pidfd_open = 434,
clone3 = 435,
close_range = 436,
openat2 = 437,
pidfd_getfd = 438,
faccessat2 = 439,
process_madvise = 440,
epoll_pwait2 = 441,
_,
};
pub const O = struct {
pub const RDONLY = 0o0;
pub const WRONLY = 0o1;
pub const RDWR = 0o2;
pub const CREAT = 0o100;
pub const EXCL = 0o200;
pub const NOCTTY = 0o400;
pub const TRUNC = 0o1000;
pub const APPEND = 0o2000;
pub const NONBLOCK = 0o4000;
pub const DSYNC = 0o10000;
pub const SYNC = 0o4010000;
pub const RSYNC = 0o4010000;
pub const DIRECTORY = 0o200000;
pub const NOFOLLOW = 0o400000;
pub const CLOEXEC = 0o2000000;
pub const ASYNC = 0o20000;
pub const DIRECT = 0o40000;
pub const LARGEFILE = 0;
pub const NOATIME = 0o1000000;
pub const PATH = 0o10000000;
pub const TMPFILE = 0o20200000;
pub const NDELAY = NONBLOCK;
};
pub const F = struct {
pub const DUPFD = 0;
pub const GETFD = 1;
pub const SETFD = 2;
pub const GETFL = 3;
pub const SETFL = 4;
pub const GETLK = 5;
pub const SETLK = 6;
pub const SETLKW = 7;
pub const SETOWN = 8;
pub const GETOWN = 9;
pub const SETSIG = 10;
pub const GETSIG = 11;
pub const SETOWN_EX = 15;
pub const GETOWN_EX = 16;
pub const GETOWNER_UIDS = 17;
pub const RDLCK = 0;
pub const WRLCK = 1;
pub const UNLCK = 2;
};
pub const MAP = struct {
/// Share changes
pub const SHARED = 0x01;
/// Changes are private
pub const PRIVATE = 0x02;
/// share + validate extension flags
pub const SHARED_VALIDATE = 0x03;
/// Mask for type of mapping
pub const TYPE = 0x0f;
/// Interpret addr exactly
pub const FIXED = 0x10;
/// don't use a file
pub const ANONYMOUS = 0x20;
/// populate (prefault) pagetables
pub const POPULATE = 0x8000;
/// do not block on IO
pub const NONBLOCK = 0x10000;
/// give out an address that is best suited for process/thread stacks
pub const STACK = 0x20000;
/// create a huge page mapping
pub const HUGETLB = 0x40000;
/// perform synchronous page faults for the mapping
pub const SYNC = 0x80000;
/// FIXED which doesn't unmap underlying mapping
pub const FIXED_NOREPLACE = 0x100000;
/// For anonymous mmap, memory could be uninitialized
pub const UNINITIALIZED = 0x4000000;
/// only give out 32bit addresses
pub const @"32BIT" = 0x40;
/// stack-like segment
pub const GROWSDOWN = 0x0100;
/// ETXTBSY
pub const DENYWRITE = 0x0800;
/// mark it as an executable
pub const EXECUTABLE = 0x1000;
/// pages are locked
pub const LOCKED = 0x2000;
/// don't check for reservations
pub const NORESERVE = 0x4000;
};
pub const VDSO = struct {
pub const CGT_SYM = "__vdso_clock_gettime";
pub const CGT_VER = "LINUX_2.6";
pub const GETCPU_SYM = "__vdso_getcpu";
pub const GETCPU_VER = "LINUX_2.6";
};
pub const ARCH = struct {
pub const SET_GS = 0x1001;
pub const SET_FS = 0x1002;
pub const GET_FS = 0x1003;
pub const GET_GS = 0x1004;
};
pub const REG = struct {
pub const R8 = 0;
pub const R9 = 1;
pub const R10 = 2;
pub const R11 = 3;
pub const R12 = 4;
pub const R13 = 5;
pub const R14 = 6;
pub const R15 = 7;
pub const RDI = 8;
pub const RSI = 9;
pub const RBP = 10;
pub const RBX = 11;
pub const RDX = 12;
pub const RAX = 13;
pub const RCX = 14;
pub const RSP = 15;
pub const RIP = 16;
pub const EFL = 17;
pub const CSGSFS = 18;
pub const ERR = 19;
pub const TRAPNO = 20;
pub const OLDMASK = 21;
pub const CR2 = 22;
};
pub const LOCK = struct {
pub const SH = 1;
pub const EX = 2;
pub const NB = 4;
pub const UN = 8;
};
pub const Flock = extern struct {
type: i16,
whence: i16,
start: off_t,
len: off_t,
pid: pid_t,
};
pub const msghdr = extern struct {
name: ?*sockaddr,
namelen: socklen_t,
iov: [*]iovec,
iovlen: i32,
__pad1: i32 = 0,
control: ?*c_void,
controllen: socklen_t,
__pad2: socklen_t = 0,
flags: i32,
};
pub const msghdr_const = extern struct {
name: ?*const sockaddr,
namelen: socklen_t,
iov: [*]iovec_const,
iovlen: i32,
__pad1: i32 = 0,
control: ?*c_void,
controllen: socklen_t,
__pad2: socklen_t = 0,
flags: i32,
};
pub const off_t = i64;
pub const ino_t = u64;
pub const dev_t = u64;
// The `stat` definition used by the Linux kernel.
pub const kernel_stat = extern struct {
dev: dev_t,
ino: ino_t,
nlink: usize,
mode: u32,
uid: uid_t,
gid: gid_t,
__pad0: u32,
rdev: dev_t,
size: off_t,
blksize: isize,
blocks: i64,
atim: timespec,
mtim: timespec,
ctim: timespec,
__unused: [3]isize,
pub fn atime(self: @This()) timespec {
return self.atim;
}
pub fn mtime(self: @This()) timespec {
return self.mtim;
}
pub fn ctime(self: @This()) timespec {
return self.ctim;
}
};
// The `stat64` definition used by the libc.
pub const libc_stat = kernel_stat;
pub const timespec = extern struct {
tv_sec: isize,
tv_nsec: isize,
};
pub const timeval = extern struct {
tv_sec: isize,
tv_usec: isize,
};
pub const timezone = extern struct {
tz_minuteswest: i32,
tz_dsttime: i32,
};
pub const Elf_Symndx = u32;
pub const greg_t = usize;
pub const gregset_t = [23]greg_t;
pub const fpstate = extern struct {
cwd: u16,
swd: u16,
ftw: u16,
fop: u16,
rip: usize,
rdp: usize,
mxcsr: u32,
mxcr_mask: u32,
st: [8]extern struct {
significand: [4]u16,
exponent: u16,
padding: [3]u16 = undefined,
},
xmm: [16]extern struct {
element: [4]u32,
},
padding: [24]u32 = undefined,
};
pub const fpregset_t = *fpstate;
pub const sigcontext = extern struct {
r8: usize,
r9: usize,
r10: usize,
r11: usize,
r12: usize,
r13: usize,
r14: usize,
r15: usize,
rdi: usize,
rsi: usize,
rbp: usize,
rbx: usize,
rdx: usize,
rax: usize,
rcx: usize,
rsp: usize,
rip: usize,
eflags: usize,
cs: u16,
gs: u16,
fs: u16,
pad0: u16 = undefined,
err: usize,
trapno: usize,
oldmask: usize,
cr2: usize,
fpstate: *fpstate,
reserved1: [8]usize = undefined,
};
pub const mcontext_t = extern struct {
gregs: gregset_t,
fpregs: fpregset_t,
reserved1: [8]usize = undefined,
};
pub const ucontext_t = extern struct {
flags: usize,
link: *ucontext_t,
stack: stack_t,
mcontext: mcontext_t,
sigmask: sigset_t,
fpregs_mem: [64]usize,
};