|
@@ -0,0 +1,101 @@
|
|
|
+//+build linux
|
|
|
+//+private
|
|
|
+package mem_virtual
|
|
|
+
|
|
|
+import "core:c"
|
|
|
+import "core:intrinsics"
|
|
|
+
|
|
|
+when ODIN_ARCH == "amd64" {
|
|
|
+ SYS_mmap :: 9
|
|
|
+ SYS_mprotect :: 10
|
|
|
+ SYS_munmap :: 11
|
|
|
+ SYS_madvise :: 28
|
|
|
+
|
|
|
+ PROT_NONE :: 0x0
|
|
|
+ PROT_READ :: 0x1
|
|
|
+ PROT_WRITE :: 0x2
|
|
|
+ PROT_EXEC :: 0x4
|
|
|
+ PROT_GROWSDOWN :: 0x01000000
|
|
|
+ PROT_GROWSUP :: 0x02000000
|
|
|
+
|
|
|
+ MAP_FIXED :: 0x1
|
|
|
+ MAP_PRIVATE :: 0x2
|
|
|
+ MAP_SHARED :: 0x4
|
|
|
+ MAP_ANONYMOUS :: 0x20
|
|
|
+
|
|
|
+ MADV_NORMAL :: 0
|
|
|
+ MADV_RANDOM :: 1
|
|
|
+ MADV_SEQUENTIAL :: 2
|
|
|
+ MADV_WILLNEED :: 3
|
|
|
+ MADV_DONTNEED :: 4
|
|
|
+ MADV_FREE :: 8
|
|
|
+ MADV_REMOVE :: 9
|
|
|
+ MADV_DONTFORK :: 10
|
|
|
+ MADV_DOFORK :: 11
|
|
|
+ MADV_MERGEABLE :: 12
|
|
|
+ MADV_UNMERGEABLE :: 13
|
|
|
+ MADV_HUGEPAGE :: 14
|
|
|
+ MADV_NOHUGEPAGE :: 15
|
|
|
+ MADV_DONTDUMP :: 16
|
|
|
+ MADV_DODUMP :: 17
|
|
|
+ MADV_WIPEONFORK :: 18
|
|
|
+ MADV_KEEPONFORK :: 19
|
|
|
+ MADV_HWPOISON :: 100
|
|
|
+} else {
|
|
|
+ #panic("Unsupported architecture")
|
|
|
+}
|
|
|
+
|
|
|
+mmap :: proc "contextless" (addr: rawptr, length: uint, prot: c.int, flags: c.int, fd: c.int, offset: uintptr) -> rawptr {
|
|
|
+ res := intrinsics.syscall(SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
|
|
|
+ return rawptr(res)
|
|
|
+}
|
|
|
+
|
|
|
+munmap :: proc "contextless" (addr: rawptr, length: uint) -> c.int {
|
|
|
+ res := intrinsics.syscall(SYS_munmap, uintptr(addr), uintptr(length))
|
|
|
+ return c.int(res)
|
|
|
+}
|
|
|
+
|
|
|
+mprotect :: proc "contextless" (addr: rawptr, length: uint, prot: c.int) -> c.int {
|
|
|
+ res := intrinsics.syscall(SYS_mprotect, uintptr(addr), uintptr(length), uint(prot))
|
|
|
+ return c.int(res)
|
|
|
+}
|
|
|
+
|
|
|
+madvise :: proc "contextless" (addr: rawptr, length: uint, advice: c.int) -> c.int {
|
|
|
+ res := intrinsics.syscall(SYS_madvise, uintptr(addr), uintptr(length), uintptr(advice))
|
|
|
+ return c.int(res)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+_reserve :: proc(size: uint) -> (data: []byte, err: Allocator_Error) {
|
|
|
+ result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
|
|
+ if result == nil {
|
|
|
+ err = .Out_Of_Memory
|
|
|
+ return
|
|
|
+ }
|
|
|
+ data = ([^]byte)(result)[:size]
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+_commit :: proc(data: rawptr, size: uint) {
|
|
|
+ mprotect(data, size, PROT_READ|PROT_WRITE)
|
|
|
+}
|
|
|
+_decommit :: proc(data: rawptr, size: uint) {
|
|
|
+ mprotect(data, size, PROT_NONE)
|
|
|
+ madvise(data, size, MADV_FREE)
|
|
|
+}
|
|
|
+_release :: proc(data: rawptr, size: uint) {
|
|
|
+ munmap(data, size)
|
|
|
+}
|
|
|
+_protect :: proc(data: rawptr, size: uint) -> bool {
|
|
|
+ err := mprotect(data, size, PROT_NONE)
|
|
|
+ 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)
|
|
|
+}
|