Skip to content

Commit 35a9eeb

Browse files
committed
fix aligned alloc on Windows
1 parent 71dc7bb commit 35a9eeb

File tree

1 file changed

+74
-71
lines changed

1 file changed

+74
-71
lines changed

Zend/zend_alloc.c

Lines changed: 74 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,14 @@ stderr_last_error(char *msg)
418418
static void zend_mm_munmap(void *addr, size_t size)
419419
{
420420
#ifdef _WIN32
421+
MEMORY_BASIC_INFORMATION mbi;
422+
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0) {
423+
#if ZEND_MM_ERROR
424+
stderr_last_error("VirtualQuery() failed");
425+
#endif
426+
}
427+
addr = mbi.AllocationBase;
428+
421429
if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
422430
#if ZEND_MM_ERROR
423431
stderr_last_error("VirtualFree() failed");
@@ -432,54 +440,34 @@ static void zend_mm_munmap(void *addr, size_t size)
432440
#endif
433441
}
434442

435-
#ifndef HAVE_MREMAP
436-
static void *zend_mm_mmap_fixed(void *addr, size_t size)
437-
{
438443
#ifdef _WIN32
439-
void *ptr = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
444+
static void *zend_mm_mmap_reserve(size_t size)
445+
{
446+
void *ptr = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_READWRITE);
440447
if (ptr == NULL) {
441448
#if ZEND_MM_ERROR
442-
stderr_last_error("VirtualAlloc() failed");
449+
stderr_last_error("VirtualAlloc() reserve failed");
443450
#endif
444451
return NULL;
445452
}
446-
ZEND_ASSERT(ptr == addr);
447453
return ptr;
448-
#else
449-
int flags = MAP_PRIVATE | MAP_ANON;
450-
#if defined(MAP_EXCL)
451-
flags |= MAP_FIXED | MAP_EXCL;
452-
#endif
453-
/* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
454-
void *ptr = mmap(addr, size, PROT_READ | PROT_WRITE, flags /*| MAP_POPULATE | MAP_HUGETLB*/, ZEND_MM_FD, 0);
455-
456-
if (ptr == MAP_FAILED) {
457-
#if ZEND_MM_ERROR && !defined(MAP_EXCL)
458-
fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
459-
#endif
460-
return NULL;
461-
} else if (ptr != addr) {
462-
zend_mm_munmap(ptr, size);
463-
return NULL;
464-
}
465-
return ptr;
466-
#endif
467454
}
468-
#endif
469455

470-
static void *zend_mm_mmap(size_t size)
456+
static void *zend_mm_mmap_commit(void *addr, size_t size)
471457
{
472-
#ifdef _WIN32
473-
void *ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
474-
458+
void *ptr = VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
475459
if (ptr == NULL) {
476460
#if ZEND_MM_ERROR
477-
stderr_last_error("VirtualAlloc() failed");
461+
stderr_last_error("VirtualAlloc() commit failed");
478462
#endif
479463
return NULL;
480464
}
465+
ZEND_ASSERT(ptr == addr);
481466
return ptr;
467+
}
482468
#else
469+
static void *zend_mm_mmap(size_t size)
470+
{
483471
void *ptr;
484472

485473
#ifdef MAP_HUGETLB
@@ -492,16 +480,39 @@ static void *zend_mm_mmap(size_t size)
492480
#endif
493481

494482
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, ZEND_MM_FD, 0);
495-
496483
if (ptr == MAP_FAILED) {
497484
#if ZEND_MM_ERROR
498485
fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
499486
#endif
500487
return NULL;
501488
}
502489
return ptr;
490+
}
491+
#endif
492+
493+
#ifndef HAVE_MREMAP
494+
#ifndef _WIN32
495+
static void *zend_mm_mmap_fixed(void *addr, size_t size)
496+
{
497+
int flags = MAP_PRIVATE | MAP_ANON;
498+
#if defined(MAP_EXCL)
499+
flags |= MAP_FIXED | MAP_EXCL;
503500
#endif
501+
/* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
502+
void *ptr = mmap(addr, size, PROT_READ | PROT_WRITE, flags /*| MAP_POPULATE | MAP_HUGETLB*/, ZEND_MM_FD, 0);
503+
if (ptr == MAP_FAILED) {
504+
#if ZEND_MM_ERROR && !defined(MAP_EXCL)
505+
fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
506+
#endif
507+
return NULL;
508+
} else if (ptr != addr) {
509+
zend_mm_munmap(ptr, size);
510+
return NULL;
511+
}
512+
return ptr;
504513
}
514+
#endif
515+
#endif
505516

506517
/***********/
507518
/* Bitmask */
@@ -667,52 +678,44 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse
667678

668679
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
669680
{
670-
void *ptr = zend_mm_mmap(size);
681+
#ifdef _WIN32
682+
void *ptr = zend_mm_mmap_reserve(size + alignment/* - REAL_PAGE_SIZE TODO check if really 4KB */);
683+
if (ptr == NULL) {
684+
return NULL;
685+
}
671686

687+
size_t offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
688+
return zend_mm_mmap_commit((void*)((char*)ptr + (alignment - offset)), size);
689+
#else
690+
void *ptr = zend_mm_mmap(size);
672691
if (ptr == NULL) {
673692
return NULL;
674-
} else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
693+
}
694+
695+
if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) != 0) {
696+
zend_mm_munmap(ptr, size);
697+
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
698+
699+
size_t offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
700+
if (offset != 0) {
701+
offset = alignment - offset;
702+
zend_mm_munmap(ptr, offset);
703+
ptr = (char*)ptr + offset;
704+
alignment -= offset;
705+
}
706+
if (alignment > REAL_PAGE_SIZE) {
707+
zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
708+
}
709+
}
710+
675711
#ifdef MADV_HUGEPAGE
676-
if (zend_mm_use_huge_pages) {
677-
madvise(ptr, size, MADV_HUGEPAGE);
678-
}
712+
if (zend_mm_use_huge_pages) {
713+
madvise(ptr, size, MADV_HUGEPAGE);
714+
}
679715
#endif
680-
return ptr;
681-
} else {
682-
size_t offset;
683716

684-
/* chunk has to be aligned */
685-
zend_mm_munmap(ptr, size);
686-
ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
687-
#ifdef _WIN32
688-
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
689-
zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
690-
ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
691-
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
692-
if (offset != 0) {
693-
zend_mm_munmap(ptr, size);
694-
return NULL;
695-
}
696-
return ptr;
697-
#else
698-
offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
699-
if (offset != 0) {
700-
offset = alignment - offset;
701-
zend_mm_munmap(ptr, offset);
702-
ptr = (char*)ptr + offset;
703-
alignment -= offset;
704-
}
705-
if (alignment > REAL_PAGE_SIZE) {
706-
zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
707-
}
708-
# ifdef MADV_HUGEPAGE
709-
if (zend_mm_use_huge_pages) {
710-
madvise(ptr, size, MADV_HUGEPAGE);
711-
}
712-
# endif
717+
return ptr;
713718
#endif
714-
return ptr;
715-
}
716719
}
717720

718721
static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment)

0 commit comments

Comments
 (0)