Merge pull request #4600 from jasonKercher/arm64-linux-fixes

Get arm64 up to speed in os2 linux
This commit is contained in:
Laytan
2024-12-30 23:38:59 +01:00
committed by GitHub
4 changed files with 73 additions and 92 deletions
+3 -19
View File
@@ -272,28 +272,12 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
} }
_remove :: proc(name: string) -> 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() TEMP_ALLOCATOR_GUARD()
name_cstr := temp_cstring(name) or_return name_cstr := temp_cstring(name) or_return
fd, errno := linux.open(name_cstr, {.NOFOLLOW}) if fd, errno := linux.open(name_cstr, _OPENDIR_FLAGS); errno == .NONE {
#partial switch (errno) { linux.close(fd)
case .ELOOP: return _get_platform_error(linux.rmdir(name_cstr))
/* 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)
} }
return _get_platform_error(linux.unlink(name_cstr)) return _get_platform_error(linux.unlink(name_cstr))
+1 -1
View File
@@ -415,7 +415,7 @@ _region_resize :: proc(alloc: ^Allocation_Header, new_size: int, alloc_is_free_l
back_idx := -1 back_idx := -1
idx: u16 idx: u16
infinite: for { 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] idx = region_iter.hdr.free_list[i]
if _get_block_count(region_iter.memory[idx]) >= new_block_count { if _get_block_count(region_iter.memory[idx]) >= new_block_count {
break infinite break infinite
+11 -36
View File
@@ -384,14 +384,6 @@ _Sys_Process_Attributes :: struct {}
@(private="package") @(private="package")
_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { _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() TEMP_ALLOCATOR_GUARD()
if len(desc.command) == 0 { 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 // search PATH if just a plain name is provided
exe_fd: linux.Fd exe_path: cstring
executable_name := desc.command[0] executable_name := desc.command[0]
if strings.index_byte(executable_name, '/') < 0 { if strings.index_byte(executable_name, '/') < 0 {
path_env := get_env("PATH", temp_allocator()) 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_byte(&exe_builder, '/')
strings.write_string(&exe_builder, executable_name) strings.write_string(&exe_builder, executable_name)
exe_path := strings.to_cstring(&exe_builder) exe_path = strings.to_cstring(&exe_builder)
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { if linux.access(exe_path, linux.X_OK) == .NONE {
continue found = true
break
} }
if !has_executable_permissions(exe_fd) {
linux.close(exe_fd)
continue
}
found = true
break
} }
if !found { if !found {
// check in cwd to match windows behavior // 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, "./")
strings.write_string(&exe_builder, executable_name) strings.write_string(&exe_builder, executable_name)
exe_path := strings.to_cstring(&exe_builder) exe_path = strings.to_cstring(&exe_builder)
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { if linux.access(exe_path, linux.X_OK) != .NONE {
return process, .Not_Exist return process, .Not_Exist
} }
if !has_executable_permissions(exe_fd) {
linux.close(exe_fd)
return process, .Permission_Denied
}
} }
} else { } else {
exe_path := temp_cstring(executable_name) or_return exe_path = temp_cstring(executable_name) or_return
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE { if linux.access(exe_path, linux.X_OK) != .NONE {
return process, _get_platform_error(errno) return process, .Not_Exist
}
if !has_executable_permissions(exe_fd) {
linux.close(exe_fd)
return process, .Permission_Denied
} }
} }
// At this point, we have an executable.
defer linux.close(exe_fd)
// args and environment need to be a list of cstrings // args and environment need to be a list of cstrings
// that are terminated by a nil pointer. // that are terminated by a nil pointer.
cargs := make([]cstring, len(desc.command) + 1, temp_allocator()) or_return 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]) defer linux.close(child_pipe_fds[READ])
// TODO: This is the traditional textbook implementation with fork. // TODO: This is the traditional textbook implementation with fork.
// A more efficient implementation with vfork: // 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) 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) assert(errno != nil)
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno) write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
} }
+58 -36
View File
@@ -152,43 +152,65 @@ Errno :: enum i32 {
RDONLY flag is not present, because it has the value of 0, i.e. it is the RDONLY flag is not present, because it has the value of 0, i.e. it is the
default, unless WRONLY or RDWR is specified. default, unless WRONLY or RDWR is specified.
*/ */
Open_Flags_Bits :: enum { when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
WRONLY = 0, Open_Flags_Bits :: enum {
RDWR = 1, WRONLY = 0,
CREAT = 6, RDWR = 1,
EXCL = 7, CREAT = 6,
NOCTTY = 8, EXCL = 7,
TRUNC = 9, NOCTTY = 8,
APPEND = 10, TRUNC = 9,
NONBLOCK = 11, APPEND = 10,
DSYNC = 12, NONBLOCK = 11,
ASYNC = 13, DSYNC = 12,
DIRECT = 14, ASYNC = 13,
LARGEFILE = 15, DIRECT = 14,
DIRECTORY = 16, LARGEFILE = 15,
NOFOLLOW = 17, DIRECTORY = 16,
NOATIME = 18, NOFOLLOW = 17,
CLOEXEC = 19, NOATIME = 18,
PATH = 21, 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,
}
} }
// 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)
/* /*
Bits for FD_Flags bitset Bits for FD_Flags bitset