virtual_darwin.odin 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //+build darwin
  2. //+private
  3. package mem_virtual
  4. foreign import libc "system:System.framework"
  5. import "core:c"
  6. PROT_NONE :: 0x0 /* [MC2] no permissions */
  7. PROT_READ :: 0x1 /* [MC2] pages can be read */
  8. PROT_WRITE :: 0x2 /* [MC2] pages can be written */
  9. PROT_EXEC :: 0x4 /* [MC2] pages can be executed */
  10. // Sharing options
  11. MAP_SHARED :: 0x1 /* [MF|SHM] share changes */
  12. MAP_PRIVATE :: 0x2 /* [MF|SHM] changes are private */
  13. // Other flags
  14. MAP_FIXED :: 0x0010 /* [MF|SHM] interpret addr exactly */
  15. MAP_RENAME :: 0x0020 /* Sun: rename private pages to file */
  16. MAP_NORESERVE :: 0x0040 /* Sun: don't reserve needed swap area */
  17. MAP_RESERVED0080 :: 0x0080 /* previously unimplemented MAP_INHERIT */
  18. MAP_NOEXTEND :: 0x0100 /* for MAP_FILE, don't change file size */
  19. MAP_HASSEMAPHORE :: 0x0200 /* region may contain semaphores */
  20. MAP_NOCACHE :: 0x0400 /* don't cache pages for this mapping */
  21. MAP_JIT :: 0x0800 /* Allocate a region that will be used for JIT purposes */
  22. // Mapping type
  23. MAP_FILE :: 0x0000 /* map from file (default) */
  24. MAP_ANONYMOUS :: 0x1000 /* allocated from memory, swap space */
  25. /*
  26. * The MAP_RESILIENT_* flags can be used when the caller wants to map some
  27. * possibly unreliable memory and be able to access it safely, possibly
  28. * getting the wrong contents rather than raising any exception.
  29. * For safety reasons, such mappings have to be read-only (PROT_READ access
  30. * only).
  31. *
  32. * MAP_RESILIENT_CODESIGN:
  33. * accessing this mapping will not generate code-signing violations,
  34. * even if the contents are tainted.
  35. * MAP_RESILIENT_MEDIA:
  36. * accessing this mapping will not generate an exception if the contents
  37. * are not available (unreachable removable or remote media, access beyond
  38. * end-of-file, ...). Missing contents will be replaced with zeroes.
  39. */
  40. MAP_RESILIENT_CODESIGN :: 0x2000 /* no code-signing failures */
  41. MAP_RESILIENT_MEDIA :: 0x4000 /* no backing-store failures */
  42. MAP_32BIT :: 0x8000 /* Return virtual addresses <4G only */
  43. // Flags used to support translated processes.
  44. MAP_TRANSLATED_ALLOW_EXECUTE :: 0x20000 /* allow execute in translated processes */
  45. MAP_UNIX03 :: 0x40000 /* UNIX03 compliance */
  46. // Process memory locking
  47. MCL_CURRENT :: 0x0001 /* [ML] Lock only current memory */
  48. MCL_FUTURE :: 0x0002 /* [ML] Lock all future memory as well */
  49. MADV_NORMAL :: 0 /* [MC1] no further special treatment */
  50. MADV_RANDOM :: 1 /* [MC1] expect random page refs */
  51. MADV_SEQUENTIAL :: 2 /* [MC1] expect sequential page refs */
  52. MADV_WILLNEED :: 3 /* [MC1] will need these pages */
  53. MADV_DONTNEED :: 4 /* [MC1] dont need these pages */
  54. MADV_FREE :: 5 /* pages unneeded, discard contents */
  55. MADV_ZERO_WIRED_PAGES :: 6 /* zero the wired pages that have not been unwired before the entry is deleted */
  56. MADV_FREE_REUSABLE :: 7 /* pages can be reused (by anyone) */
  57. MADV_FREE_REUSE :: 8 /* caller wants to reuse those pages */
  58. MADV_CAN_REUSE :: 9
  59. MADV_PAGEOUT :: 10 /* page out now (internal only) */
  60. // msync() flags
  61. MS_ASYNC :: 0x0001 /* [MF|SIO] return immediately */
  62. MS_INVALIDATE :: 0x0002 /* [MF|SIO] invalidate all cached data */
  63. MS_SYNC :: 0x0010 /* [MF|SIO] msync synchronously */
  64. MS_KILLPAGES :: 0x0004 /* invalidate pages, leave mapped */
  65. MS_DEACTIVATE :: 0x0008 /* deactivate pages, leave mapped */
  66. // Return bits from mincore
  67. MINCORE_INCORE :: 0x1 /* Page is incore */
  68. MINCORE_REFERENCED :: 0x2 /* Page has been referenced by us */
  69. MINCORE_MODIFIED :: 0x4 /* Page has been modified by us */
  70. MINCORE_REFERENCED_OTHER :: 0x8 /* Page has been referenced */
  71. MINCORE_MODIFIED_OTHER :: 0x10 /* Page has been modified */
  72. MINCORE_PAGED_OUT :: 0x20 /* Page has been paged out */
  73. MINCORE_COPIED :: 0x40 /* Page has been copied */
  74. MINCORE_ANONYMOUS :: 0x80 /* Page belongs to an anonymous object */
  75. // Allocation failure result
  76. MAP_FAILED : rawptr = rawptr(~uintptr(0))
  77. foreign libc {
  78. @(link_name="mlockall") _mlockall :: proc(flags: c.int) -> c.int ---
  79. @(link_name="munlockall") _munlockall :: proc() -> c.int ---
  80. @(link_name="mlock") _mlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
  81. @(link_name="mmap") _mmap :: proc(addr: rawptr, len: c.size_t, prot: c.int, flags: c.int, fd: c.int, offset: int) -> rawptr ---
  82. @(link_name="mprotect") _mprotect :: proc(addr: rawptr, len: c.size_t, prot: c.int) -> c.int ---
  83. @(link_name="msync") _msync :: proc(addr: rawptr, len: c.size_t) -> c.int ---
  84. @(link_name="munlock") _munlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
  85. @(link_name="munmap") _munmap :: proc(addr: rawptr, len: c.size_t) -> c.int ---
  86. @(link_name="shm_open") _shm_open :: proc(name: cstring, oflag: c.int, #c_vararg args: ..any) -> c.int ---
  87. @(link_name="shm_unlink") _shm_unlink :: proc(name: cstring) -> c.int ---
  88. @(link_name="posix_madvise") _posix_madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
  89. @(link_name="madvise") _madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
  90. @(link_name="mincore") _mincore :: proc(addr: rawptr, len: c.size_t, vec: cstring) -> c.int ---
  91. @(link_name="minherit") _minherit :: proc(addr: rawptr, len: c.size_t, inherit: c.int) -> c.int ---
  92. }
  93. _reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
  94. result := _mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
  95. if result == MAP_FAILED {
  96. return nil, .Out_Of_Memory
  97. }
  98. return ([^]byte)(uintptr(result))[:size], nil
  99. }
  100. _commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
  101. result := _mprotect(data, size, PROT_READ|PROT_WRITE)
  102. if result != 0 {
  103. return .Out_Of_Memory
  104. }
  105. return nil
  106. }
  107. _decommit :: proc "contextless" (data: rawptr, size: uint) {
  108. _mprotect(data, size, PROT_NONE)
  109. _madvise(data, size, MADV_FREE)
  110. }
  111. _release :: proc "contextless" (data: rawptr, size: uint) {
  112. _munmap(data, size)
  113. }
  114. _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
  115. pflags: c.int
  116. pflags = PROT_NONE
  117. if .Read in flags { pflags |= PROT_READ }
  118. if .Write in flags { pflags |= PROT_WRITE }
  119. if .Execute in flags { pflags |= PROT_EXEC }
  120. err := _mprotect(data, size, pflags)
  121. return err == 0
  122. }
  123. _platform_memory_init :: proc() {
  124. DEFAULT_PAGE_SIZE = 4096
  125. // is power of two
  126. assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
  127. }
  128. _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
  129. prot, mflags: c.int
  130. if .Read in flags {
  131. prot |= PROT_READ
  132. }
  133. if .Write in flags {
  134. prot |= PROT_WRITE
  135. }
  136. mflags |= MAP_SHARED
  137. addr := _mmap(nil, c.size_t(size), prot, mflags, i32(fd), 0)
  138. if addr == nil {
  139. return nil, .Map_Failure
  140. }
  141. return ([^]byte)(addr)[:size], nil
  142. }