mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-01 09:41:50 -07:00
Add virtual.map_file
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:os"
|
||||
|
||||
Mapped_File_Error :: enum {
|
||||
None,
|
||||
Open_Failure,
|
||||
Stat_Failure,
|
||||
Negative_Size,
|
||||
Too_Large_Size,
|
||||
Map_Failure,
|
||||
}
|
||||
|
||||
Mapped_File_Flag :: enum u32 {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
Mapped_File_Flags :: distinct bit_set[Mapped_File_Flag; u32]
|
||||
|
||||
map_file :: proc{
|
||||
map_file_from_path,
|
||||
map_file_from_file_descriptor,
|
||||
}
|
||||
|
||||
map_file_from_path :: proc(filename: string, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_File_Error) {
|
||||
fd, err := os.open(filename, os.O_RDWR)
|
||||
if err != 0 {
|
||||
return nil, .Open_Failure
|
||||
}
|
||||
defer os.close(fd)
|
||||
|
||||
return map_file_from_file_descriptor(uintptr(fd), flags)
|
||||
}
|
||||
|
||||
map_file_from_file_descriptor :: proc(fd: uintptr, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_File_Error) {
|
||||
size, os_err := os.file_size(os.Handle(fd))
|
||||
if os_err != 0 {
|
||||
return nil, .Stat_Failure
|
||||
}
|
||||
if size < 0 {
|
||||
return nil, .Negative_Size
|
||||
}
|
||||
if size != i64(int(size)) {
|
||||
return nil, .Too_Large_Size
|
||||
}
|
||||
return _map_file(fd, size, flags)
|
||||
}
|
||||
@@ -22,3 +22,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags)
|
||||
_platform_memory_init :: proc() {
|
||||
|
||||
}
|
||||
|
||||
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_File_Error) {
|
||||
return nil, .Map_Failure
|
||||
}
|
||||
|
||||
@@ -146,3 +146,20 @@ _platform_memory_init :: proc() {
|
||||
// is power of two
|
||||
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
|
||||
}
|
||||
|
||||
|
||||
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_File_Error) {
|
||||
prot, mflags: c.int
|
||||
if .Read in flags {
|
||||
prot |= PROT_READ
|
||||
}
|
||||
if .Write in flags {
|
||||
prot |= PROT_WRITE
|
||||
}
|
||||
mflags |= MAP_SHARED
|
||||
addr := _mmap(nil, c.size_t(size), prot, mflags, i32(fd), 0)
|
||||
if addr == nil {
|
||||
return nil, .Map_Failure
|
||||
}
|
||||
return ([^]byte)(addr)[:size], nil
|
||||
}
|
||||
|
||||
@@ -48,3 +48,21 @@ _platform_memory_init :: proc() {
|
||||
// is power of two
|
||||
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
|
||||
}
|
||||
|
||||
|
||||
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_File_Error) {
|
||||
prot: linux.Mem_Protection
|
||||
if .Read in flags {
|
||||
prot += {.READ}
|
||||
}
|
||||
if .Write in flags {
|
||||
prot += {.WRITE}
|
||||
}
|
||||
|
||||
flags := linux.Map_Flags{.SHARED}
|
||||
addr, errno := linux.mmap(0, uint(size), prot, flags, linux.Fd(fd), offset=0)
|
||||
if addr == nil || error != nil {
|
||||
return nil, .Map_Failure
|
||||
}
|
||||
return ([^]byte)(addr)[:size], nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//+private
|
||||
package mem_virtual
|
||||
|
||||
import "core:os"
|
||||
|
||||
foreign import Kernel32 "system:Kernel32.lib"
|
||||
|
||||
LPSYSTEM_INFO :: ^SYSTEM_INFO
|
||||
@@ -50,6 +52,11 @@ 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
|
||||
|
||||
@@ -60,9 +67,24 @@ foreign Kernel32 {
|
||||
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: [^]u16,
|
||||
) -> rawptr ---
|
||||
|
||||
MapViewOfFile :: proc(
|
||||
hFileMappingObject: rawptr,
|
||||
dwDesiredAccess: u32,
|
||||
dwFileOffsetHigh: u32,
|
||||
dwFileOffsetLow: u32,
|
||||
dwNumberOfBytesToMap: uint,
|
||||
) -> rawptr ---
|
||||
}
|
||||
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
result := VirtualAlloc(nil, size, MEM_RESERVE, PAGE_READWRITE)
|
||||
if result == nil {
|
||||
@@ -125,3 +147,33 @@ _platform_memory_init :: proc() {
|
||||
// is power of two
|
||||
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
|
||||
}
|
||||
|
||||
|
||||
_map_file :: proc "contextless" (fd: os.Handle, size: i64, flags: Mapped_File_Flags) -> (data: []byte, error: Mapped_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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user