|
@@ -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) ---
|
|
|
}
|