Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get arm64 up to speed in os2 linux #4600

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 3 additions & 19 deletions core/os/os2/file_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion core/os/os2/heap_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 11 additions & 36 deletions core/os/os2/process_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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())
Expand All @@ -426,46 +418,30 @@ _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
strings.builder_reset(&exe_builder)
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
Expand All @@ -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:
//
Expand Down Expand Up @@ -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)
}
Expand Down
96 changes: 59 additions & 37 deletions core/sys/linux/bits.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading