virtual_linux.odin 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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) -> rawptr {
  36. res := intrinsics.syscall(unix.SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
  37. return rawptr(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(size: uint) -> (data: []byte, err: Allocator_Error) {
  52. MAP_FAILED := rawptr(~uintptr(0))
  53. result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
  54. if result == MAP_FAILED {
  55. return nil, .Out_Of_Memory
  56. }
  57. return ([^]byte)(result)[:size], nil
  58. }
  59. _commit :: proc(data: rawptr, size: uint) -> Allocator_Error {
  60. result := mprotect(data, size, PROT_READ|PROT_WRITE)
  61. if result != 0 {
  62. // TODO(bill): Handle error value correctly
  63. return .Out_Of_Memory
  64. }
  65. return nil
  66. }
  67. _decommit :: proc(data: rawptr, size: uint) {
  68. mprotect(data, size, PROT_NONE)
  69. madvise(data, size, MADV_FREE)
  70. }
  71. _release :: proc(data: rawptr, size: uint) {
  72. munmap(data, size)
  73. }
  74. _protect :: proc(data: rawptr, size: uint, flags: Protect_Flags) -> bool {
  75. pflags: c.int
  76. pflags = PROT_NONE
  77. if .Read in flags { pflags |= PROT_READ }
  78. if .Write in flags { pflags |= PROT_WRITE }
  79. if .Execute in flags { pflags |= PROT_EXEC }
  80. err := mprotect(data, size, pflags)
  81. return err != 0
  82. }
  83. _platform_memory_init :: proc() {
  84. DEFAULT_PAGE_SIZE = 4096
  85. // is power of two
  86. assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
  87. }