virtual_linux.odin 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #+build linux
  2. #+private
  3. package mem_virtual
  4. import "core:sys/linux"
  5. _reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
  6. addr, errno := linux.mmap(0, size, {}, {.PRIVATE, .ANONYMOUS})
  7. if errno == .ENOMEM {
  8. return nil, .Out_Of_Memory
  9. } else if errno == .EINVAL {
  10. return nil, .Invalid_Argument
  11. }
  12. return (cast([^]byte)addr)[:size], nil
  13. }
  14. _commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
  15. errno := linux.mprotect(data, size, {.READ, .WRITE})
  16. if errno == .EINVAL {
  17. return .Invalid_Pointer
  18. } else if errno == .ENOMEM {
  19. return .Out_Of_Memory
  20. }
  21. return nil
  22. }
  23. _decommit :: proc "contextless" (data: rawptr, size: uint) {
  24. _ = linux.mprotect(data, size, {})
  25. _ = linux.madvise(data, size, .FREE)
  26. }
  27. _release :: proc "contextless" (data: rawptr, size: uint) {
  28. _ = linux.munmap(data, size)
  29. }
  30. _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
  31. pflags: linux.Mem_Protection
  32. pflags = {}
  33. if .Read in flags { pflags += {.READ} }
  34. if .Write in flags { pflags += {.WRITE} }
  35. if .Execute in flags { pflags += {.EXEC} }
  36. errno := linux.mprotect(data, size, pflags)
  37. return errno == .NONE
  38. }
  39. _platform_memory_init :: proc() {
  40. DEFAULT_PAGE_SIZE = 4096
  41. // is power of two
  42. assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
  43. }
  44. _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
  45. prot: linux.Mem_Protection
  46. if .Read in flags {
  47. prot += {.READ}
  48. }
  49. if .Write in flags {
  50. prot += {.WRITE}
  51. }
  52. flags := linux.Map_Flags{.SHARED}
  53. addr, errno := linux.mmap(0, uint(size), prot, flags, linux.Fd(fd), offset=0)
  54. if addr == nil || errno != nil {
  55. return nil, .Map_Failure
  56. }
  57. return ([^]byte)(addr)[:size], nil
  58. }