mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-22 14:54:43 +00:00
Write more memory mapping tests
Microsoft claims to support COW but it's probably not true.
This commit is contained in:
parent
74d48f7cb6
commit
2fdc19e7a7
6 changed files with 83 additions and 29 deletions
|
@ -28,13 +28,13 @@
|
||||||
* bypassed by calling this function. However the caller is responsible
|
* bypassed by calling this function. However the caller is responsible
|
||||||
* for passing the magic memory handle on Windows NT to CloseHandle().
|
* for passing the magic memory handle on Windows NT to CloseHandle().
|
||||||
*/
|
*/
|
||||||
noasan struct DirectMap __mmap(void *addr, size_t size, unsigned prot,
|
noasan struct DirectMap __mmap(void *addr, size_t size, int prot, int flags,
|
||||||
unsigned flags, int fd, int64_t off) {
|
int fd, int64_t off) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off),
|
return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off),
|
||||||
kNtInvalidHandleValue};
|
kNtInvalidHandleValue};
|
||||||
} else {
|
} else {
|
||||||
return __sys_mmap_nt(addr, size, prot,
|
return sys_mmap_nt(addr, size, prot, flags,
|
||||||
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
||||||
off);
|
off);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ struct DirectMap {
|
||||||
int64_t maphandle;
|
int64_t maphandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DirectMap __mmap(void *, size_t, unsigned, unsigned, int, int64_t);
|
struct DirectMap __mmap(void *, size_t, int, int, int, int64_t);
|
||||||
struct DirectMap __sys_mmap_nt(void *, size_t, unsigned, int64_t, int64_t);
|
struct DirectMap sys_mmap_nt(void *, size_t, int, int, int64_t, int64_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -18,35 +18,70 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/macros.h"
|
||||||
#include "libc/nt/enum/filemapflags.h"
|
#include "libc/nt/enum/filemapflags.h"
|
||||||
#include "libc/nt/enum/pageflags.h"
|
#include "libc/nt/enum/pageflags.h"
|
||||||
#include "libc/nt/memory.h"
|
#include "libc/nt/memory.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/runtime/directmap.h"
|
#include "libc/runtime/directmap.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
||||||
textwindows noasan struct DirectMap __sys_mmap_nt(void *addr, size_t size,
|
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
||||||
unsigned prot, int64_t handle,
|
int prot, int flags,
|
||||||
int64_t off) {
|
int64_t handle, int64_t off) {
|
||||||
|
uint32_t got;
|
||||||
|
size_t i, upsize;
|
||||||
struct DirectMap dm;
|
struct DirectMap dm;
|
||||||
|
struct NtOverlapped op;
|
||||||
|
if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE) && handle != -1) {
|
||||||
|
/*
|
||||||
|
* WIN32 claims it can do COW mappings but we still haven't found a
|
||||||
|
* combination of flags, that'll cause Windows to actually do this!
|
||||||
|
*/
|
||||||
|
upsize = ROUNDUP(size, FRAMESIZE);
|
||||||
|
if ((dm.maphandle = CreateFileMappingNuma(
|
||||||
|
-1, &kNtIsInheritable, kNtPageExecuteReadwrite, upsize >> 32,
|
||||||
|
upsize, NULL, kNtNumaNoPreferredNode))) {
|
||||||
|
if ((dm.addr = MapViewOfFileExNuma(
|
||||||
|
dm.maphandle, kNtFileMapWrite | kNtFileMapExecute, 0, 0, upsize,
|
||||||
|
addr, kNtNumaNoPreferredNode))) {
|
||||||
|
for (i = 0; i < size; i += got) {
|
||||||
|
got = 0;
|
||||||
|
op.Internal = 0;
|
||||||
|
op.InternalHigh = 0;
|
||||||
|
op.Pointer = (void *)(uintptr_t)i;
|
||||||
|
op.hEvent = 0;
|
||||||
|
if (!ReadFile(handle, (char *)dm.addr + i, size - i, &got, &op)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == size) {
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
UnmapViewOfFile(dm.addr);
|
||||||
|
}
|
||||||
|
CloseHandle(dm.maphandle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if ((dm.maphandle = CreateFileMappingNuma(
|
if ((dm.maphandle = CreateFileMappingNuma(
|
||||||
handle, &kNtIsInheritable,
|
handle, &kNtIsInheritable,
|
||||||
(prot & PROT_WRITE) ? kNtPageExecuteReadwrite : kNtPageExecuteRead,
|
(prot & PROT_WRITE) ? kNtPageExecuteReadwrite : kNtPageExecuteRead,
|
||||||
handle != -1 ? 0 : size >> 32, handle != -1 ? 0 : size, NULL,
|
handle != -1 ? 0 : size >> 32, handle != -1 ? 0 : size, NULL,
|
||||||
kNtNumaNoPreferredNode))) {
|
kNtNumaNoPreferredNode))) {
|
||||||
if (!(dm.addr = MapViewOfFileExNuma(
|
if ((dm.addr = MapViewOfFileExNuma(
|
||||||
dm.maphandle,
|
dm.maphandle,
|
||||||
(prot & PROT_WRITE)
|
(prot & PROT_WRITE) ? kNtFileMapWrite | kNtFileMapExecute
|
||||||
? kNtFileMapWrite | kNtFileMapExecute | kNtFileMapRead
|
: kNtFileMapRead | kNtFileMapExecute,
|
||||||
: kNtFileMapExecute | kNtFileMapRead,
|
|
||||||
off >> 32, off, size, addr, kNtNumaNoPreferredNode))) {
|
off >> 32, off, size, addr, kNtNumaNoPreferredNode))) {
|
||||||
CloseHandle(dm.maphandle);
|
return dm;
|
||||||
dm.maphandle = kNtInvalidHandleValue;
|
|
||||||
dm.addr = (void *)(intptr_t)__winerr();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
CloseHandle(dm.maphandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
dm.maphandle = kNtInvalidHandleValue;
|
dm.maphandle = kNtInvalidHandleValue;
|
||||||
dm.addr = (void *)(intptr_t)__winerr();
|
dm.addr = (void *)(intptr_t)__winerr();
|
||||||
}
|
|
||||||
return dm;
|
return dm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,9 @@ textwindows noasan void WinMainForked(void) {
|
||||||
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
|
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
|
||||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||||
CloseHandle(_mmi.p[i].h);
|
CloseHandle(_mmi.p[i].h);
|
||||||
_mmi.p[i].h = __sys_mmap_nt(addr, size, _mmi.p[i].prot, -1, 0).maphandle;
|
_mmi.p[i].h =
|
||||||
|
sys_mmap_nt(addr, size, _mmi.p[i].prot, _mmi.p[i].flags, -1, 0)
|
||||||
|
.maphandle;
|
||||||
ReadAll(reader, addr, size);
|
ReadAll(reader, addr, size);
|
||||||
} else {
|
} else {
|
||||||
MapViewOfFileExNuma(
|
MapViewOfFileExNuma(
|
||||||
|
|
|
@ -107,8 +107,9 @@ static noasan textwindows wontreturn void WinMainNew(void) {
|
||||||
*(/*unconst*/ int *)&__hostos = WINDOWS;
|
*(/*unconst*/ int *)&__hostos = WINDOWS;
|
||||||
addr = NtGetVersion() < kNtVersionWindows10 ? 0xff00000 : 0x777000000000;
|
addr = NtGetVersion() < kNtVersionWindows10 ? 0xff00000 : 0x777000000000;
|
||||||
size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE);
|
size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE);
|
||||||
_mmi.p[0].h = __sys_mmap_nt((char *)addr, size,
|
_mmi.p[0].h =
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC, -1, 0)
|
sys_mmap_nt((char *)addr, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_PRIVATE, -1, 0)
|
||||||
.maphandle;
|
.maphandle;
|
||||||
_mmi.p[0].x = addr >> 16;
|
_mmi.p[0].x = addr >> 16;
|
||||||
_mmi.p[0].y = (addr >> 16) + ((size >> 16) - 1);
|
_mmi.p[0].y = (addr >> 16) + ((size >> 16) - 1);
|
||||||
|
|
|
@ -120,6 +120,22 @@ TEST(mmap, fileOffset) {
|
||||||
EXPECT_NE(-1, close(fd));
|
EXPECT_NE(-1, close(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(mmap, mapPrivate_writesDontChangeFile) {
|
||||||
|
int fd;
|
||||||
|
char *map, buf[5];
|
||||||
|
ASSERT_NE(-1, (fd = open("foo", O_CREAT | O_RDWR, 0644)));
|
||||||
|
EXPECT_NE(-1, ftruncate(fd, FRAMESIZE));
|
||||||
|
EXPECT_NE(-1, pwrite(fd, "hello", 5, 0));
|
||||||
|
ASSERT_NE(MAP_FAILED, (map = mmap(NULL, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE, fd, 0)));
|
||||||
|
memcpy(map, "there", 5);
|
||||||
|
EXPECT_NE(-1, msync(map, FRAMESIZE, MS_SYNC));
|
||||||
|
EXPECT_NE(-1, munmap(map, FRAMESIZE));
|
||||||
|
EXPECT_NE(-1, pread(fd, buf, 5, 0));
|
||||||
|
EXPECT_EQ(0, memcmp(buf, "hello", 5), "%#.*s", 5, buf);
|
||||||
|
EXPECT_NE(-1, close(fd));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(isheap, nullPtr) {
|
TEST(isheap, nullPtr) {
|
||||||
ASSERT_FALSE(isheap(NULL));
|
ASSERT_FALSE(isheap(NULL));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue