From 5376d2a20b74e84967cad87ba8ee3cb3bfff4930 Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 20 Dec 2024 17:19:04 +0100 Subject: [PATCH 01/31] fix haiku --- build_odin.sh | 2 +- core/c/libc/errno.odin | 15 +- core/c/libc/locale.odin | 2 +- core/os/os_haiku.odin | 13 +- core/os/stat_unix.odin | 2 +- core/sync/futex_haiku.odin | 54 +++--- core/sys/haiku/errno.odin | 217 +++++++++++++++++++++++ core/sys/haiku/find_directory.odin | 43 ++--- core/sys/haiku/os.odin | 276 ++++++++++++++--------------- core/sys/haiku/types.odin | 14 +- core/sys/posix/errno.odin | 89 +++++++++- core/sys/posix/fcntl.odin | 69 +++++++- core/sys/posix/grp.odin | 4 +- core/sys/posix/pthread.odin | 52 +++++- core/sys/posix/sched.odin | 9 +- core/sys/posix/signal.odin | 159 ++++++++++++++++- core/sys/posix/signal_libc.odin | 2 +- core/sys/posix/sys_stat.odin | 32 +++- core/sys/posix/time.odin | 13 +- 19 files changed, 841 insertions(+), 226 deletions(-) create mode 100644 core/sys/haiku/errno.odin diff --git a/build_odin.sh b/build_odin.sh index 3547689d5..09094c151 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -115,7 +115,7 @@ OpenBSD) LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" ;; Haiku) - CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel" + CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel" LDFLAGS="$LDFLAGS -liconv" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" ;; diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin index de429a6ec..5d1ca8248 100644 --- a/core/c/libc/errno.odin +++ b/core/c/libc/errno.odin @@ -88,14 +88,15 @@ when ODIN_OS == .Haiku { _get_errno :: proc() -> ^int --- } - @(private="file") - B_GENERAL_ERROR_BASE :: min(i32) - @(private="file") - B_POSIX_ERROR_BASE :: B_GENERAL_ERROR_BASE + 0x7000 + _HAIKU_USE_POSITIVE_POSIX_ERRORS :: #config(HAIKU_USE_POSITIVE_POSIX_ERRORS, false) + _POSIX_ERROR_FACTOR :: -1 when _HAIKU_USE_POSITIVE_POSIX_ERRORS else 1 - EDOM :: B_POSIX_ERROR_BASE + 16 - EILSEQ :: B_POSIX_ERROR_BASE + 38 - ERANGE :: B_POSIX_ERROR_BASE + 17 + @(private="file") _GENERAL_ERROR_BASE :: min(int) + @(private="file") _POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000 + + EDOM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 16) + EILSEQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 38) + ERANGE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 17) } when ODIN_OS == .JS { diff --git a/core/c/libc/locale.odin b/core/c/libc/locale.odin index 371d755c5..d95f5c164 100644 --- a/core/c/libc/locale.odin +++ b/core/c/libc/locale.odin @@ -110,7 +110,7 @@ when ODIN_OS == .Windows { } } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Windows { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Windows { LC_ALL :: 0 LC_COLLATE :: 1 diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin index 4ad370724..d44ca9df0 100644 --- a/core/os/os_haiku.odin +++ b/core/os/os_haiku.odin @@ -1,11 +1,13 @@ package os -foreign import libc "system:c" +foreign import lib "system:c" import "base:runtime" import "core:c" +import "core:c/libc" import "core:strings" import "core:sys/haiku" +import "core:sys/posix" Handle :: i32 Pid :: i32 @@ -117,14 +119,13 @@ S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } +__error :: libc.errno +_unix_open :: posix.open -foreign libc { - @(link_name="_errorp") __error :: proc() -> ^c.int --- - +foreign lib { @(link_name="fork") _unix_fork :: proc() -> pid_t --- @(link_name="getthrid") _unix_getthrid :: proc() -> int --- - @(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, #c_vararg mode: ..u16) -> Handle --- @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int --- @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- @(link_name="pread") _unix_pread :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t --- @@ -203,7 +204,7 @@ fork :: proc() -> (Pid, Error) { open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) - handle := _unix_open(cstr, c.int(flags), u16(mode)) + handle := cast(Handle)_unix_open(cstr, transmute(posix.O_Flags)i32(flags), transmute(posix.mode_t)i32(mode)) if handle == -1 { return INVALID_HANDLE, get_last_error() } diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin index 7f7985e83..648987a07 100644 --- a/core/os/stat_unix.odin +++ b/core/os/stat_unix.odin @@ -53,7 +53,7 @@ File_Info :: struct { @(private, require_results) _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time { return time.Time{ - _nsec = uft.nanoseconds + uft.seconds * 1_000_000_000, + _nsec = i64(uft.nanoseconds) + i64(uft.seconds) * 1_000_000_000, } } diff --git a/core/sync/futex_haiku.odin b/core/sync/futex_haiku.odin index 21d07b801..d1b265228 100644 --- a/core/sync/futex_haiku.odin +++ b/core/sync/futex_haiku.odin @@ -1,14 +1,12 @@ #+private package sync -import "core:c" -import "core:sys/haiku" -import "core:sys/unix" +import "core:sys/posix" import "core:time" @(private="file") Wait_Node :: struct { - thread: unix.pthread_t, + thread: posix.pthread_t, futex: ^Futex, prev, next: ^Wait_Node, } @@ -58,7 +56,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) { head := &waitq.list waiter := Wait_Node{ - thread = unix.pthread_self(), + thread = posix.pthread_self(), futex = f, prev = head, next = head.next, @@ -67,25 +65,25 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) { waiter.prev.next = &waiter waiter.next.prev = &waiter - old_mask, mask: haiku.sigset_t - haiku.sigemptyset(&mask) - haiku.sigaddset(&mask, haiku.SIGCONT) - unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask) + old_mask, mask: posix.sigset_t + posix.sigemptyset(&mask) + posix.sigaddset(&mask, .SIGCONT) + posix.pthread_sigmask(.BLOCK, &mask, &old_mask) if u32(atomic_load_explicit(f, .Acquire)) == expect { waitq_unlock(waitq) defer waitq_lock(waitq) - sig: c.int - haiku.sigwait(&mask, &sig) - errno := haiku.errno() - ok = errno == .OK + sig: posix.Signal + posix.sigwait(&mask, &sig) + errno := posix.errno() + ok = errno == nil } waiter.prev.next = waiter.next waiter.next.prev = waiter.prev - _ = unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil) + _ = posix.pthread_sigmask(.SETMASK, &old_mask, nil) // FIXME: Add error handling! return @@ -101,7 +99,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration head := &waitq.list waiter := Wait_Node{ - thread = unix.pthread_self(), + thread = posix.pthread_self(), futex = f, prev = head, next = head.next, @@ -110,29 +108,29 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration waiter.prev.next = &waiter waiter.next.prev = &waiter - old_mask, mask: haiku.sigset_t - haiku.sigemptyset(&mask) - haiku.sigaddset(&mask, haiku.SIGCONT) - unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask) + old_mask, mask: posix.sigset_t + posix.sigemptyset(&mask) + posix.sigaddset(&mask, .SIGCONT) + posix.pthread_sigmask(.BLOCK, &mask, &old_mask) if u32(atomic_load_explicit(f, .Acquire)) == expect { waitq_unlock(waitq) defer waitq_lock(waitq) - info: haiku.siginfo_t - ts := unix.timespec{ - tv_sec = i64(duration / 1e9), + info: posix.siginfo_t + ts := posix.timespec{ + tv_sec = posix.time_t(i64(duration / 1e9)), tv_nsec = i64(duration % 1e9), } - haiku.sigtimedwait(&mask, &info, &ts) - errno := haiku.errno() - ok = errno == .EAGAIN || errno == .OK + posix.sigtimedwait(&mask, &info, &ts) + errno := posix.errno() + ok = errno == .EAGAIN || errno == nil } waiter.prev.next = waiter.next waiter.next.prev = waiter.prev - unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil) + posix.pthread_sigmask(.SETMASK, &old_mask, nil) // FIXME: Add error handling! return @@ -146,7 +144,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) { head := &waitq.list for waiter := head.next; waiter != head; waiter = waiter.next { if waiter.futex == f { - unix.pthread_kill(waiter.thread, haiku.SIGCONT) + posix.pthread_kill(waiter.thread, .SIGCONT) break } } @@ -160,7 +158,7 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) { head := &waitq.list for waiter := head.next; waiter != head; waiter = waiter.next { if waiter.futex == f { - unix.pthread_kill(waiter.thread, haiku.SIGCONT) + posix.pthread_kill(waiter.thread, .SIGCONT) } } } diff --git a/core/sys/haiku/errno.odin b/core/sys/haiku/errno.odin new file mode 100644 index 000000000..2b5e3681c --- /dev/null +++ b/core/sys/haiku/errno.odin @@ -0,0 +1,217 @@ +#+build haiku +package sys_haiku + +import "core:sys/posix" + +foreign import libroot "system:c" + +Errno :: enum i32 { + // Error baselines + GENERAL_ERROR_BASE = min(i32), + OS_ERROR_BASE = GENERAL_ERROR_BASE + 0x1000, + APP_ERROR_BASE = GENERAL_ERROR_BASE + 0x2000, + INTERFACE_ERROR_BASE = GENERAL_ERROR_BASE + 0x3000, + MEDIA_ERROR_BASE = GENERAL_ERROR_BASE + 0x4000, + TRANSLATION_ERROR_BASE = GENERAL_ERROR_BASE + 0x4800, + MIDI_ERROR_BASE = GENERAL_ERROR_BASE + 0x5000, + STORAGE_ERROR_BASE = GENERAL_ERROR_BASE + 0x6000, + POSIX_ERROR_BASE = GENERAL_ERROR_BASE + 0x7000, + MAIL_ERROR_BASE = GENERAL_ERROR_BASE + 0x8000, + PRINT_ERROR_BASE = GENERAL_ERROR_BASE + 0x9000, + DEVICE_ERROR_BASE = GENERAL_ERROR_BASE + 0xA000, + + // Developer-defined errors start at (ERRORS_END+1) + ERRORS_END = GENERAL_ERROR_BASE + 0xFFFF, + + // General Errors + NO_MEMORY = GENERAL_ERROR_BASE + 0, + IO_ERROR = GENERAL_ERROR_BASE + 1, + PERMISSION_DENIED = GENERAL_ERROR_BASE + 2, + BAD_INDEX = GENERAL_ERROR_BASE + 3, + BAD_TYPE = GENERAL_ERROR_BASE + 4, + BAD_VALUE = GENERAL_ERROR_BASE + 5, + MISMATCHED_VALUES = GENERAL_ERROR_BASE + 6, + NAME_NOT_FOUND = GENERAL_ERROR_BASE + 7, + NAME_IN_USE = GENERAL_ERROR_BASE + 8, + TIMED_OUT = GENERAL_ERROR_BASE + 9, + INTERRUPTED = GENERAL_ERROR_BASE + 10, + WOULD_BLOCK = GENERAL_ERROR_BASE + 11, + CANCELED = GENERAL_ERROR_BASE + 12, + NO_INIT = GENERAL_ERROR_BASE + 13, + NOT_INITIALIZED = GENERAL_ERROR_BASE + 13, + BUSY = GENERAL_ERROR_BASE + 14, + NOT_ALLOWED = GENERAL_ERROR_BASE + 15, + BAD_DATA = GENERAL_ERROR_BASE + 16, + DONT_DO_THAT = GENERAL_ERROR_BASE + 17, + + ERROR = -1, + OK = 0, + NO_ERROR = 0, + + // Kernel Kit Errors + BAD_SEM_ID = OS_ERROR_BASE + 0, + NO_MORE_SEMS = OS_ERROR_BASE + 1, + BAD_THREAD_ID = OS_ERROR_BASE + 0x100, + NO_MORE_THREADS = OS_ERROR_BASE + 0x101, + BAD_THREAD_STATE = OS_ERROR_BASE + 0x102, + BAD_TEAM_ID = OS_ERROR_BASE + 0x103, + NO_MORE_TEAMS = OS_ERROR_BASE + 0x104, + BAD_PORT_ID = OS_ERROR_BASE + 0x200, + NO_MORE_PORTS = OS_ERROR_BASE + 0x201, + BAD_IMAGE_ID = OS_ERROR_BASE + 0x300, + BAD_ADDRESS = OS_ERROR_BASE + 0x301, + NOT_AN_EXECUTABLE = OS_ERROR_BASE + 0x302, + MISSING_LIBRARY = OS_ERROR_BASE + 0x303, + MISSING_SYMBOL = OS_ERROR_BASE + 0x304, + UNKNOWN_EXECUTABLE = OS_ERROR_BASE + 0x305, + LEGACY_EXECUTABLE = OS_ERROR_BASE + 0x306, + + DEBUGGER_ALREADY_INSTALLED = OS_ERROR_BASE + 0x400, + + // Application Kit Errors + BAD_REPLY = APP_ERROR_BASE + 0, + DUPLICATE_REPLY = APP_ERROR_BASE + 1, + MESSAGE_TO_SELF = APP_ERROR_BASE + 2, + BAD_HANDLER = APP_ERROR_BASE + 3, + ALREADY_RUNNING = APP_ERROR_BASE + 4, + LAUNCH_FAILED = APP_ERROR_BASE + 5, + AMBIGUOUS_APP_LAUNCH = APP_ERROR_BASE + 6, + UNKNOWN_MIME_TYPE = APP_ERROR_BASE + 7, + BAD_SCRIPT_SYNTAX = APP_ERROR_BASE + 8, + LAUNCH_FAILED_NO_RESOLVE_LINK = APP_ERROR_BASE + 9, + LAUNCH_FAILED_EXECUTABLE = APP_ERROR_BASE + 10, + LAUNCH_FAILED_APP_NOT_FOUND = APP_ERROR_BASE + 11, + LAUNCH_FAILED_APP_IN_TRASH = APP_ERROR_BASE + 12, + LAUNCH_FAILED_NO_PREFERRED_APP = APP_ERROR_BASE + 13, + LAUNCH_FAILED_FILES_APP_NOT_FOUND = APP_ERROR_BASE + 14, + BAD_MIME_SNIFFER_RULE = APP_ERROR_BASE + 15, + NOT_A_MESSAGE = APP_ERROR_BASE + 16, + SHUTDOWN_CANCELLED = APP_ERROR_BASE + 17, + SHUTTING_DOWN = APP_ERROR_BASE + 18, + + // Storage Kit/File System Errors + FILE_ERROR = STORAGE_ERROR_BASE + 0, + // 1 was B_FILE_NOT_FOUND (deprecated) + FILE_EXISTS = STORAGE_ERROR_BASE + 2, + ENTRY_NOT_FOUND = STORAGE_ERROR_BASE + 3, + NAME_TOO_LONG = STORAGE_ERROR_BASE + 4, + NOT_A_DIRECTORY = STORAGE_ERROR_BASE + 5, + DIRECTORY_NOT_EMPTY = STORAGE_ERROR_BASE + 6, + DEVICE_FULL = STORAGE_ERROR_BASE + 7, + READ_ONLY_DEVICE = STORAGE_ERROR_BASE + 8, + IS_A_DIRECTORY = STORAGE_ERROR_BASE + 9, + NO_MORE_FDS = STORAGE_ERROR_BASE + 10, + CROSS_DEVICE_LINK = STORAGE_ERROR_BASE + 11, + LINK_LIMIT = STORAGE_ERROR_BASE + 12, + BUSTED_PIPE = STORAGE_ERROR_BASE + 13, + UNSUPPORTED = STORAGE_ERROR_BASE + 14, + PARTITION_TOO_SMALL = STORAGE_ERROR_BASE + 15, + PARTIAL_READ = STORAGE_ERROR_BASE + 16, + PARTIAL_WRITE = STORAGE_ERROR_BASE + 17, + + // New error codes that can be mapped to POSIX errors + TOO_MANY_ARGS = posix.E2BIG, + FILE_TOO_LARGE = posix.EFBIG, + DEVICE_NOT_FOUND = posix.ENODEV, + RESULT_NOT_REPRESENTABLE = posix.ERANGE, + BUFFER_OVERFLOW = posix.EOVERFLOW, + NOT_SUPPORTED = posix.EOPNOTSUPP, + + // Media Kit Errors + STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0, + SERVER_NOT_FOUND = MEDIA_ERROR_BASE + 1, + RESOURCE_NOT_FOUND = MEDIA_ERROR_BASE + 2, + RESOURCE_UNAVAILABLE = MEDIA_ERROR_BASE + 3, + BAD_SUBSCRIBER = MEDIA_ERROR_BASE + 4, + SUBSCRIBER_NOT_ENTERED = MEDIA_ERROR_BASE + 5, + BUFFER_NOT_AVAILABLE = MEDIA_ERROR_BASE + 6, + LAST_BUFFER_ERROR = MEDIA_ERROR_BASE + 7, + MEDIA_SYSTEM_FAILURE = MEDIA_ERROR_BASE + 100, + MEDIA_BAD_NODE = MEDIA_ERROR_BASE + 101, + MEDIA_NODE_BUSY = MEDIA_ERROR_BASE + 102, + MEDIA_BAD_FORMAT = MEDIA_ERROR_BASE + 103, + MEDIA_BAD_BUFFER = MEDIA_ERROR_BASE + 104, + MEDIA_TOO_MANY_NODES = MEDIA_ERROR_BASE + 105, + MEDIA_TOO_MANY_BUFFERS = MEDIA_ERROR_BASE + 106, + MEDIA_NODE_ALREADY_EXISTS = MEDIA_ERROR_BASE + 107, + MEDIA_BUFFER_ALREADY_EXISTS = MEDIA_ERROR_BASE + 108, + MEDIA_CANNOT_SEEK = MEDIA_ERROR_BASE + 109, + MEDIA_CANNOT_CHANGE_RUN_MODE = MEDIA_ERROR_BASE + 110, + MEDIA_APP_ALREADY_REGISTERED = MEDIA_ERROR_BASE + 111, + MEDIA_APP_NOT_REGISTERED = MEDIA_ERROR_BASE + 112, + MEDIA_CANNOT_RECLAIM_BUFFERS = MEDIA_ERROR_BASE + 113, + MEDIA_BUFFERS_NOT_RECLAIMED = MEDIA_ERROR_BASE + 114, + MEDIA_TIME_SOURCE_STOPPED = MEDIA_ERROR_BASE + 115, + MEDIA_TIME_SOURCE_BUSY = MEDIA_ERROR_BASE + 116, + MEDIA_BAD_SOURCE = MEDIA_ERROR_BASE + 117, + MEDIA_BAD_DESTINATION = MEDIA_ERROR_BASE + 118, + MEDIA_ALREADY_CONNECTED = MEDIA_ERROR_BASE + 119, + MEDIA_NOT_CONNECTED = MEDIA_ERROR_BASE + 120, + MEDIA_BAD_CLIP_FORMAT = MEDIA_ERROR_BASE + 121, + MEDIA_ADDON_FAILED = MEDIA_ERROR_BASE + 122, + MEDIA_ADDON_DISABLED = MEDIA_ERROR_BASE + 123, + MEDIA_CHANGE_IN_PROGRESS = MEDIA_ERROR_BASE + 124, + MEDIA_STALE_CHANGE_COUNT = MEDIA_ERROR_BASE + 125, + MEDIA_ADDON_RESTRICTED = MEDIA_ERROR_BASE + 126, + MEDIA_NO_HANDLER = MEDIA_ERROR_BASE + 127, + MEDIA_DUPLICATE_FORMAT = MEDIA_ERROR_BASE + 128, + MEDIA_REALTIME_DISABLED = MEDIA_ERROR_BASE + 129, + MEDIA_REALTIME_UNAVAILABLE = MEDIA_ERROR_BASE + 130, + + // Mail Kit Errors + MAIL_NO_DAEMON = MAIL_ERROR_BASE + 0, + MAIL_UNKNOWN_USER = MAIL_ERROR_BASE + 1, + MAIL_WRONG_PASSWORD = MAIL_ERROR_BASE + 2, + MAIL_UNKNOWN_HOST = MAIL_ERROR_BASE + 3, + MAIL_ACCESS_ERROR = MAIL_ERROR_BASE + 4, + MAIL_UNKNOWN_FIELD = MAIL_ERROR_BASE + 5, + MAIL_NO_RECIPIENT = MAIL_ERROR_BASE + 6, + MAIL_INVALID_MAIL = MAIL_ERROR_BASE + 7, + + // Printing Errors + NO_PRINT_SERVER = PRINT_ERROR_BASE + 0, + + // Device Kit Errors + DEV_INVALID_IOCTL = DEVICE_ERROR_BASE + 0, + DEV_NO_MEMORY = DEVICE_ERROR_BASE + 1, + DEV_BAD_DRIVE_NUM = DEVICE_ERROR_BASE + 2, + DEV_NO_MEDIA = DEVICE_ERROR_BASE + 3, + DEV_UNREADABLE = DEVICE_ERROR_BASE + 4, + DEV_FORMAT_ERROR = DEVICE_ERROR_BASE + 5, + DEV_TIMEOUT = DEVICE_ERROR_BASE + 6, + DEV_RECALIBRATE_ERROR = DEVICE_ERROR_BASE + 7, + DEV_SEEK_ERROR = DEVICE_ERROR_BASE + 8, + DEV_ID_ERROR = DEVICE_ERROR_BASE + 9, + DEV_READ_ERROR = DEVICE_ERROR_BASE + 10, + DEV_WRITE_ERROR = DEVICE_ERROR_BASE + 11, + DEV_NOT_READY = DEVICE_ERROR_BASE + 12, + DEV_MEDIA_CHANGED = DEVICE_ERROR_BASE + 13, + DEV_MEDIA_CHANGE_REQUESTED = DEVICE_ERROR_BASE + 14, + DEV_RESOURCE_CONFLICT = DEVICE_ERROR_BASE + 15, + DEV_CONFIGURATION_ERROR = DEVICE_ERROR_BASE + 16, + DEV_DISABLED_BY_USER = DEVICE_ERROR_BASE + 17, + DEV_DOOR_OPEN = DEVICE_ERROR_BASE + 18, + DEV_INVALID_PIPE = DEVICE_ERROR_BASE + 19, + DEV_CRC_ERROR = DEVICE_ERROR_BASE + 20, + DEV_STALLED = DEVICE_ERROR_BASE + 21, + DEV_BAD_PID = DEVICE_ERROR_BASE + 22, + DEV_UNEXPECTED_PID = DEVICE_ERROR_BASE + 23, + DEV_DATA_OVERRUN = DEVICE_ERROR_BASE + 24, + DEV_DATA_UNDERRUN = DEVICE_ERROR_BASE + 25, + DEV_FIFO_OVERRUN = DEVICE_ERROR_BASE + 26, + DEV_FIFO_UNDERRUN = DEVICE_ERROR_BASE + 27, + DEV_PENDING = DEVICE_ERROR_BASE + 28, + DEV_MULTIPLE_ERRORS = DEVICE_ERROR_BASE + 29, + DEV_TOO_LATE = DEVICE_ERROR_BASE + 30, + + // Translation Kit Errors + TRANSLATION_BASE_ERROR = TRANSLATION_ERROR_BASE + 0, + NO_TRANSLATOR = TRANSLATION_ERROR_BASE + 1, + ILLEGAL_DATA = TRANSLATION_ERROR_BASE + 2, +} + +@(default_calling_convention="c") +foreign libroot { + _to_positive_error :: proc(error: i32) -> i32 --- + _to_negative_error :: proc(error: i32) -> i32 --- +} diff --git a/core/sys/haiku/find_directory.odin b/core/sys/haiku/find_directory.odin index 758c4dff4..917394f48 100644 --- a/core/sys/haiku/find_directory.odin +++ b/core/sys/haiku/find_directory.odin @@ -1,9 +1,11 @@ #+build haiku package sys_haiku -import "core:c" +import "base:intrinsics" -directory_which :: enum c.int { +foreign import libroot "system:c" + +directory_which :: enum i32 { // Per volume directories DESKTOP_DIRECTORY = 0, TRASH_DIRECTORY, @@ -110,17 +112,18 @@ directory_which :: enum c.int { BEOS_SOUNDS_DIRECTORY, } -find_path_flags :: enum c.int { - CREATE_DIRECTORY = 0x0001, - CREATE_PARENT_DIRECTORY = 0x0002, - EXISTING_ONLY = 0x0004, +find_path_flag :: enum u32 { + CREATE_DIRECTORY = intrinsics.constant_log2(0x0001), + CREATE_PARENT_DIRECTORY = intrinsics.constant_log2(0x0002), + EXISTING_ONLY = intrinsics.constant_log2(0x0004), - // find_paths() only! - SYSTEM_ONLY = 0x0010, - USER_ONLY = 0x0020, + // find_paths() only + SYSTEM_ONLY = intrinsics.constant_log2(0x0010), + USER_ONLY = intrinsics.constant_log2(0x0020), } +find_path_flags :: distinct bit_set[find_path_flag; u32] -path_base_directory :: enum c.int { +path_base_directory :: enum i32 { INSTALLATION_LOCATION_DIRECTORY, ADD_ONS_DIRECTORY, APPS_DIRECTORY, @@ -146,7 +149,7 @@ path_base_directory :: enum c.int { TRANSLATORS_DIRECTORY, VAR_DIRECTORY, - // find_path() only! + // find_path() only IMAGE_PATH = 1000, PACKAGE_PATH, } @@ -154,15 +157,15 @@ path_base_directory :: enum c.int { // value that can be used instead of a pointer to a symbol in the program image APP_IMAGE_SYMBOL :: rawptr(addr_t(0)) // pointer to a symbol in the callers image (same as B_CURRENT_IMAGE_SYMBOL) -current_image_symbol :: proc() -> rawptr { return rawptr(current_image_symbol) } +current_image_symbol :: proc "contextless" () -> rawptr { return rawptr(current_image_symbol) } -foreign import libroot "system:c" +@(default_calling_convention="c") foreign libroot { - find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]c.char, length: i32) -> status_t --- - find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- - find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- - find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- - find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- - find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t --- - find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t --- + find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]byte, length: i32) -> status_t --- + find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- + find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- + find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- + find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- + find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uintptr) -> status_t --- + find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uintptr) -> status_t --- } diff --git a/core/sys/haiku/os.odin b/core/sys/haiku/os.odin index 6ab3ef573..a9c5ea57d 100644 --- a/core/sys/haiku/os.odin +++ b/core/sys/haiku/os.odin @@ -1,8 +1,8 @@ #+build haiku package sys_haiku +import "base:intrinsics" import "core:c" -import "core:sys/unix" foreign import libroot "system:c" @@ -18,8 +18,8 @@ OS_NAME_LENGTH :: 32 area_info :: struct { area: area_id, - name: [OS_NAME_LENGTH]c.char, - size: c.size_t, + name: [OS_NAME_LENGTH]byte, + size: uintptr, lock: u32, protection: u32, team: team_id, @@ -31,11 +31,11 @@ area_info :: struct { } area_locking :: enum u32 { - NO_LOCK = 0, - LAZY_LOCK = 1, - FULL_LOCK = 2, - CONTIGUOUS = 3, - LOMEM = 4, // CONTIGUOUS, < 16 MB physical address + NO_LOCK = 0, + LAZY_LOCK = 1, + FULL_LOCK = 2, + CONTIGUOUS = 3, + LOMEM = 4, // CONTIGUOUS, < 16 MB physical address _32_BIT_FULL_LOCK = 5, // FULL_LOCK, < 4 GB physical addresses _32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address } @@ -52,27 +52,29 @@ address_spec :: enum u32 { RANDOMIZED_BASE_ADDRESS = 7, } -area_protection_flags :: enum u32 { - READ_AREA = 1 << 0, - WRITE_AREA = 1 << 1, - EXECUTE_AREA = 1 << 2, +area_protection_flag :: enum u32 { + READ_AREA = 0, + WRITE_AREA = 1, + EXECUTE_AREA = 2, // "stack" protection is not available on most platforms - it's used // to only commit memory as needed, and have guard pages at the // bottom of the stack. - STACK_AREA = 1 << 3, - CLONEABLE_AREA = 1 << 8, + STACK_AREA = 3, + CLONEABLE_AREA = 8, } +area_protection_flags :: distinct bit_set[area_protection_flag; u32] +@(default_calling_convention="c") foreign libroot { - create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: c.size_t, lock: area_locking, protection: area_protection_flags) -> area_id --- + create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uintptr, lock: area_locking, protection: area_protection_flags) -> area_id --- clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id --- find_area :: proc(name: cstring) -> area_id --- area_for :: proc(address: rawptr) -> area_id --- delete_area :: proc(id: area_id) -> status_t --- - resize_area :: proc(id: area_id, newSize: c.size_t) -> status_t --- + resize_area :: proc(id: area_id, newSize: uintptr) -> status_t --- set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t --- - _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: c.size_t) -> status_t --- - _get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: c.size_t) -> status_t --- + _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uintptr) -> status_t --- + _get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: uintptr) -> status_t --- } // Ports @@ -80,33 +82,35 @@ foreign libroot { port_info :: struct { port: port_id, team: team_id, - name: [OS_NAME_LENGTH]c.char, + name: [OS_NAME_LENGTH]byte, capacity: i32, // queue depth queue_count: i32, // # msgs waiting to be read total_count: i32, // total # msgs read so far } -port_flags :: enum u32 { - USE_USER_MEMCPY = 0x80000000, +port_flag :: enum u32 { + USE_USER_MEMCPY = intrinsics.constant_log2(0x80000000), // read the message, but don't remove it; kernel-only; memory must be locked - PEEK_PORT_MESSAGE = 0x100, + PEEK_PORT_MESSAGE = intrinsics.constant_log2(0x100), } +port_flags :: distinct bit_set[port_flag; u32] +@(default_calling_convention="c") foreign libroot { create_port :: proc(capacity: i32, name: cstring) -> port_id --- find_port :: proc(name: cstring) -> port_id --- - read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t) -> c.ssize_t --- - read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- - write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t --- - write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> status_t --- + read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> c.ssize_t --- + read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- + write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t --- + write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> status_t --- close_port :: proc(port: port_id) -> status_t --- delete_port :: proc(port: port_id) -> status_t --- port_buffer_size :: proc(port: port_id) -> c.ssize_t --- port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- port_count :: proc(port: port_id) -> c.ssize_t --- set_port_owner :: proc(port: port_id, team: team_id) -> status_t --- - _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t --- - _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t --- + _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- + _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- } // Semaphores @@ -114,22 +118,24 @@ foreign libroot { sem_info :: struct { sem: sem_id, team: team_id, - name: [OS_NAME_LENGTH]c.char, + name: [OS_NAME_LENGTH]byte, count: i32, latest_holder: thread_id, } -semaphore_flags :: enum u32 { - CAN_INTERRUPT = 0x01, // acquisition of the semaphore can be interrupted (system use only) - CHECK_PERMISSION = 0x04, // ownership will be checked (system use only) - KILL_CAN_INTERRUPT = 0x20, // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only) +semaphore_flag :: enum u32 { + CAN_INTERRUPT = intrinsics.constant_log2(0x01), // acquisition of the semaphore can be interrupted (system use only) + CHECK_PERMISSION = intrinsics.constant_log2(0x04), // ownership will be checked (system use only) + KILL_CAN_INTERRUPT = intrinsics.constant_log2(0x20), // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only) // release_sem_etc() only flags - DO_NOT_RESCHEDULE = 0x02, // thread is not rescheduled - RELEASE_ALL = 0x08, // all waiting threads will be woken up, count will be zeroed - RELEASE_IF_WAITING_ONLY = 0x10, // release count only if there are any threads waiting + DO_NOT_RESCHEDULE = intrinsics.constant_log2(0x02), // thread is not rescheduled + RELEASE_ALL = intrinsics.constant_log2(0x08), // all waiting threads will be woken up, count will be zeroed + RELEASE_IF_WAITING_ONLY = intrinsics.constant_log2(0x10), // release count only if there are any threads waiting } +semaphore_flags :: distinct bit_set[semaphore_flag; u32] +@(default_calling_convention="c") foreign libroot { create_sem :: proc(count: i32, name: cstring) -> sem_id --- delete_sem :: proc(id: sem_id) -> status_t --- @@ -141,8 +147,8 @@ foreign libroot { switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t --- get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t --- set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t --- - _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: c.size_t) -> status_t --- - _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: c.size_t) -> status_t --- + _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uintptr) -> status_t --- + _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uintptr) -> status_t --- } // Teams @@ -155,7 +161,7 @@ team_info :: struct { debugger_nub_thread: thread_id, debugger_nub_port: port_id, argc: i32, - args: [64]c.char, + args: [64]byte, uid: uid_t, gid: gid_t, @@ -165,7 +171,7 @@ team_info :: struct { group_id: pid_t, session_id: pid_t, parent: team_id, - name: [OS_NAME_LENGTH]c.char, + name: [OS_NAME_LENGTH]byte, start_time: bigtime_t, } @@ -183,17 +189,18 @@ team_usage_who :: enum i32 { CHILDREN = -1, } +@(default_calling_convention="c") foreign libroot { // see also: send_signal() kill_team :: proc(team: team_id) -> status_t --- - _get_team_info :: proc(id: team_id, info: ^team_info, size: c.size_t) -> status_t --- - _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: c.size_t) -> status_t --- - _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: c.size_t) -> status_t --- + _get_team_info :: proc(id: team_id, info: ^team_info, size: uintptr) -> status_t --- + _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uintptr) -> status_t --- + _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uintptr) -> status_t --- } // Threads -thread_state :: enum c.int { +thread_state :: enum i32 { RUNNING = 1, READY, RECEIVING, @@ -205,7 +212,7 @@ thread_state :: enum c.int { thread_info :: struct { thread: thread_id, team: team_id, - name: [OS_NAME_LENGTH]c.char, + name: [OS_NAME_LENGTH]byte, state: thread_state, priority: thread_priority, sem: sem_id, @@ -234,6 +241,7 @@ SYSTEM_TIMEBASE :: 0 thread_func :: #type proc "c" (rawptr) -> status_t +@(default_calling_convention="c") foreign libroot { spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id --- kill_thread :: proc(thread: thread_id) -> status_t --- @@ -247,24 +255,25 @@ foreign libroot { wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t --- on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t --- find_thread :: proc(name: cstring) -> thread_id --- - send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t --- - receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: c.size_t) -> i32 --- + send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t --- + receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uintptr) -> i32 --- has_data :: proc(thread: thread_id) -> bool --- snooze :: proc(amount: bigtime_t) -> status_t --- // FIXME: Find and define those flags. - snooze_etc :: proc(amount: bigtime_t, timeBase: c.int, flags: u32) -> status_t --- - snooze_until :: proc(time: bigtime_t, timeBase: c.int) -> status_t --- - _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: c.size_t) -> status_t --- - _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: c.size_t) -> status_t --- + snooze_etc :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t --- + snooze_until :: proc(time: bigtime_t, timeBase: i32) -> status_t --- + _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uintptr) -> status_t --- + _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uintptr) -> status_t --- // bridge to the pthread API get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id --- } // Time +@(default_calling_convention="c") foreign libroot { - real_time_clock :: proc() -> c.ulong --- - set_real_time_clock :: proc(secsSinceJan1st1970: c.ulong) --- + real_time_clock :: proc() -> uint --- + set_real_time_clock :: proc(secsSinceJan1st1970: uint) --- real_time_clock_usecs :: proc() -> bigtime_t --- // time since booting in microseconds system_time :: proc() -> bigtime_t --- @@ -280,12 +289,14 @@ alarm_mode :: enum u32 { PERIODIC_ALARM, // "when" specifies the period } +@(default_calling_convention="c") foreign libroot { set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t --- } // Debugger +@(default_calling_convention="c") foreign libroot { debugger :: proc(message: cstring) --- /* @@ -296,7 +307,7 @@ foreign libroot { to re-enable the default debugger pass a zero. */ - disable_debugger :: proc(state: c.int) -> c.int --- + disable_debugger :: proc(state: i32) -> i32 --- } // System information @@ -338,15 +349,15 @@ system_info :: struct { max_teams: u32, used_teams: u32, - kernel_name: [FILE_NAME_LENGTH]c.char, - kernel_build_date: [OS_NAME_LENGTH]c.char, - kernel_build_time: [OS_NAME_LENGTH]c.char, + kernel_name: [FILE_NAME_LENGTH]byte, + kernel_build_date: [OS_NAME_LENGTH]byte, + kernel_build_time: [OS_NAME_LENGTH]byte, kernel_version: i64, abi: u32, // the system API } -topology_level_type :: enum c.int { +topology_level_type :: enum i32 { UNKNOWN, ROOT, SMT, @@ -354,7 +365,7 @@ topology_level_type :: enum c.int { PACKAGE, } -cpu_platform :: enum c.int { +cpu_platform :: enum i32 { UNKNOWN, x86, x86_64, @@ -370,7 +381,7 @@ cpu_platform :: enum c.int { RISC_V, } -cpu_vendor :: enum c.int { +cpu_vendor :: enum i32 { UNKNOWN, AMD, CYRIX, @@ -408,95 +419,68 @@ cpu_topology_node_info :: struct { }, } -// FIXME: Add cpuid_info when bit fields are ready. +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + cpuid_info :: struct #raw_union { + eax_0: struct { + max_eax: u32, + vendor_id: [12]byte, + }, + eax_1: struct { + using _: bit_field u32 { + stepping: u32 | 4, + model: u32 | 4, + family: u32 | 4, + type: u32 | 2, + reserved_0: u32 | 2, + extended_model: u32 | 4, + extended_family: u32 | 8, + reserved_1: u32 | 4, + }, + + using _: bit_field u32 { + brand_index: u32 | 8, + clflush: u32 | 8, + logical_cpus: u32 | 8, + apic_id: u32 | 8, + }, + + features: u32, + extended_features: u32, + }, + + eax_2: struct { + call_num: u8, + cache_descriptors: [15]u8, + }, + + eax_3: struct { + reserved: [2]u32, + serial_number_high: u32, + serial_number_low: u32, + }, + + as_chars: [16]byte, + + regs: struct { + eax: u32, + ebx: u32, + edx: u32, + ecx: u32, + }, + } +} + +@(default_calling_convention="c") foreign libroot { get_system_info :: proc(info: ^system_info) -> status_t --- - _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: c.size_t) -> status_t --- + _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uintptr) -> status_t --- get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t --- - is_computer_on :: proc() -> i32 --- - is_computer_on_fire :: proc() -> f64 --- -} - -// Signal.h - -SIG_BLOCK :: 1 -SIG_UNBLOCK :: 2 -SIG_SETMASK :: 3 - -/* - * The list of all defined signals: - * - * The numbering of signals for Haiku attempts to maintain - * some consistency with UN*X conventions so that things - * like "kill -9" do what you expect. - */ - -SIGHUP :: 1 // hangup -- tty is gone! -SIGINT :: 2 // interrupt -SIGQUIT :: 3 // `quit' special character typed in tty -SIGILL :: 4 // illegal instruction -SIGCHLD :: 5 // child process exited -SIGABRT :: 6 // abort() called, dont' catch -SIGPIPE :: 7 // write to a pipe w/no readers -SIGFPE :: 8 // floating point exception -SIGKILL :: 9 // kill a team (not catchable) -SIGSTOP :: 10 // suspend a thread (not catchable) -SIGSEGV :: 11 // segmentation violation (read: invalid pointer) -SIGCONT :: 12 // continue execution if suspended -SIGTSTP :: 13 // `stop' special character typed in tty -SIGALRM :: 14 // an alarm has gone off (see alarm()) -SIGTERM :: 15 // termination requested -SIGTTIN :: 16 // read of tty from bg process -SIGTTOU :: 17 // write to tty from bg process -SIGUSR1 :: 18 // app defined signal 1 -SIGUSR2 :: 19 // app defined signal 2 -SIGWINCH :: 20 // tty window size changed -SIGKILLTHR :: 21 // be specific: kill just the thread, not team -SIGTRAP :: 22 // Trace/breakpoint trap -SIGPOLL :: 23 // Pollable event -SIGPROF :: 24 // Profiling timer expired -SIGSYS :: 25 // Bad system call -SIGURG :: 26 // High bandwidth data is available at socket -SIGVTALRM :: 27 // Virtual timer expired -SIGXCPU :: 28 // CPU time limit exceeded -SIGXFSZ :: 29 // File size limit exceeded -SIGBUS :: 30 // access to undefined portion of a memory object - -sigval :: struct #raw_union { - sival_int: c.int, - sival_ptr: rawptr, -} - -siginfo_t :: struct { - si_signo: c.int, // signal number - si_code: c.int, // signal code - si_errno: c.int, // if non zero, an error number associated with this signal - - si_pid: pid_t, // sending process ID - si_uid: uid_t, // real user ID of sending process - si_addr: rawptr, // address of faulting instruction - si_status: c.int, // exit value or signal - si_band: c.long, // band event for SIGPOLL - si_value: sigval, // signal value -} - -foreign libroot { - // signal set (sigset_t) manipulation - sigemptyset :: proc(set: ^sigset_t) -> c.int --- - sigfillset :: proc(set: ^sigset_t) -> c.int --- - sigaddset :: proc(set: ^sigset_t, _signal: c.int) -> c.int --- - sigdelset :: proc(set: ^sigset_t, _signal: c.int) -> c.int --- - sigismember :: proc(set: ^sigset_t, _signal: c.int) -> c.int --- - // querying and waiting for signals - sigpending :: proc(set: ^sigset_t) -> c.int --- - sigsuspend :: proc(mask: ^sigset_t) -> c.int --- - sigpause :: proc(_signal: c.int) -> c.int --- - sigwait :: proc(set: ^sigset_t, _signal: ^c.int) -> c.int --- - sigwaitinfo :: proc(set: ^sigset_t, info: ^siginfo_t) -> c.int --- - sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^unix.timespec) -> c.int --- - - send_signal :: proc(threadID: thread_id, signal: c.uint) -> c.int --- - set_signal_stack :: proc(base: rawptr, size: c.size_t) --- + when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + get_cpuid :: proc(info: ^cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t --- + } + + is_computer_on :: proc() -> i32 --- + is_computer_on_fire :: proc() -> f64 --- } diff --git a/core/sys/haiku/types.odin b/core/sys/haiku/types.odin index 47755b0b7..f15ffb00d 100644 --- a/core/sys/haiku/types.odin +++ b/core/sys/haiku/types.odin @@ -1,9 +1,7 @@ #+build haiku package sys_haiku -import "core:c" - -status_t :: i32 +status_t :: Errno bigtime_t :: i64 nanotime_t :: i64 type_code :: u32 @@ -37,16 +35,20 @@ mode_t :: u32 umode_t :: u32 nlink_t :: i32 -caddr_t :: ^c.char +caddr_t :: [^]byte addr_t :: phys_addr_t key_t :: i32 clockid_t :: i32 -time_t :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else i32 +time_t :: int +timespec :: struct { + tv_sec: time_t, + tv_nsec: int, +} -sig_atomic_t :: c.int +sig_atomic_t :: i32 sigset_t :: u64 image_id :: i32 diff --git a/core/sys/posix/errno.odin b/core/sys/posix/errno.odin index 9bc77f12e..bb4e9e045 100644 --- a/core/sys/posix/errno.odin +++ b/core/sys/posix/errno.odin @@ -1,4 +1,4 @@ -#+build windows, darwin, linux, freebsd, openbsd, netbsd +#+build windows, darwin, linux, freebsd, openbsd, netbsd, haiku package posix import "core:c" @@ -536,5 +536,92 @@ when ODIN_OS == .Darwin { ETXTBSY :: 139 EWOULDBLOCK :: 140 EXDEV :: 18 +} else when ODIN_OS == .Haiku { + _HAIKU_USE_POSITIVE_POSIX_ERRORS :: libc._HAIKU_USE_POSITIVE_POSIX_ERRORS + _POSIX_ERROR_FACTOR :: libc._POSIX_ERROR_FACTOR + + _GENERAL_ERROR_BASE :: min(c.int) + _OS_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x1000 + _STORAGE_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x6000 + _POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000 + + EIO :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 1) // B_IO_ERROR + EACCES :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 2) // B_PERMISSION_DENIED + EINVAL :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 5) // B_BAD_VALUE + ETIMEDOUT :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 9) // B_TIMED_OUT + EINTR :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 10) // B_INTERRUPTED + EAGAIN :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* SysV compatibility */ + EWOULDBLOCK :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* BSD compatibility */ + EBUSY :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 14) // B_BUSY + EPERM :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 15) // B_NOT_ALLOWED + EFAULT :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x301) // B_BAD_ADDRESS + ENOEXEC :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x302) // B_NOT_AN_EXECUTABLE + EBADF :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 0) // B_FILE_ERROR + EEXIST :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 2) // B_FILE_EXISTS + ENOENT :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 3) // B_ENTRY_NOT_FOUND + ENAMETOOLONG :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 4) // B_NAME_TOO_LONG + ENOTDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 5) // B_NOT_A_DIRECTORY + ENOTEMPTY :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 6) // B_DIRECTORY_NOT_EMPTY + ENOSPC :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 7) // B_DEVICE_FULL + EROFS :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 8) // B_READ_ONLY_DEVICE + EISDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 9) // B_IS_A_DIRECTORY + EMFILE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 10) // B_NO_MORE_FDS + EXDEV :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 11) // B_CROSS_DEVICE_LINK + ELOOP :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 12) // B_LINK_LIMIT + EPIPE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 13) // B_BUSTED_PIPE + ENOMEM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 0) when _HAIKU_USE_POSITIVE_POSIX_ERRORS else (_GENERAL_ERROR_BASE + 0) // B_NO_MEMORY + E2BIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 1) + ECHILD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 2) + EDEADLK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 3) + EFBIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 4) + EMLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 5) + ENFILE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 6) + ENODEV :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 7) + ENOLCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 8) + ENOSYS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 9) + ENOTTY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 10) + ENXIO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 11) + ESPIPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 12) + ESRCH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 13) + EPROTOTYPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 18) + EPROTONOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 19) + EAFNOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 21) + EADDRINUSE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 22) + EADDRNOTAVAIL :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 23) + ENETDOWN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 24) + ENETUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 25) + ENETRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 26) + ECONNABORTED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 27) + ECONNRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 28) + EISCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 29) + ENOTCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 30) + ECONNREFUSED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 32) + EHOSTUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 33) + ENOPROTOOPT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 34) + ENOBUFS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 35) + EINPROGRESS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 36) + EALREADY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 37) + ENOMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 39) + ESTALE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 40) + EOVERFLOW :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 41) + EMSGSIZE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 42) + EOPNOTSUPP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 43) + ENOTSOCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 44) + EBADMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 46) + ECANCELED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 47) + EDESTADDRREQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 48) + EDQUOT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 49) + EIDRM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 50) + EMULTIHOP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 51) + ENODATA :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 52) + ENOLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 53) + ENOSR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 54) + ENOSTR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 55) + ENOTSUP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 56) + EPROTO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 57) + ETIME :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 58) + ETXTBSY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 59) + ENOTRECOVERABLE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 61) + EOWNERDEAD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 62) } diff --git a/core/sys/posix/fcntl.odin b/core/sys/posix/fcntl.odin index d948af600..bc0b5b5ba 100644 --- a/core/sys/posix/fcntl.odin +++ b/core/sys/posix/fcntl.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, openbsd, freebsd, netbsd +#+build linux, darwin, openbsd, freebsd, netbsd, haiku package posix import "core:c" @@ -343,6 +343,7 @@ when ODIN_OS == .Darwin { l_type: Lock_Type, /* [PSX] type of lock */ l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ } + } else when ODIN_OS == .OpenBSD { off_t :: distinct c.int64_t @@ -408,6 +409,72 @@ when ODIN_OS == .Darwin { l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ } +} else when ODIN_OS == .Haiku { + + off_t :: distinct c.int64_t + pid_t :: distinct c.int32_t + + /* commands that can be passed to fcntl() */ + F_DUPFD :: 0x0001 /* duplicate fd */ + F_GETFD :: 0x0002 /* get fd flags */ + F_SETFD :: 0x0004 /* set fd flags */ + F_GETFL :: 0x0008 /* get file status flags and access mode */ + F_SETFL :: 0x0010 /* set file status flags */ + F_GETLK :: 0x0020 /* get locking information */ + F_SETLK :: 0x0080 /* set locking information */ + F_SETLKW :: 0x0100 /* as above, but waits if blocked */ + F_DUPFD_CLOEXEC :: 0x0200 /* duplicate fd with close on exec set */ + F_GETOWN :: -1 // NOTE: Not supported. + F_SETOWN :: -1 // NOTE: Not supported. + + /* advisory locking types */ + F_RDLCK :: 0x0040 /* read or shared lock */ + F_UNLCK :: 0x0200 /* unlock */ + F_WRLCK :: 0x0400 /* write or exclusive lock */ + + /* file descriptor flags for fcntl() */ + FD_CLOEXEC :: 1 + + O_CLOEXEC :: 0x00000040 + O_CREAT :: 0x0200 + O_DIRECTORY :: 0x00200000 + O_EXCL :: 0x0100 + O_NOCTTY :: 0x1000 + O_NOFOLLOW :: 0x00080000 + O_TRUNC :: 0x0400 + + _O_TTY_INIT :: 0 + O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers + + O_APPEND :: 0x0800 + O_DSYNC :: 0x040000 + O_NONBLOCK :: 0x0080 + O_SYNC :: 0x010000 + O_RSYNC :: 0x020000 + + O_EXEC :: 0x04000000 // NOTE: not defined in the headers + O_RDONLY :: 0 + O_RDWR :: 0x0002 + O_WRONLY :: 0x0001 + + _O_SEARCH :: 0 + O_SEARCH :: O_Flags{} // NOTE: not defined in the headers + + AT_FDCWD: FD: -100 + + AT_EACCESS :: 0x08 + AT_SYMLINK_NOFOLLOW :: 0x01 + AT_SYMLINK_FOLLOW :: 0x02 + AT_REMOVEDIR :: 0x04 + + flock :: struct { + l_type: Lock_Type, /* [PSX] type of lock */ + l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ + l_start: off_t, /* [PSX] relative offset in bytes */ + l_len: off_t, /* [PSX] size; if 0 then until EOF */ + l_pid: pid_t, /* [PSX] process ID of the process holding the lock */ + } + } else when ODIN_OS == .Linux { off_t :: distinct c.int64_t diff --git a/core/sys/posix/grp.odin b/core/sys/posix/grp.odin index 956ed148b..3694308a0 100644 --- a/core/sys/posix/grp.odin +++ b/core/sys/posix/grp.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -115,7 +115,7 @@ foreign lib { getgrnam_r :: proc(name: cstring, grp: ^group, buffer: [^]byte, bufsize: c.size_t, result: ^^group) -> Errno --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Linux { gid_t :: distinct c.uint32_t diff --git a/core/sys/posix/pthread.odin b/core/sys/posix/pthread.odin index 490064da6..36a3cd7b3 100644 --- a/core/sys/posix/pthread.odin +++ b/core/sys/posix/pthread.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -554,6 +554,56 @@ when ODIN_OS == .Darwin { sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */ } +} else when ODIN_OS == .Haiku { + + PTHREAD_CANCEL_ASYNCHRONOUS :: 2 + PTHREAD_CANCEL_DEFERRED :: 0 + + PTHREAD_CANCEL_DISABLE :: 1 + PTHREAD_CANCEL_ENABLE :: 0 + + PTHREAD_CANCELED :: rawptr(uintptr(1)) + + PTHREAD_CREATE_DETACHED :: 0x1 + PTHREAD_CREATE_JOINABLE :: 0 + + PTHREAD_EXPLICIT_SCHED :: 0 + PTHREAD_INHERIT_SCHED :: 0x4 + + PTHREAD_PRIO_INHERIT :: 1 + PTHREAD_PRIO_NONE :: 0 + PTHREAD_PRIO_PROTECT :: 2 + + PTHREAD_PROCESS_SHARED :: 1 + PTHREAD_PROCESS_PRIVATE :: 0 + + PTHREAD_SCOPE_PROCESS :: 0 + PTHREAD_SCOPE_SYSTEM :: 0x2 + + pthread_t :: distinct rawptr + pthread_attr_t :: distinct rawptr + pthread_key_t :: distinct c.int + + pthread_mutex_t :: struct { + flags: u32, + lock: i32, + unused: i32, + owner: i32, + owner_count: i32, + } + + pthread_cond_t :: struct { + flags: u32, + unused: i32, + mutex: ^pthread_mutex_t, + waiter_count: i32, + lock: i32, + } + + sched_param :: struct { + sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */ + } + } else when ODIN_OS == .Linux { PTHREAD_CANCEL_DEFERRED :: 0 diff --git a/core/sys/posix/sched.odin b/core/sys/posix/sched.odin index e91178b09..82b335653 100644 --- a/core/sys/posix/sched.odin +++ b/core/sys/posix/sched.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -101,4 +101,11 @@ when ODIN_OS == .Darwin { SCHED_FIFO :: 1 SCHED_RR :: 2 +} else when ODIN_OS == .Haiku { + + SCHED_FIFO :: 1 + SCHED_RR :: 2 + // SCHED_SPORADIC :: 3 NOTE: not a thing on freebsd, netbsd and probably others, leaving it out + SCHED_OTHER :: 4 + } diff --git a/core/sys/posix/signal.odin b/core/sys/posix/signal.odin index 4ba4e9943..d43270410 100644 --- a/core/sys/posix/signal.odin +++ b/core/sys/posix/signal.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" @@ -185,6 +185,16 @@ foreign lib { */ sigwait :: proc(set: ^sigset_t, sig: ^Signal) -> Errno --- + when ODIN_OS != .Darwin { + /* + Wait for queued signals. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]] + */ + sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^timespec) -> result --- + } + + /* NOTE: unimplemented on darwin. void psiginfo(const siginfo_t *, const char *); @@ -1180,4 +1190,151 @@ when ODIN_OS == .Darwin { SI_TIMER :: -2 SI_MESGQ :: -3 SI_ASYNCIO :: -4 + +} else when ODIN_OS == .Haiku { + + // Request that signal be held + SIG_HOLD :: rawptr(uintptr(3)) + + uid_t :: distinct c.uint32_t + sigset_t :: distinct u64 + + SIGHUP :: 1 // hangup -- tty is gone! + //SIGINT :: 2 // interrupt + SIGQUIT :: 3 // `quit' special character typed in tty + //SIGILL :: 4 // illegal instruction + SIGCHLD :: 5 // child process exited + //SIGABRT :: 6 // abort() called, dont' catch + SIGPIPE :: 7 // write to a pipe w/no readers + //SIGFPE :: 8 // floating point exception + SIGKILL :: 9 // kill a team (not catchable) + SIGSTOP :: 10 // suspend a thread (not catchable) + //SIGSEGV :: 11 // segmentation violation (read: invalid pointer) + SIGCONT :: 12 // continue execution if suspended + SIGTSTP :: 13 // `stop' special character typed in tty + SIGALRM :: 14 // an alarm has gone off (see alarm()) + //SIGTERM :: 15 // termination requested + SIGTTIN :: 16 // read of tty from bg process + SIGTTOU :: 17 // write to tty from bg process + SIGUSR1 :: 18 // app defined signal 1 + SIGUSR2 :: 19 // app defined signal 2 + SIGWINCH :: 20 // tty window size changed + SIGKILLTHR :: 21 // be specific: kill just the thread, not team + SIGTRAP :: 22 // Trace/breakpoint trap + SIGPOLL :: 23 // Pollable event + SIGPROF :: 24 // Profiling timer expired + SIGSYS :: 25 // Bad system call + SIGURG :: 26 // High bandwidth data is available at socket + SIGVTALRM :: 27 // Virtual timer expired + SIGXCPU :: 28 // CPU time limit exceeded + SIGXFSZ :: 29 // File size limit exceeded + SIGBUS :: 30 // access to undefined portion of a memory object + + // NOTE: this is actually defined as `sigaction`, but due to the function with the same name + // `_t` has been added. + + sigaction_t :: struct { + using _: struct #raw_union { + sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */ + sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */ + }, + sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */ + sa_flags: SA_Flags, /* [PSX] special flags */ + sa_userdata: rawptr, /* will be passed to the signal handler, BeOS extension */ + } + + SIG_BLOCK :: 1 + SIG_UNBLOCK :: 2 + SIG_SETMASK :: 3 + + SA_NOCLDSTOP :: 0x01 + SA_NOCLDWAIT :: 0x02 + SA_RESETHAND :: 0x04 + SA_NODEFER :: 0x08 + SA_RESTART :: 0x10 + SA_ONSTACK :: 0x20 + SA_SIGINFO :: 0x40 + + SS_ONSTACK :: 1 + SS_DISABLE :: 2 + + MINSIGSTKSZ :: 8192 + SIGSTKSZ :: 16384 + + stack_t :: struct { + ss_sp: rawptr, /* [PSX] stack base or pointer */ + ss_size: c.size_t, /* [PSX] stack size */ + ss_flags: SS_Flags, /* [PSX] flags */ + } + + siginfo_t :: struct { + si_signo: Signal, /* [PSX] signal number */ + si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */ + ill: ILL_Code, + fpe: FPE_Code, + segv: SEGV_Code, + bus: BUS_Code, + trap: TRAP_Code, + chld: CLD_Code, + poll: POLL_Code, + any: Any_Code, + }, + si_errno: Errno, /* [PSX] errno value associated with this signal */ + si_pid: pid_t, /* sending process ID */ + si_uid: uid_t, /* real user ID of sending process */ + si_addr: rawptr, /* address of faulting instruction */ + si_status: c.int, /* exit value or signal */ + si_band: c.long, /* band event for SIGPOLL */ + si_value: sigval, /* signal value */ + } + + /* any signal */ + SI_USER :: 0 /* signal sent by user */ + SI_QUEUE :: 1 /* signal sent by sigqueue() */ + SI_TIMER :: 2 /* signal sent on timer_settime() timeout */ + SI_ASYNCIO :: 3 /* signal sent on asynchronous I/O completion */ + SI_MESGQ :: 4 /* signal sent on arrival of message on empty message queue */ + /* SIGILL */ + ILL_ILLOPC :: 10 /* illegal opcode */ + ILL_ILLOPN :: 11 /* illegal operand */ + ILL_ILLADR :: 12 /* illegal addressing mode */ + ILL_ILLTRP :: 13 /* illegal trap */ + ILL_PRVOPC :: 14 /* privileged opcode */ + ILL_PRVREG :: 15 /* privileged register */ + ILL_COPROC :: 16 /* coprocessor error */ + ILL_BADSTK :: 17 /* internal stack error */ + /* SIGFPE */ + FPE_INTDIV :: 20 /* integer division by zero */ + FPE_INTOVF :: 21 /* integer overflow */ + FPE_FLTDIV :: 22 /* floating-point division by zero */ + FPE_FLTOVF :: 23 /* floating-point overflow */ + FPE_FLTUND :: 24 /* floating-point underflow */ + FPE_FLTRES :: 25 /* floating-point inexact result */ + FPE_FLTINV :: 26 /* invalid floating-point operation */ + FPE_FLTSUB :: 27 /* subscript out of range */ + /* SIGSEGV */ + SEGV_MAPERR :: 30 /* address not mapped to object */ + SEGV_ACCERR :: 31 /* invalid permissions for mapped object */ + /* SIGBUS */ + BUS_ADRALN :: 40 /* invalid address alignment */ + BUS_ADRERR :: 41 /* nonexistent physical address */ + BUS_OBJERR :: 42 /* object-specific hardware error */ + /* SIGTRAP */ + TRAP_BRKPT :: 50 /* process breakpoint */ + TRAP_TRACE :: 51 /* process trace trap. */ + /* SIGCHLD */ + CLD_EXITED :: 60 /* child exited */ + CLD_KILLED :: 61 /* child terminated abnormally without core dump */ + CLD_DUMPED :: 62 /* child terminated abnormally with core dump */ + CLD_TRAPPED :: 63 /* traced child trapped */ + CLD_STOPPED :: 64 /* child stopped */ + CLD_CONTINUED :: 65 /* stopped child continued */ + /* SIGPOLL */ + POLL_IN :: 70 /* input available */ + POLL_OUT :: 71 /* output available */ + POLL_MSG :: 72 /* input message available */ + POLL_ERR :: 73 /* I/O error */ + POLL_PRI :: 74 /* high priority input available */ + POLL_HUP :: 75 /* device disconnected */ + } diff --git a/core/sys/posix/signal_libc.odin b/core/sys/posix/signal_libc.odin index aef22da29..7a054ddd7 100644 --- a/core/sys/posix/signal_libc.odin +++ b/core/sys/posix/signal_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd +#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" diff --git a/core/sys/posix/sys_stat.odin b/core/sys/posix/sys_stat.odin index 61b98ef35..265356e54 100644 --- a/core/sys/posix/sys_stat.odin +++ b/core/sys/posix/sys_stat.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -428,6 +428,36 @@ when ODIN_OS == .Darwin { UTIME_NOW :: -2 UTIME_OMIT :: -1 +} else when ODIN_OS == .Haiku { + + dev_t :: distinct c.int32_t + nlink_t :: distinct c.int32_t + _mode_t :: distinct c.uint32_t + blkcnt_t :: distinct c.int64_t + blksize_t :: distinct c.int32_t + ino_t :: distinct c.int64_t + + stat_t :: struct { + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_ino: ino_t, /* [PSX] file serial number */ + st_mode: mode_t, /* [PSX] mode of file */ + st_nlink: nlink_t, /* [PSX] number of hard links */ + st_uid: uid_t, /* [PSX] user ID of the file */ + st_gid: gid_t, /* [PSX] group ID of the file */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_rdev: dev_t, /* [PSX] device ID */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ + st_atim: timespec, /* [PSX] time of last access */ + st_mtim: timespec, /* [PSX] time of last data modification */ + st_ctim: timespec, /* [PSX] time of last status change */ + st_crtim: timespec, /* [PSX] time of last status change */ + st_type: c.uint32_t, + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + } + + UTIME_NOW :: 1000000000 + UTIME_OMIT :: 1000000001 + } else when ODIN_OS == .Linux { dev_t :: distinct u64 diff --git a/core/sys/posix/time.odin b/core/sys/posix/time.odin index f9c51c63c..88f0153f4 100644 --- a/core/sys/posix/time.odin +++ b/core/sys/posix/time.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -230,6 +230,17 @@ when ODIN_OS == .Darwin { getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD. +} else when ODIN_OS == .Haiku { + + clockid_t :: distinct c.int32_t + + CLOCK_MONOTONIC :: 0 + CLOCK_PROCESS_CPUTIME_ID :: -2 + CLOCK_REALTIME :: -1 + CLOCK_THREAD_CPUTIME_ID :: -3 + + getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on Haiku. + } else when ODIN_OS == .Linux { clockid_t :: distinct c.int From be4748831d9ba0c462339b20e50dc0de8da181cd Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 20 Dec 2024 17:25:15 +0100 Subject: [PATCH 02/31] Delete errors.odin --- core/sys/haiku/errors.odin | 239 ------------------------------------- 1 file changed, 239 deletions(-) delete mode 100644 core/sys/haiku/errors.odin diff --git a/core/sys/haiku/errors.odin b/core/sys/haiku/errors.odin deleted file mode 100644 index febe647ea..000000000 --- a/core/sys/haiku/errors.odin +++ /dev/null @@ -1,239 +0,0 @@ -#+build haiku -package sys_haiku - -import "core:c" - -Errno :: enum c.int { - // Error baselines - GENERAL_ERROR_BASE = min(c.int), - OS_ERROR_BASE = GENERAL_ERROR_BASE + 0x1000, - APP_ERROR_BASE = GENERAL_ERROR_BASE + 0x2000, - INTERFACE_ERROR_BASE = GENERAL_ERROR_BASE + 0x3000, - MEDIA_ERROR_BASE = GENERAL_ERROR_BASE + 0x4000, - TRANSLATION_ERROR_BASE = GENERAL_ERROR_BASE + 0x4800, - MIDI_ERROR_BASE = GENERAL_ERROR_BASE + 0x5000, - STORAGE_ERROR_BASE = GENERAL_ERROR_BASE + 0x6000, - POSIX_ERROR_BASE = GENERAL_ERROR_BASE + 0x7000, - MAIL_ERROR_BASE = GENERAL_ERROR_BASE + 0x8000, - PRINT_ERROR_BASE = GENERAL_ERROR_BASE + 0x9000, - DEVICE_ERROR_BASE = GENERAL_ERROR_BASE + 0xa000, - - // Developer-defined errors start at (ERRORS_END+1) - ERRORS_END = GENERAL_ERROR_BASE + 0xffff, - - // General Errors - NO_MEMORY = GENERAL_ERROR_BASE + 0, - IO_ERROR = GENERAL_ERROR_BASE + 1, - PERMISSION_DENIED = GENERAL_ERROR_BASE + 2, - BAD_INDEX = GENERAL_ERROR_BASE + 3, - BAD_TYPE = GENERAL_ERROR_BASE + 4, - BAD_VALUE = GENERAL_ERROR_BASE + 5, - MISMATCHED_VALUES = GENERAL_ERROR_BASE + 6, - NAME_NOT_FOUND = GENERAL_ERROR_BASE + 7, - NAME_IN_USE = GENERAL_ERROR_BASE + 8, - TIMED_OUT = GENERAL_ERROR_BASE + 9, - INTERRUPTED = GENERAL_ERROR_BASE + 10, - WOULD_BLOCK = GENERAL_ERROR_BASE + 11, - CANCELED = GENERAL_ERROR_BASE + 12, - NO_INIT = GENERAL_ERROR_BASE + 13, - NOT_INITIALIZED = GENERAL_ERROR_BASE + 13, - BUSY = GENERAL_ERROR_BASE + 14, - NOT_ALLOWED = GENERAL_ERROR_BASE + 15, - BAD_DATA = GENERAL_ERROR_BASE + 16, - DONT_DO_THAT = GENERAL_ERROR_BASE + 17, - - ERROR = -1, - OK = 0, - NO_ERROR = 0, - - // Kernel Kit Errors - BAD_SEM_ID = OS_ERROR_BASE + 0, - NO_MORE_SEMS = OS_ERROR_BASE + 1, - BAD_THREAD_ID = OS_ERROR_BASE + 0x100, - NO_MORE_THREADS = OS_ERROR_BASE + 0x101, - BAD_THREAD_STATE = OS_ERROR_BASE + 0x102, - BAD_TEAM_ID = OS_ERROR_BASE + 0x103, - NO_MORE_TEAMS = OS_ERROR_BASE + 0x104, - BAD_PORT_ID = OS_ERROR_BASE + 0x200, - NO_MORE_PORTS = OS_ERROR_BASE + 0x201, - BAD_IMAGE_ID = OS_ERROR_BASE + 0x300, - BAD_ADDRESS = OS_ERROR_BASE + 0x301, - NOT_AN_EXECUTABLE = OS_ERROR_BASE + 0x302, - MISSING_LIBRARY = OS_ERROR_BASE + 0x303, - MISSING_SYMBOL = OS_ERROR_BASE + 0x304, - UNKNOWN_EXECUTABLE = OS_ERROR_BASE + 0x305, - LEGACY_EXECUTABLE = OS_ERROR_BASE + 0x306, - - DEBUGGER_ALREADY_INSTALLED = OS_ERROR_BASE + 0x400, - - // Application Kit Errors - BAD_REPLY = APP_ERROR_BASE + 0, - DUPLICATE_REPLY = APP_ERROR_BASE + 1, - MESSAGE_TO_SELF = APP_ERROR_BASE + 2, - BAD_HANDLER = APP_ERROR_BASE + 3, - ALREADY_RUNNING = APP_ERROR_BASE + 4, - LAUNCH_FAILED = APP_ERROR_BASE + 5, - AMBIGUOUS_APP_LAUNCH = APP_ERROR_BASE + 6, - UNKNOWN_MIME_TYPE = APP_ERROR_BASE + 7, - BAD_SCRIPT_SYNTAX = APP_ERROR_BASE + 8, - LAUNCH_FAILED_NO_RESOLVE_LINK = APP_ERROR_BASE + 9, - LAUNCH_FAILED_EXECUTABLE = APP_ERROR_BASE + 10, - LAUNCH_FAILED_APP_NOT_FOUND = APP_ERROR_BASE + 11, - LAUNCH_FAILED_APP_IN_TRASH = APP_ERROR_BASE + 12, - LAUNCH_FAILED_NO_PREFERRED_APP = APP_ERROR_BASE + 13, - LAUNCH_FAILED_FILES_APP_NOT_FOUND = APP_ERROR_BASE + 14, - BAD_MIME_SNIFFER_RULE = APP_ERROR_BASE + 15, - NOT_A_MESSAGE = APP_ERROR_BASE + 16, - SHUTDOWN_CANCELLED = APP_ERROR_BASE + 17, - SHUTTING_DOWN = APP_ERROR_BASE + 18, - - // Storage Kit/File System Errors - FILE_ERROR = STORAGE_ERROR_BASE + 0, - // 1 was B_FILE_NOT_FOUND (deprecated) - FILE_EXISTS = STORAGE_ERROR_BASE + 2, - ENTRY_NOT_FOUND = STORAGE_ERROR_BASE + 3, - NAME_TOO_LONG = STORAGE_ERROR_BASE + 4, - NOT_A_DIRECTORY = STORAGE_ERROR_BASE + 5, - DIRECTORY_NOT_EMPTY = STORAGE_ERROR_BASE + 6, - DEVICE_FULL = STORAGE_ERROR_BASE + 7, - READ_ONLY_DEVICE = STORAGE_ERROR_BASE + 8, - IS_A_DIRECTORY = STORAGE_ERROR_BASE + 9, - NO_MORE_FDS = STORAGE_ERROR_BASE + 10, - CROSS_DEVICE_LINK = STORAGE_ERROR_BASE + 11, - LINK_LIMIT = STORAGE_ERROR_BASE + 12, - BUSTED_PIPE = STORAGE_ERROR_BASE + 13, - UNSUPPORTED = STORAGE_ERROR_BASE + 14, - PARTITION_TOO_SMALL = STORAGE_ERROR_BASE + 15, - PARTIAL_READ = STORAGE_ERROR_BASE + 16, - PARTIAL_WRITE = STORAGE_ERROR_BASE + 17, - - // Some POSIX errors - E2BIG = POSIX_ERROR_BASE + 1, - EFBIG = POSIX_ERROR_BASE + 4, - ENODEV = POSIX_ERROR_BASE + 7, - ERANGE = POSIX_ERROR_BASE + 17, - EOVERFLOW = POSIX_ERROR_BASE + 41, - EOPNOTSUPP = POSIX_ERROR_BASE + 43, - - ENOSYS = POSIX_ERROR_BASE + 9, - EAGAIN = WOULD_BLOCK, - - // New error codes that can be mapped to POSIX errors - TOO_MANY_ARGS_NEG = E2BIG, - FILE_TOO_LARGE_NEG = EFBIG, - DEVICE_NOT_FOUND_NEG = ENODEV, - RESULT_NOT_REPRESENTABLE_NEG = ERANGE, - BUFFER_OVERFLOW_NEG = EOVERFLOW, - NOT_SUPPORTED_NEG = EOPNOTSUPP, - - TOO_MANY_ARGS_POS = -E2BIG, - FILE_TOO_LARGE_POS = -EFBIG, - DEVICE_NOT_FOUND_POS = -ENODEV, - RESULT_NOT_REPRESENTABLE_POS = -ERANGE, - BUFFER_OVERFLOW_POS = -EOVERFLOW, - NOT_SUPPORTED_POS = -EOPNOTSUPP, - - // Media Kit Errors - STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0, - SERVER_NOT_FOUND = MEDIA_ERROR_BASE + 1, - RESOURCE_NOT_FOUND = MEDIA_ERROR_BASE + 2, - RESOURCE_UNAVAILABLE = MEDIA_ERROR_BASE + 3, - BAD_SUBSCRIBER = MEDIA_ERROR_BASE + 4, - SUBSCRIBER_NOT_ENTERED = MEDIA_ERROR_BASE + 5, - BUFFER_NOT_AVAILABLE = MEDIA_ERROR_BASE + 6, - LAST_BUFFER_ERROR = MEDIA_ERROR_BASE + 7, - MEDIA_SYSTEM_FAILURE = MEDIA_ERROR_BASE + 100, - MEDIA_BAD_NODE = MEDIA_ERROR_BASE + 101, - MEDIA_NODE_BUSY = MEDIA_ERROR_BASE + 102, - MEDIA_BAD_FORMAT = MEDIA_ERROR_BASE + 103, - MEDIA_BAD_BUFFER = MEDIA_ERROR_BASE + 104, - MEDIA_TOO_MANY_NODES = MEDIA_ERROR_BASE + 105, - MEDIA_TOO_MANY_BUFFERS = MEDIA_ERROR_BASE + 106, - MEDIA_NODE_ALREADY_EXISTS = MEDIA_ERROR_BASE + 107, - MEDIA_BUFFER_ALREADY_EXISTS = MEDIA_ERROR_BASE + 108, - MEDIA_CANNOT_SEEK = MEDIA_ERROR_BASE + 109, - MEDIA_CANNOT_CHANGE_RUN_MODE = MEDIA_ERROR_BASE + 110, - MEDIA_APP_ALREADY_REGISTERED = MEDIA_ERROR_BASE + 111, - MEDIA_APP_NOT_REGISTERED = MEDIA_ERROR_BASE + 112, - MEDIA_CANNOT_RECLAIM_BUFFERS = MEDIA_ERROR_BASE + 113, - MEDIA_BUFFERS_NOT_RECLAIMED = MEDIA_ERROR_BASE + 114, - MEDIA_TIME_SOURCE_STOPPED = MEDIA_ERROR_BASE + 115, - MEDIA_TIME_SOURCE_BUSY = MEDIA_ERROR_BASE + 116, - MEDIA_BAD_SOURCE = MEDIA_ERROR_BASE + 117, - MEDIA_BAD_DESTINATION = MEDIA_ERROR_BASE + 118, - MEDIA_ALREADY_CONNECTED = MEDIA_ERROR_BASE + 119, - MEDIA_NOT_CONNECTED = MEDIA_ERROR_BASE + 120, - MEDIA_BAD_CLIP_FORMAT = MEDIA_ERROR_BASE + 121, - MEDIA_ADDON_FAILED = MEDIA_ERROR_BASE + 122, - MEDIA_ADDON_DISABLED = MEDIA_ERROR_BASE + 123, - MEDIA_CHANGE_IN_PROGRESS = MEDIA_ERROR_BASE + 124, - MEDIA_STALE_CHANGE_COUNT = MEDIA_ERROR_BASE + 125, - MEDIA_ADDON_RESTRICTED = MEDIA_ERROR_BASE + 126, - MEDIA_NO_HANDLER = MEDIA_ERROR_BASE + 127, - MEDIA_DUPLICATE_FORMAT = MEDIA_ERROR_BASE + 128, - MEDIA_REALTIME_DISABLED = MEDIA_ERROR_BASE + 129, - MEDIA_REALTIME_UNAVAILABLE = MEDIA_ERROR_BASE + 130, - - // Mail Kit Errors - MAIL_NO_DAEMON = MAIL_ERROR_BASE + 0, - MAIL_UNKNOWN_USER = MAIL_ERROR_BASE + 1, - MAIL_WRONG_PASSWORD = MAIL_ERROR_BASE + 2, - MAIL_UNKNOWN_HOST = MAIL_ERROR_BASE + 3, - MAIL_ACCESS_ERROR = MAIL_ERROR_BASE + 4, - MAIL_UNKNOWN_FIELD = MAIL_ERROR_BASE + 5, - MAIL_NO_RECIPIENT = MAIL_ERROR_BASE + 6, - MAIL_INVALID_MAIL = MAIL_ERROR_BASE + 7, - - // Printing Errors - NO_PRINT_SERVER = PRINT_ERROR_BASE + 0, - - // Device Kit Errors - DEV_INVALID_IOCTL = DEVICE_ERROR_BASE + 0, - DEV_NO_MEMORY = DEVICE_ERROR_BASE + 1, - DEV_BAD_DRIVE_NUM = DEVICE_ERROR_BASE + 2, - DEV_NO_MEDIA = DEVICE_ERROR_BASE + 3, - DEV_UNREADABLE = DEVICE_ERROR_BASE + 4, - DEV_FORMAT_ERROR = DEVICE_ERROR_BASE + 5, - DEV_TIMEOUT = DEVICE_ERROR_BASE + 6, - DEV_RECALIBRATE_ERROR = DEVICE_ERROR_BASE + 7, - DEV_SEEK_ERROR = DEVICE_ERROR_BASE + 8, - DEV_ID_ERROR = DEVICE_ERROR_BASE + 9, - DEV_READ_ERROR = DEVICE_ERROR_BASE + 10, - DEV_WRITE_ERROR = DEVICE_ERROR_BASE + 11, - DEV_NOT_READY = DEVICE_ERROR_BASE + 12, - DEV_MEDIA_CHANGED = DEVICE_ERROR_BASE + 13, - DEV_MEDIA_CHANGE_REQUESTED = DEVICE_ERROR_BASE + 14, - DEV_RESOURCE_CONFLICT = DEVICE_ERROR_BASE + 15, - DEV_CONFIGURATION_ERROR = DEVICE_ERROR_BASE + 16, - DEV_DISABLED_BY_USER = DEVICE_ERROR_BASE + 17, - DEV_DOOR_OPEN = DEVICE_ERROR_BASE + 18, - DEV_INVALID_PIPE = DEVICE_ERROR_BASE + 19, - DEV_CRC_ERROR = DEVICE_ERROR_BASE + 20, - DEV_STALLED = DEVICE_ERROR_BASE + 21, - DEV_BAD_PID = DEVICE_ERROR_BASE + 22, - DEV_UNEXPECTED_PID = DEVICE_ERROR_BASE + 23, - DEV_DATA_OVERRUN = DEVICE_ERROR_BASE + 24, - DEV_DATA_UNDERRUN = DEVICE_ERROR_BASE + 25, - DEV_FIFO_OVERRUN = DEVICE_ERROR_BASE + 26, - DEV_FIFO_UNDERRUN = DEVICE_ERROR_BASE + 27, - DEV_PENDING = DEVICE_ERROR_BASE + 28, - DEV_MULTIPLE_ERRORS = DEVICE_ERROR_BASE + 29, - DEV_TOO_LATE = DEVICE_ERROR_BASE + 30, - - // Translation Kit Errors - TRANSLATION_BASE_ERROR = TRANSLATION_ERROR_BASE + 0, - NO_TRANSLATOR = TRANSLATION_ERROR_BASE + 1, - ILLEGAL_DATA = TRANSLATION_ERROR_BASE + 2, -} - -errno :: #force_inline proc "contextless" () -> Errno { - return Errno(_errnop()^) -} - -foreign import libroot "system:c" -foreign libroot { - _to_positive_error :: proc(error: c.int) -> c.int --- - _to_negative_error :: proc(error: c.int) -> c.int --- - - _errnop :: proc() -> ^c.int --- -} From e5f32e145512a1fb0db142a214dee2d3b42ac073 Mon Sep 17 00:00:00 2001 From: Karl Zylinski Date: Sat, 21 Dec 2024 15:47:26 +0100 Subject: [PATCH 03/31] Makes tracking allocator default to crashing on a bad free instead of add to bad_free_array. The bad_free_array remains to not break old code. The new default behavior is implemented in a callback that you can override, there's a second provided callback that provides the old behavior where an element was added to bad_free_array. Rationale: Many people are just checking the allocation_map, but don't check the bad free array. Several examples throughout core that use tracking allocator don't check bad_free_array either, so people have been taught not to check it. --- core/mem/tracking_allocator.odin | 50 ++++++++++++++++++---- core/testing/runner.odin | 1 + tests/core/container/test_core_rbtree.odin | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/core/mem/tracking_allocator.odin b/core/mem/tracking_allocator.odin index cf780de3f..25c547471 100644 --- a/core/mem/tracking_allocator.odin +++ b/core/mem/tracking_allocator.odin @@ -34,12 +34,18 @@ Tracking_Allocator_Bad_Free_Entry :: struct { location: runtime.Source_Code_Location, } +/* +Callback type for when tracking allocator runs into a bad free. +*/ +Tracking_Allocator_Bad_Free_Callback :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) + /* Tracking allocator data. */ Tracking_Allocator :: struct { backing: Allocator, allocation_map: map[rawptr]Tracking_Allocator_Entry, + bad_free_callback: Tracking_Allocator_Bad_Free_Callback, bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry, mutex: sync.Mutex, clear_on_free_all: bool, @@ -61,6 +67,7 @@ allocate the tracked data. tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) { t.backing = backing_allocator t.allocation_map.allocator = internals_allocator + t.bad_free_callback = tracking_allocator_bad_free_callback_panic t.bad_free_array.allocator = internals_allocator if .Free_All in query_features(t.backing) { t.clear_on_free_all = true @@ -109,6 +116,33 @@ tracking_allocator_reset :: proc(t: ^Tracking_Allocator) { sync.mutex_unlock(&t.mutex) } +/* +Default behavior for a bad free: Crash with error message that says where the +bad free happened. + +Override Tracking_Allocator.bad_free_callback to have something else happen. For +example, you can use tracking_allocator_bad_free_callback_add_to_array to return +the tracking allocator to the old behavior, where the bad_free_array was used. +*/ +tracking_allocator_bad_free_callback_panic :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) { + runtime.print_caller_location(location) + runtime.print_string(" Tracking allocator error: Bad free of pointer ") + runtime.print_uintptr(uintptr(memory)) + runtime.print_string("\n") + runtime.trap() +} + +/* +Alternative behavior for a bad free: Store in `bad_free_array`. If you use this, +then you must make sure to check Tracking_Allocator.bad_free_array at some point. +*/ +tracking_allocator_bad_free_callback_add_to_array :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) { + append(&t.bad_free_array, Tracking_Allocator_Bad_Free_Entry { + memory = memory, + location = location, + }) +} + /* Tracking allocator. @@ -116,8 +150,10 @@ The tracking allocator is an allocator wrapper that tracks memory allocations. This allocator stores all the allocations in a map. Whenever a pointer that's not inside of the map is freed, the `bad_free_array` entry is added. -An example of how to use the `Tracking_Allocator` to track subsequent allocations -in your program and report leaks and bad frees: +Here follows an example of how to use the `Tracking_Allocator` to track +subsequent allocations in your program and report leaks. By default, the +tracking allocator will crash on bad frees. You can override that behavior by +overriding `track.bad_free_callback`. Example: @@ -137,9 +173,6 @@ Example: for _, leak in track.allocation_map { fmt.printf("%v leaked %m\n", leak.location, leak.size) } - for bad_free in track.bad_free_array { - fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory) - } } */ @(require_results) @@ -191,10 +224,9 @@ tracking_allocator_proc :: proc( } if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map { - append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{ - memory = old_memory, - location = loc, - }) + if data.bad_free_callback != nil { + data.bad_free_callback(data, old_memory, loc) + } } else { result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return } diff --git a/core/testing/runner.odin b/core/testing/runner.odin index 6b9d610ed..83a5ac4e7 100644 --- a/core/testing/runner.odin +++ b/core/testing/runner.odin @@ -391,6 +391,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { fmt.assertf(alloc_error == nil, "Error allocating memory for task allocator #%i: %v", i, alloc_error) when TRACKING_MEMORY { mem.tracking_allocator_init(&task_memory_trackers[i], mem.rollback_stack_allocator(&task_allocators[i])) + task_memory_trackers[i].bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array } } diff --git a/tests/core/container/test_core_rbtree.odin b/tests/core/container/test_core_rbtree.odin index bdd23691c..d220b7ed6 100644 --- a/tests/core/container/test_core_rbtree.odin +++ b/tests/core/container/test_core_rbtree.odin @@ -11,6 +11,7 @@ import "core:log" test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) + track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array defer mem.tracking_allocator_destroy(&track) context.allocator = mem.tracking_allocator(&track) From cb42b88e132295760ff823f03b228a5b0a2378b8 Mon Sep 17 00:00:00 2001 From: avanspector Date: Sat, 21 Dec 2024 16:54:45 +0100 Subject: [PATCH 04/31] Update errno.odin --- core/sys/haiku/errno.odin | 97 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 6 deletions(-) diff --git a/core/sys/haiku/errno.odin b/core/sys/haiku/errno.odin index 2b5e3681c..1acdd3c0c 100644 --- a/core/sys/haiku/errno.odin +++ b/core/sys/haiku/errno.odin @@ -5,6 +5,9 @@ import "core:sys/posix" foreign import libroot "system:c" +USE_POSITIVE_POSIX_ERRORS :: posix._HAIKU_USE_POSITIVE_POSIX_ERRORS +POSIX_ERROR_FACTOR :: posix._POSIX_ERROR_FACTOR + Errno :: enum i32 { // Error baselines GENERAL_ERROR_BASE = min(i32), @@ -109,13 +112,95 @@ Errno :: enum i32 { PARTIAL_READ = STORAGE_ERROR_BASE + 16, PARTIAL_WRITE = STORAGE_ERROR_BASE + 17, + EIO = posix.EIO, + EACCES = posix.EACCES, + EINVAL = posix.EINVAL, + ETIMEDOUT = posix.ETIMEDOUT, + EINTR = posix.EINTR, + EAGAIN = posix.EAGAIN, + EWOULDBLOCK = posix.EWOULDBLOCK, + EBUSY = posix.EBUSY, + EPERM = posix.EPERM, + EFAULT = posix.EFAULT, + ENOEXEC = posix.ENOEXEC, + EBADF = posix.EBADF, + EEXIST = posix.EEXIST, + ENOENT = posix.ENOENT, + ENAMETOOLONG = posix.ENAMETOOLONG, + ENOTDIR = posix.ENOTDIR, + ENOTEMPTY = posix.ENOTEMPTY, + ENOSPC = posix.ENOSPC, + EROFS = posix.EROFS, + EISDIR = posix.EISDIR, + EMFILE = posix.EMFILE, + EXDEV = posix.EXDEV, + ELOOP = posix.ELOOP, + EPIPE = posix.EPIPE, + ENOMEM = posix.ENOMEM, + E2BIG = posix.E2BIG, + ECHILD = posix.ECHILD, + EDEADLK = posix.EDEADLK, + EFBIG = posix.EFBIG, + EMLINK = posix.EMLINK, + ENFILE = posix.ENFILE, + ENODEV = posix.ENODEV, + ENOLCK = posix.ENOLCK, + ENOSYS = posix.ENOSYS, + ENOTTY = posix.ENOTTY, + ENXIO = posix.ENXIO, + ESPIPE = posix.ESPIPE, + ESRCH = posix.ESRCH, + EDOM = posix.EDOM, + ERANGE = posix.ERANGE, + EPROTOTYPE = posix.EPROTOTYPE, + EPROTONOSUPPORT = posix.EPROTONOSUPPORT, + EAFNOSUPPORT = posix.EAFNOSUPPORT, + EADDRINUSE = posix.EADDRINUSE, + EADDRNOTAVAIL = posix.EADDRNOTAVAIL, + ENETDOWN = posix.ENETDOWN, + ENETUNREACH = posix.ENETUNREACH, + ENETRESET = posix.ENETRESET, + ECONNABORTED = posix.ECONNABORTED, + ECONNRESET = posix.ECONNRESET, + EISCONN = posix.EISCONN, + ENOTCONN = posix.ENOTCONN, + ECONNREFUSED = posix.ECONNREFUSED, + EHOSTUNREACH = posix.EHOSTUNREACH, + ENOPROTOOPT = posix.ENOPROTOOPT, + ENOBUFS = posix.ENOBUFS, + EINPROGRESS = posix.EINPROGRESS, + EALREADY = posix.EALREADY, + EILSEQ = posix.EILSEQ, + ENOMSG = posix.ENOMSG, + ESTALE = posix.ESTALE, + EOVERFLOW = posix.EOVERFLOW, + EMSGSIZE = posix.EMSGSIZE, + EOPNOTSUPP = posix.EOPNOTSUPP, + ENOTSOCK = posix.ENOTSOCK, + EBADMSG = posix.EBADMSG, + ECANCELED = posix.ECANCELED, + EDESTADDRREQ = posix.EDESTADDRREQ, + EDQUOT = posix.EDQUOT, + EIDRM = posix.EIDRM, + EMULTIHOP = posix.EMULTIHOP, + ENODATA = posix.ENODATA, + ENOLINK = posix.ENOLINK, + ENOSR = posix.ENOSR, + ENOSTR = posix.ENOSTR, + ENOTSUP = posix.ENOTSUP, + EPROTO = posix.EPROTO, + ETIME = posix.ETIME, + ETXTBSY = posix.ETXTBSY, + ENOTRECOVERABLE = posix.ENOTRECOVERABLE, + EOWNERDEAD = posix.EOWNERDEAD, + // New error codes that can be mapped to POSIX errors - TOO_MANY_ARGS = posix.E2BIG, - FILE_TOO_LARGE = posix.EFBIG, - DEVICE_NOT_FOUND = posix.ENODEV, - RESULT_NOT_REPRESENTABLE = posix.ERANGE, - BUFFER_OVERFLOW = posix.EOVERFLOW, - NOT_SUPPORTED = posix.EOPNOTSUPP, + TOO_MANY_ARGS = POSIX_ERROR_FACTOR * E2BIG, + FILE_TOO_LARGE = POSIX_ERROR_FACTOR * EFBIG, + DEVICE_NOT_FOUND = POSIX_ERROR_FACTOR * ENODEV, + RESULT_NOT_REPRESENTABLE = POSIX_ERROR_FACTOR * ERANGE, + BUFFER_OVERFLOW = POSIX_ERROR_FACTOR * EOVERFLOW, + NOT_SUPPORTED = POSIX_ERROR_FACTOR * EOPNOTSUPP, // Media Kit Errors STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0, From 365e24ce8df6abacd34ed164852267f036c12d76 Mon Sep 17 00:00:00 2001 From: avanspector Date: Sat, 21 Dec 2024 17:09:57 +0100 Subject: [PATCH 05/31] Remove error baselines from Errno to make fmt clearer --- core/sys/haiku/errno.odin | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/core/sys/haiku/errno.odin b/core/sys/haiku/errno.odin index 1acdd3c0c..ef5a360bd 100644 --- a/core/sys/haiku/errno.odin +++ b/core/sys/haiku/errno.odin @@ -8,24 +8,24 @@ foreign import libroot "system:c" USE_POSITIVE_POSIX_ERRORS :: posix._HAIKU_USE_POSITIVE_POSIX_ERRORS POSIX_ERROR_FACTOR :: posix._POSIX_ERROR_FACTOR +// Error baselines +GENERAL_ERROR_BASE :: min(i32) +OS_ERROR_BASE :: GENERAL_ERROR_BASE + 0x1000 +APP_ERROR_BASE :: GENERAL_ERROR_BASE + 0x2000 +INTERFACE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x3000 +MEDIA_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4000 +TRANSLATION_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4800 +MIDI_ERROR_BASE :: GENERAL_ERROR_BASE + 0x5000 +STORAGE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x6000 +POSIX_ERROR_BASE :: GENERAL_ERROR_BASE + 0x7000 +MAIL_ERROR_BASE :: GENERAL_ERROR_BASE + 0x8000 +PRINT_ERROR_BASE :: GENERAL_ERROR_BASE + 0x9000 +DEVICE_ERROR_BASE :: GENERAL_ERROR_BASE + 0xA000 + +// Developer-defined errors start at (ERRORS_END+1) +ERRORS_END :: GENERAL_ERROR_BASE + 0xFFFF + Errno :: enum i32 { - // Error baselines - GENERAL_ERROR_BASE = min(i32), - OS_ERROR_BASE = GENERAL_ERROR_BASE + 0x1000, - APP_ERROR_BASE = GENERAL_ERROR_BASE + 0x2000, - INTERFACE_ERROR_BASE = GENERAL_ERROR_BASE + 0x3000, - MEDIA_ERROR_BASE = GENERAL_ERROR_BASE + 0x4000, - TRANSLATION_ERROR_BASE = GENERAL_ERROR_BASE + 0x4800, - MIDI_ERROR_BASE = GENERAL_ERROR_BASE + 0x5000, - STORAGE_ERROR_BASE = GENERAL_ERROR_BASE + 0x6000, - POSIX_ERROR_BASE = GENERAL_ERROR_BASE + 0x7000, - MAIL_ERROR_BASE = GENERAL_ERROR_BASE + 0x8000, - PRINT_ERROR_BASE = GENERAL_ERROR_BASE + 0x9000, - DEVICE_ERROR_BASE = GENERAL_ERROR_BASE + 0xA000, - - // Developer-defined errors start at (ERRORS_END+1) - ERRORS_END = GENERAL_ERROR_BASE + 0xFFFF, - // General Errors NO_MEMORY = GENERAL_ERROR_BASE + 0, IO_ERROR = GENERAL_ERROR_BASE + 1, From a20d85df1eaf7a24c407256786b714044a87e5ff Mon Sep 17 00:00:00 2001 From: avanspector Date: Sat, 21 Dec 2024 17:15:53 +0100 Subject: [PATCH 06/31] Fix os_haiku.odin (again) --- core/os/os_haiku.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin index d44ca9df0..6b218af07 100644 --- a/core/os/os_haiku.odin +++ b/core/os/os_haiku.odin @@ -16,7 +16,7 @@ _Platform_Error :: haiku.Errno MAX_PATH :: haiku.PATH_MAX -ENOSYS :: _Platform_Error(i32(haiku.Errno.POSIX_ERROR_BASE) + 9) +ENOSYS :: _Platform_Error(haiku.Errno.ENOSYS) INVALID_HANDLE :: ~Handle(0) From 276dab69b69fb8429c3e2a2e4fc8f0cd994c010d Mon Sep 17 00:00:00 2001 From: Misomosi Date: Sun, 10 Nov 2024 10:41:16 -0500 Subject: [PATCH 07/31] Pack MDEI struct to fix issue #4407 --- core/sys/windows/dbghelp.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/windows/dbghelp.odin b/core/sys/windows/dbghelp.odin index 336992b4a..e32b4c874 100644 --- a/core/sys/windows/dbghelp.odin +++ b/core/sys/windows/dbghelp.odin @@ -15,7 +15,7 @@ MINIDUMP_DIRECTORY :: struct { Location: MINIDUMP_LOCATION_DESCRIPTOR, } -MINIDUMP_EXCEPTION_INFORMATION :: struct { +MINIDUMP_EXCEPTION_INFORMATION :: struct #max_field_align(4) { ThreadId: DWORD, ExceptionPointers: ^EXCEPTION_POINTERS, ClientPointers: BOOL, From b136aa26c8269c08c94380578dad0c2dcdcbfec1 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 6 Jan 2025 21:14:37 +0100 Subject: [PATCH 08/31] sys/windows: fix xinput build tag --- core/sys/windows/xinput.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/windows/xinput.odin b/core/sys/windows/xinput.odin index 014d2573a..0089f88cb 100644 --- a/core/sys/windows/xinput.odin +++ b/core/sys/windows/xinput.odin @@ -1,4 +1,4 @@ -// +build windows +#+build windows package sys_windows foreign import "system:xinput.lib" From cdef798fbc11df248a20e46447aaf014e7c690d2 Mon Sep 17 00:00:00 2001 From: Lion Schitik Date: Wed, 8 Jan 2025 01:47:36 +0100 Subject: [PATCH 09/31] Add SetWindowSubclass and RegisterHotKey functions --- core/sys/windows/comctl32.odin | 1 + core/sys/windows/types.odin | 2 ++ core/sys/windows/user32.odin | 2 ++ 3 files changed, 5 insertions(+) diff --git a/core/sys/windows/comctl32.odin b/core/sys/windows/comctl32.odin index 477800413..69c502b06 100644 --- a/core/sys/windows/comctl32.odin +++ b/core/sys/windows/comctl32.odin @@ -6,4 +6,5 @@ foreign import "system:Comctl32.lib" @(default_calling_convention="system") foreign Comctl32 { LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT --- + SetWindowSubclass :: proc(hwnd: HWND, pfnSubclass: SUBCLASSPROC, uIdSubclass: UINT_PTR, dwRefData: DWORD_PTR) --- } diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index aece4dc43..ab79c682a 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -796,6 +796,8 @@ TIMERPROC :: #type proc "system" (HWND, UINT, UINT_PTR, DWORD) WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT +SUBCLASSPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR) -> LRESULT + HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT WINEVENTPROC :: #type proc "system" ( diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index da979a3e3..9ebd86201 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -32,6 +32,8 @@ foreign user32 { RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM --- UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL --- + RegisterHotKey :: proc(hnwd: HWND, id: int, fsModifiers: UINT, vk: UINT) -> BOOL --- + CreateWindowExW :: proc( dwExStyle: DWORD, lpClassName: LPCWSTR, From 9a68eb401d74a57f2bc220abaa31fd13bb90c559 Mon Sep 17 00:00:00 2001 From: david_cauchi Date: Wed, 8 Jan 2025 15:06:17 +1100 Subject: [PATCH 10/31] Fix name of RI_MOUSE_LEFT_BUTTON_DOWN containing S at the end --- core/sys/windows/user32.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index da979a3e3..379431402 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -553,7 +553,7 @@ MOUSE_ATTRIBUTES_CHANGED :: 0x04 MOUSE_MOVE_NOCOALESCE :: 0x08 RI_MOUSE_BUTTON_1_DOWN :: 0x0001 -RI_MOUSE_LEFT_BUTTON_DOWNS :: RI_MOUSE_BUTTON_1_DOWN +RI_MOUSE_LEFT_BUTTON_DOWN :: RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_BUTTON_1_UP :: 0x0002 RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP RI_MOUSE_BUTTON_2_DOWN :: 0x0004 From ab3e2340c26577567960d74c4eaa296e276a831f Mon Sep 17 00:00:00 2001 From: Lion Schitik Date: Wed, 8 Jan 2025 12:38:28 +0100 Subject: [PATCH 11/31] review --- core/sys/windows/user32.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index 9ebd86201..19b53e349 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -2,6 +2,7 @@ package sys_windows import "base:intrinsics" +import "core:c" foreign import user32 "system:User32.lib" @(default_calling_convention="system") @@ -32,7 +33,7 @@ foreign user32 { RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM --- UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL --- - RegisterHotKey :: proc(hnwd: HWND, id: int, fsModifiers: UINT, vk: UINT) -> BOOL --- + RegisterHotKey :: proc(hnwd: HWND, id: c.int, fsModifiers: UINT, vk: UINT) -> BOOL --- CreateWindowExW :: proc( dwExStyle: DWORD, From 2aae4cfd461860bd10dcb922f867c98212a11449 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 8 Jan 2025 18:46:25 +0100 Subject: [PATCH 12/31] fix #no_nil in debug info Fixes #4664 --- src/llvm_backend_debug.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 464f7065c..3951fc977 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -415,6 +415,7 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope); unsigned element_count = cast(unsigned)bt->Union.variants.count; if (index_offset > 0) { + GB_ASSERT(index_offset == 1); element_count += 1; } @@ -437,13 +438,11 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, for_array(j, bt->Union.variants) { Type *variant = bt->Union.variants[j]; - unsigned field_index = cast(unsigned)(index_offset+j); - - char name[16] = {}; - gb_snprintf(name, gb_size_of(name), "v%u", field_index); + char name[32] = {}; + gb_snprintf(name, gb_size_of(name), "v%td", j); isize name_len = gb_strlen(name); - elements[field_index] = LLVMDIBuilderCreateMemberType( + elements[index_offset+j] = LLVMDIBuilderCreateMemberType( m->debug_builder, member_scope, name, name_len, file, line, From 7185a93a8631060958565d6e3fba03b4b6eeccce Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 8 Jan 2025 20:22:59 +0100 Subject: [PATCH 13/31] actually fix #no_nil debug info Fixes #4664 --- src/llvm_backend_debug.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 3951fc977..6740cd1a2 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -438,8 +438,13 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, for_array(j, bt->Union.variants) { Type *variant = bt->Union.variants[j]; + ptrdiff_t variant_index = j; + if (bt->Union.kind == UnionType_no_nil) { + variant_index += 1; + } + char name[32] = {}; - gb_snprintf(name, gb_size_of(name), "v%td", j); + gb_snprintf(name, gb_size_of(name), "v%td", variant_index); isize name_len = gb_strlen(name); elements[index_offset+j] = LLVMDIBuilderCreateMemberType( From b3c359557e7c3a1a298ac5b46af122415e43bf77 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 8 Jan 2025 21:24:22 +0100 Subject: [PATCH 14/31] `#no_nil` third time's the charm --- src/llvm_backend_debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 6740cd1a2..2252c4a31 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -439,7 +439,7 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, Type *variant = bt->Union.variants[j]; ptrdiff_t variant_index = j; - if (bt->Union.kind == UnionType_no_nil) { + if (bt->Union.kind != UnionType_no_nil) { variant_index += 1; } From 2620721128b2835826faa5d224bf9373a92b1998 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 8 Jan 2025 21:45:59 +0100 Subject: [PATCH 15/31] '#no_nil' I am actually disappointed in myself --- src/llvm_backend_debug.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 2252c4a31..fbb25960a 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -408,8 +408,12 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, lb_set_llvm_metadata(m, type, temp_forward_decl); isize index_offset = 1; + isize variant_offset = 1; if (is_type_union_maybe_pointer(bt)) { index_offset = 0; + variant_offset = 0; + } else if (bt->Union.kind == UnionType_no_nil) { + variant_offset = 0; } LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope); @@ -438,13 +442,8 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, for_array(j, bt->Union.variants) { Type *variant = bt->Union.variants[j]; - ptrdiff_t variant_index = j; - if (bt->Union.kind != UnionType_no_nil) { - variant_index += 1; - } - char name[32] = {}; - gb_snprintf(name, gb_size_of(name), "v%td", variant_index); + gb_snprintf(name, gb_size_of(name), "v%td", variant_offset+j); isize name_len = gb_strlen(name); elements[index_offset+j] = LLVMDIBuilderCreateMemberType( From 16e3abfe82912c1ef47008261020715d425b0dfb Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 8 Jan 2025 22:20:43 +0100 Subject: [PATCH 16/31] strings: use map_entry --- core/strings/intern.odin | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/strings/intern.odin b/core/strings/intern.odin index 4c270980c..0b8ed173e 100644 --- a/core/strings/intern.odin +++ b/core/strings/intern.odin @@ -89,6 +89,7 @@ intern_get_cstring :: proc(m: ^Intern, text: string) -> (str: cstring, err: runt entry := _intern_get_entry(m, text) or_return return cstring(&entry.str[0]), nil } + /* Internal function to lookup whether the text string exists in the map, returns the entry Sets and allocates the entry if it wasn't set yet @@ -104,13 +105,15 @@ Returns: - err: An allocator error if one occured, `nil` otherwise */ _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check { - if prev, ok := m.entries[text]; ok { - return prev, nil - } if m.allocator.procedure == nil { m.allocator = context.allocator } + key_ptr, val_ptr, inserted := map_entry(&m.entries, text) or_return + if !inserted { + return val_ptr^, nil + } + entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1 bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return new_entry = (^Intern_Entry)(raw_data(bytes)) @@ -120,6 +123,9 @@ _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry new_entry.str[new_entry.len] = 0 key := string(new_entry.str[:new_entry.len]) - m.entries[key] = new_entry - return new_entry, nil + + key_ptr^ = key + val_ptr^ = new_entry + + return } From c30cdaa7b089df1af788b97fc90833463771293c Mon Sep 17 00:00:00 2001 From: denovodavid Date: Thu, 9 Jan 2025 11:39:01 +1100 Subject: [PATCH 17/31] add d3d12 shader component mapping constants and macro-procedures --- vendor/directx/d3d12/d3d12.odin | 12 +++++++++++- vendor/directx/d3d12/d3d12_constants.odin | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index e707b0885..3e078a5ed 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -1571,7 +1571,7 @@ VIEW_INSTANCING_DESC :: struct { Flags: VIEW_INSTANCING_FLAGS, } -SHADER_COMPONENT_MAPPING :: enum i32 { +SHADER_COMPONENT_MAPPING :: enum u32 { FROM_MEMORY_COMPONENT_0 = 0, FROM_MEMORY_COMPONENT_1 = 1, FROM_MEMORY_COMPONENT_2 = 2, @@ -1579,6 +1579,16 @@ SHADER_COMPONENT_MAPPING :: enum i32 { FORCE_VALUE_0 = 4, FORCE_VALUE_1 = 5, } +ENCODE_SHADER_4_COMPONENT_MAPPING :: #force_inline proc "contextless" (Src0, Src1, Src2, Src3: u32) -> u32 { + return (Src0 & SHADER_COMPONENT_MAPPING_MASK) | + ((Src1 & SHADER_COMPONENT_MAPPING_MASK) << SHADER_COMPONENT_MAPPING_SHIFT) | + ((Src2 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 2)) | + ((Src3 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 3)) | + SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES +} +DECODE_SHADER_4_COMPONENT_MAPPING :: #force_inline proc "contextless" (ComponentToExtract, Mapping: u32) -> u32 { + return Mapping >> (SHADER_COMPONENT_MAPPING_SHIFT * ComponentToExtract) & SHADER_COMPONENT_MAPPING_MASK +} BUFFER_SRV_FLAGS :: distinct bit_set[BUFFER_SRV_FLAG; u32] BUFFER_SRV_FLAG :: enum u32 { diff --git a/vendor/directx/d3d12/d3d12_constants.odin b/vendor/directx/d3d12/d3d12_constants.odin index a30296cc1..62725656a 100644 --- a/vendor/directx/d3d12/d3d12_constants.odin +++ b/vendor/directx/d3d12/d3d12_constants.odin @@ -498,6 +498,12 @@ WHQL_DRAW_VERTEX_COUNT_2_TO_EXP :: 25 SHADER_COMPONENT_MAPPING_MASK :: 0x7 SHADER_COMPONENT_MAPPING_SHIFT :: 3 +SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES :: 1 << (SHADER_COMPONENT_MAPPING_SHIFT * 4) +DEFAULT_SHADER_4_COMPONENT_MAPPING :: (0 & SHADER_COMPONENT_MAPPING_MASK) | + ((1 & SHADER_COMPONENT_MAPPING_MASK) << SHADER_COMPONENT_MAPPING_SHIFT) | + ((2 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 2)) | + ((3 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 3)) | + SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES FILTER_REDUCTION_TYPE_MASK :: 0x3 FILTER_REDUCTION_TYPE_SHIFT :: 7 From 1511162b0a6c18c8e45f87299fee8cca82711f99 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 9 Jan 2025 17:29:31 +0100 Subject: [PATCH 18/31] webgpu: fix cstring as parameter not loading correctly --- core/sys/wasm/js/odin.js | 5 ++++- vendor/wgpu/wgpu.js | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index 07a77952c..29227c526 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -110,7 +110,10 @@ class WasmMemoryInterface { } loadCstring(ptr) { - const start = this.loadPtr(ptr); + return this.loadCstringDirect(this.loadPtr(ptr)); + } + + loadCstringDirect(start) { if (start == 0) { return null; } diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 9c43756d7..5e0482b69 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -1181,7 +1181,7 @@ class WebGPUInterface { */ wgpuBufferSetLabel: (bufferIdx, labelPtr) => { const buffer = this.buffers.get(bufferIdx); - buffer.buffer.label = this.mem.loadCstring(labelPtr); + buffer.buffer.label = this.mem.loadCstringDirect(labelPtr); }, /** @@ -1370,7 +1370,7 @@ class WebGPUInterface { */ wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); - commandEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr)); + commandEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr)); }, /** @@ -1387,7 +1387,7 @@ class WebGPUInterface { */ wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); - commandEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr)); + commandEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr)); }, /** @@ -1459,7 +1459,7 @@ class WebGPUInterface { */ wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => { const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); - computePassEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr)); + computePassEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr)); }, /** @@ -1476,7 +1476,7 @@ class WebGPUInterface { */ wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => { const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); - computePassEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr)); + computePassEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr)); }, /** @@ -2216,7 +2216,7 @@ class WebGPUInterface { wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => { const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); this.assert(markerLabelPtr != 0); - const markerLabel = this.mem.loadCstring(markerLabelPtr); + const markerLabel = this.mem.loadCstringDirect(markerLabelPtr); renderBundleEncoder.insertDebugMarker(markerLabel); }, @@ -2235,7 +2235,7 @@ class WebGPUInterface { wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => { const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); this.assert(groupLabelPtr!= 0); - const groupLabel = this.mem.loadCstring(groupLabelPtr); + const groupLabel = this.mem.loadCstringDirect(groupLabelPtr); renderBundleEncoder.pushDebugGroup(groupLabel); }, @@ -2407,7 +2407,7 @@ class WebGPUInterface { */ wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => { const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); - const markerLabel = this.mem.loadCstring(markerLabelPtr); + const markerLabel = this.mem.loadCstringDirect(markerLabelPtr); renderPassEncoder.insertDebugMarker(markerLabel); }, @@ -2425,7 +2425,7 @@ class WebGPUInterface { */ wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => { const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); - const groupLabel = this.mem.loadCstring(groupLabelPtr); + const groupLabel = this.mem.loadCstringDirect(groupLabelPtr); renderPassEncoder.pushDebugGroup(groupLabel); }, @@ -2881,11 +2881,11 @@ class WebGPUObjectManager { } /** - * @param {number} idx + * @param {?number} idx * @returns {T} */ get(idx) { - return this.objects[idx-1].object; + return this.objects[idx-1]?.object; } /** @param {number} idx */ @@ -2908,7 +2908,7 @@ class WebGPUObjectManager { if (withLabelSetter) { inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => { const obj = this.get(idx); - obj.label = this.mem.loadCstring(labelPtr); + obj.label = this.mem.loadCstringDirect(labelPtr); }; } return inter; From 509da8e63234c5d30082301d5054f9441a7d0912 Mon Sep 17 00:00:00 2001 From: sh!zeeg Date: Fri, 10 Jan 2025 05:56:56 +0300 Subject: [PATCH 19/31] add os.exists() to FreeBSD --- core/os/os_freebsd.odin | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin index 837e79f4d..87a56b057 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -624,6 +624,14 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { is_file :: proc {is_file_path, is_file_handle} is_dir :: proc {is_dir_path, is_dir_handle} +@(require_results) +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) + return res == 0 +} + // NOTE(bill): Uses startup to initialize it stdin: Handle = 0 From a6dccf5e98786b2904102730ede086d3c83aa304 Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 06:28:57 +0100 Subject: [PATCH 20/31] Haiku: fix futex bug --- core/sync/futex_haiku.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/sync/futex_haiku.odin b/core/sync/futex_haiku.odin index d1b265228..52321644a 100644 --- a/core/sync/futex_haiku.odin +++ b/core/sync/futex_haiku.odin @@ -1,6 +1,7 @@ #+private package sync +import "core:sys/haiku" import "core:sys/posix" import "core:time" @@ -75,8 +76,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) { defer waitq_lock(waitq) sig: posix.Signal - posix.sigwait(&mask, &sig) - errno := posix.errno() + errno := posix.sigwait(&mask, &sig) ok = errno == nil } @@ -122,7 +122,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration tv_sec = posix.time_t(i64(duration / 1e9)), tv_nsec = i64(duration % 1e9), } - posix.sigtimedwait(&mask, &info, &ts) + haiku.sigtimedwait(&mask, &info, &ts) errno := posix.errno() ok = errno == .EAGAIN || errno == nil } From 5d3a069e7abf76ef5f501364bcebf2e98ae6deb6 Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 06:40:29 +0100 Subject: [PATCH 21/31] Haiku: more posix --- core/c/libc/time.odin | 2 +- core/sys/haiku/os.odin | 26 +++-- core/sys/posix/arpa_inet.odin | 4 +- core/sys/posix/dirent.odin | 27 +++-- core/sys/posix/fnmatch.odin | 4 +- core/sys/posix/glob.odin | 6 +- core/sys/posix/langinfo.odin | 6 +- core/sys/posix/libgen.odin | 2 +- core/sys/posix/locale.odin | 2 +- core/sys/posix/monetary.odin | 2 +- core/sys/posix/netdb.odin | 21 +++- core/sys/posix/netinet_in.odin | 61 +++++++--- core/sys/posix/poll.odin | 49 +++++--- core/sys/posix/pwd.odin | 14 ++- core/sys/posix/signal.odin | 10 -- core/sys/posix/stdio_libc.odin | 2 +- core/sys/posix/stdlib.odin | 2 +- core/sys/posix/stdlib_libc.odin | 2 +- core/sys/posix/string.odin | 2 +- core/sys/posix/string_libc.odin | 2 +- core/sys/posix/sys_ipc.odin | 25 ++++- core/sys/posix/sys_msg.odin | 20 +++- core/sys/posix/sys_resource.odin | 53 ++++++--- core/sys/posix/sys_select.odin | 16 ++- core/sys/posix/sys_sem.odin | 28 ++++- core/sys/posix/sys_socket.odin | 66 +++++++++-- core/sys/posix/sys_time.odin | 13 ++- core/sys/posix/sys_times.odin | 4 +- core/sys/posix/sys_uio.odin | 4 +- core/sys/posix/sys_un.odin | 10 +- core/sys/posix/sys_utsname.odin | 6 +- core/sys/posix/sys_wait.odin | 54 ++++++++- core/sys/posix/termios.odin | 184 +++++++++++++++++++++++++++++-- core/sys/posix/unistd.odin | 174 ++++++++++++++++++++++++++++- core/sys/posix/unistd_libc.odin | 2 +- core/sys/posix/utime.odin | 4 +- 36 files changed, 773 insertions(+), 136 deletions(-) diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin index 6828793ec..33f8dc3af 100644 --- a/core/c/libc/time.odin +++ b/core/c/libc/time.odin @@ -95,7 +95,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS = time_t :: distinct i64 - when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { + when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku { clock_t :: distinct int32_t } else { clock_t :: distinct long diff --git a/core/sys/haiku/os.odin b/core/sys/haiku/os.odin index a9c5ea57d..f1127cb69 100644 --- a/core/sys/haiku/os.odin +++ b/core/sys/haiku/os.odin @@ -2,7 +2,7 @@ package sys_haiku import "base:intrinsics" -import "core:c" +import "core:sys/posix" foreign import libroot "system:c" @@ -74,7 +74,7 @@ foreign libroot { resize_area :: proc(id: area_id, newSize: uintptr) -> status_t --- set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t --- _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uintptr) -> status_t --- - _get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: uintptr) -> status_t --- + _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uintptr) -> status_t --- } // Ports @@ -99,15 +99,15 @@ port_flags :: distinct bit_set[port_flag; u32] foreign libroot { create_port :: proc(capacity: i32, name: cstring) -> port_id --- find_port :: proc(name: cstring) -> port_id --- - read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> c.ssize_t --- - read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- + read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> int --- + read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> int --- write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t --- write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> status_t --- close_port :: proc(port: port_id) -> status_t --- delete_port :: proc(port: port_id) -> status_t --- - port_buffer_size :: proc(port: port_id) -> c.ssize_t --- - port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- - port_count :: proc(port: port_id) -> c.ssize_t --- + port_buffer_size :: proc(port: port_id) -> int --- + port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int --- + port_count :: proc(port: port_id) -> int --- set_port_owner :: proc(port: port_id, team: team_id) -> status_t --- _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- @@ -484,3 +484,15 @@ foreign libroot { is_computer_on :: proc() -> i32 --- is_computer_on_fire :: proc() -> f64 --- } + +// POSIX signals + +@(default_calling_convention="c") +foreign libroot { + /* + Wait for queued signals. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]] + */ + sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result --- +} diff --git a/core/sys/posix/arpa_inet.odin b/core/sys/posix/arpa_inet.odin index d3592dd80..ac850ed49 100644 --- a/core/sys/posix/arpa_inet.odin +++ b/core/sys/posix/arpa_inet.odin @@ -1,10 +1,12 @@ -#+build darwin, linux, freebsd, openbsd, netbsd +#+build darwin, linux, freebsd, openbsd, netbsd, haiku package posix import "core:c" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" +} else when ODIN_OS == .Haiku { + foreign import lib "system:network" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/dirent.odin b/core/sys/posix/dirent.odin index bf32be8cf..1394f6b9e 100644 --- a/core/sys/posix/dirent.odin +++ b/core/sys/posix/dirent.odin @@ -1,4 +1,4 @@ -#+build darwin, linux, freebsd, openbsd, netbsd +#+build darwin, linux, freebsd, openbsd, netbsd, haiku package posix import "core:c" @@ -219,12 +219,23 @@ when ODIN_OS == .Darwin { } else when ODIN_OS == .Linux { - dirent :: struct { - d_ino: u64, /* [PSX] file number of entry */ - d_off: i64, /* directory offset of the next entry */ - d_reclen: u16, /* length of this record */ - d_type: D_Type, /* file type */ - d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */ - } + dirent :: struct { + d_ino: u64, /* [PSX] file number of entry */ + d_off: i64, /* directory offset of the next entry */ + d_reclen: u16, /* length of this record */ + d_type: D_Type, /* file type */ + d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */ + } + +} else when ODIN_OS == .Haiku { + + dirent :: struct { + d_dev: dev_t, /* device */ + d_pdev: dev_t, /* parent device (only for queries) */ + d_ino: ino_t, /* inode number */ + d_pino: ino_t, /* parent inode (only for queries) */ + d_reclen: c.ushort, /* length of this record, not the name */ + d_name: [0]c.char `fmt:"s,0"`, /* name of the entry (null byte terminated) */ + } } diff --git a/core/sys/posix/fnmatch.odin b/core/sys/posix/fnmatch.odin index 2d582705c..04c3d2888 100644 --- a/core/sys/posix/fnmatch.odin +++ b/core/sys/posix/fnmatch.odin @@ -1,4 +1,4 @@ -#+build darwin, linux, openbsd, freebsd, netbsd +#+build darwin, linux, openbsd, freebsd, netbsd, haiku package posix import "core:c" @@ -46,7 +46,7 @@ FNM_Flag_Bits :: enum c.int { } FNM_Flags :: bit_set[FNM_Flag_Bits; c.int] -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { FNM_NOMATCH :: 1 diff --git a/core/sys/posix/glob.odin b/core/sys/posix/glob.odin index 7c8009a59..fb90b7546 100644 --- a/core/sys/posix/glob.odin +++ b/core/sys/posix/glob.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -109,7 +109,7 @@ when ODIN_OS == .Darwin { GLOB_NOMATCH :: -3 GLOB_NOSPACE :: -1 -} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { +} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku { glob_t :: struct { gl_pathc: c.size_t, /* [PSX] count of paths matched by pattern */ @@ -134,7 +134,7 @@ when ODIN_OS == .Darwin { GLOB_ERR :: 0x0004 GLOB_MARK :: 0x0008 GLOB_NOCHECK :: 0x0010 - GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD else 0x0100 + GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD || ODIN_OS == .Haiku else 0x0100 GLOB_NOSORT :: 0x0020 GLOB_ABORTED :: -2 diff --git a/core/sys/posix/langinfo.odin b/core/sys/posix/langinfo.odin index 3c001aee0..1fddfe280 100644 --- a/core/sys/posix/langinfo.odin +++ b/core/sys/posix/langinfo.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -143,7 +143,7 @@ nl_item :: enum nl_item_t { CRNCYSTR = CRNCYSTR, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku { // NOTE: declared with `_t` so we can enumerate the real `nl_info`. nl_item_t :: distinct c.int @@ -210,7 +210,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD { YESEXPR :: 52 NOEXPR :: 53 - CRNCYSTR :: 56 + CRNCYSTR :: 54 when ODIN_OS == .Haiku else 56 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { diff --git a/core/sys/posix/libgen.odin b/core/sys/posix/libgen.odin index 69176a557..2354bf70d 100644 --- a/core/sys/posix/libgen.odin +++ b/core/sys/posix/libgen.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix when ODIN_OS == .Darwin { diff --git a/core/sys/posix/locale.odin b/core/sys/posix/locale.odin index 5b8d7c216..bbe10e803 100644 --- a/core/sys/posix/locale.odin +++ b/core/sys/posix/locale.odin @@ -1,4 +1,4 @@ -#+build windows, linux, darwin, netbsd, openbsd, freebsd +#+build windows, linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c/libc" diff --git a/core/sys/posix/monetary.odin b/core/sys/posix/monetary.odin index ee342e211..a444bff09 100644 --- a/core/sys/posix/monetary.odin +++ b/core/sys/posix/monetary.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" diff --git a/core/sys/posix/netdb.odin b/core/sys/posix/netdb.odin index 79e13a140..a8c83d83a 100644 --- a/core/sys/posix/netdb.odin +++ b/core/sys/posix/netdb.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -319,7 +319,7 @@ Info_Errno :: enum c.int { OVERFLOW = EAI_OVERFLOW, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { hostent :: struct { h_name: cstring, /* [PSX] official name of host */ @@ -431,6 +431,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS NI_NUMERICSCOPE :: 0x100 NI_DGRAM :: 16 + } else when ODIN_OS == .Haiku { + + AI_PASSIVE :: 0x001 + AI_CANONNAME :: 0x002 + AI_NUMERICHOST :: 0x004 + AI_NUMERICSERV :: 0x008 + AI_V4MAPPED :: 0x800 + AI_ALL :: 0x100 + AI_ADDRCONFIG :: 0x400 + + NI_NOFQDN :: 0x01 + NI_NUMERICHOST :: 0x02 + NI_NAMEREQD :: 0x04 + NI_NUMERICSERV :: 0x08 + NI_DGRAM :: 0x10 + NI_NUMERICSCOPE :: 0x40 + } when ODIN_OS == .OpenBSD { diff --git a/core/sys/posix/netinet_in.odin b/core/sys/posix/netinet_in.odin index a2cf904ce..ec05915de 100644 --- a/core/sys/posix/netinet_in.odin +++ b/core/sys/posix/netinet_in.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -31,20 +31,31 @@ Protocol :: enum c.int { UDP = IPPROTO_UDP, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { in_addr :: struct { s_addr: in_addr_t, /* [PSX] big endian address */ } - in6_addr :: struct { - using _: struct #raw_union { - s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ - __u6_addr16: [8]c.uint16_t, - __u6_addr32: [4]c.uint32_t, - }, + when ODIN_OS == .Haiku { + in6_addr :: struct #packed { + using _: struct #raw_union { + s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ + __u6_addr16: [8]c.uint16_t, + __u6_addr32: [4]c.uint32_t, + }, + } + } else { + in6_addr :: struct { + using _: struct #raw_union { + s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ + __u6_addr16: [8]c.uint16_t, + __u6_addr32: [4]c.uint32_t, + }, + } } + when ODIN_OS == .Linux { sockaddr_in :: struct { @@ -77,12 +88,20 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS } else { + when ODIN_OS == .Haiku { + @(private) + _SIN_ZEROSIZE :: 24 + } else { + @(private) + _SIN_ZEROSIZE :: 8 + } + sockaddr_in :: struct { sin_len: c.uint8_t, sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */ sin_port: in_port_t, /* [PSX] port number */ sin_addr: in_addr, /* [PSX] IP address */ - sin_zero: [8]c.char, + sin_zero: [_SIN_ZEROSIZE]c.char, } sockaddr_in6 :: struct { @@ -99,13 +118,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ipv6mr_interface: c.uint, /* [PSX] interface index */ } - IPV6_JOIN_GROUP :: 12 - IPV6_LEAVE_GROUP :: 13 - IPV6_MULTICAST_HOPS :: 10 - IPV6_MULTICAST_IF :: 9 - IPV6_MULTICAST_LOOP :: 11 - IPV6_UNICAST_HOPS :: 4 - IPV6_V6ONLY :: 27 + when ODIN_OS == .Haiku { + IPV6_JOIN_GROUP :: 28 + IPV6_LEAVE_GROUP :: 29 + IPV6_MULTICAST_HOPS :: 25 + IPV6_MULTICAST_IF :: 24 + IPV6_MULTICAST_LOOP :: 26 + IPV6_UNICAST_HOPS :: 27 + IPV6_V6ONLY :: 30 + } else { + IPV6_JOIN_GROUP :: 12 + IPV6_LEAVE_GROUP :: 13 + IPV6_MULTICAST_HOPS :: 10 + IPV6_MULTICAST_IF :: 9 + IPV6_MULTICAST_LOOP :: 11 + IPV6_UNICAST_HOPS :: 4 + IPV6_V6ONLY :: 27 + } } diff --git a/core/sys/posix/poll.odin b/core/sys/posix/poll.odin index 9c3b8b081..44ec767a6 100644 --- a/core/sys/posix/poll.odin +++ b/core/sys/posix/poll.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" @@ -25,7 +25,11 @@ foreign lib { poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int --- } -nfds_t :: c.uint +when ODIN_OS == .Haiku { + nfds_t :: c.ulong +} else { + nfds_t :: c.uint +} Poll_Event_Bits :: enum c.short { // Data other than high-priority data may be read without blocking. @@ -53,7 +57,7 @@ Poll_Event_Bits :: enum c.short { } Poll_Event :: bit_set[Poll_Event_Bits; c.short] -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { pollfd :: struct { fd: FD, /* [PSX] the following descriptor being polled */ @@ -61,17 +65,36 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS revents: Poll_Event, /* [PSX] the output event flags */ } - POLLIN :: 0x0001 - POLLRDNORM :: 0x0040 - POLLRDBAND :: 0x0080 - POLLPRI :: 0x0002 - POLLOUT :: 0x0004 - POLLWRNORM :: POLLOUT - POLLWRBAND :: 0x0100 + when ODIN_OS == .Haiku { + + POLLIN :: 0x0001 /* any readable data available */ + POLLOUT :: 0x0002 /* file descriptor is writeable */ + POLLRDNORM :: POLLIN + POLLWRNORM :: POLLOUT + POLLRDBAND :: 0x0008 /* priority readable data */ + POLLWRBAND :: 0x0010 /* priority data can be written */ + POLLPRI :: 0x0020 /* high priority readable data */ + + POLLERR :: 0x0004 /* errors pending */ + POLLHUP :: 0x0080 /* disconnected */ + POLLNVAL :: 0x1000 /* invalid file descriptor */ + + } else { + + POLLIN :: 0x0001 + POLLRDNORM :: 0x0040 + POLLRDBAND :: 0x0080 + POLLPRI :: 0x0002 + POLLOUT :: 0x0004 + POLLWRNORM :: POLLOUT + POLLWRBAND :: 0x0100 + + POLLERR :: 0x0008 + POLLHUP :: 0x0010 + POLLNVAL :: 0x0020 + + } - POLLERR :: 0x0008 - POLLHUP :: 0x0010 - POLLNVAL :: 0x0020 } else when ODIN_OS == .Linux { diff --git a/core/sys/posix/pwd.odin b/core/sys/posix/pwd.odin index 33cbcd7c5..75d15c899 100644 --- a/core/sys/posix/pwd.odin +++ b/core/sys/posix/pwd.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -176,4 +176,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { pw_shell: cstring, /* Shell program. */ } +} else when ODIN_OS == .Haiku { + + passwd :: struct { + pw_name: cstring, /* [PSX] user name */ + pw_passwd: cstring, /* encrypted password */ + pw_uid: uid_t, /* [PSX] user uid */ + pw_gid: gid_t, /* [PSX] user gid */ + pw_dir: cstring, /* Home directory. */ + pw_shell: cstring, /* Shell program. */ + pw_gecos: cstring, /* Real name. */ + } + } diff --git a/core/sys/posix/signal.odin b/core/sys/posix/signal.odin index d43270410..c7e2cc09b 100644 --- a/core/sys/posix/signal.odin +++ b/core/sys/posix/signal.odin @@ -185,16 +185,6 @@ foreign lib { */ sigwait :: proc(set: ^sigset_t, sig: ^Signal) -> Errno --- - when ODIN_OS != .Darwin { - /* - Wait for queued signals. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]] - */ - sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^timespec) -> result --- - } - - /* NOTE: unimplemented on darwin. void psiginfo(const siginfo_t *, const char *); diff --git a/core/sys/posix/stdio_libc.odin b/core/sys/posix/stdio_libc.odin index fbd949b2c..12706970d 100644 --- a/core/sys/posix/stdio_libc.odin +++ b/core/sys/posix/stdio_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd +#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" diff --git a/core/sys/posix/stdlib.odin b/core/sys/posix/stdlib.odin index 640c70b5a..5f1ae1908 100644 --- a/core/sys/posix/stdlib.odin +++ b/core/sys/posix/stdlib.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" diff --git a/core/sys/posix/stdlib_libc.odin b/core/sys/posix/stdlib_libc.odin index fa4d925b2..6574026f4 100644 --- a/core/sys/posix/stdlib_libc.odin +++ b/core/sys/posix/stdlib_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd +#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" diff --git a/core/sys/posix/string.odin b/core/sys/posix/string.odin index 96b6a9007..3f9dbb43e 100644 --- a/core/sys/posix/string.odin +++ b/core/sys/posix/string.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" diff --git a/core/sys/posix/string_libc.odin b/core/sys/posix/string_libc.odin index 336352cbc..72164cc4c 100644 --- a/core/sys/posix/string_libc.odin +++ b/core/sys/posix/string_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd +#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku package posix when ODIN_OS == .Windows { diff --git a/core/sys/posix/sys_ipc.odin b/core/sys/posix/sys_ipc.odin index 0f7ec06c5..bf5938ce1 100644 --- a/core/sys/posix/sys_ipc.odin +++ b/core/sys/posix/sys_ipc.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -111,4 +111,27 @@ when ODIN_OS == .Darwin { IPC_SET :: 1 IPC_STAT :: 2 +} else when ODIN_OS == .Haiku { + + key_t :: distinct c.int32_t + + ipc_perm :: struct { + key: key_t, + uid: uid_t, /* [PSX] owner's user ID */ + gid: gid_t, /* [PSX] owner's group ID */ + cuid: uid_t, /* [PSX] creator's user ID */ + cgid: gid_t, /* [PSX] creator's group ID */ + mode: mode_t, /* [PSX] read/write perms */ + } + + IPC_CREAT :: 0o01000 + IPC_EXCL :: 0o02000 + IPC_NOWAIT :: 0o04000 + + IPC_PRIVATE :: key_t(0) + + IPC_RMID :: 0 + IPC_SET :: 1 + IPC_STAT :: 2 + } diff --git a/core/sys/posix/sys_msg.odin b/core/sys/posix/sys_msg.odin index 0e78777f9..c578b1fc6 100644 --- a/core/sys/posix/sys_msg.odin +++ b/core/sys/posix/sys_msg.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -171,4 +171,22 @@ when ODIN_OS == .Darwin { __unused: [2]c.ulong, } +} else when ODIN_OS == .Haiku { + + msgqnum_t :: distinct c.uint32_t + msglen_t :: distinct c.uint32_t + + MSG_NOERROR :: 0o10000 + + msqid_ds :: struct { + msg_perm: ipc_perm, /* [PSX] operation permission structure */ + msg_qnum: msgqnum_t, /* [PSX] number of messages currently on queue */ + msg_qbytes: msglen_t, /* [PSX] maximum number of bytes allowed on queue */ + msg_lspid: pid_t, /* [PSX] process ID of last msgsnd() */ + msg_lrpid: pid_t, /* [PSX] process ID of last msgrcv() */ + msg_stime: time_t, /* [PSX] time of last msgsnd() */ + msg_rtime: time_t, /* [PSX] time of last msgrcv() */ + msg_ctime: time_t, /* [PSX] time of last change */ + } + } diff --git a/core/sys/posix/sys_resource.odin b/core/sys/posix/sys_resource.odin index 9af2a929b..ae478382a 100644 --- a/core/sys/posix/sys_resource.odin +++ b/core/sys/posix/sys_resource.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -96,15 +96,26 @@ when ODIN_OS == .NetBSD { @(private) LGETRUSAGE :: "getrusage" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { PRIO_PROCESS :: 0 PRIO_PGRP :: 1 PRIO_USER :: 2 - rlim_t :: distinct c.uint64_t + when ODIN_OS == .Haiku { + rlim_t :: distinct c.ulong + } else { + rlim_t :: distinct c.uint64_t + } - RLIM_INFINITY :: ~rlim_t(0) when ODIN_OS == .Linux else (rlim_t(1) << 63) - 1 + when ODIN_OS == .Haiku { + RLIM_INFINITY :: rlim_t(0xFFFFFFFF) + } else when ODIN_OS == .Linux { + RLIM_INFINITY :: ~rlim_t(0) + } else { + RLIM_INFINITY :: (rlim_t(1) << 63) - 1 + } + RLIM_SAVED_MAX :: RLIM_INFINITY RLIM_SAVED_CUR :: RLIM_INFINITY @@ -140,19 +151,29 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ru_nivcsw: c.long, /* involuntary " */ } - RLIMIT_CORE :: 4 - RLIMIT_CPU :: 0 - RLIMIT_DATA :: 2 - RLIMIT_FSIZE :: 1 - RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8 - RLIMIT_STACK :: 3 - - when ODIN_OS == .Linux { - RLIMIT_AS :: 9 - } else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { - RLIMIT_AS :: 5 + when ODIN_OS == .Haiku { + RLIMIT_CORE :: 0 + RLIMIT_CPU :: 1 + RLIMIT_DATA :: 2 + RLIMIT_FSIZE :: 3 + RLIMIT_NOFILE :: 4 + RLIMIT_STACK :: 5 + RLIMIT_AS :: 6 } else { - RLIMIT_AS :: 10 + RLIMIT_CORE :: 4 + RLIMIT_CPU :: 0 + RLIMIT_DATA :: 2 + RLIMIT_FSIZE :: 1 + RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8 + RLIMIT_STACK :: 3 + + when ODIN_OS == .Linux { + RLIMIT_AS :: 9 + } else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { + RLIMIT_AS :: 5 + } else { + RLIMIT_AS :: 10 + } } } diff --git a/core/sys/posix/sys_select.odin b/core/sys/posix/sys_select.odin index 2058ee777..a75e58de6 100644 --- a/core/sys/posix/sys_select.odin +++ b/core/sys/posix/sys_select.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "base:intrinsics" @@ -56,9 +56,9 @@ when ODIN_OS == .NetBSD { LSELECT :: "select" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { - suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long) + suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long) timeval :: struct { tv_sec: time_t, /* [PSX] seconds */ @@ -75,8 +75,14 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS @(private) ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t) - fd_set :: struct #align(ALIGN) { - fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t, + when ODIN_OS == .Haiku { + fd_set :: struct #align(ALIGN) { + fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t, + } + } else { + fd_set :: struct #align(ALIGN) { + fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t, + } } @(private) diff --git a/core/sys/posix/sys_sem.odin b/core/sys/posix/sys_sem.odin index 6b695e766..069315f87 100644 --- a/core/sys/posix/sys_sem.odin +++ b/core/sys/posix/sys_sem.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -154,4 +154,30 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sem_flg: c.short, /* [PSX] operation flags */ } +} else when ODIN_OS == .Haiku { + + SEM_UNDO :: 10 // undo the operation on exit + + // Commands for `semctl'. + GETPID :: 3 + GETVAL :: 4 + GETALL :: 5 + GETNCNT :: 6 + GETZCNT :: 7 + SETVAL :: 8 + SETALL :: 9 + + semid_ds :: struct { + sem_perm: ipc_perm, // [PSX] operation permission structure + sem_nsems: c.ushort, // [PSX] number of semaphores in set + sem_otime: time_t, // [PSX] last semop() + sem_ctime: time_t, // [PSX] last time changed by semctl() + } + + sembuf :: struct { + sem_num: c.ushort, /* [PSX] semaphore number */ + sem_op: c.short, /* [PSX] semaphore operation */ + sem_flg: c.short, /* [PSX] operation flags */ + } + } diff --git a/core/sys/posix/sys_socket.odin b/core/sys/posix/sys_socket.odin index 4dd6074a3..0645893d0 100644 --- a/core/sys/posix/sys_socket.odin +++ b/core/sys/posix/sys_socket.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -328,24 +328,32 @@ when ODIN_OS == .NetBSD { @(private) LSOCKET :: "socket" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { socklen_t :: distinct c.uint + when ODIN_OS == .Haiku { + @(private) + _SA_DATASIZE :: 30 + } else { + @(private) + _SA_DATASIZE :: 14 + } + when ODIN_OS == .Linux { _sa_family_t :: distinct c.ushort sockaddr :: struct { - sa_family: sa_family_t, /* [PSX] address family */ - sa_data: [14]c.char, /* [PSX] socket address */ + sa_family: sa_family_t, /* [PSX] address family */ + sa_data: [_SA_DATASIZE]c.char, /* [PSX] socket address */ } } else { _sa_family_t :: distinct c.uint8_t sockaddr :: struct { - sa_len: c.uint8_t, /* total length */ - sa_family: sa_family_t, /* [PSX] address family */ - sa_data: [14]c.char, /* [PSX] socket address */ + sa_len: c.uint8_t, /* total length */ + sa_family: sa_family_t, /* [PSX] address family */ + sa_data: [_SA_DATASIZE]c.char, /* [PSX] socket address */ } } @@ -355,6 +363,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS _SS_PAD1SIZE :: 6 @(private) _SS_PAD2SIZE :: 240 + } else when ODIN_OS == .Haiku { + @(private) + _SS_PAD1SIZE :: 6 + @(private) + _SS_PAD2SIZE :: 112 } else when ODIN_OS == .Linux { @(private) _SS_SIZE :: 128 @@ -486,6 +499,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS SO_RCVTIMEO :: 66 SO_SNDTIMEO :: 67 + } else when ODIN_OS == .Haiku { + SOL_SOCKET :: -1 + + SO_ACCEPTCONN :: 0x00000001 + SO_BROADCAST :: 0x00000002 + SO_DEBUG :: 0x00000004 + SO_DONTROUTE :: 0x00000008 + SO_ERROR :: 0x40000007 + SO_KEEPALIVE :: 0x00000010 + SO_OOBINLINE :: 0x00000020 + SO_RCVBUF :: 0x40000004 + SO_RCVLOWAT :: 0x40000005 + SO_REUSEADDR :: 0x00000040 + SO_SNDBUF :: 0x40000001 + SO_SNDLOWAT :: 0x40000002 + SO_TYPE :: 0x40000008 + + SO_LINGER :: 0x00000200 + SO_RCVTIMEO :: 0x40000006 + SO_SNDTIMEO :: 0x40000003 } else { SOL_SOCKET :: 0xffff @@ -523,7 +556,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS } // The maximum backlog queue length for listen(). - SOMAXCONN :: 128 + when ODIN_OS == .Haiku { + SOMAXCONN :: 32 + } else { + SOMAXCONN :: 128 + } when ODIN_OS == .Linux { MSG_CTRUNC :: 0x008 @@ -549,11 +586,18 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS MSG_NOSIGNAL :: 0x00020000 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { MSG_NOSIGNAL :: 0x0400 + } else when ODIN_OS == .Haiku { + MSG_NOSIGNAL :: 0x800 } } - AF_INET :: 2 - AF_UNIX :: 1 + when ODIN_OS == .Haiku { + AF_INET :: 1 + AF_UNIX :: 9 + } else { + AF_INET :: 2 + AF_UNIX :: 1 + } when ODIN_OS == .Darwin { AF_INET6 :: 30 @@ -563,6 +607,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS AF_INET6 :: 24 } else when ODIN_OS == .Linux { AF_INET6 :: 10 + } else when ODIN_OS == .Haiku { + AF_INET6 :: 5 } SHUT_RD :: 0 diff --git a/core/sys/posix/sys_time.odin b/core/sys/posix/sys_time.odin index 3036352aa..94eafec85 100644 --- a/core/sys/posix/sys_time.odin +++ b/core/sys/posix/sys_time.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -78,4 +78,15 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ITIMER_VIRTUAL :: 1 ITIMER_PROF :: 2 +} else when ODIN_OS == .Haiku { + + itimerval :: struct { + it_interval: timeval, /* [PSX] timer interval */ + it_value: timeval, /* [PSX] current value */ + } + + ITIMER_REAL :: 1 + ITIMER_VIRTUAL :: 2 + ITIMER_PROF :: 3 + } diff --git a/core/sys/posix/sys_times.odin b/core/sys/posix/sys_times.odin index 113e3f963..73db489a7 100644 --- a/core/sys/posix/sys_times.odin +++ b/core/sys/posix/sys_times.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix when ODIN_OS == .Darwin { @@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD { @(private) LTIMES :: "times" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { tms :: struct { tms_utime: clock_t, /* [PSX] user CPU time */ diff --git a/core/sys/posix/sys_uio.odin b/core/sys/posix/sys_uio.odin index a0ad2934e..5770f8058 100644 --- a/core/sys/posix/sys_uio.odin +++ b/core/sys/posix/sys_uio.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -31,7 +31,7 @@ foreign libc { writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { iovec :: struct { iov_base: rawptr, /* [PSX] base address of I/O memory region */ diff --git a/core/sys/posix/sys_un.odin b/core/sys/posix/sys_un.odin index ca5c4ee31..167bf3ce1 100644 --- a/core/sys/posix/sys_un.odin +++ b/core/sys/posix/sys_un.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -20,4 +20,12 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sun_path: [108]c.char, /* [PSX] socket pathname */ } +} else when ODIN_OS == .Haiku { + + sockaddr_un :: struct { + sun_len: c.uint8_t, + sun_family: sa_family_t, /* [PSX] address family */ + sun_path: [126]c.char, /* [PSX] socket pathname */ + } + } diff --git a/core/sys/posix/sys_utsname.odin b/core/sys/posix/sys_utsname.odin index 64930160f..5ea8807a7 100644 --- a/core/sys/posix/sys_utsname.odin +++ b/core/sys/posix/sys_utsname.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -38,10 +38,10 @@ foreign lib { uname :: proc(uname: ^utsname) -> c.int --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { @(private) - _SYS_NAMELEN :: 256 + _SYS_NAMELEN :: 32 when ODIN_OS == .Haiku else 256 utsname :: struct { sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */ diff --git a/core/sys/posix/sys_wait.odin b/core/sys/posix/sys_wait.odin index 812bd8c62..d3bcdfddd 100644 --- a/core/sys/posix/sys_wait.odin +++ b/core/sys/posix/sys_wait.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -442,4 +442,56 @@ when ODIN_OS == .Darwin { _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool { return x == 0xffff } + +} else when ODIN_OS == .Haiku { + + id_t :: distinct c.int32_t + + WCONTINUED :: 0x04 + WNOHANG :: 0x01 + WUNTRACED :: 0x02 + + WEXITED :: 0x08 + WNOWAIT :: 0x20 + WSTOPPED :: 0x10 + + _P_ALL :: 0 + _P_PID :: 1 + _P_PGID :: 2 + + @(private) + _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool { + return (x & ~(c.int)(0xff)) == 0 + } + + @(private) + _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int { + return x & 0xff + } + + @(private) + _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool { + return ((x >> 8) & 0xff) != 0 + } + + @(private) + _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { + return Signal((x >> 8) & 0xff) + } + + @(private) + _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool { + return ((x >> 16) & 0xff) != 0 + } + + @(private) + _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { + return Signal((x >> 16) & 0xff) + } + + @(private) + _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool { + return (x & 0x20000) != 0 + } + } diff --git a/core/sys/posix/termios.odin b/core/sys/posix/termios.odin index 0c07eceb9..4ca884e87 100644 --- a/core/sys/posix/termios.odin +++ b/core/sys/posix/termios.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -138,17 +138,30 @@ CLocal_Flag_Bits :: enum tcflag_t { } CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t] -CControl_Flag_Bits :: enum tcflag_t { - // CS5 = log2(CS5), /* 5 bits (pseudo) (default) */ - CS6 = log2(CS6), /* 6 bits */ - CS7 = log2(CS7), /* 7 bits */ - CS8 = log2(CS8), /* 8 bits */ - CSTOPB = log2(CSTOPB), /* send 2 stop bits */ - CREAD = log2(CREAD), /* enable receiver */ - PARENB = log2(PARENB), /* parity enable */ - PARODD = log2(PARODD), /* odd parity, else even */ - HUPCL = log2(HUPCL), /* hang up on last close */ - CLOCAL = log2(CLOCAL), /* ignore modem status lines */ +when ODIN_OS == .Haiku { + CControl_Flag_Bits :: enum tcflag_t { + // CS7 = log2(CS7), /* 7 bits (default) */ + CS8 = log2(CS8), /* 8 bits */ + CSTOPB = log2(CSTOPB), /* send 2 stop bits */ + CREAD = log2(CREAD), /* enable receiver */ + PARENB = log2(PARENB), /* parity enable */ + PARODD = log2(PARODD), /* odd parity, else even */ + HUPCL = log2(HUPCL), /* hang up on last close */ + CLOCAL = log2(CLOCAL), /* ignore modem status lines */ + } +} else { + CControl_Flag_Bits :: enum tcflag_t { + // CS5 = log2(CS5), /* 5 bits (pseudo) (default) */ + CS6 = log2(CS6), /* 6 bits */ + CS7 = log2(CS7), /* 7 bits */ + CS8 = log2(CS8), /* 8 bits */ + CSTOPB = log2(CSTOPB), /* send 2 stop bits */ + CREAD = log2(CREAD), /* enable receiver */ + PARENB = log2(PARENB), /* parity enable */ + PARODD = log2(PARODD), /* odd parity, else even */ + HUPCL = log2(HUPCL), /* hang up on last close */ + CLOCAL = log2(CLOCAL), /* ignore modem status lines */ + } } CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t] @@ -597,4 +610,151 @@ when ODIN_OS == .Darwin { TCOOFF :: 0 TCOON :: 1 +} else when ODIN_OS == .Haiku { + + cc_t :: distinct c.uchar + _speed_t :: distinct c.uint32_t + tcflag_t :: distinct c.uint16_t + + // Same as speed_t, but 16-bit. + CSpeed :: enum tcflag_t { + B0 = B0, + B50 = B50, + B75 = B75, + B110 = B110, + B134 = B134, + B150 = B150, + B200 = B200, + B300 = B300, + B600 = B600, + B1200 = B1200, + B1800 = B1800, + B2400 = B2400, + B4800 = B4800, + B9600 = B9600, + B19200 = B19200, + B38400 = B38400, + } + + termios :: struct { + c_iflag: CInput_Flags, /* [XBD] input flags */ + c_ispeed: CSpeed, /* input speed */ + c_oflag: COutput_Flags, /* [XBD] output flags */ + c_ospeed: CSpeed, /* output speed */ + c_cflag: CControl_Flags, /* [XBD] control flags */ + c_ispeed_high: tcflag_t, /* high word of input baudrate */ + c_lflag: CLocal_Flags, /* [XBD] local flag */ + c_ospeed_high: tcflag_t, /* high word of output baudrate */ + c_line: c.char, + _padding: c.uchar, + _padding2: c.uchar, + c_cc: [NCCS]cc_t, + } + + NCCS :: 11 + + VINTR :: 0 + VQUIT :: 1 + VERASE :: 2 + VKILL :: 3 + VEOF :: 4 + VEOL :: 5 + VMIN :: 4 + VTIME :: 5 + VEOL2 :: 6 + VSWTCH :: 7 + VSTART :: 8 + VSTOP :: 9 + VSUSP :: 10 + + IGNBRK :: 0x01 /* ignore break condition */ + BRKINT :: 0x02 /* break sends interrupt */ + IGNPAR :: 0x04 /* ignore characters with parity errors */ + PARMRK :: 0x08 /* mark parity errors */ + INPCK :: 0x10 /* enable input parity checking */ + ISTRIP :: 0x20 /* strip high bit from characters */ + INLCR :: 0x40 /* maps newline to CR on input */ + IGNCR :: 0x80 /* ignore carriage returns */ + ICRNL :: 0x100 /* map CR to newline on input */ + IXON :: 0x400 /* enable input SW flow control */ + IXANY :: 0x800 /* any character will restart input */ + IXOFF :: 0x1000 /* enable output SW flow control */ + + OPOST :: 0x01 /* enable postprocessing of output */ + ONLCR :: 0x04 /* map NL to CR-NL on output */ + OCRNL :: 0x08 /* map CR to NL on output */ + ONOCR :: 0x10 /* no CR output when at column 0 */ + ONLRET :: 0x20 /* newline performs CR function */ + OFILL :: 0x40 /* use fill characters for delays */ + OFDEL :: 0x80 /* Fills are DEL, otherwise NUL */ + _NLDLY :: 0x100 /* Newline delays: */ + NL0 :: 0x000 + NL1 :: 0x100 + _CRDLY :: 0x600 /* Carriage return delays: */ + CR0 :: 0x000 + CR1 :: 0x200 + CR2 :: 0x400 + CR3 :: 0x600 + _TABDLY :: 0x1800 /* Tab delays: */ + TAB0 :: 0x0000 + TAB1 :: 0x0800 + TAB3 :: 0x1800 + _BSDLY :: 0x2000 /* Backspace delays: */ + BS0 :: 0x0000 + BS1 :: 0x2000 + _VTDLY :: 0x4000 /* Vertical tab delays: */ + VT0 :: 0x0000 + VT1 :: 0x4000 + _FFDLY :: 0x8000 /* Form feed delays: */ + FF0 :: 0x0000 + FF1 :: 0x8000 + + B0 :: 0x00 /* hang up */ + B50 :: 0x01 /* 50 baud */ + B75 :: 0x02 + B110 :: 0x03 + B134 :: 0x04 + B150 :: 0x05 + B200 :: 0x06 + B300 :: 0x07 + B600 :: 0x08 + B1200 :: 0x09 + B1800 :: 0x0A + B2400 :: 0x0B + B4800 :: 0x0C + B9600 :: 0x0D + B19200 :: 0x0E + B38400 :: 0x0F + + _CSIZE :: 0x20 /* character size */ + //CS5 :: 0x00 /* only 7 and 8 bits supported */ + //CS6 :: 0x00 /* Note, it was not very wise to set all of these */ + //CS7 :: 0x00 /* to zero, but there is not much we can do about it*/ + CS8 :: 0x20 + CSTOPB :: 0x40 /* send 2 stop bits, not 1 */ + CREAD :: 0x80 /* enable receiver */ + PARENB :: 0x100 /* parity enable */ + PARODD :: 0x200 /* odd parity, else even */ + HUPCL :: 0x400 /* hangs up on last close */ + CLOCAL :: 0x800 /* indicates local line */ + + ISIG :: 0x01 /* enable signals */ + ICANON :: 0x02 /* Canonical input */ + ECHO :: 0x08 /* Enable echo */ + ECHOE :: 0x10 /* Echo erase as bs-sp-bs */ + ECHOK :: 0x20 /* Echo nl after kill */ + ECHONL :: 0x40 /* Echo nl */ + NOFLSH :: 0x80 /* Disable flush after int or quit */ + TOSTOP :: 0x100 /* stop bg processes that write to tty */ + IEXTEN :: 0x200 /* implementation defined extensions */ + + TCIFLUSH :: 1 + TCOFLUSH :: 2 + TCIOFLUSH :: 3 + + TCIOFF :: 0x04 + TCION :: 0x08 + TCOOFF :: 0x01 + TCOON :: 0x02 + } diff --git a/core/sys/posix/unistd.odin b/core/sys/posix/unistd.odin index 0526b3235..d29761a3d 100644 --- a/core/sys/posix/unistd.odin +++ b/core/sys/posix/unistd.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" @@ -1852,7 +1852,7 @@ when ODIN_OS == .Darwin { _PC_ALLOC_SIZE_MIN :: 19 _PC_SYMLINK_MAX :: 20 _PC_2_SYMLINK :: 21 - + _SC_ARG_MAX :: 1 _SC_CHILD_MAX :: 2 _SC_CLK_TCK :: 3 @@ -1992,4 +1992,174 @@ when ODIN_OS == .Darwin { // NOTE: Not implemented. _POSIX_VDISABLE :: 0 +} else when ODIN_OS == .Haiku { + + _F_OK :: 0 + X_OK :: 1 + W_OK :: 2 + R_OK :: 4 + + F_LOCK :: 1 + F_TEST :: 3 + F_TLOCK :: 2 + F_ULOCK :: 0 + + _CS_PATH :: 1 + _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFF32_CFLAGS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFF32_LIBS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS :: 0 // Undefined. + _CS_POSIX_V6_ILP32_OFFBIG_LIBS :: 0 // Undefined. + _CS_POSIX_V6_LP64_OFF64_CFLAGS :: 0 // Undefined. + _CS_POSIX_V6_LP64_OFF64_LDFLAGS :: 0 // Undefined. + _CS_POSIX_V6_LP64_OFF64_LIBS :: 0 // Undefined. + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS :: 0 // Undefined. + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS :: 0 // Undefined. + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS :: 0 // Undefined. + + _SC_ASYNCHRONOUS_IO :: 0 // Undefined. + _SC_RAW_SOCKETS :: 0 // Undefined. + _SC_SS_REPL_MAX :: 0 // Undefined. + _SC_TRACE_EVENT_NAME_MAX :: 0 // Undefined. + _SC_TRACE_NAME_MAX :: 0 // Undefined. + _SC_TRACE_SYS_MAX :: 0 // Undefined. + _SC_TRACE_USER_EVENT_MAX :: 0 // Undefined. + + _PC_CHOWN_RESTRICTED :: 1 + _PC_MAX_CANON :: 2 + _PC_MAX_INPUT :: 3 + _PC_NAME_MAX :: 4 + _PC_NO_TRUNC :: 5 + _PC_PATH_MAX :: 6 + _PC_PIPE_BUF :: 7 + _PC_VDISABLE :: 8 + _PC_LINK_MAX :: 25 + _PC_SYNC_IO :: 26 + _PC_ASYNC_IO :: 27 + _PC_PRIO_IO :: 28 + _PC_FILESIZEBITS :: 30 + _PC_REC_INCR_XFER_SIZE :: 31 + _PC_REC_MAX_XFER_SIZE :: 32 + _PC_REC_MIN_XFER_SIZE :: 33 + _PC_REC_XFER_ALIGN :: 34 + _PC_ALLOC_SIZE_MIN :: 35 + _PC_SYMLINK_MAX :: 36 + _PC_2_SYMLINK :: 37 + + _SC_ARG_MAX :: 15 + _SC_CHILD_MAX :: 16 + _SC_CLK_TCK :: 17 + _SC_JOB_CONTROL :: 18 + _SC_NGROUPS_MAX :: 19 + _SC_OPEN_MAX :: 20 + _SC_SAVED_IDS :: 21 + _SC_STREAM_MAX :: 22 + _SC_TZNAME_MAX :: 23 + _SC_VERSION :: 24 + _SC_GETGR_R_SIZE_MAX :: 25 + _SC_GETPW_R_SIZE_MAX :: 26 + _SC_PAGE_SIZE :: 27 + _SC_PAGESIZE :: _SC_PAGE_SIZE + _SC_SEM_NSEMS_MAX :: 28 + _SC_SEM_VALUE_MAX :: 29 + _SC_SEMAPHORES :: 30 + _SC_THREADS :: 31 + _SC_IOV_MAX :: 32 + _SC_NPROCESSORS_CONF :: 34 + _SC_NPROCESSORS_ONLN :: 35 + _SC_ATEXIT_MAX :: 37 + _SC_MAPPED_FILES :: 45 + _SC_THREAD_PROCESS_SHARED :: 46 + _SC_THREAD_STACK_MIN :: 47 + _SC_THREAD_ATTR_STACKADDR :: 48 + _SC_THREAD_ATTR_STACKSIZE :: 49 + _SC_THREAD_PRIORITY_SCHEDULING :: 50 + _SC_REALTIME_SIGNALS :: 51 + _SC_MEMORY_PROTECTION :: 52 + _SC_SIGQUEUE_MAX :: 53 + _SC_RTSIG_MAX :: 54 + _SC_MONOTONIC_CLOCK :: 55 + _SC_DELAYTIMER_MAX :: 56 + _SC_TIMER_MAX :: 57 + _SC_TIMERS :: 58 + _SC_CPUTIME :: 59 + _SC_THREAD_CPUTIME :: 60 + _SC_HOST_NAME_MAX :: 61 + _SC_REGEXP :: 62 + _SC_SYMLOOP_MAX :: 63 + _SC_SHELL :: 64 + _SC_TTY_NAME_MAX :: 65 + _SC_ADVISORY_INFO :: 66 + _SC_BARRIERS :: 67 + _SC_CLOCK_SELECTION :: 68 + _SC_FSYNC :: 69 + _SC_IPV6 :: 70 + _SC_MEMLOCK :: 71 + _SC_MEMLOCK_RANGE :: 72 + _SC_MESSAGE_PASSING :: 73 + _SC_PRIORITIZED_IO :: 74 + _SC_PRIORITY_SCHEDULING :: 75 + _SC_READER_WRITER_LOCKS :: 76 + _SC_SHARED_MEMORY_OBJECTS :: 77 + _SC_SPAWN :: 78 + _SC_SPIN_LOCKS :: 79 + _SC_SPORADIC_SERVER :: 80 + _SC_SYNCHRONIZED_IO :: 81 + _SC_THREAD_PRIO_INHERIT :: 82 + _SC_THREAD_PRIO_PROTECT :: 83 + _SC_THREAD_SAFE_FUNCTIONS :: 86 + _SC_THREAD_SPORADIC_SERVER :: 87 + _SC_TIMEOUTS :: 88 + _SC_TRACE :: 89 + _SC_TRACE_EVENT_FILTER :: 90 + _SC_TRACE_INHERIT :: 91 + _SC_TRACE_LOG :: 92 + _SC_TYPED_MEMORY_OBJECTS :: 93 + _SC_V6_ILP32_OFF32 :: 94 + _SC_V6_ILP32_OFFBIG :: 95 + _SC_V6_LP64_OFF64 :: 96 + _SC_V6_LPBIG_OFFBIG :: 97 + _SC_2_C_BIND :: 102 + _SC_2_C_DEV :: 103 + _SC_2_CHAR_TERM :: 104 + _SC_2_FORT_DEV :: 105 + _SC_2_FORT_RUN :: 106 + _SC_2_LOCALEDEF :: 107 + _SC_2_PBS :: 108 + _SC_2_PBS_ACCOUNTING :: 109 + _SC_2_PBS_CHECKPOINT :: 110 + _SC_2_PBS_LOCATE :: 111 + _SC_2_PBS_MESSAGE :: 112 + _SC_2_PBS_TRACK :: 113 + _SC_2_SW_DEV :: 114 + _SC_2_UPE :: 115 + _SC_2_VERSION :: 116 + _SC_XOPEN_CRYPT :: 117 + _SC_XOPEN_ENH_I18N :: 118 + _SC_XOPEN_REALTIME :: 119 + _SC_XOPEN_REALTIME_THREADS :: 120 + _SC_XOPEN_SHM :: 121 + _SC_XOPEN_STREAMS :: 122 + _SC_XOPEN_UNIX :: 123 + _SC_XOPEN_VERSION :: 125 + _SC_AIO_LISTIO_MAX :: 126 + _SC_AIO_MAX :: 127 + _SC_AIO_PRIO_DELTA_MAX :: 128 + _SC_BC_BASE_MAX :: 129 + _SC_BC_DIM_MAX :: 130 + _SC_BC_SCALE_MAX :: 131 + _SC_BC_STRING_MAX :: 132 + _SC_COLL_WEIGHTS_MAX :: 133 + _SC_EXPR_NEST_MAX :: 134 + _SC_LINE_MAX :: 135 + _SC_LOGIN_NAME_MAX :: 136 + _SC_MQ_OPEN_MAX :: 137 + _SC_MQ_PRIO_MAX :: 138 + _SC_THREAD_DESTRUCTOR_ITERATIONS :: 139 + _SC_THREAD_KEYS_MAX :: 140 + _SC_THREAD_THREADS_MAX :: 141 + _SC_RE_DUP_MAX :: 142 + } diff --git a/core/sys/posix/unistd_libc.odin b/core/sys/posix/unistd_libc.odin index bbfe3d59d..74edb6862 100644 --- a/core/sys/posix/unistd_libc.odin +++ b/core/sys/posix/unistd_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd +#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku package posix import "core:c" diff --git a/core/sys/posix/utime.odin b/core/sys/posix/utime.odin index e884eb1a3..98c8166d6 100644 --- a/core/sys/posix/utime.odin +++ b/core/sys/posix/utime.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku package posix when ODIN_OS == .Darwin { @@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD { @(private) LUTIME :: "utime" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { utimbuf :: struct { actime: time_t, /* [PSX] access time (seconds since epoch) */ From a704000c347815a621b7b69cdc24446377e7c97c Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 06:42:19 +0100 Subject: [PATCH 22/31] Haiku: add posix tests --- tests/core/sys/posix/posix.odin | 46 ++++++++++++++++------- tests/core/sys/posix/structs.odin | 2 +- tests/core/sys/posix/structs/structs.c | 13 +++++++ tests/core/sys/posix/structs/structs.odin | 11 ++++-- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/tests/core/sys/posix/posix.odin b/tests/core/sys/posix/posix.odin index 8daffc5b9..772190a3a 100644 --- a/tests/core/sys/posix/posix.odin +++ b/tests/core/sys/posix/posix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd +#+build linux, darwin, freebsd, openbsd, netbsd, haiku package tests_core_posix import "core:log" @@ -65,8 +65,17 @@ test_dirent :: proc(t: ^testing.T) { for entry in entries { defer posix.free(entry) - if entry.d_type != .REG { - continue + when ODIN_OS == .Haiku { + stat: posix.stat_t + posix.stat(cstring(raw_data(entry.d_name[:])), &stat) + + if !posix.S_ISREG(stat.st_mode) { + continue + } + } else { + if entry.d_type != .REG { + continue + } } name := string(cstring(raw_data(entry.d_name[:]))) @@ -86,8 +95,17 @@ test_dirent :: proc(t: ^testing.T) { break } - if entry.d_type != .REG { - continue + when ODIN_OS == .Haiku { + stat: posix.stat_t + posix.stat(cstring(raw_data(entry.d_name[:])), &stat) + + if !posix.S_ISREG(stat.st_mode) { + continue + } + } else { + if entry.d_type != .REG { + continue + } } name := string(cstring(raw_data(entry.d_name[:]))) @@ -140,15 +158,15 @@ test_langinfo :: proc(t: ^testing.T) { @(test) test_libgen :: proc(t: ^testing.T) { tests := [][3]cstring{ - { "usr", ".", "usr" }, - { "usr/", ".", "usr" }, - { "", ".", "." }, - { "/", "/", "/" }, - { "///", "/", "/" }, - { "/usr/", "/", "usr" }, - { "/usr/lib", "/usr", "lib" }, - { "//usr//lib//", "//usr", "lib" }, - { "/home//dwc//test", "/home//dwc", "test" }, + { "usr", ".", "usr" }, + { "usr/", ".", "usr" }, + { "", ".", "." }, + { "/", "/", "/" }, + { "///", "/", "/" }, + { "/usr/", "/", "usr" }, + { "/usr/lib", "/usr", "lib" }, + { "//usr//lib//", "//usr" + ("/" when ODIN_OS == .Haiku else ""), "lib" }, + { "/home//dwc//test", "/home//dwc" + ("/" when ODIN_OS == .Haiku else ""), "test" }, } for test in tests { diff --git a/tests/core/sys/posix/structs.odin b/tests/core/sys/posix/structs.odin index a0e8fea99..66b7cb0e1 100644 --- a/tests/core/sys/posix/structs.odin +++ b/tests/core/sys/posix/structs.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd +#+build linux, darwin, freebsd, openbsd, netbsd, haiku package tests_core_posix import "core:log" diff --git a/tests/core/sys/posix/structs/structs.c b/tests/core/sys/posix/structs/structs.c index e78e872eb..396de579e 100644 --- a/tests/core/sys/posix/structs/structs.c +++ b/tests/core/sys/posix/structs/structs.c @@ -10,7 +10,11 @@ #include #include #include + +#ifndef __HAIKU__ #include +#endif + #include #include #include @@ -25,7 +29,11 @@ #include #include #include + +#ifndef __HAIKU__ #include +#endif + #include int main(int argc, char *argv[]) @@ -67,7 +75,10 @@ int main(int argc, char *argv[]) printf("passwd %zu %zu\n", sizeof(struct passwd), _Alignof(struct passwd)); +#ifndef __HAIKU__ printf("shmid_ds %zu %zu\n", sizeof(struct shmid_ds), _Alignof(struct shmid_ds)); +#endif + printf("ipc_perm %zu %zu\n", sizeof(struct ipc_perm), _Alignof(struct ipc_perm)); printf("msqid_ds %zu %zu\n", sizeof(struct msqid_ds), _Alignof(struct msqid_ds)); @@ -95,7 +106,9 @@ int main(int argc, char *argv[]) printf("utimbuf %zu %zu\n", sizeof(struct utimbuf), _Alignof(struct utimbuf)); +#ifndef __HAIKU__ printf("wordexp_t %zu %zu\n", sizeof(wordexp_t), _Alignof(wordexp_t)); +#endif printf("time_t %zu %zu\n", sizeof(time_t), _Alignof(time_t)); printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec)); diff --git a/tests/core/sys/posix/structs/structs.odin b/tests/core/sys/posix/structs/structs.odin index c94bb7c99..a05137e87 100644 --- a/tests/core/sys/posix/structs/structs.odin +++ b/tests/core/sys/posix/structs/structs.odin @@ -42,7 +42,10 @@ main :: proc() { fmt.println("pollfd", size_of(posix.pollfd), align_of(posix.pollfd)) fmt.println("passwd", size_of(posix.passwd), align_of(posix.passwd)) - fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds)) + when ODIN_OS != .Haiku { + fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds)) + } + fmt.println("ipc_perm", size_of(posix.ipc_perm), align_of(posix.ipc_perm)) fmt.println("msqid_ds", size_of(posix.msqid_ds), align_of(posix.msqid_ds)) @@ -70,8 +73,10 @@ main :: proc() { fmt.println("utimbuf", size_of(posix.utimbuf), align_of(posix.utimbuf)) - fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t)) - + when ODIN_OS != .Haiku { + fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t)) + } + fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t)) fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec)) fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t)) From 0a985f5d02ef0821353a2bf80638519d5419d5d7 Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 07:07:40 +0100 Subject: [PATCH 23/31] Haiku: small fixes across core --- core/c/libc/stdlib.odin | 15 +++++++++++++++ core/os/os_haiku.odin | 19 +++++++++++++++++-- core/path/filepath/path_unix.odin | 2 +- core/testing/signal_handler_posix.odin | 2 +- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/core/c/libc/stdlib.odin b/core/c/libc/stdlib.odin index 98280e44b..c0e273872 100644 --- a/core/c/libc/stdlib.odin +++ b/core/c/libc/stdlib.odin @@ -42,6 +42,21 @@ when ODIN_OS == .Linux { } } +when ODIN_OS == .Haiku { + RAND_MAX :: 0x7fffffff + + // GLIBC and MUSL only + @(private="file") + @(default_calling_convention="c") + foreign libc { + __ctype_get_mb_cur_max :: proc() -> ushort --- + } + + MB_CUR_MAX :: #force_inline proc() -> size_t { + return size_t(__ctype_get_mb_cur_max()) + } +} + when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD { RAND_MAX :: 0x7fffffff diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin index 6b218af07..4a57afb87 100644 --- a/core/os/os_haiku.odin +++ b/core/os/os_haiku.odin @@ -151,6 +151,7 @@ foreign lib { @(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int --- @(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) --- @(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int --- + @(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle --- @(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr --- @(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr --- @@ -158,7 +159,7 @@ foreign lib { @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr --- @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- - @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr --- + @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: [^]byte = nil) -> cstring --- @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! --- @@ -445,7 +446,7 @@ absolute_path_from_relative :: proc(rel: string, allocator := context.allocator) if path_ptr == nil { return "", get_last_error() } - defer _unix_free(path_ptr) + defer _unix_free(rawptr(path_ptr)) path_cstr := cstring(path_ptr) return strings.clone(string(path_cstr), allocator) @@ -489,3 +490,17 @@ exit :: proc "contextless" (code: int) -> ! { runtime._cleanup_runtime_contextless() _unix_exit(i32(code)) } + +@(require_results) +current_thread_id :: proc "contextless" () -> int { + return int(haiku.find_thread(nil)) +} + +@(private, require_results) +_dup :: proc(fd: Handle) -> (Handle, Error) { + dup := _unix_dup(fd) + if dup == -1 { + return INVALID_HANDLE, get_last_error() + } + return dup, nil +} diff --git a/core/path/filepath/path_unix.odin b/core/path/filepath/path_unix.odin index 35b98a7ae..8bf412599 100644 --- a/core/path/filepath/path_unix.odin +++ b/core/path/filepath/path_unix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd +#+build linux, darwin, freebsd, openbsd, netbsd, haiku package filepath import "base:runtime" diff --git a/core/testing/signal_handler_posix.odin b/core/testing/signal_handler_posix.odin index 1bfcc875b..0efba27dc 100644 --- a/core/testing/signal_handler_posix.odin +++ b/core/testing/signal_handler_posix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd +#+build linux, darwin, netbsd, openbsd, freebsd, haiku #+private package testing From c686728184e7171a41d443c2ddbdea1409806ca1 Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 07:15:44 +0100 Subject: [PATCH 24/31] Update dir_unix.odin --- core/os/dir_unix.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/dir_unix.odin b/core/os/dir_unix.odin index 26e865204..f06bf8b37 100644 --- a/core/os/dir_unix.odin +++ b/core/os/dir_unix.odin @@ -1,4 +1,4 @@ -#+build darwin, linux, netbsd, freebsd, openbsd +#+build darwin, linux, netbsd, freebsd, openbsd, haiku package os import "core:strings" From 3d4a20918f074af8a7d99f5fcd468f21ef8d3a45 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 10 Jan 2025 10:12:36 +0000 Subject: [PATCH 25/31] Simplify stb foreign imports --- vendor/stb/image/stb_image.odin | 8 ++------ vendor/stb/image/stb_image_resize.odin | 8 ++------ vendor/stb/image/stb_image_write.odin | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin index 0c2ad7d05..2bba9aa83 100644 --- a/vendor/stb/image/stb_image.odin +++ b/vendor/stb/image/stb_image.odin @@ -18,12 +18,8 @@ when LIB != "" { } } -when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { - foreign import stbi "../lib/stb_image_wasm.o" -} else when LIB != "" { - foreign import stbi { LIB } -} else { - foreign import stbi "system:stb_image" +foreign import stbi { + LIB when LIB != "" else "system:stb_image" } NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin index 241a93eb0..d00b55b4f 100644 --- a/vendor/stb/image/stb_image_resize.odin +++ b/vendor/stb/image/stb_image_resize.odin @@ -18,12 +18,8 @@ when RESIZE_LIB != "" { } } -when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { - foreign import lib "../lib/stb_image_resize_wasm.o" -} else when RESIZE_LIB != "" { - foreign import lib { RESIZE_LIB } -} else { - foreign import lib "system:stb_image_resize" +foreign import stbi { + RESIZE_LIB when RESIZE_LIB != "" else "system:stb_image_resize" } ////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/stb/image/stb_image_write.odin b/vendor/stb/image/stb_image_write.odin index e86fa2b95..6d4c2a2e8 100644 --- a/vendor/stb/image/stb_image_write.odin +++ b/vendor/stb/image/stb_image_write.odin @@ -18,12 +18,8 @@ when WRITE_LIB != "" { } } -when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { - foreign import stbiw "../lib/stb_image_write_wasm.o" -} else when WRITE_LIB != "" { - foreign import stbiw { WRITE_LIB } -} else { - foreign import stbiw "system:stb_image_write" +foreign import stbi { + WRITE_LIB when WRITE_LIB != "" else "system:stb_image_write" } write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int) From b377ac182c5d546e0621aec4c67a2336fc6a89b4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 10 Jan 2025 10:15:15 +0000 Subject: [PATCH 26/31] Keep -vet happy --- vendor/stb/image/stb_image.odin | 2 +- vendor/stb/image/stb_image_resize.odin | 2 +- vendor/stb/image/stb_image_write.odin | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin index 2bba9aa83..e74c825b8 100644 --- a/vendor/stb/image/stb_image.odin +++ b/vendor/stb/image/stb_image.odin @@ -19,7 +19,7 @@ when LIB != "" { } foreign import stbi { - LIB when LIB != "" else "system:stb_image" + LIB when LIB != "" else "system:stb_image", } NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin index d00b55b4f..978403daf 100644 --- a/vendor/stb/image/stb_image_resize.odin +++ b/vendor/stb/image/stb_image_resize.odin @@ -19,7 +19,7 @@ when RESIZE_LIB != "" { } foreign import stbi { - RESIZE_LIB when RESIZE_LIB != "" else "system:stb_image_resize" + RESIZE_LIB when RESIZE_LIB != "" else "system:stb_image_resize", } ////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/stb/image/stb_image_write.odin b/vendor/stb/image/stb_image_write.odin index 6d4c2a2e8..315dfc34d 100644 --- a/vendor/stb/image/stb_image_write.odin +++ b/vendor/stb/image/stb_image_write.odin @@ -19,7 +19,7 @@ when WRITE_LIB != "" { } foreign import stbi { - WRITE_LIB when WRITE_LIB != "" else "system:stb_image_write" + WRITE_LIB when WRITE_LIB != "" else "system:stb_image_write", } write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int) From 4a2b13f1c24920d53ed451bd8c021aa504eee0d4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 10 Jan 2025 10:18:30 +0000 Subject: [PATCH 27/31] Fix foreign import names --- vendor/stb/image/stb_image_resize.odin | 2 +- vendor/stb/image/stb_image_write.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin index 978403daf..43909856e 100644 --- a/vendor/stb/image/stb_image_resize.odin +++ b/vendor/stb/image/stb_image_resize.odin @@ -18,7 +18,7 @@ when RESIZE_LIB != "" { } } -foreign import stbi { +foreign import lib { RESIZE_LIB when RESIZE_LIB != "" else "system:stb_image_resize", } diff --git a/vendor/stb/image/stb_image_write.odin b/vendor/stb/image/stb_image_write.odin index 315dfc34d..496f228a5 100644 --- a/vendor/stb/image/stb_image_write.odin +++ b/vendor/stb/image/stb_image_write.odin @@ -18,7 +18,7 @@ when WRITE_LIB != "" { } } -foreign import stbi { +foreign import stbiw { WRITE_LIB when WRITE_LIB != "" else "system:stb_image_write", } From 328d893cb58d4b96f12207eb49da01273deda6ce Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 10 Jan 2025 12:14:43 +0000 Subject: [PATCH 28/31] `#unroll(N) for` --- core/odin/ast/ast.odin | 7 +- core/odin/ast/clone.odin | 3 +- core/odin/parser/parser.odin | 43 ++++++- src/check_stmt.cpp | 65 +++++++++- src/llvm_backend_stmt.cpp | 239 +++++++++++++++++++++++++++-------- src/parser.cpp | 58 +++++++-- src/parser.hpp | 1 + 7 files changed, 339 insertions(+), 77 deletions(-) diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index f62feec8c..3b8998b31 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -432,10 +432,13 @@ Range_Stmt :: struct { reverse: bool, } -Inline_Range_Stmt :: struct { +Inline_Range_Stmt :: Unroll_Range_Stmt + +Unroll_Range_Stmt :: struct { using node: Stmt, label: ^Expr, - inline_pos: tokenizer.Pos, + unroll_pos: tokenizer.Pos, + args: []^Expr, for_pos: tokenizer.Pos, val0: ^Expr, val1: ^Expr, diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index 67f7ffa95..b7501e6ca 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -242,8 +242,9 @@ clone_node :: proc(node: ^Node) -> ^Node { r.vals = clone(r.vals) r.expr = clone(r.expr) r.body = clone(r.body) - case ^Inline_Range_Stmt: + case ^Unroll_Range_Stmt: r.label = clone(r.label) + r.args = clone(r.args) r.val0 = clone(r.val0) r.val1 = clone(r.val1) r.expr = clone(r.expr) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 5a7440339..63c7e388f 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1262,11 +1262,49 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl { parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast.Stmt { - for_tok := expect_token(p, .For) val0, val1: ^ast.Expr in_tok: tokenizer.Token expr: ^ast.Expr body: ^ast.Stmt + args: [dynamic]^ast.Expr + + if allow_token(p, .Open_Paren) { + p.expr_level += 1 + if p.curr_tok.kind == .Close_Paren { + error(p, p.curr_tok.pos, "#unroll expected at least 1 argument, got 0") + } else { + args = make([dynamic]^ast.Expr) + for p.curr_tok.kind != .Close_Paren && + p.curr_tok.kind != .EOF { + arg := parse_value(p) + + if p.curr_tok.kind == .Eq { + eq := expect_token(p, .Eq) + if arg != nil { + if _, ok := arg.derived.(^ast.Ident); !ok { + error(p, arg.pos, "expected an identifier for 'key=value'") + } + } + value := parse_value(p) + fv := ast.new(ast.Field_Value, arg.pos, value) + fv.field = arg + fv.sep = eq.pos + fv.value = value + + arg = fv + } + + append(&args, arg) + + allow_token(p, .Comma) or_break + } + } + + p.expr_level -= 1 + _ = expect_token_after(p, .Close_Paren, "#unroll") + } + + for_tok := expect_token(p, .For) bad_stmt := false @@ -1309,7 +1347,8 @@ parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast } range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body) - range_stmt.inline_pos = inline_tok.pos + range_stmt.unroll_pos = inline_tok.pos + range_stmt.args = args[:] range_stmt.for_pos = for_tok.pos range_stmt.val0 = val0 range_stmt.val1 = val1 diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 02ad72388..1708f7c81 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -894,15 +894,49 @@ gb_internal void error_var_decl_identifier(Ast *name) { } } -gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { +gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { ast_node(irs, UnrollRangeStmt, node); check_open_scope(ctx, node); + defer (check_close_scope(ctx)); Type *val0 = nullptr; Type *val1 = nullptr; Entity *entities[2] = {}; isize entity_count = 0; + i64 unroll_count = -1; + + if (irs->args.count > 0) { + if (irs->args.count > 1) { + error(irs->args[1], "#unroll only supports a single argument for the unroll per loop amount"); + } + Ast *arg = irs->args[0]; + if (arg->kind == Ast_FieldValue) { + error(arg, "#unroll does not yet support named arguments"); + arg = arg->FieldValue.value; + } + + Operand x = {}; + check_expr(ctx, &x, arg); + if (x.mode != Addressing_Constant || !is_type_integer(x.type)) { + gbString s = expr_to_string(x.expr); + error(x.expr, "Expected a constant integer for #unroll, got '%s'", s); + gb_string_free(s); + } else { + ExactValue value = exact_value_to_integer(x.value); + i64 v = exact_value_to_i64(value); + if (v < 1) { + error(x.expr, "Expected a constant integer >= 1 for #unroll, got %lld", cast(long long)v); + } else { + unroll_count = v; + if (v > 1024) { + error(x.expr, "Too large of a value for #unroll, got %lld, expected <= 1024", cast(long long)v); + } + } + + } + } + Ast *expr = unparen_expr(irs->expr); ExactValue inline_for_depth = exact_value_i64(0); @@ -946,18 +980,39 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod val0 = t_rune; val1 = t_int; inline_for_depth = exact_value_i64(operand.value.value_string.len); + if (unroll_count > 0) { + error(node, "#unroll(%lld) does not support strings", cast(long long)unroll_count); + } } break; case Type_Array: val0 = t->Array.elem; val1 = t_int; - inline_for_depth = exact_value_i64(t->Array.count); + inline_for_depth = unroll_count > 0 ? exact_value_i64(unroll_count) : exact_value_i64(t->Array.count); break; case Type_EnumeratedArray: val0 = t->EnumeratedArray.elem; val1 = t->EnumeratedArray.index; + if (unroll_count > 0) { + error(node, "#unroll(%lld) does not support enumerated arrays", cast(long long)unroll_count); + } inline_for_depth = exact_value_i64(t->EnumeratedArray.count); break; + + case Type_Slice: + if (unroll_count > 0) { + val0 = t->Slice.elem; + val1 = t_int; + inline_for_depth = exact_value_i64(unroll_count); + } + break; + case Type_DynamicArray: + if (unroll_count > 0) { + val0 = t->DynamicArray.elem; + val1 = t_int; + inline_for_depth = exact_value_i64(unroll_count); + } + break; } } @@ -967,7 +1022,7 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod error(operand.expr, "Cannot iterate over '%s' of type '%s' in an '#unroll for' statement", s, t); gb_string_free(t); gb_string_free(s); - } else if (operand.mode != Addressing_Constant) { + } else if (operand.mode != Addressing_Constant && unroll_count <= 0) { error(operand.expr, "An '#unroll for' expression must be known at compile time"); } } @@ -1050,8 +1105,6 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod check_stmt(ctx, irs->body, mod_flags); - - check_close_scope(ctx); } gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { @@ -2679,7 +2732,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) case_end; case_ast_node(irs, UnrollRangeStmt, node); - check_inline_range_stmt(ctx, node, mod_flags); + check_unroll_range_stmt(ctx, node, mod_flags); case_end; case_ast_node(ss, SwitchStmt, node); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index a2f0d2f4a..b05df0b46 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -256,7 +256,7 @@ gb_internal void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) { gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr, lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_, - bool is_reverse) { + bool is_reverse, i64 unroll_count=0) { lbModule *m = p->module; lbValue count = {}; @@ -1230,7 +1230,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * TypeAndValue tav = type_and_value_of_expr(expr); if (is_ast_range(expr)) { - lbAddr val0_addr = {}; lbAddr val1_addr = {}; if (val0_type) val0_addr = lb_build_addr(p, val0); @@ -1268,7 +1267,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * } } - } else if (tav.mode == Addressing_Type) { GB_ASSERT(is_type_enum(type_deref(tav.type))); Type *et = type_deref(tav.type); @@ -1293,72 +1291,203 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * if (val0_type) val0_addr = lb_build_addr(p, val0); if (val1_type) val1_addr = lb_build_addr(p, val1); - GB_ASSERT(expr->tav.mode == Addressing_Constant); - - Type *t = base_type(expr->tav.type); + ExactValue unroll_count_ev = {}; + if (rs->args.count != 0) { + unroll_count_ev = rs->args[0]->tav.value; + } - switch (t->kind) { - case Type_Basic: - GB_ASSERT(is_type_string(t)); - { - ExactValue value = expr->tav.value; - GB_ASSERT(value.kind == ExactValue_String); - String str = value.value_string; - Rune codepoint = 0; - isize offset = 0; - do { - isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint); - if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint))); - if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset))); - lb_build_stmt(p, rs->body); + if (unroll_count_ev.kind == ExactValue_Invalid) { + GB_ASSERT(expr->tav.mode == Addressing_Constant); - offset += width; - } while (offset < str.len); - } - break; - case Type_Array: - if (t->Array.count > 0) { - lbValue val = lb_build_expr(p, expr); - lbValue val_addr = lb_address_from_load_or_generate_local(p, val); + Type *t = base_type(expr->tav.type); - for (i64 i = 0; i < t->Array.count; i++) { - if (val0_type) { - // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 - lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); - lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); + switch (t->kind) { + case Type_Basic: + GB_ASSERT(is_type_string(t)); + { + ExactValue value = expr->tav.value; + GB_ASSERT(value.kind == ExactValue_String); + String str = value.value_string; + Rune codepoint = 0; + isize offset = 0; + do { + isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint); + if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint))); + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset))); + lb_build_stmt(p, rs->body); + + offset += width; + } while (offset < str.len); + } + break; + case Type_Array: + if (t->Array.count > 0) { + lbValue val = lb_build_expr(p, expr); + lbValue val_addr = lb_address_from_load_or_generate_local(p, val); + + for (i64 i = 0; i < t->Array.count; i++) { + if (val0_type) { + // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 + lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); + lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); + } + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i))); + + lb_build_stmt(p, rs->body); } - if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i))); - lb_build_stmt(p, rs->body); + } + break; + case Type_EnumeratedArray: + if (t->EnumeratedArray.count > 0) { + lbValue val = lb_build_expr(p, expr); + lbValue val_addr = lb_address_from_load_or_generate_local(p, val); + + for (i64 i = 0; i < t->EnumeratedArray.count; i++) { + if (val0_type) { + // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 + lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); + lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); + } + if (val1_type) { + ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value); + lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx)); + } + + lb_build_stmt(p, rs->body); + } + + } + break; + default: + GB_PANIC("Invalid '#unroll for' type"); + break; + } + } else { + + //////////////////////////////// + // // + // #unroll(N) logic // + // // + //////////////////////////////// + + + i64 unroll_count = exact_value_to_i64(unroll_count_ev); + gb_unused(unroll_count); + + Type *t = base_type(expr->tav.type); + + lbValue data_ptr = {}; + lbValue count_ptr = {}; + + switch (t->kind) { + case Type_Slice: + case Type_DynamicArray: { + lbValue slice = lb_build_expr(p, expr); + if (is_type_pointer(slice.type)) { + count_ptr = lb_emit_struct_ep(p, slice, 1); + slice = lb_emit_load(p, slice); + } else { + count_ptr = lb_add_local_generated(p, t_int, false).addr; + lb_emit_store(p, count_ptr, lb_slice_len(p, slice)); + } + data_ptr = lb_emit_struct_ev(p, slice, 0); + break; + } + + case Type_Array: { + lbValue array = lb_build_expr(p, expr); + count_ptr = lb_add_local_generated(p, t_int, false).addr; + lb_emit_store(p, count_ptr, lb_const_int(p->module, t_int, t->Array.count)); + + if (!is_type_pointer(array.type)) { + array = lb_address_from_load_or_generate_local(p, array); } + GB_ASSERT(is_type_pointer(array.type)); + data_ptr = lb_emit_conv(p, array, alloc_type_pointer(t->Array.elem)); + break; } - break; - case Type_EnumeratedArray: - if (t->EnumeratedArray.count > 0) { - lbValue val = lb_build_expr(p, expr); - lbValue val_addr = lb_address_from_load_or_generate_local(p, val); - for (i64 i = 0; i < t->EnumeratedArray.count; i++) { - if (val0_type) { - // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 - lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); - lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); - } - if (val1_type) { - ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value); - lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx)); - } + default: + GB_PANIC("Invalid '#unroll for' type"); + break; + } + + data_ptr.type = alloc_type_multi_pointer_to_pointer(data_ptr.type); + + lbBlock *loop_top = lb_create_block(p, "for.unroll.loop.top"); + + lbBlock *body_top = lb_create_block(p, "for.unroll.body.top"); + lbBlock *body_bot = lb_create_block(p, "for.unroll.body.bot"); + + lbBlock *done = lb_create_block(p, "for.unroll.done"); + + lbBlock *loop_bot = unroll_count > 1 ? lb_create_block(p, "for.unroll.loop.bot") : done; + + /* + i := 0 + for ; i+N <= len(array); i += N { + body + } + for ; i < len(array); i += 1 { + body + } + */ + + Entity *val_entity = val0 ? entity_of_node(val0) : nullptr; + Entity *idx_entity = val1 ? entity_of_node(val1) : nullptr; + + lbAddr val_addr = lb_add_local(p, type_deref(data_ptr.type, true), val_entity); + lbAddr idx_addr = lb_add_local(p, t_int, idx_entity); + lb_addr_store(p, idx_addr, lb_const_nil(p->module, t_int)); + + lb_emit_jump(p, loop_top); + lb_start_block(p, loop_top); + + lbValue idx_add_n = lb_addr_load(p, idx_addr); + idx_add_n = lb_emit_arith(p, Token_Add, idx_add_n, lb_const_int(p->module, t_int, unroll_count), t_int); + + lbValue cond_top = lb_emit_comp(p, Token_LtEq, idx_add_n, lb_emit_load(p, count_ptr)); + lb_emit_if(p, cond_top, body_top, loop_bot); + + lb_start_block(p, body_top); + for (i64 top = 0; top < unroll_count; top++) { + lbValue idx = lb_addr_load(p, idx_addr); + lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx)); + lb_addr_store(p, val_addr, val); + + lb_build_stmt(p, rs->body); + + lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr)); + } + lb_emit_jump(p, loop_top); + + if (unroll_count > 1) { + lb_start_block(p, loop_bot); + + lbValue cond_bot = lb_emit_comp(p, Token_Lt, lb_addr_load(p, idx_addr), lb_emit_load(p, count_ptr)); + lb_emit_if(p, cond_bot, body_bot, done); + + lb_start_block(p, body_bot); + { + lbValue idx = lb_addr_load(p, idx_addr); + lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx)); + lb_addr_store(p, val_addr, val); lb_build_stmt(p, rs->body); - } + lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr)); + } + lb_emit_jump(p, loop_bot); } - break; - default: - GB_PANIC("Invalid '#unroll for' type"); - break; + + lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body); + lb_emit_jump(p, done); + lb_start_block(p, done); + + return; } } diff --git a/src/parser.cpp b/src/parser.cpp index 03c5a5962..94f8fd42c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -348,10 +348,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) { n->RangeStmt.body = clone_ast(n->RangeStmt.body, f); break; case Ast_UnrollRangeStmt: - n->UnrollRangeStmt.val0 = clone_ast(n->UnrollRangeStmt.val0, f); - n->UnrollRangeStmt.val1 = clone_ast(n->UnrollRangeStmt.val1, f); - n->UnrollRangeStmt.expr = clone_ast(n->UnrollRangeStmt.expr, f); - n->UnrollRangeStmt.body = clone_ast(n->UnrollRangeStmt.body, f); + n->UnrollRangeStmt.args = clone_ast_array(n->UnrollRangeStmt.args, f); + n->UnrollRangeStmt.val0 = clone_ast(n->UnrollRangeStmt.val0, f); + n->UnrollRangeStmt.val1 = clone_ast(n->UnrollRangeStmt.val1, f); + n->UnrollRangeStmt.expr = clone_ast(n->UnrollRangeStmt.expr, f); + n->UnrollRangeStmt.body = clone_ast(n->UnrollRangeStmt.body, f); break; case Ast_CaseClause: n->CaseClause.list = clone_ast_array(n->CaseClause.list, f); @@ -1037,15 +1038,16 @@ gb_internal Ast *ast_range_stmt(AstFile *f, Token token, Slice vals, Toke return result; } -gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) { +gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Slice args, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) { Ast *result = alloc_ast_node(f, Ast_UnrollRangeStmt); result->UnrollRangeStmt.unroll_token = unroll_token; + result->UnrollRangeStmt.args = args; result->UnrollRangeStmt.for_token = for_token; - result->UnrollRangeStmt.val0 = val0; - result->UnrollRangeStmt.val1 = val1; - result->UnrollRangeStmt.in_token = in_token; - result->UnrollRangeStmt.expr = expr; - result->UnrollRangeStmt.body = body; + result->UnrollRangeStmt.val0 = val0; + result->UnrollRangeStmt.val1 = val1; + result->UnrollRangeStmt.in_token = in_token; + result->UnrollRangeStmt.expr = expr; + result->UnrollRangeStmt.body = body; return result; } @@ -5137,6 +5139,40 @@ gb_internal Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, T gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) { + Array args = {}; + + if (allow_token(f, Token_OpenParen)) { + f->expr_level++; + if (f->curr_token.kind == Token_CloseParen) { + syntax_error(f->curr_token, "#unroll expected at least 1 argument, got 0"); + } else { + args = array_make(ast_allocator(f)); + while (f->curr_token.kind != Token_CloseParen && + f->curr_token.kind != Token_EOF) { + Ast *arg = nullptr; + arg = parse_value(f); + + if (f->curr_token.kind == Token_Eq) { + Token eq = expect_token(f, Token_Eq); + if (arg != nullptr && arg->kind != Ast_Ident) { + syntax_error(arg, "Expected an identifier for 'key=value'"); + } + Ast *value = parse_value(f); + arg = ast_field_value(f, arg, value, eq); + } + + array_add(&args, arg); + + if (!allow_field_separator(f)) { + break; + } + } + } + f->expr_level--; + Token close = expect_closing(f, Token_CloseParen, str_lit("#unroll")); + gb_unused(close); + } + Token for_token = expect_token(f, Token_for); Ast *val0 = nullptr; Ast *val1 = nullptr; @@ -5180,7 +5216,7 @@ gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) { if (bad_stmt) { return ast_bad_stmt(f, unroll_token, f->curr_token); } - return ast_unroll_range_stmt(f, unroll_token, for_token, val0, val1, in_token, expr, body); + return ast_unroll_range_stmt(f, unroll_token, slice_from_array(args), for_token, val0, val1, in_token, expr, body); } gb_internal Ast *parse_stmt(AstFile *f) { diff --git a/src/parser.hpp b/src/parser.hpp index bbf70d03e..d2dd22667 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -563,6 +563,7 @@ AST_KIND(_ComplexStmtBegin, "", bool) \ AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \ Scope *scope; \ Token unroll_token; \ + Slice args; \ Token for_token; \ Ast *val0; \ Ast *val1; \ From ab7b5a5445cf2845437f2840ebac7a111ab0677d Mon Sep 17 00:00:00 2001 From: avanspector Date: Fri, 10 Jan 2025 15:14:03 +0100 Subject: [PATCH 29/31] Haiku: change uintptr to uint where appropriate --- core/sys/haiku/find_directory.odin | 12 ++++----- core/sys/haiku/os.odin | 42 +++++++++++++++--------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/sys/haiku/find_directory.odin b/core/sys/haiku/find_directory.odin index 917394f48..c700bd53b 100644 --- a/core/sys/haiku/find_directory.odin +++ b/core/sys/haiku/find_directory.odin @@ -162,10 +162,10 @@ current_image_symbol :: proc "contextless" () -> rawptr { return rawptr(current_ @(default_calling_convention="c") foreign libroot { find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]byte, length: i32) -> status_t --- - find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- - find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- - find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- - find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uintptr) -> status_t --- - find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uintptr) -> status_t --- - find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uintptr) -> status_t --- + find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- + find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- + find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- + find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- + find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t --- + find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t --- } diff --git a/core/sys/haiku/os.odin b/core/sys/haiku/os.odin index f1127cb69..3edee88b5 100644 --- a/core/sys/haiku/os.odin +++ b/core/sys/haiku/os.odin @@ -19,7 +19,7 @@ OS_NAME_LENGTH :: 32 area_info :: struct { area: area_id, name: [OS_NAME_LENGTH]byte, - size: uintptr, + size: uint, lock: u32, protection: u32, team: team_id, @@ -66,15 +66,15 @@ area_protection_flags :: distinct bit_set[area_protection_flag; u32] @(default_calling_convention="c") foreign libroot { - create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uintptr, lock: area_locking, protection: area_protection_flags) -> area_id --- + create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uint, lock: area_locking, protection: area_protection_flags) -> area_id --- clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id --- find_area :: proc(name: cstring) -> area_id --- area_for :: proc(address: rawptr) -> area_id --- delete_area :: proc(id: area_id) -> status_t --- - resize_area :: proc(id: area_id, newSize: uintptr) -> status_t --- + resize_area :: proc(id: area_id, newSize: uint) -> status_t --- set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t --- - _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uintptr) -> status_t --- - _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uintptr) -> status_t --- + _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uint) -> status_t --- + _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uint) -> status_t --- } // Ports @@ -99,18 +99,18 @@ port_flags :: distinct bit_set[port_flag; u32] foreign libroot { create_port :: proc(capacity: i32, name: cstring) -> port_id --- find_port :: proc(name: cstring) -> port_id --- - read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> int --- - read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> int --- - write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t --- - write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> status_t --- + read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint) -> int --- + read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> int --- + write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t --- + write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> status_t --- close_port :: proc(port: port_id) -> status_t --- delete_port :: proc(port: port_id) -> status_t --- port_buffer_size :: proc(port: port_id) -> int --- port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int --- port_count :: proc(port: port_id) -> int --- set_port_owner :: proc(port: port_id, team: team_id) -> status_t --- - _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- - _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uintptr) -> status_t --- + _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uint) -> status_t --- + _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uint) -> status_t --- } // Semaphores @@ -147,8 +147,8 @@ foreign libroot { switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t --- get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t --- set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t --- - _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uintptr) -> status_t --- - _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uintptr) -> status_t --- + _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uint) -> status_t --- + _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uint) -> status_t --- } // Teams @@ -193,9 +193,9 @@ team_usage_who :: enum i32 { foreign libroot { // see also: send_signal() kill_team :: proc(team: team_id) -> status_t --- - _get_team_info :: proc(id: team_id, info: ^team_info, size: uintptr) -> status_t --- - _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uintptr) -> status_t --- - _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uintptr) -> status_t --- + _get_team_info :: proc(id: team_id, info: ^team_info, size: uint) -> status_t --- + _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uint) -> status_t --- + _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uint) -> status_t --- } // Threads @@ -255,15 +255,15 @@ foreign libroot { wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t --- on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t --- find_thread :: proc(name: cstring) -> thread_id --- - send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t --- - receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uintptr) -> i32 --- + send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t --- + receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uint) -> i32 --- has_data :: proc(thread: thread_id) -> bool --- snooze :: proc(amount: bigtime_t) -> status_t --- // FIXME: Find and define those flags. snooze_etc :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t --- snooze_until :: proc(time: bigtime_t, timeBase: i32) -> status_t --- - _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uintptr) -> status_t --- - _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uintptr) -> status_t --- + _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uint) -> status_t --- + _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uint) -> status_t --- // bridge to the pthread API get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id --- } @@ -474,7 +474,7 @@ when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { @(default_calling_convention="c") foreign libroot { get_system_info :: proc(info: ^system_info) -> status_t --- - _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uintptr) -> status_t --- + _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uint) -> status_t --- get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t --- when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { From e3c0cc9dfc1dccc83d620b75a82008ed7c918273 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 11 Jan 2025 00:18:36 +0100 Subject: [PATCH 30/31] time: add haiku --- core/time/time_other.odin | 1 + core/time/time_unix.odin | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/time/time_other.odin b/core/time/time_other.odin index d89bcbd42..3f0f06e9b 100644 --- a/core/time/time_other.odin +++ b/core/time/time_other.odin @@ -9,6 +9,7 @@ #+build !wasi #+build !windows #+build !orca +#+build !haiku package time _IS_SUPPORTED :: false diff --git a/core/time/time_unix.odin b/core/time/time_unix.odin index 61c4e91d3..c384d6d07 100644 --- a/core/time/time_unix.odin +++ b/core/time/time_unix.odin @@ -1,5 +1,5 @@ #+private -#+build darwin, freebsd, openbsd, netbsd +#+build darwin, freebsd, openbsd, netbsd, haiku package time import "core:sys/posix" From 896319d0d503ae613510d4f8a5374b8ee0b4a2a3 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 11 Jan 2025 00:51:14 +0100 Subject: [PATCH 31/31] ci: test issues on windows --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53600b258..7eef69221 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,6 +208,12 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + - name: Check issues + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + cd tests/issues + call run.bat - name: Check benchmarks shell: cmd run: |