os2: process API for Darwin and most of it for BSDs

This commit is contained in:
Laytan Laats
2024-08-22 23:07:24 +02:00
parent b9043db434
commit a66520ba57
6 changed files with 587 additions and 121 deletions
+44 -20
View File
@@ -8,6 +8,7 @@ import "core:bytes"
import "core:sys/darwin"
import "core:sys/posix"
import "core:sys/unix"
import "core:time"
foreign import lib "system:System.framework"
@@ -19,8 +20,6 @@ foreign lib {
) -> posix.result ---
}
import "core:fmt"
_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
get_pidinfo :: proc(pid: int, selection: Process_Info_Fields) -> (ppid: u32, prio: Maybe(i32), uid: posix.uid_t, ok: bool) {
// Short info is enough and requires less permissions if the priority isn't requested.
@@ -258,31 +257,56 @@ _process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error)
}
_process_open :: proc(pid: int, flags: Process_Open_Flags) -> (process: Process, err: Error) {
// NOTE(laytan): pids can get reused, and afaik posix/macos doesn't have a unique identifier
// for a specific process execution, next best thing to me is checking the time the process
// started as some extra "uniqueness". We could also hash a bunch of the fields in this info.
// This incidentally also checks if the pid is actually valid so that's nice.
pinfo: darwin.proc_bsdinfo
ret := darwin.proc_pidinfo(posix.pid_t(pid), .BSDINFO, 0, &pinfo, size_of(pinfo))
if ret <= 0 {
rusage: darwin.rusage_info_v0
if ret := darwin.proc_pid_rusage(posix.pid_t(pid), .V0, &rusage); ret != 0 {
err = _get_platform_error()
return
}
assert(ret == size_of(pinfo))
process = { int(pid), uintptr(pinfo.pbi_start_tvusec) }
// XOR fold the UUID so it fits the handle, I think this is enough to verify pid uniqueness.
#assert(size_of(uintptr) == size_of(u64))
a := intrinsics.unaligned_load((^u64)(&rusage.ri_uuid))
b := intrinsics.unaligned_load((^u64)(&rusage.ri_uuid[8]))
process.handle = uintptr(a ~ b)
process.pid = int(pid)
return
}
process_posix_handle_still_valid :: proc(p: Process) -> bool {
pinfo: darwin.proc_bsdinfo
ret := darwin.proc_pidinfo(posix.pid_t(p.pid), .BSDINFO, 0, &pinfo, size_of(pinfo))
if ret <= 0 {
return false
_process_handle_still_valid :: proc(p: Process) -> Error {
rusage: darwin.rusage_info_v0
if ret := darwin.proc_pid_rusage(posix.pid_t(p.pid), .V0, &rusage); ret != 0 {
return _get_platform_error()
}
return uintptr(pinfo.pbi_start_tvusec) == p.handle
// XOR fold the UUID so it fits the handle, I think this is enough to verify pid uniqueness.
#assert(size_of(uintptr) == size_of(u64))
a := intrinsics.unaligned_load((^u64)(&rusage.ri_uuid))
b := intrinsics.unaligned_load((^u64)(&rusage.ri_uuid[8]))
handle := uintptr(a ~ b)
if p.handle != handle {
return posix.Errno.ESRCH
}
return nil
}
_process_state_update_times :: proc(p: Process, state: ^Process_State) {
rusage: darwin.rusage_info_v0
if ret := darwin.proc_pid_rusage(posix.pid_t(p.pid), .V0, &rusage); ret != 0 {
return
}
// NOTE(laytan): I have no clue if this is correct, the output seems correct comparing it with `time`'s output.
HZ :: 20000000
state.user_time = (
(time.Duration(rusage.ri_user_time) / HZ * time.Second) +
time.Duration(rusage.ri_user_time % HZ))
state.system_time = (
(time.Duration(rusage.ri_system_time) / HZ * time.Second) +
time.Duration(rusage.ri_system_time % HZ))
return
}