aboutsummaryrefslogtreecommitdiff
path: root/core/mem/virtual/virtual_posix.odin
blob: 4bb161770780f7e73c3d5618c4fd10399b06bee6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#+build darwin, netbsd, freebsd, openbsd
#+private
package mem_virtual

import "core:sys/posix"

_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
	if posix.mprotect(data, size, { .READ, .WRITE }) != .OK {
		#partial switch posix.errno() {
		case .EACCES, .EPERM:   return .Invalid_Pointer
		case .ENOTSUP, .EINVAL: return .Invalid_Argument
		case:                   return .Out_Of_Memory
		}
	}

	return nil
}

_release :: proc "contextless" (data: rawptr, size: uint) {
	posix.munmap(data, size)
}

_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
	#assert(i32(posix.Prot_Flag_Bits.READ)  == i32(Protect_Flag.Read))
	#assert(i32(posix.Prot_Flag_Bits.WRITE) == i32(Protect_Flag.Write))
	#assert(i32(posix.Prot_Flag_Bits.EXEC)  == i32(Protect_Flag.Execute))

	return posix.mprotect(data, size, transmute(posix.Prot_Flags)flags) == .OK
}

_platform_memory_init :: proc "contextless" () {
	// NOTE: `posix.PAGESIZE` due to legacy reasons could be wrong so we use `sysconf`.
	size := posix.sysconf(._PAGESIZE)
	DEFAULT_PAGE_SIZE = uint(max(size, posix.PAGESIZE))

	// is power of two
	assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}

_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
	#assert(i32(posix.Prot_Flag_Bits.READ)  == i32(Map_File_Flag.Read))
	#assert(i32(posix.Prot_Flag_Bits.WRITE) == i32(Map_File_Flag.Write))

	addr := posix.mmap(nil, uint(size), transmute(posix.Prot_Flags)flags, { .SHARED }, posix.FD(fd))
	if addr == posix.MAP_FAILED || addr == nil {
		return nil, .Map_Failure
	}
	return ([^]byte)(addr)[:size], nil
}