mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-20 16:36:46 +00:00
Merge branch 'master' into new-temp-allocator
This commit is contained in:
@@ -12,7 +12,7 @@ _rand_bytes :: proc (dst: []byte) {
|
||||
|
||||
for l > 0 {
|
||||
to_read := min(l, _MAX_PER_CALL_BYTES)
|
||||
ret := unix.sys_getrandom(raw_data(dst), to_read, 0)
|
||||
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
|
||||
if ret < 0 {
|
||||
switch os.Errno(-ret) {
|
||||
case os.EINTR:
|
||||
|
||||
@@ -283,7 +283,7 @@ wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -
|
||||
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
|
||||
|
||||
// x86 Targets (i386, amd64)
|
||||
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
|
||||
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
|
||||
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
|
||||
|
||||
|
||||
@@ -305,4 +305,4 @@ valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2,
|
||||
|
||||
// Internal compiler use only
|
||||
|
||||
__entry_point :: proc() ---
|
||||
__entry_point :: proc() ---
|
||||
|
||||
+42
-34
@@ -277,8 +277,10 @@ foreign libc {
|
||||
|
||||
@(link_name="open") _unix_open :: proc(path: cstring, flags: i32, mode: u16) -> Handle ---
|
||||
@(link_name="close") _unix_close :: proc(handle: Handle) -> c.int ---
|
||||
@(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---
|
||||
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---
|
||||
@(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
|
||||
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
|
||||
@(link_name="pread") _unix_pread :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
||||
@(link_name="pwrite") _unix_pwrite :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
||||
@(link_name="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: int) -> int ---
|
||||
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
||||
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
|
||||
@@ -386,45 +388,51 @@ close :: proc(fd: Handle) -> bool {
|
||||
@(private)
|
||||
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
|
||||
|
||||
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
assert(fd != -1)
|
||||
|
||||
bytes_total := len(data)
|
||||
bytes_written_total := 0
|
||||
|
||||
for bytes_written_total < bytes_total {
|
||||
bytes_to_write := min(bytes_total - bytes_written_total, MAX_RW)
|
||||
slice := data[bytes_written_total:bytes_written_total + bytes_to_write]
|
||||
bytes_written := _unix_write(fd, raw_data(slice), bytes_to_write)
|
||||
if bytes_written == -1 {
|
||||
return bytes_written_total, 1
|
||||
}
|
||||
bytes_written_total += bytes_written
|
||||
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
return bytes_written_total, 0
|
||||
bytes_written := _unix_write(fd, raw_data(data), c.size_t(len(data)))
|
||||
if bytes_written < 0 {
|
||||
return -1, Errno(get_last_error())
|
||||
}
|
||||
return bytes_written, ERROR_NONE
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
assert(fd != -1)
|
||||
|
||||
bytes_total := len(data)
|
||||
bytes_read_total := 0
|
||||
|
||||
for bytes_read_total < bytes_total {
|
||||
bytes_to_read := min(bytes_total - bytes_read_total, MAX_RW)
|
||||
slice := data[bytes_read_total:bytes_read_total + bytes_to_read]
|
||||
bytes_read := _unix_read(fd, raw_data(slice), bytes_to_read)
|
||||
if bytes_read == -1 {
|
||||
return bytes_read_total, 1
|
||||
}
|
||||
if bytes_read == 0 {
|
||||
break
|
||||
}
|
||||
bytes_read_total += bytes_read
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
return bytes_read_total, 0
|
||||
bytes_read := _unix_read(fd, raw_data(data), c.size_t(len(data)))
|
||||
if bytes_read < 0 {
|
||||
return -1, Errno(get_last_error())
|
||||
}
|
||||
return bytes_read, ERROR_NONE
|
||||
}
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
bytes_read := _unix_pread(fd, raw_data(data), c.size_t(len(data)), offset)
|
||||
if bytes_read < 0 {
|
||||
return -1, Errno(get_last_error())
|
||||
}
|
||||
return bytes_read, ERROR_NONE
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
bytes_written := _unix_pwrite(fd, raw_data(data), c.size_t(len(data)), offset)
|
||||
if bytes_written < 0 {
|
||||
return -1, Errno(get_last_error())
|
||||
}
|
||||
return bytes_written, ERROR_NONE
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
|
||||
+70
-157
@@ -270,136 +270,6 @@ AT_FDCWD :: ~uintptr(99) /* -100 */
|
||||
AT_REMOVEDIR :: uintptr(0x200)
|
||||
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
|
||||
|
||||
_unix_personality :: proc(persona: u64) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_personality, uintptr(persona)))
|
||||
}
|
||||
|
||||
_unix_fork :: proc() -> Pid {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
res := int(intrinsics.syscall(unix.SYS_fork))
|
||||
} else {
|
||||
res := int(intrinsics.syscall(unix.SYS_clone, unix.SIGCHLD))
|
||||
}
|
||||
return -1 if res < 0 else Pid(res)
|
||||
}
|
||||
|
||||
_unix_open :: proc(path: cstring, flags: int, mode: int = 0o000) -> Handle {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
res := int(intrinsics.syscall(unix.SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||
} else { // NOTE: arm64 does not have open
|
||||
res := int(intrinsics.syscall(unix.SYS_openat, AT_FDCWD, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||
}
|
||||
return -1 if res < 0 else Handle(res)
|
||||
}
|
||||
|
||||
_unix_close :: proc(fd: Handle) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_close, uintptr(fd)))
|
||||
}
|
||||
|
||||
_unix_read :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_read, uintptr(fd), uintptr(buf), uintptr(size)))
|
||||
}
|
||||
|
||||
_unix_write :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_write, uintptr(fd), uintptr(buf), uintptr(size)))
|
||||
}
|
||||
|
||||
_unix_seek :: proc(fd: Handle, offset: i64, whence: int) -> i64 {
|
||||
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
|
||||
return i64(intrinsics.syscall(unix.SYS_lseek, uintptr(fd), uintptr(offset), uintptr(whence)))
|
||||
} else {
|
||||
low := uintptr(offset & 0xFFFFFFFF)
|
||||
high := uintptr(offset >> 32)
|
||||
result: i64
|
||||
res := i64(intrinsics.syscall(unix.SYS__llseek, uintptr(fd), high, low, uintptr(&result), uintptr(whence)))
|
||||
return -1 if res < 0 else result
|
||||
}
|
||||
}
|
||||
|
||||
_unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> int {
|
||||
when ODIN_ARCH == .amd64 {
|
||||
return int(intrinsics.syscall(unix.SYS_stat, uintptr(rawptr(path)), uintptr(stat)))
|
||||
} else when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_stat64, uintptr(rawptr(path)), uintptr(stat)))
|
||||
} else { // NOTE: arm64 does not have stat
|
||||
return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), 0))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> int {
|
||||
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_fstat, uintptr(fd), uintptr(stat)))
|
||||
} else {
|
||||
return int(intrinsics.syscall(unix.SYS_fstat64, uintptr(fd), uintptr(stat)))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> int {
|
||||
when ODIN_ARCH == .amd64 {
|
||||
return int(intrinsics.syscall(unix.SYS_lstat, uintptr(rawptr(path)), uintptr(stat)))
|
||||
} else when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_lstat64, uintptr(rawptr(path)), uintptr(stat)))
|
||||
} else { // NOTE: arm64 does not have any lstat
|
||||
return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_readlink :: proc(path: cstring, buf: rawptr, bufsiz: uint) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_readlink, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
|
||||
} else { // NOTE: arm64 does not have readlink
|
||||
return int(intrinsics.syscall(unix.SYS_readlinkat, AT_FDCWD, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_access :: proc(path: cstring, mask: int) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_access, uintptr(rawptr(path)), uintptr(mask)))
|
||||
} else { // NOTE: arm64 does not have access
|
||||
return int(intrinsics.syscall(unix.SYS_faccessat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mask)))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_getcwd :: proc(buf: rawptr, size: uint) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_getcwd, uintptr(buf), uintptr(size)))
|
||||
}
|
||||
|
||||
_unix_chdir :: proc(path: cstring) -> int {
|
||||
return int(intrinsics.syscall(unix.SYS_chdir, uintptr(rawptr(path))))
|
||||
}
|
||||
|
||||
_unix_rename :: proc(old, new: cstring) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_rename, uintptr(rawptr(old)), uintptr(rawptr(new))))
|
||||
} else { // NOTE: arm64 does not have rename
|
||||
return int(intrinsics.syscall(unix.SYS_renameat, AT_FDCWD, uintptr(rawptr(old)), uintptr(rawptr(new))))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_unlink :: proc(path: cstring) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_unlink, uintptr(rawptr(path))))
|
||||
} else { // NOTE: arm64 does not have unlink
|
||||
return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), 0))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_rmdir :: proc(path: cstring) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_rmdir, uintptr(rawptr(path))))
|
||||
} else { // NOTE: arm64 does not have rmdir
|
||||
return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), AT_REMOVEDIR))
|
||||
}
|
||||
}
|
||||
|
||||
_unix_mkdir :: proc(path: cstring, mode: u32) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(unix.SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
|
||||
} else { // NOTE: arm64 does not have mkdir
|
||||
return int(intrinsics.syscall(unix.SYS_mkdirat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mode)))
|
||||
}
|
||||
}
|
||||
|
||||
foreign libc {
|
||||
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
|
||||
|
||||
@@ -415,6 +285,7 @@ foreign libc {
|
||||
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
||||
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
|
||||
|
||||
@(link_name="execvp") _unix_execvp :: proc(path: cstring, argv: [^]cstring) -> int ---
|
||||
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
|
||||
@(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int ---
|
||||
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
||||
@@ -447,7 +318,7 @@ get_last_error :: proc "contextless" () -> int {
|
||||
}
|
||||
|
||||
personality :: proc(persona: u64) -> (Errno) {
|
||||
res := _unix_personality(persona)
|
||||
res := unix.sys_personality(persona)
|
||||
if res == -1 {
|
||||
return _get_errno(res)
|
||||
}
|
||||
@@ -455,29 +326,47 @@ personality :: proc(persona: u64) -> (Errno) {
|
||||
}
|
||||
|
||||
fork :: proc() -> (Pid, Errno) {
|
||||
pid := _unix_fork()
|
||||
pid := unix.sys_fork()
|
||||
if pid == -1 {
|
||||
return -1, _get_errno(int(pid))
|
||||
return -1, _get_errno(pid)
|
||||
}
|
||||
return pid, ERROR_NONE
|
||||
return Pid(pid), ERROR_NONE
|
||||
}
|
||||
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
|
||||
execvp :: proc(path: string, args: []string) -> Errno {
|
||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
|
||||
args_cstrs := make([]cstring, len(args) + 2, context.temp_allocator)
|
||||
args_cstrs[0] = strings.clone_to_cstring(path, context.temp_allocator)
|
||||
for i := 0; i < len(args); i += 1 {
|
||||
args_cstrs[i+1] = strings.clone_to_cstring(args[i], context.temp_allocator)
|
||||
}
|
||||
|
||||
_unix_execvp(path_cstr, raw_data(args_cstrs))
|
||||
return Errno(get_last_error())
|
||||
}
|
||||
|
||||
|
||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Errno) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
handle := _unix_open(cstr, flags, mode)
|
||||
handle := unix.sys_open(cstr, flags, uint(mode))
|
||||
if handle < 0 {
|
||||
return INVALID_HANDLE, _get_errno(int(handle))
|
||||
return INVALID_HANDLE, _get_errno(handle)
|
||||
}
|
||||
return handle, ERROR_NONE
|
||||
return Handle(handle), ERROR_NONE
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) -> Errno {
|
||||
return _get_errno(_unix_close(fd))
|
||||
return _get_errno(unix.sys_close(int(fd)))
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
bytes_read := unix.sys_read(int(fd), raw_data(data), len(data))
|
||||
if bytes_read < 0 {
|
||||
return -1, _get_errno(bytes_read)
|
||||
}
|
||||
@@ -488,25 +377,49 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
bytes_written := _unix_write(fd, &data[0], uint(len(data)))
|
||||
|
||||
bytes_written := unix.sys_write(int(fd), raw_data(data), len(data))
|
||||
if bytes_written < 0 {
|
||||
return -1, _get_errno(bytes_written)
|
||||
}
|
||||
return int(bytes_written), ERROR_NONE
|
||||
return bytes_written, ERROR_NONE
|
||||
}
|
||||
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
bytes_read := unix.sys_pread(int(fd), raw_data(data), len(data), offset)
|
||||
if bytes_read < 0 {
|
||||
return -1, _get_errno(bytes_read)
|
||||
}
|
||||
return bytes_read, ERROR_NONE
|
||||
}
|
||||
|
||||
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE
|
||||
}
|
||||
|
||||
bytes_written := unix.sys_pwrite(int(fd), raw_data(data), uint(len(data)), offset)
|
||||
if bytes_written < 0 {
|
||||
return -1, _get_errno(bytes_written)
|
||||
}
|
||||
return bytes_written, ERROR_NONE
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
res := _unix_seek(fd, offset, whence)
|
||||
res := unix.sys_lseek(int(fd), offset, whence)
|
||||
if res < 0 {
|
||||
return -1, _get_errno(int(res))
|
||||
}
|
||||
return res, ERROR_NONE
|
||||
return i64(res), ERROR_NONE
|
||||
}
|
||||
|
||||
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
// deliberately uninitialized; the syscall fills this buffer for us
|
||||
s: OS_Stat = ---
|
||||
result := _unix_fstat(fd, &s)
|
||||
result := unix.sys_fstat(int(fd), rawptr(&s))
|
||||
if result < 0 {
|
||||
return 0, _get_errno(result)
|
||||
}
|
||||
@@ -517,25 +430,25 @@ rename :: proc(old_path, new_path: string) -> Errno {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
|
||||
new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator)
|
||||
return _get_errno(_unix_rename(old_path_cstr, new_path_cstr))
|
||||
return _get_errno(unix.sys_rename(old_path_cstr, new_path_cstr))
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> Errno {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
return _get_errno(_unix_unlink(path_cstr))
|
||||
return _get_errno(unix.sys_unlink(path_cstr))
|
||||
}
|
||||
|
||||
make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
return _get_errno(_unix_mkdir(path_cstr, mode))
|
||||
return _get_errno(unix.sys_mkdir(path_cstr, uint(mode)))
|
||||
}
|
||||
|
||||
remove_directory :: proc(path: string) -> Errno {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
return _get_errno(_unix_rmdir(path_cstr))
|
||||
return _get_errno(unix.sys_rmdir(path_cstr))
|
||||
}
|
||||
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
@@ -589,7 +502,7 @@ is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
exists :: proc(path: string) -> bool {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
res := _unix_access(cpath, O_RDONLY)
|
||||
res := unix.sys_access(cpath, O_RDONLY)
|
||||
return res == 0
|
||||
}
|
||||
|
||||
@@ -628,7 +541,7 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
|
||||
|
||||
// deliberately uninitialized; the syscall fills this buffer for us
|
||||
s: OS_Stat = ---
|
||||
result := _unix_stat(cstr, &s)
|
||||
result := unix.sys_stat(cstr, &s)
|
||||
if result < 0 {
|
||||
return s, _get_errno(result)
|
||||
}
|
||||
@@ -642,7 +555,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
||||
|
||||
// deliberately uninitialized; the syscall fills this buffer for us
|
||||
s: OS_Stat = ---
|
||||
result := _unix_lstat(cstr, &s)
|
||||
result := unix.sys_lstat(cstr, &s)
|
||||
if result < 0 {
|
||||
return s, _get_errno(result)
|
||||
}
|
||||
@@ -653,7 +566,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
||||
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
||||
// deliberately uninitialized; the syscall fills this buffer for us
|
||||
s: OS_Stat = ---
|
||||
result := _unix_fstat(fd, &s)
|
||||
result := unix.sys_fstat(int(fd), rawptr(&s))
|
||||
if result < 0 {
|
||||
return s, _get_errno(result)
|
||||
}
|
||||
@@ -711,7 +624,7 @@ _readlink :: proc(path: string) -> (string, Errno) {
|
||||
bufsz : uint = 256
|
||||
buf := make([]byte, bufsz)
|
||||
for {
|
||||
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
|
||||
rc := unix.sys_readlink(path_cstr, &(buf[0]), bufsz)
|
||||
if rc < 0 {
|
||||
delete(buf)
|
||||
return "", _get_errno(rc)
|
||||
@@ -760,7 +673,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
|
||||
access :: proc(path: string, mask: int) -> (bool, Errno) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
result := _unix_access(cstr, mask)
|
||||
result := unix.sys_access(cstr, mask)
|
||||
if result < 0 {
|
||||
return false, _get_errno(result)
|
||||
}
|
||||
@@ -831,7 +744,7 @@ get_current_directory :: proc() -> string {
|
||||
page_size := get_page_size()
|
||||
buf := make([dynamic]u8, page_size)
|
||||
for {
|
||||
#no_bounds_check res := _unix_getcwd(&buf[0], uint(len(buf)))
|
||||
#no_bounds_check res := unix.sys_getcwd(&buf[0], uint(len(buf)))
|
||||
|
||||
if res >= 0 {
|
||||
return strings.string_from_nul_terminated_ptr(&buf[0], len(buf))
|
||||
@@ -848,7 +761,7 @@ get_current_directory :: proc() -> string {
|
||||
set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
res := _unix_chdir(cstr)
|
||||
res := unix.sys_chdir(cstr)
|
||||
if res < 0 {
|
||||
return _get_errno(res)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
package prof_spall
|
||||
|
||||
import "core:os"
|
||||
import "core:time"
|
||||
import "core:intrinsics"
|
||||
import "core:mem"
|
||||
|
||||
// File Format
|
||||
|
||||
MANUAL_MAGIC :: u64le(0x0BADF00D)
|
||||
|
||||
Manual_Header :: struct #packed {
|
||||
magic: u64le,
|
||||
version: u64le,
|
||||
timestamp_scale: f64le,
|
||||
reserved: u64le,
|
||||
}
|
||||
|
||||
Manual_Event_Type :: enum u8 {
|
||||
Invalid = 0,
|
||||
|
||||
Begin = 3,
|
||||
End = 4,
|
||||
Instant = 5,
|
||||
|
||||
Pad_Skip = 7,
|
||||
}
|
||||
|
||||
Begin_Event :: struct #packed {
|
||||
type: Manual_Event_Type,
|
||||
category: u8,
|
||||
pid: u32le,
|
||||
tid: u32le,
|
||||
ts: f64le,
|
||||
name_len: u8,
|
||||
args_len: u8,
|
||||
}
|
||||
BEGIN_EVENT_MAX :: size_of(Begin_Event) + 255 + 255
|
||||
|
||||
End_Event :: struct #packed {
|
||||
type: Manual_Event_Type,
|
||||
pid: u32le,
|
||||
tid: u32le,
|
||||
ts: f64le,
|
||||
}
|
||||
|
||||
Pad_Skip :: struct #packed {
|
||||
type: Manual_Event_Type,
|
||||
size: u32le,
|
||||
}
|
||||
|
||||
// User Interface
|
||||
|
||||
Context :: struct {
|
||||
precise_time: bool,
|
||||
timestamp_scale: f64,
|
||||
fd: os.Handle,
|
||||
}
|
||||
|
||||
Buffer :: struct {
|
||||
data: []u8,
|
||||
head: int,
|
||||
tid: u32,
|
||||
pid: u32,
|
||||
}
|
||||
|
||||
BUFFER_DEFAULT_SIZE :: 0x10_0000
|
||||
|
||||
|
||||
context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok {
|
||||
fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
|
||||
if err != os.ERROR_NONE {
|
||||
return
|
||||
}
|
||||
ctx.fd = fd
|
||||
|
||||
freq, freq_ok := time.tsc_frequency()
|
||||
ctx.precise_time = freq_ok
|
||||
ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
|
||||
|
||||
temp := [size_of(Manual_Header)]u8{}
|
||||
_build_header(temp[:], ctx.timestamp_scale)
|
||||
os.write(ctx.fd, temp[:])
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
context_destroy :: proc(ctx: ^Context) {
|
||||
if ctx == nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.close(ctx.fd)
|
||||
ctx^ = Context{}
|
||||
}
|
||||
|
||||
buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok {
|
||||
assert(len(data) > 0)
|
||||
buffer.data = data
|
||||
buffer.tid = tid
|
||||
buffer.pid = pid
|
||||
buffer.head = 0
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
buffer_flush :: proc(ctx: ^Context, buffer: ^Buffer) {
|
||||
os.write(ctx.fd, buffer.data[:buffer.head])
|
||||
buffer.head = 0
|
||||
}
|
||||
|
||||
buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) {
|
||||
buffer_flush(ctx, buffer)
|
||||
|
||||
buffer^ = Buffer{}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(deferred_in=_scoped_buffer_end)
|
||||
SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool {
|
||||
_buffer_begin(ctx, buffer, name, args, location)
|
||||
return true
|
||||
}
|
||||
|
||||
@(private)
|
||||
_scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) {
|
||||
_buffer_end(ctx, buffer)
|
||||
}
|
||||
|
||||
|
||||
_trace_now :: proc "contextless" (ctx: ^Context) -> f64 {
|
||||
if !ctx.precise_time {
|
||||
return f64(time.tick_now()._nsec) / 1_000
|
||||
}
|
||||
|
||||
return f64(intrinsics.read_cycle_counter())
|
||||
}
|
||||
|
||||
_build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok {
|
||||
header_size = size_of(Manual_Header)
|
||||
if header_size > len(buffer) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
hdr := (^Manual_Header)(raw_data(buffer))
|
||||
hdr.magic = MANUAL_MAGIC
|
||||
hdr.version = 1
|
||||
hdr.timestamp_scale = f64le(timestamp_scale)
|
||||
hdr.reserved = 0
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
_build_begin :: proc "contextless" (buffer: []u8, name: string, args: string, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok {
|
||||
ev := (^Begin_Event)(raw_data(buffer))
|
||||
name_len := min(len(name), 255)
|
||||
args_len := min(len(args), 255)
|
||||
|
||||
event_size = size_of(Begin_Event) + name_len + args_len
|
||||
if event_size > len(buffer) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
ev.type = .Begin
|
||||
ev.pid = u32le(pid)
|
||||
ev.tid = u32le(tid)
|
||||
ev.ts = f64le(ts)
|
||||
ev.name_len = u8(name_len)
|
||||
ev.args_len = u8(args_len)
|
||||
mem.copy(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len)
|
||||
mem.copy(raw_data(buffer[size_of(Begin_Event)+name_len:]), raw_data(args), args_len)
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
_build_end :: proc(buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok {
|
||||
ev := (^End_Event)(raw_data(buffer))
|
||||
event_size = size_of(End_Event)
|
||||
if event_size > len(buffer) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
ev.type = .End
|
||||
ev.pid = u32le(pid)
|
||||
ev.tid = u32le(tid)
|
||||
ev.ts = f64le(ts)
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
_buffer_begin :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) {
|
||||
if buffer.head + BEGIN_EVENT_MAX > len(buffer.data) {
|
||||
buffer_flush(ctx, buffer)
|
||||
}
|
||||
name := location.procedure if name == "" else name
|
||||
buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx), buffer.tid, buffer.pid)
|
||||
}
|
||||
|
||||
_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer) {
|
||||
ts := _trace_now(ctx)
|
||||
|
||||
if buffer.head + size_of(End_Event) > len(buffer.data) {
|
||||
buffer_flush(ctx, buffer)
|
||||
}
|
||||
|
||||
buffer.head += _build_end(buffer.data[buffer.head:], ts, buffer.tid, buffer.pid)
|
||||
}
|
||||
@@ -507,11 +507,8 @@ Odin_Endian_Type :: type_of(ODIN_ENDIAN)
|
||||
foreign {
|
||||
@(link_name="__$startup_runtime")
|
||||
_startup_runtime :: proc "odin" () ---
|
||||
}
|
||||
|
||||
@(link_name="__$cleanup_runtime")
|
||||
_cleanup_runtime :: proc() {
|
||||
default_temp_allocator_destroy(&global_default_temp_allocator_data)
|
||||
@(link_name="__$cleanup_runtime")
|
||||
_cleanup_runtime :: proc "odin" () ---
|
||||
}
|
||||
|
||||
_cleanup_runtime_contextless :: proc "contextless" () {
|
||||
|
||||
@@ -72,3 +72,8 @@ default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator
|
||||
data = allocator,
|
||||
}
|
||||
}
|
||||
|
||||
@(fini, private)
|
||||
_destroy_temp_allocator_fini :: proc() {
|
||||
default_temp_allocator_destroy(&global_default_temp_allocator_data)
|
||||
}
|
||||
|
||||
+11
-10
@@ -184,32 +184,33 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
|
||||
return
|
||||
}
|
||||
|
||||
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
if allocator.procedure == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if new_size == 0 {
|
||||
if ptr != nil {
|
||||
_, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
||||
return nil, err
|
||||
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
||||
return
|
||||
}
|
||||
return nil, nil
|
||||
return
|
||||
} else if ptr == nil {
|
||||
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||
} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
|
||||
return ([^]byte)(ptr)[:old_size], nil
|
||||
data = ([^]byte)(ptr)[:old_size]
|
||||
return
|
||||
}
|
||||
|
||||
data, err := allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
|
||||
data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
|
||||
if err == .Mode_Not_Implemented {
|
||||
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||
if err != nil {
|
||||
return data, err
|
||||
return
|
||||
}
|
||||
copy(data, ([^]byte)(ptr)[:old_size])
|
||||
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
||||
}
|
||||
return data, err
|
||||
return
|
||||
}
|
||||
|
||||
memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
||||
@@ -223,7 +224,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
||||
|
||||
when size_of(uint) == 8 {
|
||||
if word_length := length >> 3; word_length != 0 {
|
||||
for i in 0..<word_length {
|
||||
for _ in 0..<word_length {
|
||||
if intrinsics.unaligned_load((^u64)(a)) != intrinsics.unaligned_load((^u64)(b)) {
|
||||
return false
|
||||
}
|
||||
@@ -254,7 +255,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
||||
return true
|
||||
} else {
|
||||
if word_length := length >> 2; word_length != 0 {
|
||||
for i in 0..<word_length {
|
||||
for _ in 0..<word_length {
|
||||
if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
|
||||
return false
|
||||
}
|
||||
|
||||
+20
-19
@@ -2,6 +2,9 @@ package runtime
|
||||
|
||||
_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
@(private="file")
|
||||
_INTEGER_DIGITS_VAR := _INTEGER_DIGITS
|
||||
|
||||
when !ODIN_DISALLOW_RTTI {
|
||||
print_any_single :: proc(arg: any) {
|
||||
x := arg
|
||||
@@ -105,14 +108,14 @@ encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
|
||||
return buf, 4
|
||||
}
|
||||
|
||||
print_string :: proc "contextless" (str: string) -> (int, _OS_Errno) {
|
||||
return os_write(transmute([]byte)str)
|
||||
print_string :: proc "contextless" (str: string) -> (n: int) {
|
||||
n, _ = os_write(transmute([]byte)str)
|
||||
return
|
||||
}
|
||||
|
||||
print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno) {
|
||||
print_strings :: proc "contextless" (args: ..string) -> (n: int) {
|
||||
for str in args {
|
||||
m: int
|
||||
m, err = os_write(transmute([]byte)str)
|
||||
m, err := os_write(transmute([]byte)str)
|
||||
n += m
|
||||
if err != 0 {
|
||||
break
|
||||
@@ -121,8 +124,9 @@ print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno)
|
||||
return
|
||||
}
|
||||
|
||||
print_byte :: proc "contextless" (b: byte) -> (int, _OS_Errno) {
|
||||
return os_write([]byte{b})
|
||||
print_byte :: proc "contextless" (b: byte) -> (n: int) {
|
||||
n, _ = os_write([]byte{b})
|
||||
return
|
||||
}
|
||||
|
||||
print_encoded_rune :: proc "contextless" (r: rune) {
|
||||
@@ -141,11 +145,10 @@ print_encoded_rune :: proc "contextless" (r: rune) {
|
||||
if r <= 0 {
|
||||
print_string("\\x00")
|
||||
} else if r < 32 {
|
||||
digits := _INTEGER_DIGITS
|
||||
n0, n1 := u8(r) >> 4, u8(r) & 0xf
|
||||
print_string("\\x")
|
||||
print_byte(digits[n0])
|
||||
print_byte(digits[n1])
|
||||
print_byte(_INTEGER_DIGITS_VAR[n0])
|
||||
print_byte(_INTEGER_DIGITS_VAR[n1])
|
||||
} else {
|
||||
print_rune(r)
|
||||
}
|
||||
@@ -153,7 +156,7 @@ print_encoded_rune :: proc "contextless" (r: rune) {
|
||||
print_byte('\'')
|
||||
}
|
||||
|
||||
print_rune :: proc "contextless" (r: rune) -> (int, _OS_Errno) #no_bounds_check {
|
||||
print_rune :: proc "contextless" (r: rune) -> int #no_bounds_check {
|
||||
RUNE_SELF :: 0x80
|
||||
|
||||
if r < RUNE_SELF {
|
||||
@@ -161,29 +164,27 @@ print_rune :: proc "contextless" (r: rune) -> (int, _OS_Errno) #no_bounds_check
|
||||
}
|
||||
|
||||
b, n := encode_rune(r)
|
||||
return os_write(b[:n])
|
||||
m, _ := os_write(b[:n])
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
|
||||
digits := _INTEGER_DIGITS
|
||||
|
||||
a: [129]byte
|
||||
i := len(a)
|
||||
b := u64(10)
|
||||
u := x
|
||||
for u >= b {
|
||||
i -= 1; a[i] = digits[u % b]
|
||||
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||
u /= b
|
||||
}
|
||||
i -= 1; a[i] = digits[u % b]
|
||||
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||
|
||||
os_write(a[i:])
|
||||
}
|
||||
|
||||
|
||||
print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
|
||||
digits := _INTEGER_DIGITS
|
||||
b :: i64(10)
|
||||
|
||||
u := x
|
||||
@@ -193,10 +194,10 @@ print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
|
||||
a: [129]byte
|
||||
i := len(a)
|
||||
for u >= b {
|
||||
i -= 1; a[i] = digits[u % b]
|
||||
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||
u /= b
|
||||
}
|
||||
i -= 1; a[i] = digits[u % b]
|
||||
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||
if neg {
|
||||
i -= 1; a[i] = '-'
|
||||
}
|
||||
|
||||
@@ -236,4 +236,4 @@ _panic :: proc "contextless" (msg: string) -> ! {
|
||||
runtime.print_string(msg)
|
||||
runtime.print_byte('\n')
|
||||
runtime.trap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package darwin
|
||||
|
||||
unix_offset_syscall :: proc(number: System_Call_Number) -> uintptr {
|
||||
unix_offset_syscall :: proc "contextless" (number: System_Call_Number) -> uintptr {
|
||||
return uintptr(number) + uintptr(0x2000000)
|
||||
}
|
||||
|
||||
|
||||
@@ -229,191 +229,191 @@ _Proc_Bsdinfo :: struct {
|
||||
|
||||
/*--==========================================================================--*/
|
||||
|
||||
syscall_fsync :: #force_inline proc(fildes: c.int) -> bool {
|
||||
syscall_fsync :: #force_inline proc "contextless" (fildes: c.int) -> bool {
|
||||
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.fsync), uintptr(fildes)))
|
||||
}
|
||||
|
||||
syscall_write :: #force_inline proc (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
|
||||
syscall_write :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
|
||||
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.write), uintptr(fildes), uintptr(buf), uintptr(nbyte)))
|
||||
}
|
||||
|
||||
syscall_read :: #force_inline proc(fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
|
||||
syscall_read :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
|
||||
return cast(i64)intrinsics.syscall(unix_offset_syscall(.read), uintptr(fildes), uintptr(buf), uintptr(nbyte))
|
||||
}
|
||||
|
||||
syscall_open :: #force_inline proc(path: cstring, oflag: u32, mode: u32) -> c.int {
|
||||
syscall_open :: #force_inline proc "contextless" (path: cstring, oflag: u32, mode: u32) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.open), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
|
||||
}
|
||||
|
||||
syscall_close :: #force_inline proc(fd: c.int) -> bool {
|
||||
syscall_close :: #force_inline proc "contextless" (fd: c.int) -> bool {
|
||||
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.close), uintptr(fd)))
|
||||
}
|
||||
|
||||
syscall_fchmod :: #force_inline proc(fildes: c.int, mode: u32) -> c.int {
|
||||
syscall_fchmod :: #force_inline proc "contextless" (fildes: c.int, mode: u32) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.fchmod), uintptr(fildes), uintptr(mode)))
|
||||
}
|
||||
|
||||
syscall_chmod :: #force_inline proc(path: cstring, mode: u32) -> c.int {
|
||||
syscall_chmod :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.chmod), transmute(uintptr)path, uintptr(mode)))
|
||||
}
|
||||
|
||||
syscall_mkdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
|
||||
syscall_mkdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), transmute(uintptr)path, uintptr(mode)))
|
||||
}
|
||||
|
||||
syscall_mkdir_at :: #force_inline proc(fd: c.int, path: cstring, mode: u32) -> c.int {
|
||||
syscall_mkdir_at :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: u32) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), uintptr(fd), transmute(uintptr)path, uintptr(mode)))
|
||||
}
|
||||
|
||||
syscall_rmdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
|
||||
syscall_rmdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rmdir), transmute(uintptr)path, uintptr(mode)))
|
||||
}
|
||||
|
||||
syscall_rename :: #force_inline proc(path_old: cstring, path_new: cstring) -> c.int {
|
||||
syscall_rename :: #force_inline proc "contextless" (path_old: cstring, path_new: cstring) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rename), transmute(uintptr)path_old, transmute(uintptr)path_new))
|
||||
}
|
||||
|
||||
syscall_rename_at :: #force_inline proc(from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
|
||||
syscall_rename_at :: #force_inline proc "contextless" (from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
|
||||
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.renameat), uintptr(from_fd), transmute(uintptr)from, uintptr(to_fd), transmute(uintptr)to))
|
||||
}
|
||||
|
||||
syscall_lseek :: #force_inline proc(fd: c.int, offset: i64, whence: c.int) -> i64 {
|
||||
syscall_lseek :: #force_inline proc "contextless" (fd: c.int, offset: i64, whence: c.int) -> i64 {
|
||||
return cast(i64)intrinsics.syscall(unix_offset_syscall(.lseek), uintptr(fd), uintptr(offset), uintptr(whence))
|
||||
}
|
||||
|
||||
syscall_gettid :: #force_inline proc() -> u64 {
|
||||
syscall_gettid :: #force_inline proc "contextless" () -> u64 {
|
||||
return cast(u64)intrinsics.syscall(unix_offset_syscall(.gettid))
|
||||
}
|
||||
|
||||
syscall_fstat :: #force_inline proc(fd: c.int, status: ^stat) -> c.int {
|
||||
syscall_fstat :: #force_inline proc "contextless" (fd: c.int, status: ^stat) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstat), uintptr(fd), uintptr(status))
|
||||
}
|
||||
|
||||
syscall_lstat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
|
||||
syscall_lstat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.lstat), transmute(uintptr)path, uintptr(status))
|
||||
}
|
||||
|
||||
syscall_stat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
|
||||
syscall_stat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.stat), transmute(uintptr)path, uintptr(status))
|
||||
}
|
||||
|
||||
syscall_fstatat :: #force_inline proc(fd: c.int, path: cstring, status: ^stat) -> c.int {
|
||||
syscall_fstatat :: #force_inline proc "contextless" (fd: c.int, path: cstring, status: ^stat) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstatat), uintptr(fd), transmute(uintptr)path, uintptr(status))
|
||||
}
|
||||
|
||||
syscall_link :: #force_inline proc(path: cstring, to_link: cstring) -> c.int {
|
||||
syscall_link :: #force_inline proc "contextless" (path: cstring, to_link: cstring) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.link), transmute(uintptr)path, transmute(uintptr)to_link)
|
||||
}
|
||||
|
||||
syscall_linkat :: #force_inline proc(fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
|
||||
syscall_linkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.linkat), uintptr(fd), transmute(uintptr)path, uintptr(fd2), transmute(uintptr)to_link)
|
||||
}
|
||||
|
||||
syscall_readlink :: #force_inline proc(path: cstring, buf: ^u8, buf_size: u64) -> i64 {
|
||||
syscall_readlink :: #force_inline proc "contextless" (path: cstring, buf: ^u8, buf_size: u64) -> i64 {
|
||||
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlink), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
|
||||
}
|
||||
|
||||
syscall_readlinkat :: #force_inline proc(fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
|
||||
syscall_readlinkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
|
||||
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlinkat), uintptr(fd), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
|
||||
}
|
||||
|
||||
syscall_access :: #force_inline proc(path: cstring, mode: c.int) -> c.int {
|
||||
syscall_access :: #force_inline proc "contextless" (path: cstring, mode: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.access), transmute(uintptr)path, uintptr(mode))
|
||||
}
|
||||
|
||||
syscall_faccessat :: #force_inline proc(fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
|
||||
syscall_faccessat :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.faccessat), uintptr(fd), transmute(uintptr)path, uintptr(mode), uintptr(flag))
|
||||
}
|
||||
|
||||
syscall_getdirentries :: #force_inline proc(fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
|
||||
syscall_getdirentries :: #force_inline proc "contextless" (fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getdirentries), uintptr(fd), uintptr(buf), uintptr(nbytes), uintptr(base_pointer))
|
||||
}
|
||||
|
||||
syscall_truncate :: #force_inline proc (path: cstring, length: off_t) -> c.int {
|
||||
syscall_truncate :: #force_inline proc "contextless" (path: cstring, length: off_t) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.truncate), transmute(uintptr)path, uintptr(length))
|
||||
}
|
||||
|
||||
syscall_ftruncate :: #force_inline proc (fd: c.int, length: off_t) -> c.int {
|
||||
syscall_ftruncate :: #force_inline proc "contextless" (fd: c.int, length: off_t) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.ftruncate), uintptr(fd), uintptr(length))
|
||||
}
|
||||
|
||||
syscall_sysctl :: #force_inline proc (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
|
||||
syscall_sysctl :: #force_inline proc "contextless" (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctl), uintptr(name), uintptr(namelen), uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
|
||||
}
|
||||
|
||||
syscall_copyfile :: #force_inline proc(from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
|
||||
syscall_copyfile :: #force_inline proc "contextless" (from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.copyfile), transmute(uintptr)from, transmute(uintptr)to, uintptr(state), uintptr(flags))
|
||||
}
|
||||
|
||||
// think about this? last arg should be more than one
|
||||
syscall_fcntl :: #force_inline proc(fd: c.int, cmd: c.int, other: rawptr) -> c.int {
|
||||
syscall_fcntl :: #force_inline proc "contextless" (fd: c.int, cmd: c.int, other: rawptr) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fsctl), uintptr(fd), uintptr(cmd), uintptr(other))
|
||||
}
|
||||
|
||||
syscall_exit :: #force_inline proc(code: c.int) {
|
||||
syscall_exit :: #force_inline proc "contextless" (code: c.int) {
|
||||
intrinsics.syscall(unix_offset_syscall(.exit), uintptr(code))
|
||||
}
|
||||
|
||||
syscall_kill :: #force_inline proc(pid: pid_t, sig: c.int) -> c.int {
|
||||
syscall_kill :: #force_inline proc "contextless" (pid: pid_t, sig: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.kill), uintptr(pid), uintptr(sig))
|
||||
}
|
||||
|
||||
syscall_dup :: #force_inline proc(fd: c.int) -> c.int {
|
||||
syscall_dup :: #force_inline proc "contextless" (fd: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.dup), uintptr(fd))
|
||||
}
|
||||
|
||||
syscall_execve :: #force_inline proc(path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
|
||||
syscall_execve :: #force_inline proc "contextless" (path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.execve), transmute(uintptr)path, transmute(uintptr)argv, transmute(uintptr)env)
|
||||
}
|
||||
|
||||
syscall_munmap :: #force_inline proc(addr: rawptr, len: u64) -> c.int {
|
||||
syscall_munmap :: #force_inline proc "contextless" (addr: rawptr, len: u64) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len))
|
||||
}
|
||||
|
||||
syscall_mmap :: #force_inline proc(addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
|
||||
syscall_mmap :: #force_inline proc "contextless" (addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
|
||||
return cast(^u8)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len), uintptr(port), uintptr(flags), uintptr(fd), uintptr(offset))
|
||||
}
|
||||
|
||||
syscall_flock :: #force_inline proc(fd: c.int, operation: c.int) -> c.int {
|
||||
syscall_flock :: #force_inline proc "contextless" (fd: c.int, operation: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.flock), uintptr(fd), uintptr(operation))
|
||||
}
|
||||
|
||||
syscall_utimes :: #force_inline proc(path: cstring, times: ^timeval) -> c.int {
|
||||
syscall_utimes :: #force_inline proc "contextless" (path: cstring, times: ^timeval) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.utimes), transmute(uintptr)path, uintptr(times))
|
||||
}
|
||||
|
||||
syscall_futimes :: #force_inline proc(fd: c.int, times: ^timeval) -> c.int {
|
||||
syscall_futimes :: #force_inline proc "contextless" (fd: c.int, times: ^timeval) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.futimes), uintptr(fd), uintptr(times))
|
||||
}
|
||||
|
||||
syscall_adjtime :: #force_inline proc(delta: ^timeval, old_delta: ^timeval) -> c.int {
|
||||
syscall_adjtime :: #force_inline proc "contextless" (delta: ^timeval, old_delta: ^timeval) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.adjtime), uintptr(delta), uintptr(old_delta))
|
||||
}
|
||||
|
||||
syscall_sysctlbyname :: #force_inline proc(name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
|
||||
syscall_sysctlbyname :: #force_inline proc "contextless" (name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctlbyname), transmute(uintptr)name, uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
|
||||
}
|
||||
|
||||
syscall_proc_info :: #force_inline proc(num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
|
||||
syscall_proc_info :: #force_inline proc "contextless" (num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.proc_info), uintptr(num), uintptr(pid), uintptr(flavor), uintptr(arg), uintptr(buffer), uintptr(buffer_size))
|
||||
}
|
||||
|
||||
syscall_openat :: #force_inline proc(fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
|
||||
syscall_openat :: #force_inline proc "contextless" (fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.openat), uintptr(fd), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
|
||||
}
|
||||
|
||||
syscall_getentropy :: #force_inline proc(buf: [^]u8, buflen: u64) -> c.int {
|
||||
syscall_getentropy :: #force_inline proc "contextless" (buf: [^]u8, buflen: u64) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(buf), uintptr(buflen))
|
||||
}
|
||||
|
||||
syscall_pipe :: #force_inline proc(fds: [^]c.int) -> c.int {
|
||||
syscall_pipe :: #force_inline proc "contextless" (fds: [^]c.int) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(&fds[0]), uintptr(&fds[1]))
|
||||
}
|
||||
|
||||
syscall_chdir :: #force_inline proc(path: cstring) -> c.int {
|
||||
syscall_chdir :: #force_inline proc "contextless" (path: cstring) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), transmute(uintptr)path)
|
||||
}
|
||||
|
||||
syscall_fchdir :: #force_inline proc(fd: c.int, path: cstring) -> c.int {
|
||||
syscall_fchdir :: #force_inline proc "contextless" (fd: c.int, path: cstring) -> c.int {
|
||||
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(fd), transmute(uintptr)path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1563,15 +1563,167 @@ MADV_WIPEONFORK :: 18
|
||||
MADV_KEEPONFORK :: 19
|
||||
MADV_HWPOISON :: 100
|
||||
|
||||
// pipe2 flags
|
||||
O_CLOEXEC :: 0o2000000
|
||||
|
||||
// perf event data
|
||||
Perf_Sample :: struct #raw_union {
|
||||
period: u64,
|
||||
frequency: u64,
|
||||
}
|
||||
Perf_Wakeup :: struct #raw_union {
|
||||
events: u32,
|
||||
watermark: u32,
|
||||
}
|
||||
Perf_Field1 :: struct #raw_union {
|
||||
breakpoint_addr: u64,
|
||||
kprobe_func: u64,
|
||||
uprobe_path: u64,
|
||||
config1: u64,
|
||||
}
|
||||
Perf_Field2 :: struct #raw_union {
|
||||
breakpoint_len: u64,
|
||||
kprobe_addr: u64,
|
||||
uprobe_offset: u64,
|
||||
config2: u64,
|
||||
}
|
||||
Perf_Event_Attr :: struct #packed {
|
||||
type: u32,
|
||||
size: u32,
|
||||
config: u64,
|
||||
sample: Perf_Sample,
|
||||
sample_type: u64,
|
||||
read_format: u64,
|
||||
flags: Perf_Flags,
|
||||
wakeup: Perf_Wakeup,
|
||||
breakpoint_type: u32,
|
||||
field1: Perf_Field1,
|
||||
field2: Perf_Field2,
|
||||
branch_sample_type: u64,
|
||||
sample_regs_user: u64,
|
||||
sample_stack_user: u32,
|
||||
clock_id: i32,
|
||||
sample_regs_intr: u64,
|
||||
aux_watermark: u32,
|
||||
sample_max_stack: u16,
|
||||
_padding: u16,
|
||||
}
|
||||
|
||||
Perf_Event_Flags :: distinct bit_set[Perf_Event_Flag; u64]
|
||||
Perf_Event_Flag :: enum u64 {
|
||||
Bit0 = 0,
|
||||
Bit0_Is_Deprecated = 1,
|
||||
User_Rdpmc = 2,
|
||||
User_Time = 3,
|
||||
User_Time_Zero = 4,
|
||||
User_Time_Short = 5,
|
||||
}
|
||||
Perf_Capabilities :: struct #raw_union {
|
||||
capabilities: u64,
|
||||
flags: Perf_Event_Flags,
|
||||
}
|
||||
Perf_Event_mmap_Page :: struct #packed {
|
||||
version: u32,
|
||||
compat_version: u32,
|
||||
lock: u32,
|
||||
index: u32,
|
||||
offset: i64,
|
||||
time_enabled: u64,
|
||||
time_running: u64,
|
||||
cap: Perf_Capabilities,
|
||||
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,
|
||||
}
|
||||
|
||||
Perf_Type_Id :: enum u32 {
|
||||
Hardware = 0,
|
||||
Software = 1,
|
||||
Tracepoint = 2,
|
||||
HW_Cache = 3,
|
||||
Raw = 4,
|
||||
Breakpoint = 5,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
Perf_Flags :: distinct bit_set[Perf_Flag; u64]
|
||||
Perf_Flag :: 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,
|
||||
}
|
||||
|
||||
sys_gettid :: proc "contextless" () -> int {
|
||||
return cast(int)intrinsics.syscall(SYS_gettid)
|
||||
return int(intrinsics.syscall(SYS_gettid))
|
||||
}
|
||||
|
||||
sys_getrandom :: proc "contextless" (buf: [^]byte, buflen: int, flags: uint) -> int {
|
||||
return cast(int)intrinsics.syscall(SYS_getrandom, uintptr(buf), uintptr(buflen), uintptr(flags))
|
||||
sys_getrandom :: proc "contextless" (buf: [^]byte, buflen: uint, flags: int) -> int {
|
||||
return int(intrinsics.syscall(SYS_getrandom, uintptr(buf), uintptr(buflen), uintptr(flags)))
|
||||
}
|
||||
|
||||
sys_open :: proc "contextless" (path: cstring, flags: int, mode: int = 0o000) -> int {
|
||||
sys_open :: proc "contextless" (path: cstring, flags: int, mode: uint = 0o000) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||
} else { // NOTE: arm64 does not have open
|
||||
@@ -1579,7 +1731,7 @@ sys_open :: proc "contextless" (path: cstring, flags: int, mode: int = 0o000) ->
|
||||
}
|
||||
}
|
||||
|
||||
sys_openat :: proc "contextless" (dfd: int, path: cstring, flags: int, mode: int = 0o000) -> int {
|
||||
sys_openat :: proc "contextless" (dfd: int, path: cstring, flags: int, mode: uint = 0o000) -> int {
|
||||
return int(intrinsics.syscall(SYS_openat, uintptr(dfd), uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||
}
|
||||
|
||||
@@ -1691,7 +1843,7 @@ sys_fchdir :: proc "contextless" (fd: int) -> int {
|
||||
return int(intrinsics.syscall(SYS_fchdir, uintptr(fd)))
|
||||
}
|
||||
|
||||
sys_chmod :: proc "contextless" (path: cstring, mode: int) -> int {
|
||||
sys_chmod :: proc "contextless" (path: cstring, mode: uint) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(SYS_chmod, uintptr(rawptr(path)), uintptr(mode)))
|
||||
} else { // NOTE: arm64 does not have chmod
|
||||
@@ -1699,7 +1851,7 @@ sys_chmod :: proc "contextless" (path: cstring, mode: int) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
sys_fchmod :: proc "contextless" (fd: int, mode: int) -> int {
|
||||
sys_fchmod :: proc "contextless" (fd: int, mode: uint) -> int {
|
||||
return int(intrinsics.syscall(SYS_fchmod, uintptr(fd), uintptr(mode)))
|
||||
}
|
||||
|
||||
@@ -1759,7 +1911,7 @@ sys_rmdir :: proc "contextless" (path: cstring) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
sys_mkdir :: proc "contextless" (path: cstring, mode: int) -> int {
|
||||
sys_mkdir :: proc "contextless" (path: cstring, mode: uint) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
|
||||
} else { // NOTE: arm64 does not have mkdir
|
||||
@@ -1767,11 +1919,11 @@ sys_mkdir :: proc "contextless" (path: cstring, mode: int) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
sys_mkdirat :: proc "contextless" (dfd: int, path: cstring, mode: int) -> int {
|
||||
sys_mkdirat :: proc "contextless" (dfd: int, path: cstring, mode: uint) -> int {
|
||||
return int(intrinsics.syscall(SYS_mkdirat, uintptr(dfd), uintptr(rawptr(path)), uintptr(mode)))
|
||||
}
|
||||
|
||||
sys_mknod :: proc "contextless" (path: cstring, mode: int, dev: int) -> int {
|
||||
sys_mknod :: proc "contextless" (path: cstring, mode: uint, dev: int) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(SYS_mknod, uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
|
||||
} else { // NOTE: arm64 does not have mknod
|
||||
@@ -1779,7 +1931,7 @@ sys_mknod :: proc "contextless" (path: cstring, mode: int, dev: int) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
sys_mknodat :: proc "contextless" (dfd: int, path: cstring, mode: int, dev: int) -> int {
|
||||
sys_mknodat :: proc "contextless" (dfd: int, path: cstring, mode: uint, dev: int) -> int {
|
||||
return int(intrinsics.syscall(SYS_mknodat, uintptr(dfd), uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
|
||||
}
|
||||
|
||||
@@ -1818,6 +1970,16 @@ sys_fork :: proc "contextless" () -> int {
|
||||
return int(intrinsics.syscall(SYS_clone, SIGCHLD))
|
||||
}
|
||||
}
|
||||
sys_pipe2 :: proc "contextless" (fds: rawptr, flags: int) -> int {
|
||||
return int(intrinsics.syscall(SYS_pipe2, uintptr(fds), uintptr(flags)))
|
||||
}
|
||||
sys_dup2 :: proc "contextless" (oldfd: int, newfd: int) -> int {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
return int(intrinsics.syscall(SYS_dup2, uintptr(oldfd), uintptr(newfd)))
|
||||
} else {
|
||||
return int(intrinsics.syscall(SYS_dup3, uintptr(oldfd), uintptr(newfd), 0))
|
||||
}
|
||||
}
|
||||
|
||||
sys_mmap :: proc "contextless" (addr: rawptr, length: uint, prot, flags, fd: int, offset: uintptr) -> int {
|
||||
return int(intrinsics.syscall(SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset))
|
||||
@@ -1846,6 +2008,14 @@ sys_utimensat :: proc "contextless" (dfd: int, path: cstring, times: rawptr, fla
|
||||
return int(intrinsics.syscall(SYS_utimensat, uintptr(dfd), uintptr(rawptr(path)), uintptr(times), uintptr(flags)))
|
||||
}
|
||||
|
||||
sys_perf_event_open :: proc "contextless" (event_attr: rawptr, pid: i32, cpu: i32, group_fd: i32, flags: u32) -> int {
|
||||
return int(intrinsics.syscall(SYS_perf_event_open, uintptr(event_attr), uintptr(pid), uintptr(cpu), uintptr(group_fd), uintptr(flags)))
|
||||
}
|
||||
|
||||
sys_personality :: proc(persona: u64) -> int {
|
||||
return int(intrinsics.syscall(SYS_personality, uintptr(persona)))
|
||||
}
|
||||
|
||||
get_errno :: proc "contextless" (res: int) -> i32 {
|
||||
if res < 0 && res > -4096 {
|
||||
return i32(-res)
|
||||
|
||||
@@ -315,6 +315,13 @@ foreign kernel32 {
|
||||
lpOverlapped: LPOVERLAPPED,
|
||||
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||
) -> BOOL ---
|
||||
FindFirstChangeNotificationW :: proc(
|
||||
lpPathName: LPWSTR,
|
||||
bWatchSubtree: BOOL,
|
||||
dwNotifyFilter: DWORD,
|
||||
) -> HANDLE ---
|
||||
FindNextChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
|
||||
FindCloseChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
|
||||
|
||||
InitializeSRWLock :: proc(SRWLock: ^SRWLOCK) ---
|
||||
AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) ---
|
||||
|
||||
+49
-2
@@ -1,11 +1,11 @@
|
||||
package time
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
|
||||
Tick :: struct {
|
||||
_nsec: i64, // relative amount
|
||||
}
|
||||
|
||||
tick_now :: proc "contextless" () -> Tick {
|
||||
return _tick_now()
|
||||
}
|
||||
@@ -40,6 +40,53 @@ _tick_duration_end :: proc "contextless" (d: ^Duration, t: Tick) {
|
||||
d^ = tick_since(t)
|
||||
}
|
||||
|
||||
when ODIN_ARCH == .amd64 {
|
||||
@(private)
|
||||
x86_has_invariant_tsc :: proc "contextless" () -> bool {
|
||||
eax, _, _, _ := intrinsics.x86_cpuid(0x80_000_000, 0)
|
||||
|
||||
// Is this processor *really* ancient?
|
||||
if eax < 0x80_000_007 {
|
||||
return false
|
||||
}
|
||||
|
||||
// check if the invariant TSC bit is set
|
||||
_, _, _, edx := intrinsics.x86_cpuid(0x80_000_007, 0)
|
||||
return (edx & (1 << 8)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
has_invariant_tsc :: proc "contextless" () -> bool {
|
||||
when ODIN_ARCH == .amd64 {
|
||||
return x86_has_invariant_tsc()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
if !has_invariant_tsc() {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
hz, ok := _get_tsc_frequency()
|
||||
if !ok {
|
||||
// fallback to approximate TSC
|
||||
tsc_begin := intrinsics.read_cycle_counter()
|
||||
tick_begin := tick_now()
|
||||
|
||||
sleep(2 * Second)
|
||||
|
||||
tsc_end := intrinsics.read_cycle_counter()
|
||||
tick_end := tick_now()
|
||||
|
||||
time_diff := u128(duration_nanoseconds(tick_diff(tick_begin, tick_end)))
|
||||
hz = u64((u128(tsc_end - tsc_begin) * 1_000_000_000) / time_diff)
|
||||
}
|
||||
|
||||
return hz, true
|
||||
}
|
||||
|
||||
/*
|
||||
Benchmark helpers
|
||||
*/
|
||||
@@ -94,4 +141,4 @@ benchmark :: proc(options: ^Benchmark_Options, allocator := context.allocator) -
|
||||
options->teardown(allocator) or_return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//+private
|
||||
//+build darwin
|
||||
package time
|
||||
|
||||
import "core:c"
|
||||
|
||||
foreign import libc "System.framework"
|
||||
foreign libc {
|
||||
@(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
|
||||
}
|
||||
|
||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
tmp_freq : u64 = 0
|
||||
tmp_size : i64 = size_of(tmp_freq)
|
||||
ret := _sysctlbyname("machdep.tsc.frequency", &tmp_freq, &tmp_size, nil, 0)
|
||||
if ret < 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return tmp_freq, true
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//+private
|
||||
//+build freebsd
|
||||
package time
|
||||
|
||||
import "core:c"
|
||||
|
||||
foreign import libc "system:c"
|
||||
foreign libc {
|
||||
@(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
|
||||
}
|
||||
|
||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
tmp_freq : u64 = 0
|
||||
tmp_size : i64 = size_of(tmp_freq)
|
||||
ret := _sysctlbyname("machdep.tsc_freq", &tmp_freq, &tmp_size, nil, 0)
|
||||
if ret < 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return tmp_freq, true
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//+private
|
||||
//+build linux
|
||||
package time
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:sys/unix"
|
||||
|
||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
perf_attr := unix.Perf_Event_Attr{}
|
||||
perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
|
||||
perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
|
||||
perf_attr.size = size_of(perf_attr)
|
||||
perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
|
||||
fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
|
||||
if fd == -1 {
|
||||
return 0, false
|
||||
}
|
||||
defer unix.sys_close(fd)
|
||||
|
||||
page_size : uint = 4096
|
||||
ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
|
||||
if ret < 0 && ret > -4096 {
|
||||
return 0, false
|
||||
}
|
||||
addr := rawptr(uintptr(ret))
|
||||
defer unix.sys_munmap(addr, page_size)
|
||||
|
||||
event_page := (^unix.Perf_Event_mmap_Page)(addr)
|
||||
if .User_Time not_in event_page.cap.flags {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
|
||||
return frequency, true
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//+private
|
||||
//+build openbsd
|
||||
package time
|
||||
|
||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
return 0, false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//+private
|
||||
//+build windows
|
||||
package time
|
||||
|
||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||
return 0, false
|
||||
}
|
||||
Reference in New Issue
Block a user