33
33
#include <mach/vm_statistics.h>
34
34
#endif
35
35
36
+ #include "zend_execute.h"
37
+
36
38
#if defined(MAP_ANON ) && !defined(MAP_ANONYMOUS )
37
39
# define MAP_ANONYMOUS MAP_ANON
38
40
#endif
39
41
#if defined(MAP_ALIGNED_SUPER )
40
42
# define MAP_HUGETLB MAP_ALIGNED_SUPER
41
43
#endif
42
44
45
+ #if defined(__linux__ ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
46
+ static void * find_prefered_mmap_base (size_t requested_size )
47
+ {
48
+ FILE * f ;
49
+ size_t huge_page_size = 2 * 1024 * 1024 ;
50
+ uintptr_t last_free_addr = 0 ;
51
+ uintptr_t last_candidate = (uintptr_t )MAP_FAILED ;
52
+ uintptr_t start , end , text_start = 0 ;
53
+ char buffer [MAXPATHLEN ];
54
+
55
+ f = fopen ("/proc/self/maps" , "r" );
56
+ if (!f ) {
57
+ return MAP_FAILED ;
58
+ }
59
+
60
+ while (fgets (buffer , MAXPATHLEN , f ) && sscanf (buffer , "%lx-%lx" , & start , & end ) == 2 ) {
61
+ if ((uintptr_t )execute_ex >= start ) {
62
+ /* the current segment lays before PHP .text segment or PHP .text segment itself */
63
+ if (last_free_addr + requested_size <= start ) {
64
+ last_candidate = last_free_addr ;
65
+ }
66
+ if ((uintptr_t )execute_ex < end ) {
67
+ /* the current segment is PHP .text segment itself */
68
+ if (last_candidate != (uintptr_t )MAP_FAILED ) {
69
+ if (end - last_candidate < UINT32_MAX ) {
70
+ /* we have found a big anough hole before the text segment */
71
+ break ;
72
+ }
73
+ last_candidate = (uintptr_t )MAP_FAILED ;
74
+ }
75
+ text_start = start ;
76
+ }
77
+ } else {
78
+ /* the current segment lays after PHP .text segment */
79
+ if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
80
+ /* the current segment and the following segments lay too far from PHP .text segment */
81
+ break ;
82
+ }
83
+ if (last_free_addr + requested_size <= start ) {
84
+ last_candidate = last_free_addr ;
85
+ break ;
86
+ }
87
+ }
88
+ last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (end , huge_page_size );
89
+
90
+ }
91
+ fclose (f );
92
+
93
+ return (void * )last_candidate ;
94
+ }
95
+ #endif
96
+
43
97
static int create_segments (size_t requested_size , zend_shared_segment * * * shared_segments_p , int * shared_segments_count , char * * error_in )
44
98
{
45
99
zend_shared_segment * shared_segment ;
@@ -55,6 +109,24 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
55
109
#ifdef PROT_MAX
56
110
flags |= PROT_MAX (PROT_READ | PROT_WRITE | PROT_EXEC );
57
111
#endif
112
+ #if defined(__linux__ ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
113
+ void * hint = find_prefered_mmap_base (requested_size );
114
+ if (hint != MAP_FAILED ) {
115
+ # ifdef MAP_HUGETLB
116
+ size_t huge_page_size = 2 * 1024 * 1024 ;
117
+ if (requested_size >= huge_page_size && requested_size % huge_page_size == 0 ) {
118
+ p = mmap (hint , requested_size , flags , MAP_SHARED |MAP_ANONYMOUS |MAP_HUGETLB |MAP_FIXED , -1 , 0 );
119
+ if (p != MAP_FAILED ) {
120
+ goto success ;
121
+ }
122
+ }
123
+ #endif
124
+ p = mmap (hint , requested_size , flags , MAP_SHARED |MAP_ANONYMOUS |MAP_FIXED , -1 , 0 );
125
+ if (p != MAP_FAILED ) {
126
+ goto success ;
127
+ }
128
+ }
129
+ #endif
58
130
#ifdef MAP_HUGETLB
59
131
size_t huge_page_size = 2 * 1024 * 1024 ;
60
132
0 commit comments