Browse Source

Added virtual memory headers for Darwin.

Christoffer Lerno 3 years ago
parent
commit
f45e8e5d47
1 changed files with 148 additions and 0 deletions
  1. 148 0
      core/mem/virtual/virtual_darwin.odin

+ 148 - 0
core/mem/virtual/virtual_darwin.odin

@@ -0,0 +1,148 @@
+//+build darwin
+//+private
+package mem_virtual
+
+foreign import libc "System.framework"
+import "core:c"
+
+PROT_NONE  :: 0x0 /* [MC2] no permissions */
+PROT_READ  :: 0x1 /* [MC2] pages can be read */
+PROT_WRITE :: 0x2 /* [MC2] pages can be written */
+PROT_EXEC  :: 0x4 /* [MC2] pages can be executed */
+
+// Sharing options
+MAP_SHARED    :: 0x1 /* [MF|SHM] share changes */
+MAP_PRIVATE   :: 0x2 /* [MF|SHM] changes are private */
+
+// Other flags
+MAP_FIXED        :: 0x0010 /* [MF|SHM] interpret addr exactly */
+MAP_RENAME       :: 0x0020 /* Sun: rename private pages to file */
+MAP_NORESERVE    :: 0x0040 /* Sun: don't reserve needed swap area */
+MAP_RESERVED0080 :: 0x0080 /* previously unimplemented MAP_INHERIT */
+MAP_NOEXTEND     :: 0x0100 /* for MAP_FILE, don't change file size */
+MAP_HASSEMAPHORE :: 0x0200 /* region may contain semaphores */
+MAP_NOCACHE      :: 0x0400 /* don't cache pages for this mapping */
+MAP_JIT          :: 0x0800 /* Allocate a region that will be used for JIT purposes */
+
+// Mapping type
+MAP_FILE         :: 0x0000  /* map from file (default) */
+MAP_ANONYMOUS    :: 0x1000  /* allocated from memory, swap space */
+
+
+/*
+ * The MAP_RESILIENT_* flags can be used when the caller wants to map some
+ * possibly unreliable memory and be able to access it safely, possibly
+ * getting the wrong contents rather than raising any exception.
+ * For safety reasons, such mappings have to be read-only (PROT_READ access
+ * only).
+ *
+ * MAP_RESILIENT_CODESIGN:
+ *      accessing this mapping will not generate code-signing violations,
+ *	even if the contents are tainted.
+ * MAP_RESILIENT_MEDIA:
+ *	accessing this mapping will not generate an exception if the contents
+ *	are not available (unreachable removable or remote media, access beyond
+ *	end-of-file, ...).  Missing contents will be replaced with zeroes.
+ */
+MAP_RESILIENT_CODESIGN :: 0x2000 /* no code-signing failures */
+MAP_RESILIENT_MEDIA    :: 0x4000 /* no backing-store failures */
+
+MAP_32BIT        :: 0x8000          /* Return virtual addresses <4G only */
+
+// Flags used to support translated processes.
+MAP_TRANSLATED_ALLOW_EXECUTE :: 0x20000 /* allow execute in translated processes */
+MAP_UNIX03       :: 0x40000 /* UNIX03 compliance */
+
+// Process memory locking
+MCL_CURRENT     :: 0x0001  /* [ML] Lock only current memory */
+MCL_FUTURE      :: 0x0002  /* [ML] Lock all future memory as well */
+
+MADV_NORMAL      :: 0 /* [MC1] no further special treatment */
+MADV_RANDOM      :: 1 /* [MC1] expect random page refs */
+MADV_SEQUENTIAL  :: 2 /* [MC1] expect sequential page refs */
+MADV_WILLNEED    :: 3 /* [MC1] will need these pages */
+MADV_DONTNEED    :: 4 /* [MC1] dont need these pages */
+MADV_FREE        :: 5 /* pages unneeded, discard contents */
+MADV_ZERO_WIRED_PAGES :: 6 /* zero the wired pages that have not been unwired before the entry is deleted */
+MADV_FREE_REUSABLE :: 7 /* pages can be reused (by anyone) */
+MADV_FREE_REUSE  :: 8 /* caller wants to reuse those pages */
+MADV_CAN_REUSE   :: 9
+MADV_PAGEOUT     :: 10 /* page out now (internal only) */
+
+// msync() flags
+MS_ASYNC        :: 0x0001  /* [MF|SIO] return immediately */
+MS_INVALIDATE   :: 0x0002  /* [MF|SIO] invalidate all cached data */
+MS_SYNC         :: 0x0010  /* [MF|SIO] msync synchronously */
+MS_KILLPAGES    :: 0x0004  /* invalidate pages, leave mapped */
+MS_DEACTIVATE   :: 0x0008  /* deactivate pages, leave mapped */
+
+// Return bits from mincore
+MINCORE_INCORE           :: 0x1      /* Page is incore */
+MINCORE_REFERENCED       :: 0x2      /* Page has been referenced by us */
+MINCORE_MODIFIED         :: 0x4      /* Page has been modified by us */
+MINCORE_REFERENCED_OTHER :: 0x8      /* Page has been referenced */
+MINCORE_MODIFIED_OTHER   :: 0x10     /* Page has been modified */
+MINCORE_PAGED_OUT        :: 0x20     /* Page has been paged out */
+MINCORE_COPIED           :: 0x40     /* Page has been copied */
+MINCORE_ANONYMOUS        :: 0x80     /* Page belongs to an anonymous object */
+
+// Allocation failure result
+MAP_FAILED : rawptr = rawptr(~uintptr(0))
+
+foreign libc {
+	@(link_name="mlockall")         _mlockall           :: proc(flags: c.int) -> c.int ---
+	@(link_name="munlockall")       _munlockall         :: proc() -> c.int ---
+	@(link_name="mlock")            _mlock              :: proc(addr: rawptr, len: c.size_t) -> c.int ---
+	@(link_name="mmap")             _mmap               :: proc(addr: rawptr, len: c.size_t, prot: c.int, flags: c.int, fd: c.int, offset: int) -> rawptr ---
+	@(link_name="mprotect")         _mprotect           :: proc(addr: rawptr, len: c.size_t, prot: c.int) -> c.int ---
+	@(link_name="msync")            _msync              :: proc(addr: rawptr, len: c.size_t) -> c.int ---
+	@(link_name="munlock")          _munlock            :: proc(addr: rawptr, len: c.size_t) -> c.int ---
+	@(link_name="munmap")           _munmap             :: proc(addr: rawptr, len: c.size_t) -> c.int ---
+	@(link_name="shm_open")         _shm_open           :: proc(name: cstring, oflag: c.int, #c_vararg args: ..any) -> c.int ---
+	@(link_name="shm_unlink")       _shm_unlink         :: proc(name: cstring) -> c.int ---
+	@(link_name="posix_madvise")    _posix_madvise      :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
+	@(link_name="madvise")          _madvise            :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
+	@(link_name="mincore")          _mincore            :: proc(addr: rawptr, len: c.size_t, vec: cstring) -> c.int ---
+	@(link_name="minherit")         _minherit           :: proc(addr: rawptr, len: c.size_t, inherit: c.int) -> c.int ---
+}
+
+
+_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
+	result := _mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+	if result == MAP_FAILED {
+		return nil, .Out_Of_Memory
+	}
+	return ([^]byte)(uintptr(result))[:size], nil
+}
+
+_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
+	result := _mprotect(data, size, PROT_READ|PROT_WRITE)
+	if result != 0 {
+		return .Out_Of_Memory
+	}
+	return nil
+}
+_decommit :: proc "contextless" (data: rawptr, size: uint) {
+	_mprotect(data, size, PROT_NONE)
+	_madvise(data, size, MADV_FREE)
+}
+_release :: proc "contextless" (data: rawptr, size: uint) {
+	_munmap(data, size)
+}
+_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
+	pflags: c.int
+	pflags = PROT_NONE
+	if .Read    in flags { pflags |= PROT_READ  }
+	if .Write   in flags { pflags |= PROT_WRITE }
+	if .Execute in flags { pflags |= PROT_EXEC  }
+	err := _mprotect(data, size, pflags)
+	return err != 0
+}
+
+
+_platform_memory_init :: proc() {
+	DEFAULT_PAGE_SIZE = 4096
+	
+	// is power of two
+	assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
+}