39
39
# define MAP_ANONYMOUS MAP_ANON
40
40
#endif
41
41
#if defined(MAP_ALIGNED_SUPER )
42
+ # include <sys/types.h>
43
+ # include <sys/sysctl.h>
44
+ # include <sys/user.h>
42
45
# define MAP_HUGETLB MAP_ALIGNED_SUPER
43
46
#endif
44
47
45
- #if defined(__linux__ ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
48
+ #if ( defined(__linux__ ) || defined( __FreeBSD__ ) ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
46
49
static void * find_prefered_mmap_base (size_t requested_size )
47
50
{
48
- FILE * f ;
49
51
size_t huge_page_size = 2 * 1024 * 1024 ;
50
52
uintptr_t last_free_addr = 0 ;
51
53
uintptr_t last_candidate = (uintptr_t )MAP_FAILED ;
52
54
uintptr_t start , end , text_start = 0 ;
55
+ #if defined(__linux__ )
56
+ FILE * f ;
53
57
char buffer [MAXPATHLEN ];
54
58
55
59
f = fopen ("/proc/self/maps" , "r" );
@@ -89,6 +93,59 @@ static void *find_prefered_mmap_base(size_t requested_size)
89
93
90
94
}
91
95
fclose (f );
96
+ #elif defined(__FreeBSD__ )
97
+ size_t s = 0 ;
98
+ int mib [4 ] = {CTL_KERN , KERN_PROC , KERN_PROC_VMMAP , getpid ()};
99
+ if (sysctl (mib , 4 , NULL , & s , NULL , 0 ) == 0 ) {
100
+ s = s * 4 / 3 ;
101
+ void * addr = mmap (NULL , s , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANON , -1 , 0 );
102
+ if (addr != MAP_FAILED ) {
103
+ if (sysctl (mib , 4 , addr , & s , NULL , 0 ) == 0 ) {
104
+ start = (uintptr_t )addr ;
105
+ end = start + s ;
106
+ while (start < end ) {
107
+ struct kinfo_vmentry * entry = (struct kinfo_vmentry * )start ;
108
+ size_t sz = entry -> kve_structsize ;
109
+ if (sz == 0 ) {
110
+ break ;
111
+ }
112
+ uintptr_t e_start = entry -> kve_start ;
113
+ uintptr_t e_end = entry -> kve_end ;
114
+ if ((uintptr_t )execute_ex >= e_start ) {
115
+ /* the current segment lays before PHP .text segment or PHP .text segment itself */
116
+ if (last_free_addr + requested_size <= e_start ) {
117
+ last_candidate = last_free_addr ;
118
+ }
119
+ if ((uintptr_t )execute_ex < e_end ) {
120
+ /* the current segment is PHP .text segment itself */
121
+ if (last_candidate != (uintptr_t )MAP_FAILED ) {
122
+ if (e_end - last_candidate < UINT32_MAX ) {
123
+ /* we have found a big enough hole before the text segment */
124
+ break ;
125
+ }
126
+ last_candidate = (uintptr_t )MAP_FAILED ;
127
+ }
128
+ text_start = e_start ;
129
+ }
130
+ } else {
131
+ /* the current segment lays after PHP .text segment */
132
+ if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
133
+ /* the current segment and the following segments lay too far from PHP .text segment */
134
+ break ;
135
+ }
136
+ if (last_free_addr + requested_size <= e_start ) {
137
+ last_candidate = last_free_addr ;
138
+ break ;
139
+ }
140
+ }
141
+ last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (e_end , huge_page_size );
142
+ start += sz ;
143
+ }
144
+ }
145
+ munmap (addr , s );
146
+ }
147
+ }
148
+ #endif
92
149
93
150
return (void * )last_candidate ;
94
151
}
@@ -109,7 +166,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
109
166
#ifdef PROT_MAX
110
167
flags |= PROT_MAX (PROT_READ | PROT_WRITE | PROT_EXEC );
111
168
#endif
112
- #if defined(__linux__ ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
169
+ #if ( defined(__linux__ ) || defined( __FreeBSD__ ) ) && (defined(__x86_64__ ) || defined (__aarch64__ ))
113
170
void * hint = find_prefered_mmap_base (requested_size );
114
171
if (hint != MAP_FAILED ) {
115
172
# ifdef MAP_HUGETLB
0 commit comments