@@ -419,6 +419,14 @@ stderr_last_error(char *msg)
419
419
static void zend_mm_munmap (void * addr , size_t size )
420
420
{
421
421
#ifdef _WIN32
422
+ MEMORY_BASIC_INFORMATION mbi ;
423
+ if (VirtualQuery (addr , & mbi , sizeof (mbi )) == 0 ) {
424
+ #if ZEND_MM_ERROR
425
+ stderr_last_error ("VirtualQuery() failed" );
426
+ #endif
427
+ }
428
+ addr = mbi .AllocationBase ;
429
+
422
430
if (VirtualFree (addr , 0 , MEM_RELEASE ) == 0 ) {
423
431
#if ZEND_MM_ERROR
424
432
stderr_last_error ("VirtualFree() failed" );
@@ -433,19 +441,52 @@ static void zend_mm_munmap(void *addr, size_t size)
433
441
#endif
434
442
}
435
443
436
- static void * zend_mm_mmap (size_t size )
437
- {
438
444
#ifdef _WIN32
439
- void * ptr = VirtualAlloc (NULL , size , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE );
445
+ static void * zend_mm_mmap_win_reserve (size_t size )
446
+ {
447
+ void * ptr = VirtualAlloc (NULL , size , MEM_RESERVE , PAGE_READWRITE );
448
+ if (ptr == NULL ) {
449
+ #if ZEND_MM_ERROR
450
+ stderr_last_error ("VirtualAlloc() reserve failed" );
451
+ #endif
452
+ return NULL ;
453
+ }
454
+ return ptr ;
455
+ }
440
456
457
+ #ifndef _WIN64
458
+ static void * zend_mm_mmap_win_reserve_fixed (void * addr , size_t size )
459
+ {
460
+ void * ptr = VirtualAlloc (addr , size , MEM_RESERVE , PAGE_READWRITE );
441
461
if (ptr == NULL ) {
462
+ /** ERROR_INVALID_ADDRESS is expected when addr - addr+size is not free */
463
+ if (GetLastError () != ERROR_INVALID_ADDRESS ) {
442
464
#if ZEND_MM_ERROR
443
- stderr_last_error ("VirtualAlloc() failed" );
465
+ stderr_last_error ("VirtualAlloc() reserve fixed failed" );
444
466
#endif
467
+ }
468
+ SetLastError (0 );
445
469
return NULL ;
446
470
}
447
471
return ptr ;
448
- #else
472
+ }
473
+ #endif
474
+
475
+ static void * zend_mm_mmap_win_commit (void * addr , size_t size )
476
+ {
477
+ void * ptr = VirtualAlloc (addr , size , MEM_COMMIT , PAGE_READWRITE );
478
+ if (ptr == NULL ) {
479
+ #if ZEND_MM_ERROR
480
+ stderr_last_error ("VirtualAlloc() commit failed" );
481
+ #endif
482
+ return NULL ;
483
+ }
484
+ ZEND_ASSERT (ptr == addr );
485
+ return ptr ;
486
+ }
487
+ #else /* not Windows */
488
+ static void * zend_mm_mmap (size_t size )
489
+ {
449
490
void * ptr ;
450
491
451
492
#ifdef MAP_HUGETLB
@@ -458,43 +499,39 @@ static void *zend_mm_mmap(size_t size)
458
499
#endif
459
500
460
501
ptr = mmap (NULL , size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANON , ZEND_MM_FD , 0 );
461
-
462
502
if (ptr == MAP_FAILED ) {
463
503
#if ZEND_MM_ERROR
464
504
fprintf (stderr , "\nmmap() failed: [%d] %s\n" , errno , strerror (errno ));
465
505
#endif
466
506
return NULL ;
467
507
}
468
508
return ptr ;
469
- #endif
470
509
}
510
+ #endif
471
511
472
512
#ifndef HAVE_MREMAP
513
+ #ifndef _WIN32
473
514
static void * zend_mm_mmap_fixed (void * addr , size_t size )
474
515
{
475
- #ifdef _WIN32
476
- return VirtualAlloc (addr , size , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE );
477
- #else
478
516
int flags = MAP_PRIVATE | MAP_ANON ;
479
517
#if defined(MAP_EXCL )
480
518
flags |= MAP_FIXED | MAP_EXCL ;
481
519
#endif
482
520
/* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
483
521
void * ptr = mmap (addr , size , PROT_READ | PROT_WRITE , flags /*| MAP_POPULATE | MAP_HUGETLB*/ , ZEND_MM_FD , 0 );
484
-
485
522
if (ptr == MAP_FAILED ) {
486
523
#if ZEND_MM_ERROR && !defined(MAP_EXCL )
487
- fprintf (stderr , "\nmmap() failed: [%d] %s\n" , errno , strerror (errno ));
524
+ fprintf (stderr , "\nmmap() fixed failed: [%d] %s\n" , errno , strerror (errno ));
488
525
#endif
489
526
return NULL ;
490
527
} else if (ptr != addr ) {
491
528
zend_mm_munmap (ptr , size );
492
529
return NULL ;
493
530
}
494
531
return ptr ;
495
- #endif
496
532
}
497
533
#endif
534
+ #endif
498
535
499
536
/***********/
500
537
/* Bitmask */
@@ -660,28 +697,47 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse
660
697
661
698
static void * zend_mm_chunk_alloc_int (size_t size , size_t alignment )
662
699
{
663
- void * ptr = zend_mm_mmap (size );
664
-
700
+ #ifdef _WIN32
701
+ void * ptr = NULL ;
702
+ size_t offset ;
703
+ #ifndef _WIN64
704
+ /* 32-bit build has limited memory address space and partical deallocation is not supported,
705
+ * try to reserve exact aligned size first, GH-9650 */
706
+ ptr = zend_mm_mmap_win_reserve (size + alignment );
665
707
if (ptr == NULL ) {
666
708
return NULL ;
667
- } else if (ZEND_MM_ALIGNED_OFFSET (ptr , alignment ) != 0 ) {
668
- size_t offset ;
709
+ }
669
710
670
- /* chunk has to be aligned */
671
- zend_mm_munmap ( ptr , size );
672
- ptr = zend_mm_mmap ( size + alignment - REAL_PAGE_SIZE ) ;
673
- #ifdef _WIN32
674
- offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
675
- zend_mm_munmap ( ptr , size + alignment - REAL_PAGE_SIZE );
676
- ptr = zend_mm_mmap_fixed (( void * )(( char * ) ptr + ( alignment - offset )), size );
677
- offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
678
- if ( offset != 0 ) {
679
- zend_mm_munmap (ptr , size );
711
+ offset = ZEND_MM_ALIGNED_OFFSET ( ptr , alignment );
712
+ if ( offset != 0 ) {
713
+ offset = alignment - offset ;
714
+ }
715
+ zend_mm_munmap (ptr , size + alignment );
716
+ ptr = zend_mm_mmap_win_reserve_fixed (( void * )(( char * ) ptr + offset ), size );
717
+ #endif
718
+ if (ptr == NULL ) {
719
+ ptr = zend_mm_mmap_win_reserve ( size + alignment );
720
+ if (ptr == NULL ) {
680
721
return NULL ;
681
722
}
682
- return ptr ;
723
+ }
724
+
725
+ offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
726
+ if (offset != 0 ) {
727
+ offset = alignment - offset ;
728
+ }
729
+ return zend_mm_mmap_win_commit ((void * )((char * )ptr + offset ), size );
683
730
#else
684
- offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
731
+ void * ptr = zend_mm_mmap (size );
732
+ if (ptr == NULL ) {
733
+ return NULL ;
734
+ }
735
+
736
+ if (ZEND_MM_ALIGNED_OFFSET (ptr , alignment ) != 0 ) {
737
+ zend_mm_munmap (ptr , size );
738
+ ptr = zend_mm_mmap (size + alignment - REAL_PAGE_SIZE );
739
+
740
+ size_t offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
685
741
if (offset != 0 ) {
686
742
offset = alignment - offset ;
687
743
zend_mm_munmap (ptr , offset );
@@ -691,7 +747,6 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
691
747
if (alignment > REAL_PAGE_SIZE ) {
692
748
zend_mm_munmap ((char * )ptr + size , alignment - REAL_PAGE_SIZE );
693
749
}
694
- #endif
695
750
}
696
751
697
752
#ifdef MADV_HUGEPAGE
@@ -701,6 +756,7 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
701
756
#endif
702
757
703
758
return ptr ;
759
+ #endif
704
760
}
705
761
706
762
static void * zend_mm_chunk_alloc (zend_mm_heap * heap , size_t size , size_t alignment )
@@ -1838,11 +1894,7 @@ static zend_mm_heap *zend_mm_init(void)
1838
1894
1839
1895
if (UNEXPECTED (chunk == NULL )) {
1840
1896
#if ZEND_MM_ERROR
1841
- #ifdef _WIN32
1842
- stderr_last_error ("Can't initialize heap" );
1843
- #else
1844
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
1845
- #endif
1897
+ fprintf (stderr , "Can't initialize heap\n" );
1846
1898
#endif
1847
1899
return NULL ;
1848
1900
}
@@ -2969,11 +3021,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
2969
3021
chunk = (zend_mm_chunk * )handlers -> chunk_alloc (& tmp_storage , ZEND_MM_CHUNK_SIZE , ZEND_MM_CHUNK_SIZE );
2970
3022
if (UNEXPECTED (chunk == NULL )) {
2971
3023
#if ZEND_MM_ERROR
2972
- #ifdef _WIN32
2973
- stderr_last_error ("Can't initialize heap" );
2974
- #else
2975
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
2976
- #endif
3024
+ fprintf (stderr , "Can't initialize heap\n" );
2977
3025
#endif
2978
3026
return NULL ;
2979
3027
}
@@ -3016,11 +3064,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
3016
3064
if (!storage ) {
3017
3065
handlers -> chunk_free (& tmp_storage , chunk , ZEND_MM_CHUNK_SIZE );
3018
3066
#if ZEND_MM_ERROR
3019
- #ifdef _WIN32
3020
- stderr_last_error ("Can't initialize heap" );
3021
- #else
3022
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
3023
- #endif
3067
+ fprintf (stderr , "Can't initialize heap\n" );
3024
3068
#endif
3025
3069
return NULL ;
3026
3070
}
0 commit comments