improve core:sys

This commit is contained in:
avanspector
2024-02-28 22:29:06 +01:00
parent 87f6f3a1fe
commit bf37bee4f7
4 changed files with 467 additions and 14 deletions
+3 -2
View File
@@ -3,9 +3,9 @@ package sys_haiku
import "core:c"
Errno :: enum i32 {
Errno :: enum c.int {
// Error baselines
GENERAL_ERROR_BASE = -(1<<31),
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,
@@ -115,6 +115,7 @@ Errno :: enum i32 {
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
+168
View File
@@ -0,0 +1,168 @@
//+build haiku
package sys_haiku
import "core:c"
directory_which :: enum c.int {
// Per volume directories
DESKTOP_DIRECTORY = 0,
TRASH_DIRECTORY,
// System directories
SYSTEM_DIRECTORY = 1000,
SYSTEM_ADDONS_DIRECTORY = 1002,
SYSTEM_BOOT_DIRECTORY,
SYSTEM_FONTS_DIRECTORY,
SYSTEM_LIB_DIRECTORY,
SYSTEM_SERVERS_DIRECTORY,
SYSTEM_APPS_DIRECTORY,
SYSTEM_BIN_DIRECTORY,
SYSTEM_DOCUMENTATION_DIRECTORY = 1010,
SYSTEM_PREFERENCES_DIRECTORY,
SYSTEM_TRANSLATORS_DIRECTORY,
SYSTEM_MEDIA_NODES_DIRECTORY,
SYSTEM_SOUNDS_DIRECTORY,
SYSTEM_DATA_DIRECTORY,
SYSTEM_DEVELOP_DIRECTORY,
SYSTEM_PACKAGES_DIRECTORY,
SYSTEM_HEADERS_DIRECTORY,
SYSTEM_ETC_DIRECTORY = 2008,
SYSTEM_SETTINGS_DIRECTORY = 2010,
SYSTEM_LOG_DIRECTORY = 2012,
SYSTEM_SPOOL_DIRECTORY,
SYSTEM_TEMP_DIRECTORY,
SYSTEM_VAR_DIRECTORY,
SYSTEM_CACHE_DIRECTORY = 2020,
SYSTEM_NONPACKAGED_DIRECTORY = 2023,
SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY,
SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY,
SYSTEM_NONPACKAGED_BIN_DIRECTORY,
SYSTEM_NONPACKAGED_DATA_DIRECTORY,
SYSTEM_NONPACKAGED_FONTS_DIRECTORY,
SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY,
SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY,
SYSTEM_NONPACKAGED_LIB_DIRECTORY,
SYSTEM_NONPACKAGED_HEADERS_DIRECTORY,
SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY,
// User directories. These are interpreted in the context of the user making the find_directory call.
USER_DIRECTORY = 3000,
USER_CONFIG_DIRECTORY,
USER_ADDONS_DIRECTORY,
USER_BOOT_DIRECTORY,
USER_FONTS_DIRECTORY,
USER_LIB_DIRECTORY,
USER_SETTINGS_DIRECTORY,
USER_DESKBAR_DIRECTORY,
USER_PRINTERS_DIRECTORY,
USER_TRANSLATORS_DIRECTORY,
USER_MEDIA_NODES_DIRECTORY,
USER_SOUNDS_DIRECTORY,
USER_DATA_DIRECTORY,
USER_CACHE_DIRECTORY,
USER_PACKAGES_DIRECTORY,
USER_HEADERS_DIRECTORY,
USER_NONPACKAGED_DIRECTORY,
USER_NONPACKAGED_ADDONS_DIRECTORY,
USER_NONPACKAGED_TRANSLATORS_DIRECTORY,
USER_NONPACKAGED_MEDIA_NODES_DIRECTORY,
USER_NONPACKAGED_BIN_DIRECTORY,
USER_NONPACKAGED_DATA_DIRECTORY,
USER_NONPACKAGED_FONTS_DIRECTORY,
USER_NONPACKAGED_SOUNDS_DIRECTORY,
USER_NONPACKAGED_DOCUMENTATION_DIRECTORY,
USER_NONPACKAGED_LIB_DIRECTORY,
USER_NONPACKAGED_HEADERS_DIRECTORY,
USER_NONPACKAGED_DEVELOP_DIRECTORY,
USER_DEVELOP_DIRECTORY,
USER_DOCUMENTATION_DIRECTORY,
USER_SERVERS_DIRECTORY,
USER_APPS_DIRECTORY,
USER_BIN_DIRECTORY,
USER_PREFERENCES_DIRECTORY,
USER_ETC_DIRECTORY,
USER_LOG_DIRECTORY,
USER_SPOOL_DIRECTORY,
USER_VAR_DIRECTORY,
// Global directories
APPS_DIRECTORY = 4000,
PREFERENCES_DIRECTORY,
UTILITIES_DIRECTORY,
PACKAGE_LINKS_DIRECTORY,
// Obsolete: Legacy BeOS definition to be phased out
BEOS_DIRECTORY = 1000,
BEOS_SYSTEM_DIRECTORY,
BEOS_ADDONS_DIRECTORY,
BEOS_BOOT_DIRECTORY,
BEOS_FONTS_DIRECTORY,
BEOS_LIB_DIRECTORY,
BEOS_SERVERS_DIRECTORY,
BEOS_APPS_DIRECTORY,
BEOS_BIN_DIRECTORY,
BEOS_ETC_DIRECTORY,
BEOS_DOCUMENTATION_DIRECTORY,
BEOS_PREFERENCES_DIRECTORY,
BEOS_TRANSLATORS_DIRECTORY,
BEOS_MEDIA_NODES_DIRECTORY,
BEOS_SOUNDS_DIRECTORY,
}
find_path_flags :: enum c.int {
CREATE_DIRECTORY = 0x0001,
CREATE_PARENT_DIRECTORY = 0x0002,
EXISTING_ONLY = 0x0004,
// find_paths() only!
SYSTEM_ONLY = 0x0010,
USER_ONLY = 0x0020,
}
path_base_directory :: enum c.int {
INSTALLATION_LOCATION_DIRECTORY,
ADD_ONS_DIRECTORY,
APPS_DIRECTORY,
BIN_DIRECTORY,
BOOT_DIRECTORY,
CACHE_DIRECTORY,
DATA_DIRECTORY,
DEVELOP_DIRECTORY,
DEVELOP_LIB_DIRECTORY,
DOCUMENTATION_DIRECTORY,
ETC_DIRECTORY,
FONTS_DIRECTORY,
HEADERS_DIRECTORY,
LIB_DIRECTORY,
LOG_DIRECTORY,
MEDIA_NODES_DIRECTORY,
PACKAGES_DIRECTORY,
PREFERENCES_DIRECTORY,
SERVERS_DIRECTORY,
SETTINGS_DIRECTORY,
SOUNDS_DIRECTORY,
SPOOL_DIRECTORY,
TRANSLATORS_DIRECTORY,
VAR_DIRECTORY,
// find_path() only!
IMAGE_PATH = 1000,
PACKAGE_PATH,
}
// 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) }
foreign import libroot "system: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 ---
}
+292 -12
View File
@@ -14,6 +14,291 @@ FILE_NAME_LENGTH :: NAME_MAX
PATH_NAME_LENGTH :: MAXPATHLEN
OS_NAME_LENGTH :: 32
// Areas
area_info :: struct {
area: area_id,
name: [OS_NAME_LENGTH]c.char,
size: c.size_t,
lock: u32,
protection: u32,
team: team_id,
ram_size: u32,
copy_count: u32,
in_count: u32,
out_count: u32,
address: rawptr,
}
area_locking :: enum u32 {
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
}
// for create_area() and clone_area()
address_spec :: enum u32 {
ANY_ADDRESS = 0,
EXACT_ADDRESS = 1,
BASE_ADDRESS = 2,
CLONE_ADDRESS = 3,
ANY_KERNEL_ADDRESS = 4,
// ANY_KERNEL_BLOCK_ADDRESS = 5,
RANDOMIZED_ANY_ADDRESS = 6,
RANDOMIZED_BASE_ADDRESS = 7,
}
area_protection_flags :: enum u32 {
READ_AREA = 1 << 0,
WRITE_AREA = 1 << 1,
EXECUTE_AREA = 1 << 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,
}
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 ---
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 ---
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 ---
}
// Ports
port_info :: struct {
port: port_id,
team: team_id,
name: [OS_NAME_LENGTH]c.char,
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,
// read the message, but don't remove it; kernel-only; memory must be locked
PEEK_PORT_MESSAGE = 0x100,
}
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 ---
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 ---
}
// Semaphores
sem_info :: struct {
sem: sem_id,
team: team_id,
name: [OS_NAME_LENGTH]c.char,
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)
// 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
}
foreign libroot {
create_sem :: proc(count: i32, name: cstring) -> sem_id ---
delete_sem :: proc(id: sem_id) -> status_t ---
acquire_sem :: proc(id: sem_id) -> status_t ---
acquire_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
release_sem :: proc(id: sem_id) -> status_t ---
release_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags) -> status_t ---
switch_sem :: proc(semToBeReleased: sem_id) -> status_t ---
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 ---
}
// Teams
team_info :: struct {
team: team_id,
thread_count: i32,
image_count: i32,
area_count: i32,
debugger_nub_thread: thread_id,
debugger_nub_port: port_id,
argc: i32,
args: [64]c.char,
uid: uid_t,
gid: gid_t,
// Haiku R1 extensions
real_uid: uid_t,
real_gid: gid_t,
group_id: pid_t,
session_id: pid_t,
parent: team_id,
name: [OS_NAME_LENGTH]c.char,
start_time: bigtime_t,
}
CURRENT_TEAM :: 0
SYSTEM_TEAM :: 1
team_usage_info :: struct {
user_time: bigtime_t,
kernel_time: bigtime_t,
}
team_usage_who :: enum i32 {
// compatible to sys/resource.h RUSAGE_SELF and RUSAGE_CHILDREN
SELF = 0,
CHILDREN = -1,
}
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 ---
}
// Threads
thread_state :: enum c.int {
RUNNING = 1,
READY,
RECEIVING,
ASLEEP,
SUSPENDED,
WAITING,
}
thread_info :: struct {
thread: thread_id,
team: team_id,
name: [OS_NAME_LENGTH]c.char,
state: thread_state,
priority: thread_priority,
sem: sem_id,
user_time: bigtime_t,
kernel_time: bigtime_t,
stack_base: rawptr,
stack_end: rawptr,
}
thread_priority :: enum i32 {
IDLE_PRIORITY = 0,
LOWEST_ACTIVE_PRIORITY = 1,
LOW_PRIORITY = 5,
NORMAL_PRIORITY = 10,
DISPLAY_PRIORITY = 15,
URGENT_DISPLAY_PRIORITY = 20,
REAL_TIME_DISPLAY_PRIORITY = 100,
URGENT_PRIORITY = 110,
REAL_TIME_PRIORITY = 120,
}
FIRST_REAL_TIME_PRIORITY :: thread_priority.REAL_TIME_PRIORITY
// time base for snooze_*(), compatible with the clockid_t constants defined in <time.h>
SYSTEM_TIMEBASE :: 0
thread_func :: #type proc "c" (rawptr) -> status_t
foreign libroot {
spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id ---
kill_thread :: proc(thread: thread_id) -> status_t ---
resume_thread :: proc(thread: thread_id) -> status_t ---
suspend_thread :: proc(thread: thread_id) -> status_t ---
rename_thread :: proc(thread: thread_id, newName: cstring) -> status_t ---
set_thread_priority :: proc(thread: thread_id, newPriority: thread_priority) -> status_t ---
exit_thread :: proc(status: status_t) ---
wait_for_thread :: proc(thread: thread_id, returnValue: ^status_t) -> status_t ---
// FIXME: Find and define those flags.
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 ---
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 ---
// bridge to the pthread API
get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id ---
}
// Time
foreign libroot {
real_time_clock :: proc() -> c.ulong ---
set_real_time_clock :: proc(secsSinceJan1st1970: c.ulong) ---
real_time_clock_usecs :: proc() -> bigtime_t ---
// time since booting in microseconds
system_time :: proc() -> bigtime_t ---
// time since booting in nanoseconds
system_time_nsecs :: proc() -> nanotime_t ---
}
// Alarm
alarm_mode :: enum u32 {
ONE_SHOT_ABSOLUTE_ALARM = 1,
ONE_SHOT_RELATIVE_ALARM,
PERIODIC_ALARM, // "when" specifies the period
}
foreign libroot {
set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t ---
}
// Debugger
foreign libroot {
debugger :: proc(message: cstring) ---
/*
calling this function with a non-zero value will cause your thread
to receive signals for any exceptional conditions that occur (i.e.
you'll get SIGSEGV for data access exceptions, SIGFPE for floating
point errors, SIGILL for illegal instructions, etc).
to re-enable the default debugger pass a zero.
*/
disable_debugger :: proc(state: c.int) -> c.int ---
}
// System information
cpu_info :: struct {
@@ -123,23 +408,15 @@ cpu_topology_node_info :: struct {
},
}
// FIXME: Add cpuid_info when bit fields are ready.
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_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t ---
debugger :: proc(message: cstring) ---
/*
calling this function with a non-zero value will cause your thread
to receive signals for any exceptional conditions that occur (i.e.
you'll get SIGSEGV for data access exceptions, SIGFPE for floating
point errors, SIGILL for illegal instructions, etc).
to re-enable the default debugger pass a zero.
*/
disable_debugger :: proc(state: c.int) -> c.int ---
find_thread :: proc(name: cstring) -> thread_id ---
is_computer_on :: proc() -> i32 ---
is_computer_on_fire :: proc() -> f64 ---
}
// Signal.h
@@ -219,4 +496,7 @@ foreign libroot {
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) ---
}
+4
View File
@@ -48,3 +48,7 @@ time_t :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else i32
sig_atomic_t :: c.int
sigset_t :: u64
image_id :: i32
pthread_t :: rawptr