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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#+build windows
#+private
package mem_virtual
foreign import Kernel32 "system:Kernel32.lib"
LPSYSTEM_INFO :: ^SYSTEM_INFO
SYSTEM_INFO :: struct {
using DUMMYUNIONNAME: struct #raw_union {
dwOemId: u32,
using DUMMYSTRUCTNAME:struct {
wProcessorArchitecture: u16,
wReserved: u16,
},
},
dwPageSize: u32,
lpMinimumApplicationAddress: rawptr,
lpMaximumApplicationAddress: rawptr,
dwActiveProcessorMask: uint,
dwNumberOfProcessors: u32,
dwProcessorType: u32,
dwAllocationGranularity: u32,
wProcessorLevel: u16,
wProcessorRevision: u16,
}
MEM_COMMIT :: 0x00001000
MEM_RESERVE :: 0x00002000
MEM_RESET :: 0x00080000
MEM_RESET_UNDO :: 0x01000000
MEM_LARGE_PAGES :: 0x20000000
MEM_PHYSICAL :: 0x00400000
MEM_TOP_DOWN :: 0x00100000
MEM_WRITE_WATCH :: 0x00200000
MEM_DECOMMIT :: 0x00004000
MEM_RELEASE :: 0x00008000
MEM_COALESCE_PLACEHOLDERS :: 0x00000001
MEM_PRESERVE_PLACEHOLDER :: 0x00000002
PAGE_EXECUTE :: 0x10
PAGE_EXECUTE_READ :: 0x20
PAGE_EXECUTE_READWRITE :: 0x40
PAGE_EXECUTE_WRITECOPY :: 0x80
PAGE_NOACCESS :: 0x01
PAGE_READONLY :: 0x02
PAGE_READWRITE :: 0x04
PAGE_WRITECOPY :: 0x08
PAGE_TARGETS_INVALID :: 0x40000000
PAGE_TARGETS_NO_UPDATE :: 0x40000000
SECTION_MAP_WRITE :: 0x0002
SECTION_MAP_READ :: 0x0004
FILE_MAP_WRITE :: SECTION_MAP_WRITE
FILE_MAP_READ :: SECTION_MAP_READ
ERROR_INVALID_ADDRESS :: 487
ERROR_COMMITMENT_LIMIT :: 1455
@(default_calling_convention="system")
foreign Kernel32 {
GetSystemInfo :: proc(lpSystemInfo: LPSYSTEM_INFO) ---
VirtualAlloc :: proc(lpAddress: rawptr, dwSize: uint, flAllocationType: u32, flProtect: u32) -> rawptr ---
VirtualFree :: proc(lpAddress: rawptr, dwSize: uint, dwFreeType: u32) -> b32 ---
VirtualProtect :: proc(lpAddress: rawptr, dwSize: uint, flNewProtect: u32, lpflOldProtect: ^u32) -> b32 ---
GetLastError :: proc() -> u32 ---
CreateFileMappingW :: proc(
hFile: rawptr,
lpFileMappingAttributes: rawptr,
flProtect: u32,
dwMaximumSizeHigh: u32,
dwMaximumSizeLow: u32,
lpName: cstring16,
) -> rawptr ---
MapViewOfFile :: proc(
hFileMappingObject: rawptr,
dwDesiredAccess: u32,
dwFileOffsetHigh: u32,
dwFileOffsetLow: u32,
dwNumberOfBytesToMap: uint,
) -> rawptr ---
}
@(no_sanitize_address)
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := VirtualAlloc(nil, size, MEM_RESERVE, PAGE_READWRITE)
if result == nil {
err = .Out_Of_Memory
return
}
data = ([^]byte)(result)[:size]
return
}
@(no_sanitize_address)
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
result := VirtualAlloc(data, size, MEM_COMMIT, PAGE_READWRITE)
if result == nil {
switch err := GetLastError(); err {
case 0:
return .Invalid_Argument
case ERROR_INVALID_ADDRESS, ERROR_COMMITMENT_LIMIT:
return .Out_Of_Memory
}
return .Out_Of_Memory
}
return nil
}
@(no_sanitize_address)
_decommit :: proc "contextless" (data: rawptr, size: uint) {
VirtualFree(data, size, MEM_DECOMMIT)
}
@(no_sanitize_address)
_release :: proc "contextless" (data: rawptr, size: uint) {
VirtualFree(data, 0, MEM_RELEASE)
}
@(no_sanitize_address)
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
pflags: u32
pflags = PAGE_NOACCESS
switch flags {
case {}: pflags = PAGE_NOACCESS
case {.Read}: pflags = PAGE_READONLY
case {.Read, .Write}: pflags = PAGE_READWRITE
case {.Write}: pflags = PAGE_WRITECOPY
case {.Execute}: pflags = PAGE_EXECUTE
case {.Execute, .Read}: pflags = PAGE_EXECUTE_READ
case {.Execute, .Read, .Write}: pflags = PAGE_EXECUTE_READWRITE
case {.Execute, .Write}: pflags = PAGE_EXECUTE_WRITECOPY
case:
return false
}
old_protect: u32
ok := VirtualProtect(data, size, pflags, &old_protect)
return bool(ok)
}
@(no_sanitize_address)
_platform_memory_init :: proc "contextless" () {
sys_info: SYSTEM_INFO
GetSystemInfo(&sys_info)
DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, uint(sys_info.dwPageSize))
// is power of two
assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
@(no_sanitize_address)
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
page_flags: u32
if flags == {.Read} {
page_flags = PAGE_READONLY
} else if flags == {.Write} {
page_flags = PAGE_READWRITE
} else if flags == {.Read, .Write} {
page_flags = PAGE_READWRITE
} else {
page_flags = PAGE_NOACCESS
}
maximum_size := transmute([2]u32)size
handle := CreateFileMappingW(rawptr(fd), nil, page_flags, maximum_size[1], maximum_size[0], nil)
if handle == nil {
return nil, .Map_Failure
}
desired_access: u32
if .Read in flags {
desired_access |= FILE_MAP_READ
}
if .Write in flags {
desired_access |= FILE_MAP_WRITE
}
file_data := MapViewOfFile(handle, desired_access, 0, 0, uint(size))
return ([^]byte)(file_data)[:size], nil
}
|