diff --git a/core/mem/virtual/virtual_linux.odin b/core/mem/virtual/virtual_linux.odin new file mode 100644 index 000000000..df542aea1 --- /dev/null +++ b/core/mem/virtual/virtual_linux.odin @@ -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) +}