123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- //+build haiku
- package sys_haiku
- import "core:c"
- import "core:sys/unix"
- foreign import libroot "system:c"
- PATH_MAX :: 1024
- NAME_MAX :: 256
- MAXPATHLEN :: PATH_MAX
- 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 {
- active_time: bigtime_t,
- enabled: bool,
- current_frequency: u64,
- }
- system_info :: struct {
- boot_time: bigtime_t, // time of boot (usecs since 1/1/1970)
- cpu_count: u32, // number of cpus
- max_pages: u64, // total # of accessible pages
- used_pages: u64, // # of accessible pages in use
- cached_pages: u64,
- block_cache_pages: u64,
- ignored_pages: u64, // # of ignored/inaccessible pages
- needed_memory: u64,
- free_memory: u64,
- max_swap_pages: u64,
- free_swap_pages: u64,
- page_faults: u32, // # of page faults
- max_sems: u32,
- used_sems: u32,
- max_ports: u32,
- used_ports: u32,
- max_threads: u32,
- used_threads: u32,
- 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_version: i64,
- abi: u32, // the system API
- }
- topology_level_type :: enum c.int {
- UNKNOWN,
- ROOT,
- SMT,
- CORE,
- PACKAGE,
- }
- cpu_platform :: enum c.int {
- UNKNOWN,
- x86,
- x86_64,
- PPC,
- PPC_64,
- M68K,
- ARM,
- ARM_64,
- ALPHA,
- MIPS,
- SH,
- SPARC,
- RISC_V,
- }
- cpu_vendor :: enum c.int {
- UNKNOWN,
- AMD,
- CYRIX,
- IDT,
- INTEL,
- NATIONAL_SEMICONDUCTOR,
- RISE,
- TRANSMETA,
- VIA,
- IBM,
- MOTOROLA,
- NEC,
- HYGON,
- SUN,
- FUJITSU,
- }
- cpu_topology_node_info :: struct {
- id: u32,
- type: topology_level_type,
- level: u32,
- data: struct #raw_union {
- _root: struct {
- platform: cpu_platform,
- },
- _package: struct {
- vendor: cpu_vendor,
- cache_line_size: u32
- },
- _core: struct {
- model: u32,
- default_frequency: u64,
- },
- },
- }
- // 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 ---
- 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) ---
- }
|