From b73275cf423186c558e637f629a846eb21c45f24 Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 19 Dec 2024 17:12:07 -0500 Subject: [PATCH] Get arm64 up to speed in os2 linux Readded open flags for arm64 to sys/linux/bits.odin. Make process_start name based instead of descriptor based to allow running of scripts. Fix bug in heap_linux. Fix and simplify os2.remove. --- core/os/os2/file_linux.odin | 22 ++------ core/os/os2/heap_linux.odin | 2 +- core/os/os2/process_linux.odin | 47 ++++------------- core/sys/linux/bits.odin | 96 +++++++++++++++++++++------------- 4 files changed, 74 insertions(+), 93 deletions(-) diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index e9ce1344739..20f179f7794 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -272,28 +272,12 @@ _truncate :: proc(f: ^File, size: i64) -> Error { } _remove :: proc(name: string) -> Error { - is_dir_fd :: proc(fd: linux.Fd) -> bool { - s: linux.Stat - if linux.fstat(fd, &s) != .NONE { - return false - } - return linux.S_ISDIR(s.mode) - } - TEMP_ALLOCATOR_GUARD() name_cstr := temp_cstring(name) or_return - fd, errno := linux.open(name_cstr, {.NOFOLLOW}) - #partial switch (errno) { - case .ELOOP: - /* symlink */ - case .NONE: - defer linux.close(fd) - if is_dir_fd(fd) { - return _get_platform_error(linux.rmdir(name_cstr)) - } - case: - return _get_platform_error(errno) + if fd, errno := linux.open(name_cstr, _OPENDIR_FLAGS); errno == .NONE { + linux.close(fd) + return _get_platform_error(linux.rmdir(name_cstr)) } return _get_platform_error(linux.unlink(name_cstr)) diff --git a/core/os/os2/heap_linux.odin b/core/os/os2/heap_linux.odin index ede5eb2acc4..8819dfac7b4 100644 --- a/core/os/os2/heap_linux.odin +++ b/core/os/os2/heap_linux.odin @@ -415,7 +415,7 @@ _region_resize :: proc(alloc: ^Allocation_Header, new_size: int, alloc_is_free_l back_idx := -1 idx: u16 infinite: for { - for i := 0; i < len(region_iter.hdr.free_list); i += 1 { + for i := 0; i < int(region_iter.hdr.free_list_len); i += 1 { idx = region_iter.hdr.free_list[i] if _get_block_count(region_iter.memory[idx]) >= new_block_count { break infinite diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin index 7eb4dfa446a..936fbfc405f 100644 --- a/core/os/os2/process_linux.odin +++ b/core/os/os2/process_linux.odin @@ -384,14 +384,6 @@ _Sys_Process_Attributes :: struct {} @(private="package") _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { - has_executable_permissions :: proc(fd: linux.Fd) -> bool { - backing: [48]u8 - b := strings.builder_from_bytes(backing[:]) - strings.write_string(&b, "/proc/self/fd/") - strings.write_int(&b, int(fd)) - return linux.access(strings.to_cstring(&b), linux.X_OK) == .NONE - } - TEMP_ALLOCATOR_GUARD() if len(desc.command) == 0 { @@ -411,7 +403,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { } // search PATH if just a plain name is provided - exe_fd: linux.Fd + exe_path: cstring executable_name := desc.command[0] if strings.index_byte(executable_name, '/') < 0 { path_env := get_env("PATH", temp_allocator()) @@ -426,16 +418,11 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_byte(&exe_builder, '/') strings.write_string(&exe_builder, executable_name) - exe_path := strings.to_cstring(&exe_builder) - if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { - continue - } - if !has_executable_permissions(exe_fd) { - linux.close(exe_fd) - continue + exe_path = strings.to_cstring(&exe_builder) + if linux.access(exe_path, linux.X_OK) == .NONE { + found = true + break } - found = true - break } if !found { // check in cwd to match windows behavior @@ -443,29 +430,18 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_string(&exe_builder, "./") strings.write_string(&exe_builder, executable_name) - exe_path := strings.to_cstring(&exe_builder) - if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { + exe_path = strings.to_cstring(&exe_builder) + if linux.access(exe_path, linux.X_OK) != .NONE { return process, .Not_Exist } - if !has_executable_permissions(exe_fd) { - linux.close(exe_fd) - return process, .Permission_Denied - } } } else { - exe_path := temp_cstring(executable_name) or_return - if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { - return process, _get_platform_error(errno) - } - if !has_executable_permissions(exe_fd) { - linux.close(exe_fd) - return process, .Permission_Denied + exe_path = temp_cstring(executable_name) or_return + if linux.access(exe_path, linux.X_OK) != .NONE { + return process, .Not_Exist } } - // At this point, we have an executable. - defer linux.close(exe_fd) - // args and environment need to be a list of cstrings // that are terminated by a nil pointer. cargs := make([]cstring, len(desc.command) + 1, temp_allocator()) or_return @@ -492,7 +468,6 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { } defer linux.close(child_pipe_fds[READ]) - // TODO: This is the traditional textbook implementation with fork. // A more efficient implementation with vfork: // @@ -573,7 +548,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno) } - errno = linux.execveat(exe_fd, "", &cargs[0], env, {.AT_EMPTY_PATH}) + errno = linux.execveat(dir_fd, exe_path, &cargs[0], env) assert(errno != nil) write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno) } diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 9ce2e206e74..c304397deea 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -152,43 +152,65 @@ Errno :: enum i32 { RDONLY flag is not present, because it has the value of 0, i.e. it is the default, unless WRONLY or RDWR is specified. */ -Open_Flags_Bits :: enum { - WRONLY = 0, - RDWR = 1, - CREAT = 6, - EXCL = 7, - NOCTTY = 8, - TRUNC = 9, - APPEND = 10, - NONBLOCK = 11, - DSYNC = 12, - ASYNC = 13, - DIRECT = 14, - LARGEFILE = 15, - DIRECTORY = 16, - NOFOLLOW = 17, - NOATIME = 18, - CLOEXEC = 19, - PATH = 21, -} -// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19 -#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1) -#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2) -#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100) -#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200) -#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400) -#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000) -#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000) -#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000) -#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000) -#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000) -#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000) -#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000) -#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000) -#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000) -#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000) -#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000) -#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000) +when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 { + Open_Flags_Bits :: enum { + WRONLY = 0, + RDWR = 1, + CREAT = 6, + EXCL = 7, + NOCTTY = 8, + TRUNC = 9, + APPEND = 10, + NONBLOCK = 11, + DSYNC = 12, + ASYNC = 13, + DIRECT = 14, + LARGEFILE = 15, + DIRECTORY = 16, + NOFOLLOW = 17, + NOATIME = 18, + CLOEXEC = 19, + PATH = 21, + } + // https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19 + #assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1) + #assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2) + #assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100) + #assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200) + #assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400) + #assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000) + #assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000) + #assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000) + #assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000) + #assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000) + #assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000) + #assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000) + #assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000) + #assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000) + #assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000) + #assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000) + #assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000) +} else { + Open_Flags_Bits :: enum { + WRONLY = 0, + RDWR = 1, + CREAT = 6, + EXCL = 7, + NOCTTY = 8, + TRUNC = 9, + APPEND = 10, + NONBLOCK = 11, + DSYNC = 12, + ASYNC = 13, + DIRECTORY = 14, + NOFOLLOW = 15, + DIRECT = 16, + LARGEFILE = 17, + NOATIME = 18, + CLOEXEC = 19, + PATH = 21, + } +} /* Bits for FD_Flags bitset