os.odin 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. #+build haiku
  2. package sys_haiku
  3. import "base:intrinsics"
  4. import "core:sys/posix"
  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]byte,
  16. size: uint,
  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_flag :: enum u32 {
  47. READ_AREA = 0,
  48. WRITE_AREA = 1,
  49. EXECUTE_AREA = 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 = 3,
  54. CLONEABLE_AREA = 8,
  55. }
  56. area_protection_flags :: distinct bit_set[area_protection_flag; u32]
  57. @(default_calling_convention="c")
  58. foreign libroot {
  59. create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uint, lock: area_locking, protection: area_protection_flags) -> area_id ---
  60. clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id ---
  61. find_area :: proc(name: cstring) -> area_id ---
  62. area_for :: proc(address: rawptr) -> area_id ---
  63. delete_area :: proc(id: area_id) -> status_t ---
  64. resize_area :: proc(id: area_id, newSize: uint) -> status_t ---
  65. set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t ---
  66. _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uint) -> status_t ---
  67. _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uint) -> status_t ---
  68. }
  69. // Ports
  70. port_info :: struct {
  71. port: port_id,
  72. team: team_id,
  73. name: [OS_NAME_LENGTH]byte,
  74. capacity: i32, // queue depth
  75. queue_count: i32, // # msgs waiting to be read
  76. total_count: i32, // total # msgs read so far
  77. }
  78. port_flag :: enum u32 {
  79. USE_USER_MEMCPY = intrinsics.constant_log2(0x80000000),
  80. // read the message, but don't remove it; kernel-only; memory must be locked
  81. PEEK_PORT_MESSAGE = intrinsics.constant_log2(0x100),
  82. }
  83. port_flags :: distinct bit_set[port_flag; u32]
  84. @(default_calling_convention="c")
  85. foreign libroot {
  86. create_port :: proc(capacity: i32, name: cstring) -> port_id ---
  87. find_port :: proc(name: cstring) -> port_id ---
  88. read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint) -> int ---
  89. read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> int ---
  90. write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
  91. write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> status_t ---
  92. close_port :: proc(port: port_id) -> status_t ---
  93. delete_port :: proc(port: port_id) -> status_t ---
  94. port_buffer_size :: proc(port: port_id) -> int ---
  95. port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int ---
  96. port_count :: proc(port: port_id) -> int ---
  97. set_port_owner :: proc(port: port_id, team: team_id) -> status_t ---
  98. _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
  99. _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
  100. }
  101. // Semaphores
  102. sem_info :: struct {
  103. sem: sem_id,
  104. team: team_id,
  105. name: [OS_NAME_LENGTH]byte,
  106. count: i32,
  107. latest_holder: thread_id,
  108. }
  109. semaphore_flag :: enum u32 {
  110. CAN_INTERRUPT = intrinsics.constant_log2(0x01), // acquisition of the semaphore can be interrupted (system use only)
  111. CHECK_PERMISSION = intrinsics.constant_log2(0x04), // ownership will be checked (system use only)
  112. KILL_CAN_INTERRUPT = intrinsics.constant_log2(0x20), // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only)
  113. // release_sem_etc() only flags
  114. DO_NOT_RESCHEDULE = intrinsics.constant_log2(0x02), // thread is not rescheduled
  115. RELEASE_ALL = intrinsics.constant_log2(0x08), // all waiting threads will be woken up, count will be zeroed
  116. RELEASE_IF_WAITING_ONLY = intrinsics.constant_log2(0x10), // release count only if there are any threads waiting
  117. }
  118. semaphore_flags :: distinct bit_set[semaphore_flag; u32]
  119. @(default_calling_convention="c")
  120. foreign libroot {
  121. create_sem :: proc(count: i32, name: cstring) -> sem_id ---
  122. delete_sem :: proc(id: sem_id) -> status_t ---
  123. acquire_sem :: proc(id: sem_id) -> status_t ---
  124. acquire_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
  125. release_sem :: proc(id: sem_id) -> status_t ---
  126. release_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags) -> status_t ---
  127. switch_sem :: proc(semToBeReleased: sem_id) -> status_t ---
  128. switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
  129. get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t ---
  130. set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t ---
  131. _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uint) -> status_t ---
  132. _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uint) -> status_t ---
  133. }
  134. // Teams
  135. team_info :: struct {
  136. team: team_id,
  137. thread_count: i32,
  138. image_count: i32,
  139. area_count: i32,
  140. debugger_nub_thread: thread_id,
  141. debugger_nub_port: port_id,
  142. argc: i32,
  143. args: [64]byte,
  144. uid: uid_t,
  145. gid: gid_t,
  146. // Haiku R1 extensions
  147. real_uid: uid_t,
  148. real_gid: gid_t,
  149. group_id: pid_t,
  150. session_id: pid_t,
  151. parent: team_id,
  152. name: [OS_NAME_LENGTH]byte,
  153. start_time: bigtime_t,
  154. }
  155. CURRENT_TEAM :: 0
  156. SYSTEM_TEAM :: 1
  157. team_usage_info :: struct {
  158. user_time: bigtime_t,
  159. kernel_time: bigtime_t,
  160. }
  161. team_usage_who :: enum i32 {
  162. // compatible to sys/resource.h RUSAGE_SELF and RUSAGE_CHILDREN
  163. SELF = 0,
  164. CHILDREN = -1,
  165. }
  166. @(default_calling_convention="c")
  167. foreign libroot {
  168. // see also: send_signal()
  169. kill_team :: proc(team: team_id) -> status_t ---
  170. _get_team_info :: proc(id: team_id, info: ^team_info, size: uint) -> status_t ---
  171. _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uint) -> status_t ---
  172. _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uint) -> status_t ---
  173. }
  174. // Threads
  175. thread_state :: enum i32 {
  176. RUNNING = 1,
  177. READY,
  178. RECEIVING,
  179. ASLEEP,
  180. SUSPENDED,
  181. WAITING,
  182. }
  183. thread_info :: struct {
  184. thread: thread_id,
  185. team: team_id,
  186. name: [OS_NAME_LENGTH]byte,
  187. state: thread_state,
  188. priority: thread_priority,
  189. sem: sem_id,
  190. user_time: bigtime_t,
  191. kernel_time: bigtime_t,
  192. stack_base: rawptr,
  193. stack_end: rawptr,
  194. }
  195. thread_priority :: enum i32 {
  196. IDLE_PRIORITY = 0,
  197. LOWEST_ACTIVE_PRIORITY = 1,
  198. LOW_PRIORITY = 5,
  199. NORMAL_PRIORITY = 10,
  200. DISPLAY_PRIORITY = 15,
  201. URGENT_DISPLAY_PRIORITY = 20,
  202. REAL_TIME_DISPLAY_PRIORITY = 100,
  203. URGENT_PRIORITY = 110,
  204. REAL_TIME_PRIORITY = 120,
  205. }
  206. FIRST_REAL_TIME_PRIORITY :: thread_priority.REAL_TIME_PRIORITY
  207. // time base for snooze_*(), compatible with the clockid_t constants defined in <time.h>
  208. SYSTEM_TIMEBASE :: 0
  209. thread_func :: #type proc "c" (rawptr) -> status_t
  210. @(default_calling_convention="c")
  211. foreign libroot {
  212. spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id ---
  213. kill_thread :: proc(thread: thread_id) -> status_t ---
  214. resume_thread :: proc(thread: thread_id) -> status_t ---
  215. suspend_thread :: proc(thread: thread_id) -> status_t ---
  216. rename_thread :: proc(thread: thread_id, newName: cstring) -> status_t ---
  217. set_thread_priority :: proc(thread: thread_id, newPriority: thread_priority) -> status_t ---
  218. exit_thread :: proc(status: status_t) ---
  219. wait_for_thread :: proc(thread: thread_id, returnValue: ^status_t) -> status_t ---
  220. // FIXME: Find and define those flags.
  221. wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t ---
  222. on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t ---
  223. find_thread :: proc(name: cstring) -> thread_id ---
  224. send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
  225. receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uint) -> i32 ---
  226. has_data :: proc(thread: thread_id) -> bool ---
  227. snooze :: proc(amount: bigtime_t) -> status_t ---
  228. // FIXME: Find and define those flags.
  229. snooze_etc :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t ---
  230. snooze_until :: proc(time: bigtime_t, timeBase: i32) -> status_t ---
  231. _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uint) -> status_t ---
  232. _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uint) -> status_t ---
  233. // bridge to the pthread API
  234. get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id ---
  235. }
  236. // Time
  237. @(default_calling_convention="c")
  238. foreign libroot {
  239. real_time_clock :: proc() -> uint ---
  240. set_real_time_clock :: proc(secsSinceJan1st1970: uint) ---
  241. real_time_clock_usecs :: proc() -> bigtime_t ---
  242. // time since booting in microseconds
  243. system_time :: proc() -> bigtime_t ---
  244. // time since booting in nanoseconds
  245. system_time_nsecs :: proc() -> nanotime_t ---
  246. }
  247. // Alarm
  248. alarm_mode :: enum u32 {
  249. ONE_SHOT_ABSOLUTE_ALARM = 1,
  250. ONE_SHOT_RELATIVE_ALARM,
  251. PERIODIC_ALARM, // "when" specifies the period
  252. }
  253. @(default_calling_convention="c")
  254. foreign libroot {
  255. set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t ---
  256. }
  257. // Debugger
  258. @(default_calling_convention="c")
  259. foreign libroot {
  260. debugger :: proc(message: cstring) ---
  261. /*
  262. calling this function with a non-zero value will cause your thread
  263. to receive signals for any exceptional conditions that occur (i.e.
  264. you'll get SIGSEGV for data access exceptions, SIGFPE for floating
  265. point errors, SIGILL for illegal instructions, etc).
  266. to re-enable the default debugger pass a zero.
  267. */
  268. disable_debugger :: proc(state: i32) -> i32 ---
  269. }
  270. // System information
  271. cpu_info :: struct {
  272. active_time: bigtime_t,
  273. enabled: bool,
  274. current_frequency: u64,
  275. }
  276. system_info :: struct {
  277. boot_time: bigtime_t, // time of boot (usecs since 1/1/1970)
  278. cpu_count: u32, // number of cpus
  279. max_pages: u64, // total # of accessible pages
  280. used_pages: u64, // # of accessible pages in use
  281. cached_pages: u64,
  282. block_cache_pages: u64,
  283. ignored_pages: u64, // # of ignored/inaccessible pages
  284. needed_memory: u64,
  285. free_memory: u64,
  286. max_swap_pages: u64,
  287. free_swap_pages: u64,
  288. page_faults: u32, // # of page faults
  289. max_sems: u32,
  290. used_sems: u32,
  291. max_ports: u32,
  292. used_ports: u32,
  293. max_threads: u32,
  294. used_threads: u32,
  295. max_teams: u32,
  296. used_teams: u32,
  297. kernel_name: [FILE_NAME_LENGTH]byte,
  298. kernel_build_date: [OS_NAME_LENGTH]byte,
  299. kernel_build_time: [OS_NAME_LENGTH]byte,
  300. kernel_version: i64,
  301. abi: u32, // the system API
  302. }
  303. topology_level_type :: enum i32 {
  304. UNKNOWN,
  305. ROOT,
  306. SMT,
  307. CORE,
  308. PACKAGE,
  309. }
  310. cpu_platform :: enum i32 {
  311. UNKNOWN,
  312. x86,
  313. x86_64,
  314. PPC,
  315. PPC_64,
  316. M68K,
  317. ARM,
  318. ARM_64,
  319. ALPHA,
  320. MIPS,
  321. SH,
  322. SPARC,
  323. RISC_V,
  324. }
  325. cpu_vendor :: enum i32 {
  326. UNKNOWN,
  327. AMD,
  328. CYRIX,
  329. IDT,
  330. INTEL,
  331. NATIONAL_SEMICONDUCTOR,
  332. RISE,
  333. TRANSMETA,
  334. VIA,
  335. IBM,
  336. MOTOROLA,
  337. NEC,
  338. HYGON,
  339. SUN,
  340. FUJITSU,
  341. }
  342. cpu_topology_node_info :: struct {
  343. id: u32,
  344. type: topology_level_type,
  345. level: u32,
  346. data: struct #raw_union {
  347. _root: struct {
  348. platform: cpu_platform,
  349. },
  350. _package: struct {
  351. vendor: cpu_vendor,
  352. cache_line_size: u32,
  353. },
  354. _core: struct {
  355. model: u32,
  356. default_frequency: u64,
  357. },
  358. },
  359. }
  360. when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
  361. cpuid_info :: struct #raw_union {
  362. eax_0: struct {
  363. max_eax: u32,
  364. vendor_id: [12]byte,
  365. },
  366. eax_1: struct {
  367. using _: bit_field u32 {
  368. stepping: u32 | 4,
  369. model: u32 | 4,
  370. family: u32 | 4,
  371. type: u32 | 2,
  372. reserved_0: u32 | 2,
  373. extended_model: u32 | 4,
  374. extended_family: u32 | 8,
  375. reserved_1: u32 | 4,
  376. },
  377. using _: bit_field u32 {
  378. brand_index: u32 | 8,
  379. clflush: u32 | 8,
  380. logical_cpus: u32 | 8,
  381. apic_id: u32 | 8,
  382. },
  383. features: u32,
  384. extended_features: u32,
  385. },
  386. eax_2: struct {
  387. call_num: u8,
  388. cache_descriptors: [15]u8,
  389. },
  390. eax_3: struct {
  391. reserved: [2]u32,
  392. serial_number_high: u32,
  393. serial_number_low: u32,
  394. },
  395. as_chars: [16]byte,
  396. regs: struct {
  397. eax: u32,
  398. ebx: u32,
  399. edx: u32,
  400. ecx: u32,
  401. },
  402. }
  403. }
  404. @(default_calling_convention="c")
  405. foreign libroot {
  406. get_system_info :: proc(info: ^system_info) -> status_t ---
  407. _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uint) -> status_t ---
  408. get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t ---
  409. when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
  410. get_cpuid :: proc(info: ^cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t ---
  411. }
  412. is_computer_on :: proc() -> i32 ---
  413. is_computer_on_fire :: proc() -> f64 ---
  414. }
  415. // POSIX signals
  416. @(default_calling_convention="c")
  417. foreign libroot {
  418. /*
  419. Wait for queued signals.
  420. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]]
  421. */
  422. sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result ---
  423. }