virtual_linux.odin 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. //+build linux
  2. //+private
  3. package mem_virtual
  4. import "core:c"
  5. import "core:intrinsics"
  6. import "core:sys/unix"
  7. PROT_NONE :: 0x0
  8. PROT_READ :: 0x1
  9. PROT_WRITE :: 0x2
  10. PROT_EXEC :: 0x4
  11. PROT_GROWSDOWN :: 0x01000000
  12. PROT_GROWSUP :: 0x02000000
  13. MAP_FIXED :: 0x1
  14. MAP_PRIVATE :: 0x2
  15. MAP_SHARED :: 0x4
  16. MAP_ANONYMOUS :: 0x20
  17. MADV_NORMAL :: 0
  18. MADV_RANDOM :: 1
  19. MADV_SEQUENTIAL :: 2
  20. MADV_WILLNEED :: 3
  21. MADV_DONTNEED :: 4
  22. MADV_FREE :: 8
  23. MADV_REMOVE :: 9
  24. MADV_DONTFORK :: 10
  25. MADV_DOFORK :: 11
  26. MADV_MERGEABLE :: 12
  27. MADV_UNMERGEABLE :: 13
  28. MADV_HUGEPAGE :: 14
  29. MADV_NOHUGEPAGE :: 15
  30. MADV_DONTDUMP :: 16
  31. MADV_DODUMP :: 17
  32. MADV_WIPEONFORK :: 18
  33. MADV_KEEPONFORK :: 19
  34. MADV_HWPOISON :: 100
  35. mmap :: proc "contextless" (addr: rawptr, length: uint, prot: c.int, flags: c.int, fd: c.int, offset: uintptr) -> int {
  36. res := intrinsics.syscall(unix.SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
  37. return int(res)
  38. }
  39. munmap :: proc "contextless" (addr: rawptr, length: uint) -> c.int {
  40. res := intrinsics.syscall(unix.SYS_munmap, uintptr(addr), uintptr(length))
  41. return c.int(res)
  42. }
  43. mprotect :: proc "contextless" (addr: rawptr, length: uint, prot: c.int) -> c.int {
  44. res := intrinsics.syscall(unix.SYS_mprotect, uintptr(addr), uintptr(length), uint(prot))
  45. return c.int(res)
  46. }
  47. madvise :: proc "contextless" (addr: rawptr, length: uint, advice: c.int) -> c.int {
  48. res := intrinsics.syscall(unix.SYS_madvise, uintptr(addr), uintptr(length), uintptr(advice))
  49. return c.int(res)
  50. }
  51. _reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
  52. result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
  53. if result < 0 && result > -4096 {
  54. return nil, .Out_Of_Memory
  55. }
  56. return ([^]byte)(uintptr(result))[:size], nil
  57. }
  58. _commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
  59. result := mprotect(data, size, PROT_READ|PROT_WRITE)
  60. if result != 0 {
  61. // TODO(bill): Handle error value correctly
  62. return .Out_Of_Memory
  63. }
  64. return nil
  65. }
  66. _decommit :: proc "contextless" (data: rawptr, size: uint) {
  67. mprotect(data, size, PROT_NONE)
  68. madvise(data, size, MADV_FREE)
  69. }
  70. _release :: proc "contextless" (data: rawptr, size: uint) {
  71. munmap(data, size)
  72. }
  73. _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
  74. pflags: c.int
  75. pflags = PROT_NONE
  76. if .Read in flags { pflags |= PROT_READ }
  77. if .Write in flags { pflags |= PROT_WRITE }
  78. if .Execute in flags { pflags |= PROT_EXEC }
  79. err := mprotect(data, size, pflags)
  80. return err != 0
  81. }
  82. _platform_memory_init :: proc() {
  83. DEFAULT_PAGE_SIZE = 4096
  84. // is power of two
  85. assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
  86. }