123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- package darwin
- foreign import mach "system:System.framework"
- import "core:c"
- import "base:intrinsics"
- kern_return_t :: distinct c.int
- mach_port_t :: distinct c.uint
- vm_map_t :: mach_port_t
- mem_entry_name_port_t :: mach_port_t
- ipc_space_t :: mach_port_t
- thread_t :: mach_port_t
- task_t :: mach_port_t
- semaphore_t :: mach_port_t
- vm_size_t :: distinct c.uintptr_t
- vm_address_t :: vm_offset_t
- vm_offset_t :: distinct c.uintptr_t
- // NOTE(beau): typedefed to int in the original headers
- boolean_t :: b32
- vm_prot_t :: distinct c.int
- vm_inherit_t :: distinct c.uint
- mach_port_name_t :: distinct c.uint
- sync_policy_t :: distinct c.int
- @(default_calling_convention="c")
- foreign mach {
- mach_task_self :: proc() -> mach_port_t ---
- semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return ---
- semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return ---
- semaphore_signal :: proc(semaphore: semaphore_t) -> Kern_Return ---
- semaphore_signal_all :: proc(semaphore: semaphore_t) -> Kern_Return ---
- semaphore_signal_thread :: proc(semaphore: semaphore_t, thread: thread_t) -> Kern_Return ---
- semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return ---
- vm_allocate :: proc (target_task : vm_map_t, address: ^vm_address_t, size: vm_size_t, flags: VM_Flags) -> Kern_Return ---
- vm_deallocate :: proc(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) -> Kern_Return ---
- vm_map :: proc(
- target_task: vm_map_t,
- address: ^vm_address_t,
- size: vm_size_t,
- mask: vm_address_t,
- flags: VM_Flags,
- object: mem_entry_name_port_t,
- offset: vm_offset_t,
- copy: boolean_t,
- cur_protection,
- max_protection: VM_Prot_Flags,
- inheritance: VM_Inherit,
- ) -> Kern_Return ---
- mach_make_memory_entry :: proc(
- target_task: vm_map_t,
- size: ^vm_size_t,
- offset: vm_offset_t,
- permission: VM_Prot_Flags,
- object_handle: ^mem_entry_name_port_t,
- parent_entry: mem_entry_name_port_t,
- ) -> Kern_Return ---
- mach_port_deallocate :: proc(
- task: ipc_space_t,
- name: mach_port_name_t,
- ) -> Kern_Return ---
- vm_page_size: vm_size_t
- }
- Kern_Return :: enum kern_return_t {
- Success,
- /* Specified address is not currently valid.
- */
- Invalid_Address,
- /* Specified memory is valid, but does not permit the
- * required forms of access.
- */
- Protection_Failure,
- /* The address range specified is already in use, or
- * no address range of the size specified could be
- * found.
- */
- No_Space,
- /* The function requested was not applicable to this
- * type of argument, or an argument is invalid
- */
- Invalid_Argument,
- /* The function could not be performed. A catch-all.
- */
- Failure,
- /* A system resource could not be allocated to fulfill
- * this request. This failure may not be permanent.
- */
- Resource_Shortage,
- /* The task in question does not hold receive rights
- * for the port argument.
- */
- Not_Receiver,
- /* Bogus access restriction.
- */
- No_Access,
- /* During a page fault, the target address refers to a
- * memory object that has been destroyed. This
- * failure is permanent.
- */
- Memory_Failure,
- /* During a page fault, the memory object indicated
- * that the data could not be returned. This failure
- * may be temporary; future attempts to access this
- * same data may succeed, as defined by the memory
- * object.
- */
- Memory_Error,
- /* The receive right is already a member of the portset.
- */
- Already_In_Set,
- /* The receive right is not a member of a port set.
- */
- Not_In_Set,
- /* The name already denotes a right in the task.
- */
- Name_Exists,
- /* The operation was aborted. Ipc code will
- * catch this and reflect it as a message error.
- */
- Aborted,
- /* The name doesn't denote a right in the task.
- */
- Invalid_Name,
- /* Target task isn't an active task.
- */
- Invalid_Task,
- /* The name denotes a right, but not an appropriate right.
- */
- Invalid_Right,
- /* A blatant range error.
- */
- Invalid_Value,
- /* Operation would overflow limit on user-references.
- */
- URefs_Overflow,
- /* The supplied (port) capability is improper.
- */
- Invalid_Capability,
- /* The task already has send or receive rights
- * for the port under another name.
- */
- Right_Exists,
- /* Target host isn't actually a host.
- */
- Invalid_Host,
- /* An attempt was made to supply "precious" data
- * for memory that is already present in a
- * memory object.
- */
- Memory_Present,
- /* A page was requested of a memory manager via
- * memory_object_data_request for an object using
- * a MEMORY_OBJECT_COPY_CALL strategy, with the
- * VM_PROT_WANTS_COPY flag being used to specify
- * that the page desired is for a copy of the
- * object, and the memory manager has detected
- * the page was pushed into a copy of the object
- * while the kernel was walking the shadow chain
- * from the copy to the object. This error code
- * is delivered via memory_object_data_error
- * and is handled by the kernel (it forces the
- * kernel to restart the fault). It will not be
- * seen by users.
- */
- Memory_Data_Moved,
- /* A strategic copy was attempted of an object
- * upon which a quicker copy is now possible.
- * The caller should retry the copy using
- * vm_object_copy_quickly. This error code
- * is seen only by the kernel.
- */
- Memory_Restart_Copy,
- /* An argument applied to assert processor set privilege
- * was not a processor set control port.
- */
- Invalid_Processor_Set,
- /* The specified scheduling attributes exceed the thread's
- * limits.
- */
- Policy_Limit,
- /* The specified scheduling policy is not currently
- * enabled for the processor set.
- */
- Invalid_Policy,
- /* The external memory manager failed to initialize the
- * memory object.
- */
- Invalid_Object,
- /* A thread is attempting to wait for an event for which
- * there is already a waiting thread.
- */
- Already_Waiting,
- /* An attempt was made to destroy the default processor
- * set.
- */
- Default_Set,
- /* An attempt was made to fetch an exception port that is
- * protected, or to abort a thread while processing a
- * protected exception.
- */
- Exception_Protected,
- /* A ledger was required but not supplied.
- */
- Invalid_Ledger,
- /* The port was not a memory cache control port.
- */
- Invalid_Memory_Control,
- /* An argument supplied to assert security privilege
- * was not a host security port.
- */
- Invalid_Security,
- /* thread_depress_abort was called on a thread which
- * was not currently depressed.
- */
- Not_Depressed,
- /* Object has been terminated and is no longer available
- */
- Terminated,
- /* Lock set has been destroyed and is no longer available.
- */
- Lock_Set_Destroyed,
- /* The thread holding the lock terminated before releasing
- * the lock
- */
- Lock_Unstable,
- /* The lock is already owned by another thread
- */
- Lock_Owned,
- /* The lock is already owned by the calling thread
- */
- Lock_Owned_Self,
- /* Semaphore has been destroyed and is no longer available.
- */
- Semaphore_Destroyed,
- /* Return from RPC indicating the target server was
- * terminated before it successfully replied
- */
- Rpc_Server_Terminated,
- /* Terminate an orphaned activation.
- */
- RPC_Terminate_Orphan,
- /* Allow an orphaned activation to continue executing.
- */
- RPC_Continue_Orphan,
- /* Empty thread activation (No thread linked to it)
- */
- Not_Supported,
- /* Remote node down or inaccessible.
- */
- Node_Down,
- /* A signalled thread was not actually waiting. */
- Not_Waiting,
- /* Some thread-oriented operation (semaphore_wait) timed out
- */
- Operation_Timed_Out,
- /* During a page fault, indicates that the page was rejected
- * as a result of a signature check.
- */
- Codesign_Error,
- /* The requested property cannot be changed at this time.
- */
- Policy_Static,
- /* The provided buffer is of insufficient size for the requested data.
- */
- Insufficient_Buffer_Size,
- /* Denied by security policy
- */
- Denied,
- /* The KC on which the function is operating is missing
- */
- Missing_KC,
- /* The KC on which the function is operating is invalid
- */
- Invalid_KC,
- /* A search or query operation did not return a result
- */
- Not_Found,
- /* Maximum return value allowable
- */
- Return_Max = 0x100,
- }
- /*
- * VM allocation flags:
- *
- * VM_FLAGS_FIXED
- * (really the absence of VM_FLAGS_ANYWHERE)
- * Allocate new VM region at the specified virtual address, if possible.
- *
- * VM_FLAGS_ANYWHERE
- * Allocate new VM region anywhere it would fit in the address space.
- *
- * VM_FLAGS_PURGABLE
- * Create a purgable VM object for that new VM region.
- *
- * VM_FLAGS_4GB_CHUNK
- * The new VM region will be chunked up into 4GB sized pieces.
- *
- * VM_FLAGS_NO_PMAP_CHECK
- * (for DEBUG kernel config only, ignored for other configs)
- * Do not check that there is no stale pmap mapping for the new VM region.
- * This is useful for kernel memory allocations at bootstrap when building
- * the initial kernel address space while some memory is already in use.
- *
- * VM_FLAGS_OVERWRITE
- * The new VM region can replace existing VM regions if necessary
- * (to be used in combination with VM_FLAGS_FIXED).
- *
- * VM_FLAGS_NO_CACHE
- * Pages brought in to this VM region are placed on the speculative
- * queue instead of the active queue. In other words, they are not
- * cached so that they will be stolen first if memory runs low.
- */
- @(private="file")
- LOG2 :: intrinsics.constant_log2
- VM_Flag :: enum c.int {
- Anywhere,
- Purgable,
- _4GB_Chunk,
- Random_Addr,
- No_Cache,
- Resilient_Codesign,
- Resilient_Media,
- Permanent,
- // NOTE(beau): log 2 of the bit we want in the bit set so we get that bit in
- // the bit set
- TPRO = LOG2(0x1000),
- Overwrite = LOG2(0x4000),/* delete any existing mappings first */
- Superpage_Size_Any = LOG2(0x10000),
- Superpage_Size_2MB = LOG2(0x20000),
- __Superpage3 = LOG2(0x40000),
- Return_Data_Addr = LOG2(0x100000),
- Return_4K_Data_Addr = LOG2(0x800000),
- Alias_Mask1 = 24,
- Alias_Mask2,
- Alias_Mask3,
- Alias_Mask4,
- Alias_Mask5,
- Alias_Mask6,
- Alias_Mask7,
- Alias_Mask8,
- HW = TPRO,
- }
- VM_Flags :: distinct bit_set[VM_Flag; c.int]
- VM_FLAGS_FIXED :: VM_Flags{}
- /*
- * VM_FLAGS_SUPERPAGE_MASK
- * 3 bits that specify whether large pages should be used instead of
- * base pages (!=0), as well as the requested page size.
- */
- VM_FLAGS_SUPERPAGE_MASK :: VM_Flags {
- .Superpage_Size_Any,
- .Superpage_Size_2MB,
- .__Superpage3,
- }
- // 0xFF000000
- VM_FLAGS_ALIAS_MASK :: VM_Flags {
- .Alias_Mask1,
- .Alias_Mask2,
- .Alias_Mask3,
- .Alias_Mask4,
- .Alias_Mask5,
- .Alias_Mask6,
- .Alias_Mask7,
- .Alias_Mask8,
- }
- VM_GET_FLAGS_ALIAS :: proc(flags: VM_Flags) -> c.int {
- return transmute(c.int)(flags & VM_FLAGS_ALIAS_MASK) >> 24
- }
- // NOTE(beau): no need for VM_SET_FLAGS_ALIAS, just mask in things from
- // VM_Flag.Alias_Mask*
- /* These are the flags that we accept from user-space */
- VM_FLAGS_USER_ALLOCATE :: VM_Flags {
- .Anywhere,
- .Purgable,
- ._4GB_Chunk,
- .Random_Addr,
- .No_Cache,
- .Permanent,
- .Overwrite,
- } | VM_FLAGS_FIXED | VM_FLAGS_SUPERPAGE_MASK | VM_FLAGS_ALIAS_MASK
- VM_FLAGS_USER_MAP :: VM_Flags {
- .Return_4K_Data_Addr,
- .Return_Data_Addr,
- } | VM_FLAGS_USER_ALLOCATE
- VM_FLAGS_USER_REMAP :: VM_Flags {
- .Anywhere,
- .Random_Addr,
- .Overwrite,
- .Return_Data_Addr,
- .Resilient_Codesign,
- .Resilient_Media,
- } | VM_FLAGS_FIXED
- VM_FLAGS_SUPERPAGE_NONE :: VM_Flags{} /* no superpages, if all bits are 0 */
- /*
- * Protection values, defined as bits within the vm_prot_t type
- */
- VM_Prot :: enum vm_prot_t {
- Read,
- Write,
- Execute,
- }
- VM_Prot_Flags :: distinct bit_set[VM_Prot; vm_prot_t]
- VM_PROT_NONE :: VM_Prot_Flags{}
- VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write}
- VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute}
- /*
- * Enumeration of valid values for vm_inherit_t.
- */
- VM_Inherit :: enum vm_inherit_t {
- Share,
- Copy,
- None,
- Donate_Copy,
- Default = Copy,
- Last_Valid = None,
- }
- Sync_Policy :: enum sync_policy_t {
- Fifo,
- Fixed_Priority,
- Reversed,
- Order_Mask,
- Lifo = Fifo | Reversed,
- }
|