mach_darwin.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package darwin
  2. foreign import mach "system:System.framework"
  3. import "core:c"
  4. import "base:intrinsics"
  5. kern_return_t :: distinct c.int
  6. mach_port_t :: distinct c.uint
  7. vm_map_t :: mach_port_t
  8. mem_entry_name_port_t :: mach_port_t
  9. ipc_space_t :: mach_port_t
  10. thread_t :: mach_port_t
  11. task_t :: mach_port_t
  12. semaphore_t :: mach_port_t
  13. vm_size_t :: distinct c.uintptr_t
  14. vm_address_t :: vm_offset_t
  15. vm_offset_t :: distinct c.uintptr_t
  16. // NOTE(beau): typedefed to int in the original headers
  17. boolean_t :: b32
  18. vm_prot_t :: distinct c.int
  19. vm_inherit_t :: distinct c.uint
  20. mach_port_name_t :: distinct c.uint
  21. sync_policy_t :: distinct c.int
  22. @(default_calling_convention="c")
  23. foreign mach {
  24. mach_task_self :: proc() -> mach_port_t ---
  25. semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return ---
  26. semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return ---
  27. semaphore_signal :: proc(semaphore: semaphore_t) -> Kern_Return ---
  28. semaphore_signal_all :: proc(semaphore: semaphore_t) -> Kern_Return ---
  29. semaphore_signal_thread :: proc(semaphore: semaphore_t, thread: thread_t) -> Kern_Return ---
  30. semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return ---
  31. vm_allocate :: proc (target_task : vm_map_t, address: ^vm_address_t, size: vm_size_t, flags: VM_Flags) -> Kern_Return ---
  32. vm_deallocate :: proc(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) -> Kern_Return ---
  33. vm_map :: proc(
  34. target_task: vm_map_t,
  35. address: ^vm_address_t,
  36. size: vm_size_t,
  37. mask: vm_address_t,
  38. flags: VM_Flags,
  39. object: mem_entry_name_port_t,
  40. offset: vm_offset_t,
  41. copy: boolean_t,
  42. cur_protection,
  43. max_protection: VM_Prot_Flags,
  44. inheritance: VM_Inherit,
  45. ) -> Kern_Return ---
  46. mach_make_memory_entry :: proc(
  47. target_task: vm_map_t,
  48. size: ^vm_size_t,
  49. offset: vm_offset_t,
  50. permission: VM_Prot_Flags,
  51. object_handle: ^mem_entry_name_port_t,
  52. parent_entry: mem_entry_name_port_t,
  53. ) -> Kern_Return ---
  54. mach_port_deallocate :: proc(
  55. task: ipc_space_t,
  56. name: mach_port_name_t,
  57. ) -> Kern_Return ---
  58. vm_page_size: vm_size_t
  59. }
  60. Kern_Return :: enum kern_return_t {
  61. Success,
  62. /* Specified address is not currently valid.
  63. */
  64. Invalid_Address,
  65. /* Specified memory is valid, but does not permit the
  66. * required forms of access.
  67. */
  68. Protection_Failure,
  69. /* The address range specified is already in use, or
  70. * no address range of the size specified could be
  71. * found.
  72. */
  73. No_Space,
  74. /* The function requested was not applicable to this
  75. * type of argument, or an argument is invalid
  76. */
  77. Invalid_Argument,
  78. /* The function could not be performed. A catch-all.
  79. */
  80. Failure,
  81. /* A system resource could not be allocated to fulfill
  82. * this request. This failure may not be permanent.
  83. */
  84. Resource_Shortage,
  85. /* The task in question does not hold receive rights
  86. * for the port argument.
  87. */
  88. Not_Receiver,
  89. /* Bogus access restriction.
  90. */
  91. No_Access,
  92. /* During a page fault, the target address refers to a
  93. * memory object that has been destroyed. This
  94. * failure is permanent.
  95. */
  96. Memory_Failure,
  97. /* During a page fault, the memory object indicated
  98. * that the data could not be returned. This failure
  99. * may be temporary; future attempts to access this
  100. * same data may succeed, as defined by the memory
  101. * object.
  102. */
  103. Memory_Error,
  104. /* The receive right is already a member of the portset.
  105. */
  106. Already_In_Set,
  107. /* The receive right is not a member of a port set.
  108. */
  109. Not_In_Set,
  110. /* The name already denotes a right in the task.
  111. */
  112. Name_Exists,
  113. /* The operation was aborted. Ipc code will
  114. * catch this and reflect it as a message error.
  115. */
  116. Aborted,
  117. /* The name doesn't denote a right in the task.
  118. */
  119. Invalid_Name,
  120. /* Target task isn't an active task.
  121. */
  122. Invalid_Task,
  123. /* The name denotes a right, but not an appropriate right.
  124. */
  125. Invalid_Right,
  126. /* A blatant range error.
  127. */
  128. Invalid_Value,
  129. /* Operation would overflow limit on user-references.
  130. */
  131. URefs_Overflow,
  132. /* The supplied (port) capability is improper.
  133. */
  134. Invalid_Capability,
  135. /* The task already has send or receive rights
  136. * for the port under another name.
  137. */
  138. Right_Exists,
  139. /* Target host isn't actually a host.
  140. */
  141. Invalid_Host,
  142. /* An attempt was made to supply "precious" data
  143. * for memory that is already present in a
  144. * memory object.
  145. */
  146. Memory_Present,
  147. /* A page was requested of a memory manager via
  148. * memory_object_data_request for an object using
  149. * a MEMORY_OBJECT_COPY_CALL strategy, with the
  150. * VM_PROT_WANTS_COPY flag being used to specify
  151. * that the page desired is for a copy of the
  152. * object, and the memory manager has detected
  153. * the page was pushed into a copy of the object
  154. * while the kernel was walking the shadow chain
  155. * from the copy to the object. This error code
  156. * is delivered via memory_object_data_error
  157. * and is handled by the kernel (it forces the
  158. * kernel to restart the fault). It will not be
  159. * seen by users.
  160. */
  161. Memory_Data_Moved,
  162. /* A strategic copy was attempted of an object
  163. * upon which a quicker copy is now possible.
  164. * The caller should retry the copy using
  165. * vm_object_copy_quickly. This error code
  166. * is seen only by the kernel.
  167. */
  168. Memory_Restart_Copy,
  169. /* An argument applied to assert processor set privilege
  170. * was not a processor set control port.
  171. */
  172. Invalid_Processor_Set,
  173. /* The specified scheduling attributes exceed the thread's
  174. * limits.
  175. */
  176. Policy_Limit,
  177. /* The specified scheduling policy is not currently
  178. * enabled for the processor set.
  179. */
  180. Invalid_Policy,
  181. /* The external memory manager failed to initialize the
  182. * memory object.
  183. */
  184. Invalid_Object,
  185. /* A thread is attempting to wait for an event for which
  186. * there is already a waiting thread.
  187. */
  188. Already_Waiting,
  189. /* An attempt was made to destroy the default processor
  190. * set.
  191. */
  192. Default_Set,
  193. /* An attempt was made to fetch an exception port that is
  194. * protected, or to abort a thread while processing a
  195. * protected exception.
  196. */
  197. Exception_Protected,
  198. /* A ledger was required but not supplied.
  199. */
  200. Invalid_Ledger,
  201. /* The port was not a memory cache control port.
  202. */
  203. Invalid_Memory_Control,
  204. /* An argument supplied to assert security privilege
  205. * was not a host security port.
  206. */
  207. Invalid_Security,
  208. /* thread_depress_abort was called on a thread which
  209. * was not currently depressed.
  210. */
  211. Not_Depressed,
  212. /* Object has been terminated and is no longer available
  213. */
  214. Terminated,
  215. /* Lock set has been destroyed and is no longer available.
  216. */
  217. Lock_Set_Destroyed,
  218. /* The thread holding the lock terminated before releasing
  219. * the lock
  220. */
  221. Lock_Unstable,
  222. /* The lock is already owned by another thread
  223. */
  224. Lock_Owned,
  225. /* The lock is already owned by the calling thread
  226. */
  227. Lock_Owned_Self,
  228. /* Semaphore has been destroyed and is no longer available.
  229. */
  230. Semaphore_Destroyed,
  231. /* Return from RPC indicating the target server was
  232. * terminated before it successfully replied
  233. */
  234. Rpc_Server_Terminated,
  235. /* Terminate an orphaned activation.
  236. */
  237. RPC_Terminate_Orphan,
  238. /* Allow an orphaned activation to continue executing.
  239. */
  240. RPC_Continue_Orphan,
  241. /* Empty thread activation (No thread linked to it)
  242. */
  243. Not_Supported,
  244. /* Remote node down or inaccessible.
  245. */
  246. Node_Down,
  247. /* A signalled thread was not actually waiting. */
  248. Not_Waiting,
  249. /* Some thread-oriented operation (semaphore_wait) timed out
  250. */
  251. Operation_Timed_Out,
  252. /* During a page fault, indicates that the page was rejected
  253. * as a result of a signature check.
  254. */
  255. Codesign_Error,
  256. /* The requested property cannot be changed at this time.
  257. */
  258. Policy_Static,
  259. /* The provided buffer is of insufficient size for the requested data.
  260. */
  261. Insufficient_Buffer_Size,
  262. /* Denied by security policy
  263. */
  264. Denied,
  265. /* The KC on which the function is operating is missing
  266. */
  267. Missing_KC,
  268. /* The KC on which the function is operating is invalid
  269. */
  270. Invalid_KC,
  271. /* A search or query operation did not return a result
  272. */
  273. Not_Found,
  274. /* Maximum return value allowable
  275. */
  276. Return_Max = 0x100,
  277. }
  278. /*
  279. * VM allocation flags:
  280. *
  281. * VM_FLAGS_FIXED
  282. * (really the absence of VM_FLAGS_ANYWHERE)
  283. * Allocate new VM region at the specified virtual address, if possible.
  284. *
  285. * VM_FLAGS_ANYWHERE
  286. * Allocate new VM region anywhere it would fit in the address space.
  287. *
  288. * VM_FLAGS_PURGABLE
  289. * Create a purgable VM object for that new VM region.
  290. *
  291. * VM_FLAGS_4GB_CHUNK
  292. * The new VM region will be chunked up into 4GB sized pieces.
  293. *
  294. * VM_FLAGS_NO_PMAP_CHECK
  295. * (for DEBUG kernel config only, ignored for other configs)
  296. * Do not check that there is no stale pmap mapping for the new VM region.
  297. * This is useful for kernel memory allocations at bootstrap when building
  298. * the initial kernel address space while some memory is already in use.
  299. *
  300. * VM_FLAGS_OVERWRITE
  301. * The new VM region can replace existing VM regions if necessary
  302. * (to be used in combination with VM_FLAGS_FIXED).
  303. *
  304. * VM_FLAGS_NO_CACHE
  305. * Pages brought in to this VM region are placed on the speculative
  306. * queue instead of the active queue. In other words, they are not
  307. * cached so that they will be stolen first if memory runs low.
  308. */
  309. @(private="file")
  310. LOG2 :: intrinsics.constant_log2
  311. VM_Flag :: enum c.int {
  312. Anywhere,
  313. Purgable,
  314. _4GB_Chunk,
  315. Random_Addr,
  316. No_Cache,
  317. Resilient_Codesign,
  318. Resilient_Media,
  319. Permanent,
  320. // NOTE(beau): log 2 of the bit we want in the bit set so we get that bit in
  321. // the bit set
  322. TPRO = LOG2(0x1000),
  323. Overwrite = LOG2(0x4000),/* delete any existing mappings first */
  324. Superpage_Size_Any = LOG2(0x10000),
  325. Superpage_Size_2MB = LOG2(0x20000),
  326. __Superpage3 = LOG2(0x40000),
  327. Return_Data_Addr = LOG2(0x100000),
  328. Return_4K_Data_Addr = LOG2(0x800000),
  329. Alias_Mask1 = 24,
  330. Alias_Mask2,
  331. Alias_Mask3,
  332. Alias_Mask4,
  333. Alias_Mask5,
  334. Alias_Mask6,
  335. Alias_Mask7,
  336. Alias_Mask8,
  337. HW = TPRO,
  338. }
  339. VM_Flags :: distinct bit_set[VM_Flag; c.int]
  340. VM_FLAGS_FIXED :: VM_Flags{}
  341. /*
  342. * VM_FLAGS_SUPERPAGE_MASK
  343. * 3 bits that specify whether large pages should be used instead of
  344. * base pages (!=0), as well as the requested page size.
  345. */
  346. VM_FLAGS_SUPERPAGE_MASK :: VM_Flags {
  347. .Superpage_Size_Any,
  348. .Superpage_Size_2MB,
  349. .__Superpage3,
  350. }
  351. // 0xFF000000
  352. VM_FLAGS_ALIAS_MASK :: VM_Flags {
  353. .Alias_Mask1,
  354. .Alias_Mask2,
  355. .Alias_Mask3,
  356. .Alias_Mask4,
  357. .Alias_Mask5,
  358. .Alias_Mask6,
  359. .Alias_Mask7,
  360. .Alias_Mask8,
  361. }
  362. VM_GET_FLAGS_ALIAS :: proc(flags: VM_Flags) -> c.int {
  363. return transmute(c.int)(flags & VM_FLAGS_ALIAS_MASK) >> 24
  364. }
  365. // NOTE(beau): no need for VM_SET_FLAGS_ALIAS, just mask in things from
  366. // VM_Flag.Alias_Mask*
  367. /* These are the flags that we accept from user-space */
  368. VM_FLAGS_USER_ALLOCATE :: VM_Flags {
  369. .Anywhere,
  370. .Purgable,
  371. ._4GB_Chunk,
  372. .Random_Addr,
  373. .No_Cache,
  374. .Permanent,
  375. .Overwrite,
  376. } | VM_FLAGS_FIXED | VM_FLAGS_SUPERPAGE_MASK | VM_FLAGS_ALIAS_MASK
  377. VM_FLAGS_USER_MAP :: VM_Flags {
  378. .Return_4K_Data_Addr,
  379. .Return_Data_Addr,
  380. } | VM_FLAGS_USER_ALLOCATE
  381. VM_FLAGS_USER_REMAP :: VM_Flags {
  382. .Anywhere,
  383. .Random_Addr,
  384. .Overwrite,
  385. .Return_Data_Addr,
  386. .Resilient_Codesign,
  387. .Resilient_Media,
  388. } | VM_FLAGS_FIXED
  389. VM_FLAGS_SUPERPAGE_NONE :: VM_Flags{} /* no superpages, if all bits are 0 */
  390. /*
  391. * Protection values, defined as bits within the vm_prot_t type
  392. */
  393. VM_Prot :: enum vm_prot_t {
  394. Read,
  395. Write,
  396. Execute,
  397. }
  398. VM_Prot_Flags :: distinct bit_set[VM_Prot; vm_prot_t]
  399. VM_PROT_NONE :: VM_Prot_Flags{}
  400. VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write}
  401. VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute}
  402. /*
  403. * Enumeration of valid values for vm_inherit_t.
  404. */
  405. VM_Inherit :: enum vm_inherit_t {
  406. Share,
  407. Copy,
  408. None,
  409. Donate_Copy,
  410. Default = Copy,
  411. Last_Valid = None,
  412. }
  413. Sync_Policy :: enum sync_policy_t {
  414. Fifo,
  415. Fixed_Priority,
  416. Reversed,
  417. Order_Mask,
  418. Lifo = Fifo | Reversed,
  419. }