ensure accessible memory around mmapped files
This commit is contained in:
parent
200d4f6900
commit
307be40ac7
@ -1,9 +1,7 @@
|
|||||||
#define MM_C 1
|
#define MM_C 1
|
||||||
#define ALLOC_PADDING 1024 // number of accessible padding bytes always required around an object
|
|
||||||
|
|
||||||
#include "../core.h"
|
#include "../core.h"
|
||||||
|
#include "../utils/mem.h"
|
||||||
|
|
||||||
ux getPageSize(void);
|
|
||||||
static u64 prepAllocSize(u64 sz) {
|
static u64 prepAllocSize(u64 sz) {
|
||||||
u64 psz = getPageSize();
|
u64 psz = getPageSize();
|
||||||
u64 minTotPad = ALLOC_PADDING*2 + 128;
|
u64 minTotPad = ALLOC_PADDING*2 + 128;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "../core.h"
|
#include "../core.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "mem.h"
|
||||||
#include "talloc.h"
|
#include "talloc.h"
|
||||||
#include "cstr.h"
|
#include "cstr.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@ -44,7 +45,7 @@ void fileRef_freeO(Value* v) {
|
|||||||
fclose(((FileRef*)v)->file);
|
fclose(((FileRef*)v)->file);
|
||||||
}
|
}
|
||||||
NOINLINE FILE* fileRef_open(FILE* f) {
|
NOINLINE FILE* fileRef_open(FILE* f) {
|
||||||
FileRef* fr = m_customObj(sizeof(FileRef), noop_visit, fileRef_freeO);
|
FileRef* fr = m_customObj(sizeof(FileRef), noop_visit, fileRef_freeO); // TODO uhh this could OOM
|
||||||
fr->file = f;
|
fr->file = f;
|
||||||
gsAdd(tag(fr, OBJ_TAG));
|
gsAdd(tag(fr, OBJ_TAG));
|
||||||
return f;
|
return f;
|
||||||
@ -315,7 +316,8 @@ typedef struct MmapHolder {
|
|||||||
struct Arr;
|
struct Arr;
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
int fd;
|
int fd;
|
||||||
u64 size;
|
void* mmap_start;
|
||||||
|
u64 mmap_size;
|
||||||
#else
|
#else
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
HANDLE hMapFile;
|
HANDLE hMapFile;
|
||||||
@ -327,7 +329,7 @@ void mmapH_visit(Value* v) { }
|
|||||||
DEF_FREE(mmapH) {
|
DEF_FREE(mmapH) {
|
||||||
MmapHolder* p = (MmapHolder*)x;
|
MmapHolder* p = (MmapHolder*)x;
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
if (munmap(p->a, p->size)) thrF("Failed to unmap: %S", strerror(errno));
|
if (munmap(p->mmap_start, p->mmap_size)) thrF("Failed to unmap: %S", strerror(errno));
|
||||||
if (close(p->fd)) thrF("Failed to close file: %S", strerror(errno));
|
if (close(p->fd)) thrF("Failed to close file: %S", strerror(errno));
|
||||||
#else
|
#else
|
||||||
if (!UnmapViewOfFile(p->a)) thrF("Failed to unmap: %S", winError());
|
if (!UnmapViewOfFile(p->a)) thrF("Failed to unmap: %S", winError());
|
||||||
@ -342,6 +344,7 @@ static NOINLINE Arr* mmapH_slice(B x, usz s, usz ia) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
B mmap_file(B path) {
|
B mmap_file(B path) {
|
||||||
|
// TODO count mapped memory in some memory usage counter
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
char* p = toCStr(path);
|
char* p = toCStr(path);
|
||||||
dec(path);
|
dec(path);
|
||||||
@ -350,8 +353,18 @@ B mmap_file(B path) {
|
|||||||
if (fd==-1) thrF("Failed to open file: %S", strerror(errno));
|
if (fd==-1) thrF("Failed to open file: %S", strerror(errno));
|
||||||
u64 len = lseek(fd, 0, SEEK_END);
|
u64 len = lseek(fd, 0, SEEK_END);
|
||||||
|
|
||||||
u8* data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); // TODO count in some memory usage counter
|
u64 pgsz = getPageSize();
|
||||||
if (data==MAP_FAILED) {
|
u64 head = pgsz;
|
||||||
|
PLAINLOOP while (head < ALLOC_PADDING) head+= pgsz;
|
||||||
|
u64 mmap_size = len+head*2;
|
||||||
|
u8* mmap_start = mmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (mmap_start==MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
thrM("failed to pre-allocate mmap region");
|
||||||
|
}
|
||||||
|
u8* arr_data = mmap(mmap_start+head, len, PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, 0);
|
||||||
|
if (arr_data==MAP_FAILED) {
|
||||||
|
munmap(mmap_start, mmap_size);
|
||||||
close(fd);
|
close(fd);
|
||||||
thrM("failed to mmap file");
|
thrM("failed to mmap file");
|
||||||
}
|
}
|
||||||
@ -376,19 +389,21 @@ B mmap_file(B path) {
|
|||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
thrF("Failed to create file mapping: %S", winError());
|
thrF("Failed to create file mapping: %S", winError());
|
||||||
}
|
}
|
||||||
u8* data = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
u8* arr_data = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
||||||
if (data==NULL) {
|
// TODO should ensure ALLOC_PADDING padding around allocated memory
|
||||||
|
if (arr_data==NULL) {
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
CloseHandle(hMapFile);
|
CloseHandle(hMapFile);
|
||||||
thrF("Failed to map view of file: %S", winError());
|
thrF("Failed to map view of file: %S", winError());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MmapHolder* holder = m_arrUnchecked(sizeof(MmapHolder), t_mmapH, len);
|
MmapHolder* holder = m_arrUnchecked(sizeof(MmapHolder), t_mmapH, len); // TODO this can OOM
|
||||||
holder->a = data;
|
holder->a = arr_data;
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
holder->fd = fd;
|
holder->fd = fd;
|
||||||
holder->size = len;
|
holder->mmap_start = mmap_start;
|
||||||
|
holder->mmap_size = mmap_size;
|
||||||
#else
|
#else
|
||||||
holder->hFile = hFile;
|
holder->hFile = hFile;
|
||||||
holder->hMapFile = hMapFile;
|
holder->hMapFile = hMapFile;
|
||||||
|
|||||||
3
src/utils/mem.h
Normal file
3
src/utils/mem.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
ux getPageSize(void);
|
||||||
|
#define ALLOC_PADDING 1024 // number of accessible padding bytes always required around an object
|
||||||
2
src/vm.h
2
src/vm.h
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "utils/mem.h"
|
||||||
#if !NO_MMAP
|
#if !NO_MMAP
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
@ -248,7 +249,6 @@ NOINLINE B vm_fmtPoint(B src, B prepend, B path, usz cs, usz ce); // consumes pr
|
|||||||
NOINLINE void printErrMsg(B msg);
|
NOINLINE void printErrMsg(B msg);
|
||||||
NOINLINE void unwindEnv(Env* envNew); // envNew==envStart-1 for emptying the env stack
|
NOINLINE void unwindEnv(Env* envNew); // envNew==envStart-1 for emptying the env stack
|
||||||
NOINLINE void unwindCompiler(void); // unwind to the env of the invocation of the compiler; UB when not in compiler!
|
NOINLINE void unwindCompiler(void); // unwind to the env of the invocation of the compiler; UB when not in compiler!
|
||||||
ux getPageSize(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user