os.odin 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. //+build haiku
  2. package sys_haiku
  3. import "core:c"
  4. import "core:sys/unix"
  5. foreign import libroot "system:c"
  6. PATH_MAX :: 1024
  7. NAME_MAX :: 256
  8. MAXPATHLEN :: PATH_MAX
  9. FILE_NAME_LENGTH :: NAME_MAX
  10. PATH_NAME_LENGTH :: MAXPATHLEN
  11. OS_NAME_LENGTH :: 32
  12. // Areas
  13. area_info :: struct {
  14. area: area_id,
  15. name: [OS_NAME_LENGTH]c.char,
  16. size: c.size_t,
  17. lock: u32,
  18. protection: u32,
  19. team: team_id,
  20. ram_size: u32,
  21. copy_count: u32,
  22. in_count: u32,
  23. out_count: u32,
  24. address: rawptr,
  25. }
  26. area_locking :: enum u32 {
  27. NO_LOCK = 0,
  28. LAZY_LOCK = 1,
  29. FULL_LOCK = 2,
  30. CONTIGUOUS = 3,
  31. LOMEM = 4, // CONTIGUOUS, < 16 MB physical address
  32. _32_BIT_FULL_LOCK = 5, // FULL_LOCK, < 4 GB physical addresses
  33. _32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address
  34. }
  35. // for create_area() and clone_area()
  36. address_spec :: enum u32 {
  37. ANY_ADDRESS = 0,
  38. EXACT_ADDRESS = 1,
  39. BASE_ADDRESS = 2,
  40. CLONE_ADDRESS = 3,
  41. ANY_KERNEL_ADDRESS = 4,
  42. // ANY_KERNEL_BLOCK_ADDRESS = 5,
  43. RANDOMIZED_ANY_ADDRESS = 6,
  44. RANDOMIZED_BASE_ADDRESS = 7,
  45. }
  46. area_protection_flags :: enum u32 {
  47. READ_AREA = 1 << 0,
  48. WRITE_AREA = 1 << 1,
  49. EXECUTE_AREA = 1 << 2,
  50. // "stack" protection is not available on most platforms - it's used
  51. // to only commit memory as needed, and have guard pages at the
  52. // bottom of the stack.
  53. STACK_AREA = 1 << 3,
  54. CLONEABLE_AREA = 1 << 8,
  55. }
  56. foreign libroot {
  57. create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: c.size_t, lock: area_locking, protection: area_protection_flags) -> area_id ---
  58. clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id ---
  59. find_area :: proc(name: cstring) -> area_id ---
  60. area_for :: proc(address: rawptr) -> area_id ---
  61. delete_area :: proc(id: area_id) -> status_t ---
  62. resize_area :: proc(id: area_id, newSize: c.size_t) -> status_t ---
  63. set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t ---
  64. _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: c.size_t) -> status_t ---
  65. _get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: c.size_t) -> status_t ---
  66. }
  67. // Ports
  68. port_info :: struct {
  69. port: port_id,
  70. team: team_id,
  71. name: [OS_NAME_LENGTH]c.char,
  72. capacity: i32, // queue depth
  73. queue_count: i32, // # msgs waiting to be read
  74. total_count: i32, // total # msgs read so far
  75. }
  76. port_flags :: enum u32 {
  77. USE_USER_MEMCPY = 0x80000000,
  78. // read the message, but don't remove it; kernel-only; memory must be locked
  79. PEEK_PORT_MESSAGE = 0x100,
  80. }
  81. foreign libroot {
  82. create_port :: proc(capacity: i32, name: cstring) -> port_id ---
  83. find_port :: proc(name: cstring) -> port_id ---
  84. read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t) -> c.ssize_t ---
  85. read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
  86. write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t ---
  87. write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> status_t ---
  88. close_port :: proc(port: port_id) -> status_t ---
  89. delete_port :: proc(port: port_id) -> status_t ---
  90. port_buffer_size :: proc(port: port_id) -> c.ssize_t ---
  91. port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
  92. port_count :: proc(port: port_id) -> c.ssize_t ---
  93. set_port_owner :: proc(port: port_id, team: team_id) -> status_t ---
  94. _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t ---
  95. _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t ---
  96. }
  97. // Semaphores
  98. sem_info :: struct {
  99. sem: sem_id,
  100. team: team_id,
  101. name: [OS_NAME_LENGTH]c.char,
  102. count: i32,
  103. latest_holder: thread_id,
  104. }
  105. semaphore_flags :: enum u32 {
  106. CAN_INTERRUPT = 0x01, // acquisition of the semaphore can be interrupted (system use only)
  107. CHECK_PERMISSION = 0x04, // ownership will be checked (system use only)
  108. KILL_CAN_INTERRUPT = 0x20, // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only)
  109. // release_sem_etc() only flags
  110. DO_NOT_RESCHEDULE = 0x02, // thread is not rescheduled
  111. RELEASE_ALL = 0x08, // all waiting threads will be woken up, count will be zeroed
  112. RELEASE_IF_WAITING_ONLY = 0x10, // release count only if there are any threads waiting
  113. }
  114. foreign libroot {
  115. create_sem :: proc(count: i32, name: cstring) -> sem_id ---
  116. delete_sem :: proc(id: sem_id) -> status_t ---
  117. acquire_sem :: proc(id: sem_id) -> status_t ---
  118. acquire_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
  119. release_sem :: proc(id: sem_id) -> status_t ---
  120. release_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags) -> status_t ---
  121. switch_sem :: proc(semToBeReleased: sem_id) -> status_t ---
  122. switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
  123. get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t ---
  124. set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t ---
  125. _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: c.size_t) -> status_t ---
  126. _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: c.size_t) -> status_t ---
  127. }
  128. // Teams
  129. team_info :: struct {
  130. team: team_id,
  131. thread_count: i32,
  132. image_count: i32,
  133. area_count: i32,
  134. debugger_nub_thread: thread_id,
  135. debugger_nub_port: port_id,
  136. argc: i32,
  137. args: [64]c.char,
  138. uid: uid_t,
  139. gid: gid_t,
  140. // Haiku R1 extensions
  141. real_uid: uid_t,
  142. real_gid: gid_t,
  143. group_id: pid_t,
  144. session_id: pid_t,
  145. parent: team_id,
  146. name: [OS_NAME_LENGTH]c.char,
  147. start_time: bigtime_t,
  148. }
  149. CURRENT_TEAM :: 0
  150. SYSTEM_TEAM :: 1
  151. team_usage_info :: struct {
  152. user_time: bigtime_t,
  153. kernel_time: bigtime_t,
  154. }
  155. team_usage_who :: enum i32 {
  156. // compatible to sys/resource.h RUSAGE_SELF and RUSAGE_CHILDREN
  157. SELF = 0,
  158. CHILDREN = -1,
  159. }
  160. foreign libroot {
  161. // see also: send_signal()
  162. kill_team :: proc(team: team_id) -> status_t ---
  163. _get_team_info :: proc(id: team_id, info: ^team_info, size: c.size_t) -> status_t ---
  164. _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: c.size_t) -> status_t ---
  165. _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: c.size_t) -> status_t ---
  166. }
  167. // Threads
  168. thread_state :: enum c.int {
  169. RUNNING = 1,
  170. READY,
  171. RECEIVING,
  172. ASLEEP,
  173. SUSPENDED,
  174. WAITING,
  175. }
  176. thread_info :: struct {
  177. thread: thread_id,
  178. team: team_id,
  179. name: [OS_NAME_LENGTH]c.char,
  180. state: thread_state,
  181. priority: thread_priority,
  182. sem: sem_id,
  183. user_time: bigtime_t,
  184. kernel_time: bigtime_t,
  185. stack_base: rawptr,
  186. stack_end: rawptr,
  187. }
  188. thread_priority :: enum i32 {
  189. IDLE_PRIORITY = 0,
  190. LOWEST_ACTIVE_PRIORITY = 1,
  191. LOW_PRIORITY = 5,
  192. NORMAL_PRIORITY = 10,
  193. DISPLAY_PRIORITY = 15,
  194. URGENT_DISPLAY_PRIORITY = 20,
  195. REAL_TIME_DISPLAY_PRIORITY = 100,
  196. URGENT_PRIORITY = 110,
  197. REAL_TIME_PRIORITY = 120,
  198. }
  199. FIRST_REAL_TIME_PRIORITY :: thread_priority.REAL_TIME_PRIORITY
  200. // time base for snooze_*(), compatible with the clockid_t constants defined in <time.h>
  201. SYSTEM_TIMEBASE :: 0
  202. thread_func :: #type proc "c" (rawptr) -> status_t
  203. foreign libroot {
  204. spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id ---
  205. kill_thread :: proc(thread: thread_id) -> status_t ---
  206. resume_thread :: proc(thread: thread_id) -> status_t ---
  207. suspend_thread :: proc(thread: thread_id) -> status_t ---
  208. rename_thread :: proc(thread: thread_id, newName: cstring) -> status_t ---
  209. set_thread_priority :: proc(thread: thread_id, newPriority: thread_priority) -> status_t ---
  210. exit_thread :: proc(status: status_t) ---
  211. wait_for_thread :: proc(thread: thread_id, returnValue: ^status_t) -> status_t ---
  212. // FIXME: Find and define those flags.
  213. wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t ---
  214. on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t ---
  215. find_thread :: proc(name: cstring) -> thread_id ---
  216. send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t ---
  217. receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: c.size_t) -> i32 ---
  218. has_data :: proc(thread: thread_id) -> bool ---
  219. snooze :: proc(amount: bigtime_t) -> status_t ---
  220. // FIXME: Find and define those flags.
  221. snooze_etc :: proc(amount: bigtime_t, timeBase: c.int, flags: u32) -> status_t ---
  222. snooze_until :: proc(time: bigtime_t, timeBase: c.int) -> status_t ---
  223. _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: c.size_t) -> status_t ---
  224. _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: c.size_t) -> status_t ---
  225. // bridge to the pthread API
  226. get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id ---
  227. }
  228. // Time
  229. foreign libroot {
  230. real_time_clock :: proc() -> c.ulong ---
  231. set_real_time_clock :: proc(secsSinceJan1st1970: c.ulong) ---
  232. real_time_clock_usecs :: proc() -> bigtime_t ---
  233. // time since booting in microseconds
  234. system_time :: proc() -> bigtime_t ---
  235. // time since booting in nanoseconds
  236. system_time_nsecs :: proc() -> nanotime_t ---
  237. }
  238. // Alarm
  239. alarm_mode :: enum u32 {
  240. ONE_SHOT_ABSOLUTE_ALARM = 1,
  241. ONE_SHOT_RELATIVE_ALARM,
  242. PERIODIC_ALARM, // "when" specifies the period
  243. }
  244. foreign libroot {
  245. set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t ---
  246. }
  247. // Debugger
  248. foreign libroot {
  249. debugger :: proc(message: cstring) ---
  250. /*
  251. calling this function with a non-zero value will cause your thread
  252. to receive signals for any exceptional conditions that occur (i.e.
  253. you'll get SIGSEGV for data access exceptions, SIGFPE for floating
  254. point errors, SIGILL for illegal instructions, etc).
  255. to re-enable the default debugger pass a zero.
  256. */
  257. disable_debugger :: proc(state: c.int) -> c.int ---
  258. }
  259. // System information
  260. cpu_info :: struct {
  261. active_time: bigtime_t,
  262. enabled: bool,
  263. current_frequency: u64,
  264. }
  265. system_info :: struct {
  266. boot_time: bigtime_t, // time of boot (usecs since 1/1/1970)
  267. cpu_count: u32, // number of cpus
  268. max_pages: u64, // total # of accessible pages
  269. used_pages: u64, // # of accessible pages in use
  270. cached_pages: u64,
  271. block_cache_pages: u64,
  272. ignored_pages: u64, // # of ignored/inaccessible pages
  273. needed_memory: u64,
  274. free_memory: u64,
  275. max_swap_pages: u64,
  276. free_swap_pages: u64,
  277. page_faults: u32, // # of page faults
  278. max_sems: u32,
  279. used_sems: u32,
  280. max_ports: u32,
  281. used_ports: u32,
  282. max_threads: u32,
  283. used_threads: u32,
  284. max_teams: u32,
  285. used_teams: u32,
  286. kernel_name: [FILE_NAME_LENGTH]c.char,
  287. kernel_build_date: [OS_NAME_LENGTH]c.char,
  288. kernel_build_time: [OS_NAME_LENGTH]c.char,
  289. kernel_version: i64,
  290. abi: u32, // the system API
  291. }
  292. topology_level_type :: enum c.int {
  293. UNKNOWN,
  294. ROOT,
  295. SMT,
  296. CORE,
  297. PACKAGE,
  298. }
  299. cpu_platform :: enum c.int {
  300. UNKNOWN,
  301. x86,
  302. x86_64,
  303. PPC,
  304. PPC_64,
  305. M68K,
  306. ARM,
  307. ARM_64,
  308. ALPHA,
  309. MIPS,
  310. SH,
  311. SPARC,
  312. RISC_V,
  313. }
  314. cpu_vendor :: enum c.int {
  315. UNKNOWN,
  316. AMD,
  317. CYRIX,
  318. IDT,
  319. INTEL,
  320. NATIONAL_SEMICONDUCTOR,
  321. RISE,
  322. TRANSMETA,
  323. VIA,
  324. IBM,
  325. MOTOROLA,
  326. NEC,
  327. HYGON,
  328. SUN,
  329. FUJITSU,
  330. }
  331. cpu_topology_node_info :: struct {
  332. id: u32,
  333. type: topology_level_type,
  334. level: u32,
  335. data: struct #raw_union {
  336. _root: struct {
  337. platform: cpu_platform,
  338. },
  339. _package: struct {
  340. vendor: cpu_vendor,
  341. cache_line_size: u32
  342. },
  343. _core: struct {
  344. model: u32,
  345. default_frequency: u64,
  346. },
  347. },
  348. }
  349. // FIXME: Add cpuid_info when bit fields are ready.
  350. foreign libroot {
  351. get_system_info :: proc(info: ^system_info) -> status_t ---
  352. _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: c.size_t) -> status_t ---
  353. get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t ---
  354. is_computer_on :: proc() -> i32 ---
  355. is_computer_on_fire :: proc() -> f64 ---
  356. }
  357. // Signal.h
  358. SIG_BLOCK :: 1
  359. SIG_UNBLOCK :: 2
  360. SIG_SETMASK :: 3
  361. /*
  362. * The list of all defined signals:
  363. *
  364. * The numbering of signals for Haiku attempts to maintain
  365. * some consistency with UN*X conventions so that things
  366. * like "kill -9" do what you expect.
  367. */
  368. SIGHUP :: 1 // hangup -- tty is gone!
  369. SIGINT :: 2 // interrupt
  370. SIGQUIT :: 3 // `quit' special character typed in tty
  371. SIGILL :: 4 // illegal instruction
  372. SIGCHLD :: 5 // child process exited
  373. SIGABRT :: 6 // abort() called, dont' catch
  374. SIGPIPE :: 7 // write to a pipe w/no readers
  375. SIGFPE :: 8 // floating point exception
  376. SIGKILL :: 9 // kill a team (not catchable)
  377. SIGSTOP :: 10 // suspend a thread (not catchable)
  378. SIGSEGV :: 11 // segmentation violation (read: invalid pointer)
  379. SIGCONT :: 12 // continue execution if suspended
  380. SIGTSTP :: 13 // `stop' special character typed in tty
  381. SIGALRM :: 14 // an alarm has gone off (see alarm())
  382. SIGTERM :: 15 // termination requested
  383. SIGTTIN :: 16 // read of tty from bg process
  384. SIGTTOU :: 17 // write to tty from bg process
  385. SIGUSR1 :: 18 // app defined signal 1
  386. SIGUSR2 :: 19 // app defined signal 2
  387. SIGWINCH :: 20 // tty window size changed
  388. SIGKILLTHR :: 21 // be specific: kill just the thread, not team
  389. SIGTRAP :: 22 // Trace/breakpoint trap
  390. SIGPOLL :: 23 // Pollable event
  391. SIGPROF :: 24 // Profiling timer expired
  392. SIGSYS :: 25 // Bad system call
  393. SIGURG :: 26 // High bandwidth data is available at socket
  394. SIGVTALRM :: 27 // Virtual timer expired
  395. SIGXCPU :: 28 // CPU time limit exceeded
  396. SIGXFSZ :: 29 // File size limit exceeded
  397. SIGBUS :: 30 // access to undefined portion of a memory object
  398. sigval :: struct #raw_union {
  399. sival_int: c.int,
  400. sival_ptr: rawptr,
  401. }
  402. siginfo_t :: struct {
  403. si_signo: c.int, // signal number
  404. si_code: c.int, // signal code
  405. si_errno: c.int, // if non zero, an error number associated with this signal
  406. si_pid: pid_t, // sending process ID
  407. si_uid: uid_t, // real user ID of sending process
  408. si_addr: rawptr, // address of faulting instruction
  409. si_status: c.int, // exit value or signal
  410. si_band: c.long, // band event for SIGPOLL
  411. si_value: sigval, // signal value
  412. }
  413. foreign libroot {
  414. // signal set (sigset_t) manipulation
  415. sigemptyset :: proc(set: ^sigset_t) -> c.int ---
  416. sigfillset :: proc(set: ^sigset_t) -> c.int ---
  417. sigaddset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
  418. sigdelset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
  419. sigismember :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
  420. // querying and waiting for signals
  421. sigpending :: proc(set: ^sigset_t) -> c.int ---
  422. sigsuspend :: proc(mask: ^sigset_t) -> c.int ---
  423. sigpause :: proc(_signal: c.int) -> c.int ---
  424. sigwait :: proc(set: ^sigset_t, _signal: ^c.int) -> c.int ---
  425. sigwaitinfo :: proc(set: ^sigset_t, info: ^siginfo_t) -> c.int ---
  426. sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^unix.timespec) -> c.int ---
  427. send_signal :: proc(threadID: thread_id, signal: c.uint) -> c.int ---
  428. set_signal_stack :: proc(base: rawptr, size: c.size_t) ---
  429. }