@@ -416,50 +416,77 @@ stderr_last_error(char *msg)
416
416
/* OS Allocation */
417
417
/*****************/
418
418
419
- #ifndef HAVE_MREMAP
420
- static void * zend_mm_mmap_fixed (void * addr , size_t size )
419
+ static void zend_mm_munmap (void * addr , size_t size )
421
420
{
422
421
#ifdef _WIN32
423
- return VirtualAlloc (addr , size , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE );
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
+
430
+ if (VirtualFree (addr , 0 , MEM_RELEASE ) == 0 ) {
431
+ #if ZEND_MM_ERROR
432
+ stderr_last_error ("VirtualFree() failed" );
433
+ #endif
434
+ }
424
435
#else
425
- int flags = MAP_PRIVATE | MAP_ANON ;
426
- #if defined( MAP_EXCL )
427
- flags |= MAP_FIXED | MAP_EXCL ;
436
+ if ( munmap ( addr , size ) != 0 ) {
437
+ #if ZEND_MM_ERROR
438
+ fprintf ( stderr , "\nmunmap() failed: [%d] %s\n" , errno , strerror ( errno )) ;
428
439
#endif
429
- /* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
430
- void * ptr = mmap (addr , size , PROT_READ | PROT_WRITE , flags /*| MAP_POPULATE | MAP_HUGETLB*/ , ZEND_MM_FD , 0 );
440
+ }
441
+ #endif
442
+ }
431
443
432
- if (ptr == MAP_FAILED ) {
433
- #if ZEND_MM_ERROR && !defined(MAP_EXCL )
434
- fprintf (stderr , "\nmmap() failed: [%d] %s\n" , errno , strerror (errno ));
444
+ #ifdef _WIN32
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" );
435
451
#endif
436
452
return NULL ;
437
- } else if (ptr != addr ) {
438
- if (munmap (ptr , size ) != 0 ) {
453
+ }
454
+ return ptr ;
455
+ }
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 );
461
+ if (ptr == NULL ) {
462
+ /** ERROR_INVALID_ADDRESS is expected when addr - addr+size is not free */
463
+ if (GetLastError () != ERROR_INVALID_ADDRESS ) {
439
464
#if ZEND_MM_ERROR
440
- fprintf ( stderr , "\nmunmap () failed: [%d] %s\n" , errno , strerror ( errno ) );
465
+ stderr_last_error ( "VirtualAlloc () reserve fixed failed" );
441
466
#endif
442
467
}
468
+ SetLastError (0 );
443
469
return NULL ;
444
470
}
445
471
return ptr ;
446
- #endif
447
472
}
448
473
#endif
449
474
450
- static void * zend_mm_mmap ( size_t size )
475
+ static void * zend_mm_mmap_win_commit ( void * addr , size_t size )
451
476
{
452
- #ifdef _WIN32
453
- void * ptr = VirtualAlloc (NULL , size , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE );
454
-
477
+ void * ptr = VirtualAlloc (addr , size , MEM_COMMIT , PAGE_READWRITE );
455
478
if (ptr == NULL ) {
456
479
#if ZEND_MM_ERROR
457
- stderr_last_error ("VirtualAlloc() failed" );
480
+ stderr_last_error ("VirtualAlloc() commit failed" );
458
481
#endif
459
482
return NULL ;
460
483
}
484
+ ZEND_ASSERT (ptr == addr );
461
485
return ptr ;
462
- #else
486
+ }
487
+ #else /* not Windows */
488
+ static void * zend_mm_mmap (size_t size )
489
+ {
463
490
void * ptr ;
464
491
465
492
#ifdef MAP_HUGETLB
@@ -472,33 +499,39 @@ static void *zend_mm_mmap(size_t size)
472
499
#endif
473
500
474
501
ptr = mmap (NULL , size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANON , ZEND_MM_FD , 0 );
475
-
476
502
if (ptr == MAP_FAILED ) {
477
503
#if ZEND_MM_ERROR
478
504
fprintf (stderr , "\nmmap() failed: [%d] %s\n" , errno , strerror (errno ));
479
505
#endif
480
506
return NULL ;
481
507
}
482
508
return ptr ;
483
- #endif
484
509
}
510
+ #endif
485
511
486
- static void zend_mm_munmap (void * addr , size_t size )
512
+ #ifndef HAVE_MREMAP
513
+ #ifndef _WIN32
514
+ static void * zend_mm_mmap_fixed (void * addr , size_t size )
487
515
{
488
- #ifdef _WIN32
489
- if (VirtualFree (addr , 0 , MEM_RELEASE ) == 0 ) {
490
- #if ZEND_MM_ERROR
491
- stderr_last_error ("VirtualFree() failed" );
516
+ int flags = MAP_PRIVATE | MAP_ANON ;
517
+ #if defined(MAP_EXCL )
518
+ flags |= MAP_FIXED | MAP_EXCL ;
492
519
#endif
493
- }
494
- #else
495
- if (munmap ( addr , size ) != 0 ) {
496
- #if ZEND_MM_ERROR
497
- fprintf (stderr , "\nmunmap() failed: [%d] %s\n" , errno , strerror (errno ));
520
+ /* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
521
+ void * ptr = mmap ( addr , size , PROT_READ | PROT_WRITE , flags /*| MAP_POPULATE | MAP_HUGETLB*/ , ZEND_MM_FD , 0 );
522
+ if (ptr == MAP_FAILED ) {
523
+ #if ZEND_MM_ERROR && !defined( MAP_EXCL )
524
+ fprintf (stderr , "\nmmap() fixed failed: [%d] %s\n" , errno , strerror (errno ));
498
525
#endif
526
+ return NULL ;
527
+ } else if (ptr != addr ) {
528
+ zend_mm_munmap (ptr , size );
529
+ return NULL ;
499
530
}
500
- #endif
531
+ return ptr ;
501
532
}
533
+ #endif
534
+ #endif
502
535
503
536
/***********/
504
537
/* Bitmask */
@@ -664,35 +697,47 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse
664
697
665
698
static void * zend_mm_chunk_alloc_int (size_t size , size_t alignment )
666
699
{
667
- void * ptr = zend_mm_mmap (size );
668
-
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 );
669
707
if (ptr == NULL ) {
670
708
return NULL ;
671
- } else if (ZEND_MM_ALIGNED_OFFSET (ptr , alignment ) == 0 ) {
672
- #ifdef MADV_HUGEPAGE
673
- if (zend_mm_use_huge_pages ) {
674
- madvise (ptr , size , MADV_HUGEPAGE );
675
- }
676
- #endif
677
- return ptr ;
678
- } else {
679
- size_t offset ;
709
+ }
680
710
681
- /* chunk has to be aligned */
682
- zend_mm_munmap ( ptr , size );
683
- ptr = zend_mm_mmap ( size + alignment - REAL_PAGE_SIZE ) ;
684
- #ifdef _WIN32
685
- offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
686
- zend_mm_munmap ( ptr , size + alignment - REAL_PAGE_SIZE );
687
- ptr = zend_mm_mmap_fixed (( void * )(( char * ) ptr + ( alignment - offset )), size );
688
- offset = ZEND_MM_ALIGNED_OFFSET (ptr , alignment );
689
- if ( offset != 0 ) {
690
- 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 ) {
691
721
return NULL ;
692
722
}
693
- 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 );
694
730
#else
695
- 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 );
696
741
if (offset != 0 ) {
697
742
offset = alignment - offset ;
698
743
zend_mm_munmap (ptr , offset );
@@ -702,14 +747,16 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
702
747
if (alignment > REAL_PAGE_SIZE ) {
703
748
zend_mm_munmap ((char * )ptr + size , alignment - REAL_PAGE_SIZE );
704
749
}
705
- # ifdef MADV_HUGEPAGE
706
- if (zend_mm_use_huge_pages ) {
707
- madvise (ptr , size , MADV_HUGEPAGE );
708
- }
709
- # endif
710
- #endif
711
- return ptr ;
712
750
}
751
+
752
+ #ifdef MADV_HUGEPAGE
753
+ if (zend_mm_use_huge_pages ) {
754
+ madvise (ptr , size , MADV_HUGEPAGE );
755
+ }
756
+ #endif
757
+
758
+ return ptr ;
759
+ #endif
713
760
}
714
761
715
762
static void * zend_mm_chunk_alloc (zend_mm_heap * heap , size_t size , size_t alignment )
@@ -1847,11 +1894,7 @@ static zend_mm_heap *zend_mm_init(void)
1847
1894
1848
1895
if (UNEXPECTED (chunk == NULL )) {
1849
1896
#if ZEND_MM_ERROR
1850
- #ifdef _WIN32
1851
- stderr_last_error ("Can't initialize heap" );
1852
- #else
1853
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
1854
- #endif
1897
+ fprintf (stderr , "Can't initialize heap\n" );
1855
1898
#endif
1856
1899
return NULL ;
1857
1900
}
@@ -2978,11 +3021,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
2978
3021
chunk = (zend_mm_chunk * )handlers -> chunk_alloc (& tmp_storage , ZEND_MM_CHUNK_SIZE , ZEND_MM_CHUNK_SIZE );
2979
3022
if (UNEXPECTED (chunk == NULL )) {
2980
3023
#if ZEND_MM_ERROR
2981
- #ifdef _WIN32
2982
- stderr_last_error ("Can't initialize heap" );
2983
- #else
2984
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
2985
- #endif
3024
+ fprintf (stderr , "Can't initialize heap\n" );
2986
3025
#endif
2987
3026
return NULL ;
2988
3027
}
@@ -3025,11 +3064,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
3025
3064
if (!storage ) {
3026
3065
handlers -> chunk_free (& tmp_storage , chunk , ZEND_MM_CHUNK_SIZE );
3027
3066
#if ZEND_MM_ERROR
3028
- #ifdef _WIN32
3029
- stderr_last_error ("Can't initialize heap" );
3030
- #else
3031
- fprintf (stderr , "\nCan't initialize heap: [%d] %s\n" , errno , strerror (errno ));
3032
- #endif
3067
+ fprintf (stderr , "Can't initialize heap\n" );
3033
3068
#endif
3034
3069
return NULL ;
3035
3070
}
0 commit comments