From b396280df76b34bc2d741ded6a72e89d32c70565 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Sun, 25 Aug 2024 03:57:59 -0700 Subject: [PATCH 01/22] add stuff needed for process control --- core/os/os_darwin.odin | 25 ++++++++++++ core/sys/darwin/mach_darwin.odin | 65 ++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 1253e9ae6..69411fdb7 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -9,6 +9,7 @@ import "core:strings" import "core:c" Handle :: distinct i32 +Pid :: distinct i32 File_Time :: distinct u64 INVALID_HANDLE :: ~Handle(0) @@ -584,6 +585,8 @@ F_GETPATH :: 50 // return the full path of the fd foreign libc { @(link_name="__error") __error :: proc() -> ^c.int --- + @(link_name="posix_spawn") _unix_posix_spawn :: proc(pid: ^Pid, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- + @(link_name="open") _unix_open :: proc(path: cstring, flags: i32, #c_vararg mode: ..u16) -> Handle --- @(link_name="close") _unix_close :: proc(handle: Handle) -> c.int --- @(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int --- @@ -677,6 +680,28 @@ get_last_error_string :: proc() -> string { return string(_darwin_string_error(__error()^)) } +posix_spawn :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (Pid, Error) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + path_cstr := strings.clone_to_cstring(path, context.temp_allocator) + + args_cstrs := make([]cstring, len(args) + 2, context.temp_allocator) + args_cstrs[0] = strings.clone_to_cstring(path, context.temp_allocator) + for i := 0; i < len(args); i += 1 { + args_cstrs[i+1] = strings.clone_to_cstring(args[i], context.temp_allocator) + } + + envs_cstrs := make([]cstring, len(envs) + 1, context.temp_allocator) + for i := 0; i < len(envs); i += 1 { + envs_cstrs[i] = strings.clone_to_cstring(envs[i], context.temp_allocator) + } + + child_pid: Pid + status := _unix_posix_spawn(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) + if status != 0 { + return 0, get_last_error() + } + return child_pid, nil +} @(require_results) open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) { diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index ac33ebb62..33f37637d 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -1,6 +1,6 @@ package darwin -foreign import pthread "system:System.framework" +foreign import mach "system:System.framework" import "core:c" @@ -8,15 +8,74 @@ import "core:c" // However all other sync primitives are aligned for robustness. // I cannot currently align these though. // See core/sys/unix/pthread_linux.odin/pthread_t. -task_t :: distinct u64 +mach_port_t :: distinct i32 +task_t :: mach_port_t + semaphore_t :: distinct u64 kern_return_t :: distinct u64 thread_act_t :: distinct u64 +MACH_MSG_PORT_DESCRIPTOR :: 0 + +MACH_SEND_MSG :: 0x00000001 +MACH_RCV_MSG :: 0x00000002 +MACH_SEND_TIMEOUT :: 0x00000010 +MACH_RCV_TIMEOUT :: 0x00000100 + +MACH_MSG_TYPE_COPY_SEND :: 19 +MACH_MSG_TYPE_MAKE_SEND :: 20 +MACH_MSGH_BITS_COMPLEX :: 0x80000000 + +MACH_PORT_RIGHT_SEND :: 0 +MACH_PORT_RIGHT_RECEIVE :: 1 + +TASK_BOOTSTRAP_PORT :: 4 + +mach_msg_option_t :: distinct i32 +name_t :: distinct cstring + +mach_msg_port_descriptor_t :: struct { + name: mach_port_t, + _: u32, + extra: bit_field u32 { + _: u32 | 16, + disposition: u32 | 8, + type: u32 | 8, + }, +} + +mach_msg_header_t :: struct { + msgh_bits: u32, + msgh_size: u32, + msgh_remote_port: mach_port_t, + msgh_local_port: mach_port_t, + msgh_voucher_port: u32, + msgh_id: i32, +} + +mach_msg_body_t :: struct { + msgh_descriptor_count: u32, +} + +mach_msg_trailer_t :: struct { + msgh_trailer_type: u32, + msgh_trailer_size: u32, +} + @(default_calling_convention="c") -foreign pthread { +foreign mach { mach_task_self :: proc() -> task_t --- + mach_msg :: proc(header: rawptr, option: mach_msg_option_t, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- + mach_msg_send :: proc(header: rawptr) -> kern_return_t --- + + mach_port_allocate :: proc(task: task_t, right: u32, name: rawptr) -> kern_return_t --- + mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- + mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> kern_return_t --- + + task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> kern_return_t --- + bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> kern_return_t --- + bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> kern_return_t --- semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy, value: c.int) -> kern_return_t --- semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> kern_return_t --- From 3209b319e85fa943f904d3af8e37c14ba58b6080 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 28 Aug 2024 23:50:17 -0700 Subject: [PATCH 02/22] more useful pieces --- core/sys/darwin/mach_darwin.odin | 80 +++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 33f37637d..1482a93d0 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -13,8 +13,10 @@ task_t :: mach_port_t semaphore_t :: distinct u64 -kern_return_t :: distinct u64 -thread_act_t :: distinct u64 +kern_return_t :: distinct u64 +thread_act_t :: distinct u64 +thread_state_t :: distinct ^u32 +thread_list_t :: [^]thread_act_t MACH_MSG_PORT_DESCRIPTOR :: 0 @@ -30,15 +32,30 @@ MACH_MSGH_BITS_COMPLEX :: 0x80000000 MACH_PORT_RIGHT_SEND :: 0 MACH_PORT_RIGHT_RECEIVE :: 1 +VM_PROT_NONE :: 0 +VM_PROT_READ :: 1 +VM_PROT_WRITE :: 2 +VM_PROT_EXECUTE :: 4 + +VM_INHERIT_SHARE :: 0 +VM_INHERIT_COPY :: 1 +VM_INHERIT_NONE :: 2 +VM_INHERIT_DONATE_COPY :: 3 + TASK_BOOTSTRAP_PORT :: 4 +X86_THREAD_STATE32 :: 1 +X86_THREAD_STATE64 :: 4 +X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32) +X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32) + mach_msg_option_t :: distinct i32 name_t :: distinct cstring mach_msg_port_descriptor_t :: struct { name: mach_port_t, _: u32, - extra: bit_field u32 { + using _: bit_field u32 { _: u32 | 16, disposition: u32 | 8, type: u32 | 8, @@ -63,17 +80,68 @@ mach_msg_trailer_t :: struct { msgh_trailer_size: u32, } +x86_thread_state32_t :: struct { + eax: u32, + ebx: u32, + ecx: u32, + edx: u32, + edi: u32, + esi: u32, + ebp: u32, + esp: u32, + ss: u32, + eflags: u32, + eip: u32, + cs: u32, + ds: u32, + es: u32, + fs: u32, + gs: u32, +} + +x86_thread_state64_t :: struct { + rax: u64, + rbx: u64, + rcx: u64, + rdx: u64, + rdi: u64, + rsi: u64, + rbp: u64, + rsp: u64, + r8: u64, + r9: u64, + r10: u64, + r11: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + rip: u64, + rflags: u64, + cs: u64, + fs: u64, + gs: u64, +} + @(default_calling_convention="c") foreign mach { - mach_task_self :: proc() -> task_t --- - mach_msg :: proc(header: rawptr, option: mach_msg_option_t, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- - mach_msg_send :: proc(header: rawptr) -> kern_return_t --- + mach_task_self :: proc() -> task_t --- + mach_msg :: proc(header: rawptr, option: mach_msg_option_t, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- + mach_msg_send :: proc(header: rawptr) -> kern_return_t --- + mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> kern_return_t --- + mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> kern_return_t --- + mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: i32) -> kern_return_t --- mach_port_allocate :: proc(task: task_t, right: u32, name: rawptr) -> kern_return_t --- mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> kern_return_t --- task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> kern_return_t --- + task_suspend :: proc(task: task_t) -> kern_return_t --- + task_resume :: proc(task: task_t) -> kern_return_t --- + task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> kern_return_t --- + thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> kern_return_t --- + bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> kern_return_t --- bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> kern_return_t --- From c520f029bb4702a3190c92945eef15dd4fca52ba Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 00:54:45 -0700 Subject: [PATCH 03/22] initial posix/spawn --- core/sys/posix/spawn.odin | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 core/sys/posix/spawn.odin diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin new file mode 100644 index 000000000..3ef738b52 --- /dev/null +++ b/core/sys/posix/spawn.odin @@ -0,0 +1,13 @@ +package posix + +import "core:c" + +when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +foreign lib { + posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- +} From 0e344ae2d6b5be224433e82cdb13515e87339097 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 01:54:09 -0700 Subject: [PATCH 04/22] add ARM thread state --- core/sys/darwin/mach_darwin.odin | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 1482a93d0..31aff259c 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -18,6 +18,9 @@ thread_act_t :: distinct u64 thread_state_t :: distinct ^u32 thread_list_t :: [^]thread_act_t +MACH_PORT_NULL :: 0 +MACH_PORT_DEAD :: ~mach_port_t(0) + MACH_MSG_PORT_DESCRIPTOR :: 0 MACH_SEND_MSG :: 0x00000001 @@ -44,10 +47,12 @@ VM_INHERIT_DONATE_COPY :: 3 TASK_BOOTSTRAP_PORT :: 4 +BOOTSTRAP_NAME_IN_USE :: 1101 + X86_THREAD_STATE32 :: 1 X86_THREAD_STATE64 :: 4 -X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32) -X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32) +ARM_THREAD_STATE64 :: 6 + mach_msg_option_t :: distinct i32 name_t :: distinct cstring @@ -98,6 +103,7 @@ x86_thread_state32_t :: struct { fs: u32, gs: u32, } +X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32) x86_thread_state64_t :: struct { rax: u64, @@ -122,6 +128,18 @@ x86_thread_state64_t :: struct { fs: u64, gs: u64, } +X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32) + +arm_thread_state64_t :: struct { + x: [29]u64, + fp: u64, + lr: u64, + sp: u64, + pc: u64, + cpsr: u32, + pad: u32, +} +ARM_THREAD_STATE64_COUNT :: size_of(arm_thread_state64_t) / size_of(u32) @(default_calling_convention="c") foreign mach { From d026ac2df24bc8c4fe2c8e418d028b9ecebef845 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 11:41:36 -0700 Subject: [PATCH 05/22] add thread-info and memmap-info --- core/sys/darwin/mach_darwin.odin | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 31aff259c..2bcb12cbb 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -17,6 +17,7 @@ kern_return_t :: distinct u64 thread_act_t :: distinct u64 thread_state_t :: distinct ^u32 thread_list_t :: [^]thread_act_t +vm_region_recurse_info_t :: distinct ^i32 MACH_PORT_NULL :: 0 MACH_PORT_DEAD :: ~mach_port_t(0) @@ -141,6 +142,36 @@ arm_thread_state64_t :: struct { } ARM_THREAD_STATE64_COUNT :: size_of(arm_thread_state64_t) / size_of(u32) +THREAD_IDENTIFIER_INFO :: 4 +thread_identifier_info :: struct { + thread_id: u64, + thread_handler: u64, + dispatch_qaddr: u64, +} +THREAD_IDENTIFIER_INFO_COUNT :: size_of(thread_identifier_info) / size_of(u32) + +vm_region_submap_info_64 :: struct { + protection: u32, + max_protection: u32, + inheritance: u32, + offset: u64, + user_tag: u32, + pages_residept: u32, + pages_shared_now_private: u32, + pages_swapped_out: u32, + pages_dirtied: u32, + ref_count: u32, + shadow_depth: u16, + external_pager: u8, + share_mode: u8, + is_submap: b32, + behavior: i32, + object_id: u32, + user_wired_count: u16, + pages_reusable: u32, +} +VM_REGION_SUBMAP_INFO_COUNT_64 :: size_of(vm_region_submap_info_64) / size_of(u32) + @(default_calling_convention="c") foreign mach { mach_task_self :: proc() -> task_t --- @@ -149,6 +180,7 @@ foreign mach { mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> kern_return_t --- mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> kern_return_t --- mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: i32) -> kern_return_t --- + mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> kern_return_t --- mach_port_allocate :: proc(task: task_t, right: u32, name: rawptr) -> kern_return_t --- mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- @@ -158,7 +190,9 @@ foreign mach { task_suspend :: proc(task: task_t) -> kern_return_t --- task_resume :: proc(task: task_t) -> kern_return_t --- task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> kern_return_t --- + thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> kern_return_t --- + thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> kern_return_t --- bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> kern_return_t --- bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> kern_return_t --- From cc6e1bdcd6b638c0379079e293dc3381d772b666 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 12:02:54 -0700 Subject: [PATCH 06/22] add more dyld info collect --- core/sys/darwin/mach_darwin.odin | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 2bcb12cbb..47bc97c9b 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -18,6 +18,7 @@ thread_act_t :: distinct u64 thread_state_t :: distinct ^u32 thread_list_t :: [^]thread_act_t vm_region_recurse_info_t :: distinct ^i32 +task_info_t :: distinct ^i32 MACH_PORT_NULL :: 0 MACH_PORT_DEAD :: ~mach_port_t(0) @@ -54,6 +55,7 @@ X86_THREAD_STATE32 :: 1 X86_THREAD_STATE64 :: 4 ARM_THREAD_STATE64 :: 6 +TASK_DYLD_INFO :: 17 mach_msg_option_t :: distinct i32 name_t :: distinct cstring @@ -172,6 +174,14 @@ vm_region_submap_info_64 :: struct { } VM_REGION_SUBMAP_INFO_COUNT_64 :: size_of(vm_region_submap_info_64) / size_of(u32) +TASK_DYLD_INFO :: 17 +task_dyld_info :: struct { + all_image_info_addr: u64, + all_image_info_size: u64, + all_image_info_format: i32, +} +TASK_DYLD_INFO_COUNT :: size_of(task_dyld_info) / size_of(u32) + @(default_calling_convention="c") foreign mach { mach_task_self :: proc() -> task_t --- @@ -190,6 +200,7 @@ foreign mach { task_suspend :: proc(task: task_t) -> kern_return_t --- task_resume :: proc(task: task_t) -> kern_return_t --- task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> kern_return_t --- + task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> kern_return_t --- thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> kern_return_t --- thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> kern_return_t --- From 06bc3b2a3667360faa79c2b1f9008cdddb73b23b Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 13:41:53 -0700 Subject: [PATCH 07/22] oops, duplicate const --- core/sys/darwin/mach_darwin.odin | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 47bc97c9b..42c8c6bc1 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -55,8 +55,6 @@ X86_THREAD_STATE32 :: 1 X86_THREAD_STATE64 :: 4 ARM_THREAD_STATE64 :: 6 -TASK_DYLD_INFO :: 17 - mach_msg_option_t :: distinct i32 name_t :: distinct cstring From 2119062a5a8d35ac77dfc931a59e7254859681cb Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 29 Aug 2024 17:00:02 -0700 Subject: [PATCH 08/22] add more dyld support --- core/sys/darwin/mach_darwin.odin | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 42c8c6bc1..bbaa290e6 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -180,6 +180,59 @@ task_dyld_info :: struct { } TASK_DYLD_INFO_COUNT :: size_of(task_dyld_info) / size_of(u32) +dyld_image_info :: struct { + image_load_addr: u64, + image_file_path: cstring, + image_file_mod_date: u64, +} + +dyld_uuid_info :: struct { + image_load_addr: u64, + image_uuid: [16]u8, +} + +dyld_all_image_infos :: struct { + version: u32, + info_array_count: u32, + info_array: rawptr, + notification: rawptr, + process_detached_from_shared_region: b32, + libSystem_initialized: b32, + dyld_image_load_addr: u64, + jit_info: rawptr, + dyld_version: cstring, + error_message: cstring, + termination_flags: u64, + core_symbolication_shm_page: rawptr, + system_order_flag: u64, + uuid_array_count: u64, + uuid_array: rawptr, + dyld_all_image_infos_addr: u64, + initial_image_count: u64, + error_kind: u64, + error_client_of_dylib_path: cstring, + error_target_dylib_path: cstring, + error_symbol: cstring, + shared_cache_slide: u64, + shared_cache_uuid: [16]u8, + shared_cache_base_addr: u64, + info_array_change_timestamp: u64, + dyld_path: cstring, + notify_ports: [8]mach_port_t, + reserved: [7]u64, + shared_cache_fsid: u64, + shared_cache_fsobjid: u64, + compact_dyld_image_info_addr: u64, + compact_dyld_image_info_size: u64, + platform: u32, + aot_info_count: u32, + aot_info_array: rawptr, + aot_info_array_change_timestamp: u64, + aot_shared_cache_base_address: u64, + aot_shared_cache_uuid: [16]u8, +} + + @(default_calling_convention="c") foreign mach { mach_task_self :: proc() -> task_t --- @@ -189,6 +242,9 @@ foreign mach { mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> kern_return_t --- mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: i32) -> kern_return_t --- mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> kern_return_t --- + vm_page_size: u64 + vm_page_mask: u64 + vm_page_shift: i32 mach_port_allocate :: proc(task: task_t, right: u32, name: rawptr) -> kern_return_t --- mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- @@ -215,3 +271,7 @@ foreign mach { semaphore_wait :: proc(semaphore: semaphore_t) -> kern_return_t --- } + +mach_vm_trunc_page :: proc(v: u64) -> u64 { + return v & ~vm_page_mask +} From 99938c7d4fb26d43a07dd4b8f4f00ab87e67e73f Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 24 Sep 2024 02:31:44 -0700 Subject: [PATCH 09/22] spawn tweaks --- core/os/os_darwin.odin | 22 ++++++++++++++++------ core/sys/darwin/mach_darwin.odin | 1 + core/sys/posix/spawn.odin | 1 + 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 69411fdb7..f694dd588 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -7,6 +7,7 @@ foreign import pthread "system:System.framework" import "base:runtime" import "core:strings" import "core:c" +import "core:sys/posix" Handle :: distinct i32 Pid :: distinct i32 @@ -585,8 +586,6 @@ F_GETPATH :: 50 // return the full path of the fd foreign libc { @(link_name="__error") __error :: proc() -> ^c.int --- - @(link_name="posix_spawn") _unix_posix_spawn :: proc(pid: ^Pid, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- - @(link_name="open") _unix_open :: proc(path: cstring, flags: i32, #c_vararg mode: ..u16) -> Handle --- @(link_name="close") _unix_close :: proc(handle: Handle) -> c.int --- @(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int --- @@ -680,7 +679,7 @@ get_last_error_string :: proc() -> string { return string(_darwin_string_error(__error()^)) } -posix_spawn :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (Pid, Error) { +_spawn :: #force_inline proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr, is_spawnp: bool) -> (posix.pid_t, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() path_cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -695,13 +694,24 @@ posix_spawn :: proc(path: string, args: []string, envs: []string, file_actions: envs_cstrs[i] = strings.clone_to_cstring(envs[i], context.temp_allocator) } - child_pid: Pid - status := _unix_posix_spawn(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) + child_pid: posix.pid_t + status: i32 + if is_spawnp { + status = posix.posix_spawnp(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) + } else { + status = posix.posix_spawn(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) + } if status != 0 { - return 0, get_last_error() + return 0, Platform_Error(status) } return child_pid, nil } +spawn :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (posix.pid_t, Error) { + return _spawn(path, args, envs, file_actions, attributes, false) +} +spawnp :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (posix.pid_t, Error) { + return _spawn(path, args, envs, file_actions, attributes, true) +} @(require_results) open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) { diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index bbaa290e6..1e728fe78 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -255,6 +255,7 @@ foreign mach { task_resume :: proc(task: task_t) -> kern_return_t --- task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> kern_return_t --- task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> kern_return_t --- + task_terminate :: proc(task: task_t) -> kern_return_t --- thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> kern_return_t --- thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> kern_return_t --- diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin index 3ef738b52..154509160 100644 --- a/core/sys/posix/spawn.odin +++ b/core/sys/posix/spawn.odin @@ -10,4 +10,5 @@ when ODIN_OS == .Darwin { foreign lib { posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- + posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- } From b1ed22d84f2aae617c90c60701e9f25345cab980 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Sun, 8 Jun 2025 16:16:34 -0700 Subject: [PATCH 10/22] fix frequency grab --- core/sys/darwin/mach_darwin.odin | 4 ++-- core/time/tsc_darwin.odin | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 01affa6e8..2c8f38002 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -123,7 +123,7 @@ x86_thread_state32_t :: struct { } X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32) -x86_thread_state64_t :: struct { +x86_thread_state64_t :: struct #packed { rax: u64, rbx: u64, rcx: u64, @@ -148,7 +148,7 @@ x86_thread_state64_t :: struct { } X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32) -arm_thread_state64_t :: struct { +arm_thread_state64_t :: struct #packed { x: [29]u64, fp: u64, lr: u64, diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin index 3726cff49..1210992a6 100644 --- a/core/time/tsc_darwin.odin +++ b/core/time/tsc_darwin.odin @@ -4,7 +4,13 @@ package time import "core:sys/unix" _get_tsc_frequency :: proc "contextless" () -> (freq: u64, ok: bool) { - unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return + if ODIN_ARCH == .amd64 { + unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return + } else if ODIN_ARCH == .arm64 { + unix.sysctlbyname("hw.tbfrequency", &freq) or_return + } else { + return + } ok = true return } From 2dae1d8a4134226887a6e6a0aad0318e46e40cde Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Mon, 7 Jul 2025 14:36:31 -0700 Subject: [PATCH 11/22] fix tabbing --- core/sys/darwin/mach_darwin.odin | 4 ---- core/time/tsc_darwin.odin | 14 +++++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 2c8f38002..b66b90325 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -5,10 +5,6 @@ foreign import mach "system:System.framework" import "core:c" import "base:intrinsics" -// NOTE(tetra): Unclear whether these should be aligned 16 or not. -// However all other sync primitives are aligned for robustness. -// I cannot currently align these though. -// See core/sys/unix/pthread_linux.odin/pthread_t. mach_port_t :: distinct c.uint task_t :: mach_port_t diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin index 1210992a6..fdda5db77 100644 --- a/core/time/tsc_darwin.odin +++ b/core/time/tsc_darwin.odin @@ -4,13 +4,13 @@ package time import "core:sys/unix" _get_tsc_frequency :: proc "contextless" () -> (freq: u64, ok: bool) { - if ODIN_ARCH == .amd64 { - unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return - } else if ODIN_ARCH == .arm64 { - unix.sysctlbyname("hw.tbfrequency", &freq) or_return - } else { - return - } + if ODIN_ARCH == .amd64 { + unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return + } else if ODIN_ARCH == .arm64 { + unix.sysctlbyname("hw.tbfrequency", &freq) or_return + } else { + return + } ok = true return } From 1848e0df05a14679d49e5b87988fa6c7b609739b Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Mon, 28 Jul 2025 15:10:42 -0700 Subject: [PATCH 12/22] use the correct frequency for the arm tsc timer --- base/intrinsics/intrinsics.odin | 3 +++ core/time/tsc_darwin.odin | 3 ++- src/check_builtin.cpp | 1 + src/checker_builtin_procs.hpp | 3 +++ src/llvm_backend_proc.cpp | 13 +++++++++++++ 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 7e45abb8f..7057aba84 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -361,6 +361,9 @@ wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_u x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) --- x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- +// Arm64 targets +arm64_read_cycle_counter_frequency :: proc() -> i64 --- + // Darwin targets only objc_object :: struct{} diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin index fdda5db77..55abf5868 100644 --- a/core/time/tsc_darwin.odin +++ b/core/time/tsc_darwin.odin @@ -1,13 +1,14 @@ #+private package time +import "base:intrinsics" import "core:sys/unix" _get_tsc_frequency :: proc "contextless" () -> (freq: u64, ok: bool) { if ODIN_ARCH == .amd64 { unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return } else if ODIN_ARCH == .arm64 { - unix.sysctlbyname("hw.tbfrequency", &freq) or_return + freq = u64(intrinsics.arm64_read_cycle_counter_frequency()) } else { return } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 58fa44ec9..e9da79932 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4713,6 +4713,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } break; + case BuiltinProc_arm64_read_cycle_counter_frequency: case BuiltinProc_read_cycle_counter: operand->mode = Addressing_Value; operand->type = t_i64; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 91cef481e..474932970 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -225,6 +225,8 @@ BuiltinProc__simd_end, BuiltinProc_x86_cpuid, BuiltinProc_x86_xgetbv, + BuiltinProc_arm64_read_cycle_counter_frequency, + // Constant type tests BuiltinProc__type_begin, @@ -584,6 +586,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("syscall_bsd"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("x86_cpuid"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("x86_xgetbv"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("arm64_read_cycle_counter_frequency"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index ffa434278..3f5819b43 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2809,6 +2809,19 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } return res; } + case BuiltinProc_arm64_read_cycle_counter_frequency: + { + lbValue res = {}; + res.type = tv.type; + + LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false); + bool has_side_effects = false; + LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs $0, cntfrq_el0"), str_lit("=r"), has_side_effects); + GB_ASSERT(the_asm != nullptr); + res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); + + return res; + } case BuiltinProc_count_trailing_zeros: return lb_emit_count_trailing_zeros(p, lb_build_expr(p, ce->args[0]), tv.type); From 76b00c046b3c58670c60badbf5f15a66cbe25f85 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Mon, 28 Jul 2025 15:30:24 -0700 Subject: [PATCH 13/22] arm64 has an invariant tsc too --- core/time/perf.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/time/perf.odin b/core/time/perf.odin index 265a20edf..f4e1b4aa8 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -104,6 +104,8 @@ TSC at a fixed frequency, independent of ACPI state, and CPU frequency. has_invariant_tsc :: proc "contextless" () -> bool { when ODIN_ARCH == .amd64 { return x86_has_invariant_tsc() + } else when ODIN_ARCH == .arm64 { + return true } return false From 1a9b128bfc4edff7b2651d68d1d350ec39b7e3a5 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Mon, 28 Jul 2025 16:32:10 -0700 Subject: [PATCH 14/22] update linux-arm to use the asm intrin for freq --- core/time/tsc_linux.odin | 53 ++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index a83634414..92712f136 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -5,29 +5,34 @@ package time import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { - // Get the file descriptor for the perf mapping - perf_attr := linux.Perf_Event_Attr{} - perf_attr.size = size_of(perf_attr) - perf_attr.type = .HARDWARE - perf_attr.config.hw = .INSTRUCTIONS - perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV} - fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {}) - if perf_errno != nil { - return 0, false + if ODIN_ARCH == .arm64 { + freq = u64(intrinsics.arm64_read_cycle_counter_frequency()) + return frequency, true + } else { + // Get the file descriptor for the perf mapping + perf_attr := linux.Perf_Event_Attr{} + perf_attr.size = size_of(perf_attr) + perf_attr.type = .HARDWARE + perf_attr.config.hw = .INSTRUCTIONS + perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV} + fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {}) + if perf_errno != nil { + return 0, false + } + defer linux.close(fd) + // Map it into the memory + page_size : uint = 4096 + addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd) + if mmap_errno != nil { + return 0, false + } + defer linux.munmap(addr, page_size) + // Get the frequency from the mapped page + event_page := cast(^linux.Perf_Event_Mmap_Page) addr + if .User_Time not_in event_page.cap.flags { + return 0, false + } + frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult)) + return frequency, true } - defer linux.close(fd) - // Map it into the memory - page_size : uint = 4096 - addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd) - if mmap_errno != nil { - return 0, false - } - defer linux.munmap(addr, page_size) - // Get the frequency from the mapped page - event_page := cast(^linux.Perf_Event_Mmap_Page) addr - if .User_Time not_in event_page.cap.flags { - return 0, false - } - frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult)) - return frequency, true } From b5629aeed9eea4daadacad8b174947a17a11670b Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Mon, 28 Jul 2025 16:34:53 -0700 Subject: [PATCH 15/22] copy-paste typo fix --- core/time/tsc_linux.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index 92712f136..b9381dba2 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -6,7 +6,7 @@ import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { if ODIN_ARCH == .arm64 { - freq = u64(intrinsics.arm64_read_cycle_counter_frequency()) + frequency := u64(intrinsics.arm64_read_cycle_counter_frequency()) return frequency, true } else { // Get the file descriptor for the perf mapping From fe2b48dec4ba99239a6f8fe9944b1545aac9a355 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 11:48:58 -0700 Subject: [PATCH 16/22] enum pass --- core/os/os_darwin.odin | 4 +- core/sys/darwin/mach_darwin.odin | 135 +++++++++++++++++++++++++------ core/sys/posix/spawn.odin | 6 +- core/time/tsc_linux.odin | 1 + 4 files changed, 115 insertions(+), 31 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 3c12e8c7f..a27add029 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -695,13 +695,13 @@ _spawn :: #force_inline proc(path: string, args: []string, envs: []string, file_ } child_pid: posix.pid_t - status: i32 + status: posix.Errno if is_spawnp { status = posix.posix_spawnp(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) } else { status = posix.posix_spawn(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) } - if status != 0 { + if status != .NONE { return 0, Platform_Error(status) } return child_pid, nil diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index ce8594a6c..2e57bc1c9 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -22,27 +22,6 @@ MACH_PORT_DEAD :: ~mach_port_t(0) MACH_MSG_PORT_DESCRIPTOR :: 0 -MACH_SEND_MSG :: 0x00000001 -MACH_RCV_MSG :: 0x00000002 -MACH_SEND_TIMEOUT :: 0x00000010 -MACH_RCV_TIMEOUT :: 0x00000100 - -MACH_MSG_TYPE_COPY_SEND :: 19 -MACH_MSG_TYPE_MAKE_SEND :: 20 -MACH_MSGH_BITS_COMPLEX :: 0x80000000 - -MACH_PORT_RIGHT_SEND :: 0 -MACH_PORT_RIGHT_RECEIVE :: 1 - -VM_INHERIT_SHARE :: 0 -VM_INHERIT_COPY :: 1 -VM_INHERIT_NONE :: 2 -VM_INHERIT_DONATE_COPY :: 3 - -TASK_BOOTSTRAP_PORT :: 4 - -BOOTSTRAP_NAME_IN_USE :: 1101 - X86_THREAD_STATE32 :: 1 X86_THREAD_STATE64 :: 4 ARM_THREAD_STATE64 :: 6 @@ -69,6 +48,8 @@ vm_inherit_t :: distinct c.uint mach_port_name_t :: distinct c.uint +mach_port_right_t :: distinct c.uint + sync_policy_t :: distinct c.int mach_msg_port_descriptor_t :: struct { @@ -81,6 +62,77 @@ mach_msg_port_descriptor_t :: struct { }, } +Task_Port_Type :: enum u32 { + Kernel = 1, + Host, + Name, + Bootstrap, + Seatbelt = 7, + Access = 9, +} + +Bootstrap_Error :: enum u32 { + Success, + Not_Privileged = 1100, + Name_In_Use = 1101, + Unknown_Service = 1102, + Service_Active = 1103, + Bad_Count = 1104, + No_Memory = 1105, + No_Children = 1106, +} + +Msg_Type :: enum u32 { + Unstructured = 0, + Bit = 0, + Boolean = 0, + Integer_16 = 1, + Integer_32 = 2, + Char = 8, + Byte = 9, + Integer_8 = 9, + Real = 10, + Integer_64 = 11, + String = 12, + String_C = 12, + + Port_Name = 15, + + Move_Receive = 16, + Port_Receive = 16, + Move_Send = 17, + Port_Send = 17, + Move_Send_Once = 18, + Port_Send_Once = 18, + Copy_Send = 19, + Make_Send = 20, + Make_Send_Once = 21, +} + +Msg_Header_Bits :: enum u32 { + Zero = 0, + Remote_Mask = 0xff, + Local_Mask = 0xff00, + Migrated = 0x08000000, + Unused = 0x07ff0000, + Complex_Data = 0x10000000, + Complex_Ports = 0x20000000, + Circular = 0x40000000, + Complex = 0x80000000, +} + +mach_msg_type_t :: struct { + using _: bit_field u32 { + name: u32 | 8, + size: u32 | 8, + number: u32 | 12, + inline: u32 | 1, + longform: u32 | 1, + deallocate: u32 | 1, + unused: u32 | 1, + }, +} + mach_msg_header_t :: struct { msgh_bits: u32, msgh_size: u32, @@ -248,18 +300,18 @@ dyld_all_image_infos :: struct { @(default_calling_convention="c") foreign mach { - mach_task_self :: proc() -> task_t --- - mach_msg :: proc(header: rawptr, option: mach_msg_option_t, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- + mach_task_self :: proc() -> mach_port_t --- + mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- mach_msg_send :: proc(header: rawptr) -> kern_return_t --- mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> kern_return_t --- mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> kern_return_t --- - mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: i32) -> kern_return_t --- + mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> kern_return_t --- mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> kern_return_t --- vm_page_size: u64 vm_page_mask: u64 vm_page_shift: i32 - mach_port_allocate :: proc(task: task_t, right: u32, name: rawptr) -> kern_return_t --- + mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> kern_return_t --- mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> kern_return_t --- @@ -732,6 +784,39 @@ VM_PROT_NONE :: VM_Prot_Flags{} VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write} VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute} +/* + * Mach msg options, defined as bits within the mach_msg_option_t type + */ + +Msg_Option :: enum mach_msg_option_t { + Send_Msg, + Receive_Msg, + + Send_Timeout = LOG2(0x10), + Send_Notify = LOG2(0x20), + Send_Interrupt = LOG2(0x40), + Send_Cancel = LOG2(0x80), + Receive_Timeout = LOG2(0x100), + Receive_Notify = LOG2(0x200), + Receive_Interrupt = LOG2(0x400), + Receive_Large = LOG2(0x800), + Send_Always = LOG2(0x10000), +} + +Msg_Option_Flags :: distinct bit_set[Msg_Option; mach_msg_option_t] + +/* + * Enumeration of valid values for mach_port_right_t + */ + +Port_Right :: enum mach_port_right_t { + Send, + Receive, + Send_Once, + Port_Set, + Dead_Name, +} + /* * Enumeration of valid values for vm_inherit_t. */ diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin index 154509160..8933915be 100644 --- a/core/sys/posix/spawn.odin +++ b/core/sys/posix/spawn.odin @@ -1,7 +1,5 @@ package posix -import "core:c" - when ODIN_OS == .Darwin { foreign import lib "system:System.framework" } else { @@ -9,6 +7,6 @@ when ODIN_OS == .Darwin { } foreign lib { - posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- - posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> c.int --- + posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- + posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- } diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index b9381dba2..bfae79fb4 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -2,6 +2,7 @@ #+build linux package time +import "base:intrinsics" import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { From 0a102bd757fb0a5871a00a28db6d46cf025bb8d0 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 11:52:58 -0700 Subject: [PATCH 17/22] shuffle to Kern_Return --- core/sys/darwin/mach_darwin.odin | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 2e57bc1c9..19515fe87 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -301,26 +301,26 @@ dyld_all_image_infos :: struct { @(default_calling_convention="c") foreign mach { mach_task_self :: proc() -> mach_port_t --- - mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> kern_return_t --- - mach_msg_send :: proc(header: rawptr) -> kern_return_t --- - mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> kern_return_t --- - mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> kern_return_t --- - mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> kern_return_t --- - mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> kern_return_t --- + mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> Kern_Return --- + mach_msg_send :: proc(header: rawptr) -> Kern_Return --- + mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> Kern_Return --- + mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> Kern_Return --- + mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> Kern_Return --- + mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> Kern_Return --- vm_page_size: u64 vm_page_mask: u64 vm_page_shift: i32 - mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> kern_return_t --- - mach_port_deallocate :: proc(task: task_t, name: u32) -> kern_return_t --- - mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> kern_return_t --- + mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> Kern_Return --- + mach_port_deallocate :: proc(task: task_t, name: u32) -> Kern_Return --- + mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> Kern_Return --- - task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> kern_return_t --- - task_suspend :: proc(task: task_t) -> kern_return_t --- - task_resume :: proc(task: task_t) -> kern_return_t --- - task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> kern_return_t --- - task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> kern_return_t --- - task_terminate :: proc(task: task_t) -> kern_return_t --- + task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> Kern_Return --- + task_suspend :: proc(task: task_t) -> Kern_Return --- + task_resume :: proc(task: task_t) -> Kern_Return --- + task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> Kern_Return --- + task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> Kern_Return --- + task_terminate :: proc(task: task_t) -> Kern_Return --- semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return --- semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return --- @@ -331,11 +331,11 @@ foreign mach { semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return --- - thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> kern_return_t --- - thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> kern_return_t --- + thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> Kern_Return --- + thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> Kern_Return --- - bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> kern_return_t --- - bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> kern_return_t --- + bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> Kern_Return --- + bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> Kern_Return --- vm_map :: proc( target_task: vm_map_t, From c1b3d035e4be4bdbebb397035a95e6dbc60f1bd6 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 12:12:15 -0700 Subject: [PATCH 18/22] remove spawn from os, comment sys/posix/spawn --- core/os/os_darwin.odin | 35 ----------------------------------- core/sys/posix/spawn.odin | 8 ++++++++ 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index a27add029..1010d27a8 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -7,10 +7,8 @@ foreign import pthread "system:System" import "base:runtime" import "core:strings" import "core:c" -import "core:sys/posix" Handle :: distinct i32 -Pid :: distinct i32 File_Time :: distinct u64 INVALID_HANDLE :: ~Handle(0) @@ -679,39 +677,6 @@ get_last_error_string :: proc() -> string { return string(_darwin_string_error(__error()^)) } -_spawn :: #force_inline proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr, is_spawnp: bool) -> (posix.pid_t, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - path_cstr := strings.clone_to_cstring(path, context.temp_allocator) - - args_cstrs := make([]cstring, len(args) + 2, context.temp_allocator) - args_cstrs[0] = strings.clone_to_cstring(path, context.temp_allocator) - for i := 0; i < len(args); i += 1 { - args_cstrs[i+1] = strings.clone_to_cstring(args[i], context.temp_allocator) - } - - envs_cstrs := make([]cstring, len(envs) + 1, context.temp_allocator) - for i := 0; i < len(envs); i += 1 { - envs_cstrs[i] = strings.clone_to_cstring(envs[i], context.temp_allocator) - } - - child_pid: posix.pid_t - status: posix.Errno - if is_spawnp { - status = posix.posix_spawnp(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) - } else { - status = posix.posix_spawn(&child_pid, path_cstr, file_actions, attributes, raw_data(args_cstrs), raw_data(envs_cstrs)) - } - if status != .NONE { - return 0, Platform_Error(status) - } - return child_pid, nil -} -spawn :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (posix.pid_t, Error) { - return _spawn(path, args, envs, file_actions, attributes, false) -} -spawnp :: proc(path: string, args: []string, envs: []string, file_actions: rawptr, attributes: rawptr) -> (posix.pid_t, Error) { - return _spawn(path, args, envs, file_actions, attributes, true) -} @(require_results) open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (handle: Handle, err: Error) { diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin index 8933915be..584201bcf 100644 --- a/core/sys/posix/spawn.odin +++ b/core/sys/posix/spawn.odin @@ -7,6 +7,14 @@ when ODIN_OS == .Darwin { } foreign lib { + /* + Creates a child process from a provided filepath + spawnp searches directories on the path for the file + + Returns: 0 on success, with the child pid returned in the pid argument, or error values on failure. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html ]] + */ posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- } From 9a2e6fff481968f201e6bf6a601ab7a4e3fbef45 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 12:21:46 -0700 Subject: [PATCH 19/22] switch to read_cycle_counter_frequency from arm64_read_cycle_counter_freq, trap on invalid arch --- base/intrinsics/intrinsics.odin | 3 +-- core/time/tsc_darwin.odin | 2 +- core/time/tsc_linux.odin | 2 +- src/check_builtin.cpp | 2 +- src/checker_builtin_procs.hpp | 4 ++-- src/llvm_backend_proc.cpp | 16 ++++++++++------ 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 7057aba84..be75739fe 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -32,6 +32,7 @@ trap :: proc() -> ! --- alloca :: proc(size, align: int) -> [^]u8 --- cpu_relax :: proc() --- read_cycle_counter :: proc() -> i64 --- +read_cycle_counter_frequency :: proc() -> i64 --- count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- @@ -361,8 +362,6 @@ wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_u x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) --- x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- -// Arm64 targets -arm64_read_cycle_counter_frequency :: proc() -> i64 --- // Darwin targets only diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin index 55abf5868..78d5b33f8 100644 --- a/core/time/tsc_darwin.odin +++ b/core/time/tsc_darwin.odin @@ -8,7 +8,7 @@ _get_tsc_frequency :: proc "contextless" () -> (freq: u64, ok: bool) { if ODIN_ARCH == .amd64 { unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return } else if ODIN_ARCH == .arm64 { - freq = u64(intrinsics.arm64_read_cycle_counter_frequency()) + freq = u64(intrinsics.read_cycle_counter_frequency()) } else { return } diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index bfae79fb4..7232e0631 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -7,7 +7,7 @@ import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { if ODIN_ARCH == .arm64 { - frequency := u64(intrinsics.arm64_read_cycle_counter_frequency()) + frequency := u64(intrinsics.read_cycle_counter_frequency()) return frequency, true } else { // Get the file descriptor for the perf mapping diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index e9da79932..66be3c69e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4713,7 +4713,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } break; - case BuiltinProc_arm64_read_cycle_counter_frequency: + case BuiltinProc_read_cycle_counter_frequency: case BuiltinProc_read_cycle_counter: operand->mode = Addressing_Value; operand->type = t_i64; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 474932970..8e135ab10 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -61,6 +61,7 @@ enum BuiltinProcId { BuiltinProc_trap, BuiltinProc_debug_trap, BuiltinProc_read_cycle_counter, + BuiltinProc_read_cycle_counter_frequency, BuiltinProc_count_ones, BuiltinProc_count_zeros, @@ -225,7 +226,6 @@ BuiltinProc__simd_end, BuiltinProc_x86_cpuid, BuiltinProc_x86_xgetbv, - BuiltinProc_arm64_read_cycle_counter_frequency, // Constant type tests @@ -423,6 +423,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("trap"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics, /*diverging*/true}, {STR_LIT("debug_trap"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics, /*diverging*/false}, {STR_LIT("read_cycle_counter"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("read_cycle_counter_frequency"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_ones"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -586,7 +587,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("syscall_bsd"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("x86_cpuid"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("x86_xgetbv"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("arm64_read_cycle_counter_frequency"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 3f5819b43..5e38e6bdc 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2809,16 +2809,20 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } return res; } - case BuiltinProc_arm64_read_cycle_counter_frequency: + case BuiltinProc_read_cycle_counter_frequency: { lbValue res = {}; res.type = tv.type; - LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false); - bool has_side_effects = false; - LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs $0, cntfrq_el0"), str_lit("=r"), has_side_effects); - GB_ASSERT(the_asm != nullptr); - res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); + if (build_context.metrics.arch == TargetArch_arm64) { + LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false); + bool has_side_effects = false; + LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs $0, cntfrq_el0"), str_lit("=r"), has_side_effects); + GB_ASSERT(the_asm != nullptr); + res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); + } else { + GB_PANIC("Unsupported architecture: %.*s", LIT(target_arch_names[build_context.metrics.arch])); + } return res; } From 4d9fdf5bd381c21ae68e08e52a0d98729a390cfe Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 13:09:05 -0700 Subject: [PATCH 20/22] move to checker error, rather than panic --- src/check_builtin.cpp | 8 ++++++++ src/llvm_backend_proc.cpp | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 66be3c69e..974224ed2 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4714,6 +4714,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; case BuiltinProc_read_cycle_counter_frequency: + if (build_context.metrics.arch != TargetArch_arm64) { + error(call, "'%.*s' is only allowed on arm64 targets", LIT(builtin_name)); + return false; + } + operand->mode = Addressing_Value; + operand->type = t_i64; + break; + case BuiltinProc_read_cycle_counter: operand->mode = Addressing_Value; operand->type = t_i64; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 5e38e6bdc..d89720e0d 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2820,8 +2820,6 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs $0, cntfrq_el0"), str_lit("=r"), has_side_effects); GB_ASSERT(the_asm != nullptr); res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); - } else { - GB_PANIC("Unsupported architecture: %.*s", LIT(target_arch_names[build_context.metrics.arch])); } return res; From 517e392abedcdb3ac76fbbf737318b65e855e0c5 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 13:18:40 -0700 Subject: [PATCH 21/22] if -> when --- core/time/tsc_linux.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index 7232e0631..5b4c1c2c2 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -6,7 +6,7 @@ import "base:intrinsics" import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { - if ODIN_ARCH == .arm64 { + when ODIN_ARCH == .arm64 { frequency := u64(intrinsics.read_cycle_counter_frequency()) return frequency, true } else { From 35a95fc3e4c67dcf32462c112675699673c037f2 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Tue, 29 Jul 2025 13:28:04 -0700 Subject: [PATCH 22/22] workaround to avoid excessive file-splitting --- core/time/tsc_linux.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index 5b4c1c2c2..f59a0338b 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -3,7 +3,7 @@ package time import "base:intrinsics" -import linux "core:sys/linux" +@(require) import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { when ODIN_ARCH == .arm64 {