1dnl -*- Autoconf -*- 2dnl Copyright (C) 1993-2010, 2017-2018 Free Software Foundation, Inc. 3dnl This file is free software, distributed under the terms of the GNU 4dnl General Public License. As a special exception to the GNU General 5dnl Public License, this file may be distributed as part of a program 6dnl that contains a configuration script generated by Autoconf, under 7dnl the same distribution terms as the rest of that program. 8 9dnl From Bruno Haible, Marcus Daniels, Sam Steingold. 10 11AC_PREREQ([2.57]) 12 13AC_DEFUN([CL_MMAP], 14[ 15 AC_BEFORE([$0], [CL_MUNMAP]) 16 AC_BEFORE([$0], [CL_MPROTECT]) 17 AC_CHECK_HEADER([sys/mman.h], [], [no_mmap=1]) 18 if test -z "$no_mmap"; then 19 AC_CHECK_FUNC([mmap], [], [no_mmap=1]) 20 if test -z "$no_mmap"; then 21 AC_DEFINE([HAVE_MMAP],,[have <sys/mmap.h> and the mmap() function]) 22 dnl Test whether mmap with MAP_FIXED works. 23 dnl We cannot expect that it works at *all* addresses that we try, 24 dnl because every platform has a different address space layout. 25 dnl Therefore here we try whether it works at least for *some* addresses. 26 dnl The determination of the mmapable address ranges is done later. 27 AC_CACHE_CHECK([for mmap at fixed addresses], [cl_cv_func_mmap_fixed], 28 [mmap_prog_1=' 29 #include <stdlib.h> 30 #ifdef HAVE_UNISTD_H 31 #include <unistd.h> 32 #endif 33 #include <fcntl.h> 34 #include <sys/types.h> 35 #include <sys/mman.h> 36 int main () 37 { 38 ' 39 mmap_prog_2=' 40 { 41 unsigned long my_size = 32768; /* hope that 32768 is a multiple of the page size */ 42 unsigned int successful_calls = 0; 43 unsigned long addr; 44 for (addr = 0x01230000UL;;) 45 { 46 if (mmap((void*)(addr & -my_size),my_size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) != (void*)-1) 47 { 48 /* Require at least 2 successful mmap calls. This avoids 49 spurious success on HP-UX IA-64 with 32-bit ABI. */ 50 if (++successful_calls >= 2) 51 exit(0); 52 } 53 { 54 unsigned long next_addr = (unsigned long)((double)addr * 1.94); 55 if (next_addr <= addr) break; 56 addr = next_addr; 57 } 58 } 59 exit(1); 60 } 61 } 62 ' 63 succeeded= 64 AC_TRY_RUN(GL_NOCRASH[ 65 $mmap_prog_1 66 int flags = MAP_ANON | MAP_PRIVATE; 67 int fd = -1; 68 nocrash_init(); 69 $mmap_prog_2 70 ], 71 [succeeded="$succeeded"${succeeded:+,}"MAP_ANON"], 72 [], 73 [: # When cross-compiling, don't assume anything.]) 74 AC_TRY_RUN(GL_NOCRASH[ 75 $mmap_prog_1 76 int flags = MAP_ANONYMOUS | MAP_PRIVATE; 77 int fd = -1; 78 nocrash_init(); 79 $mmap_prog_2 80 ], 81 [succeeded="$succeeded"${succeeded:+,}"MAP_ANONYMOUS"], 82 [], 83 [: # When cross-compiling, don't assume anything.]) 84 AC_TRY_RUN(GL_NOCRASH[ 85 $mmap_prog_1 86 #ifndef MAP_FILE 87 #define MAP_FILE 0 88 #endif 89 int flags = MAP_FILE | MAP_PRIVATE; 90 int fd = open("/dev/zero",O_RDONLY,0666); 91 if (fd<0) exit(1); 92 nocrash_init(); 93 $mmap_prog_2 94 ], 95 [succeeded="$succeeded"${succeeded:+,}"/dev/zero"], 96 [], 97 [: # When cross-compiling, don't assume anything.]) 98 if test -n "$succeeded"; then 99 cl_cv_func_mmap_fixed="yes ($succeeded)" 100 else 101 cl_cv_func_mmap_fixed=no 102 fi 103 ]) 104 succeeded=`echo "$cl_cv_func_mmap_fixed" | LC_ALL=C tr '()' ',,'` 105 case "$succeeded" in 106 yes*,MAP_ANON,* ) 107 AC_DEFINE([HAVE_MMAP_ANON],,[<sys/mman.h> defines MAP_ANON and mmaping with MAP_FIXED | MAP_ANON works]) 108 ;; 109 esac 110 case "$succeeded" in 111 yes*,MAP_ANONYMOUS,* ) 112 AC_DEFINE([HAVE_MMAP_ANONYMOUS],,[<sys/mman.h> defines MAP_ANONYMOUS and mmaping with MAP_FIXED | MAP_ANONYMOUS works]) 113 ;; 114 esac 115 case "$succeeded" in 116 yes*,/dev/zero,* ) 117 AC_DEFINE([HAVE_MMAP_DEVZERO],,[mmaping of the special device /dev/zero with MAP_FIXED works]) 118 ;; 119 esac 120 fi 121 fi 122 123 case "$cl_cv_func_mmap_fixed" in 124 yes*) 125 dnl For SINGLEMAP_MEMORY and the TYPECODES object representation: 126 dnl Test which is the highest bit number < 63 (or < 31) at which the kernel 127 dnl allows us to mmap memory with MAP_FIXED. That is, try 128 dnl 0x4000000000000000 -> 62 129 dnl 0x2000000000000000 -> 61 130 dnl 0x1000000000000000 -> 60 131 dnl ... 132 dnl and return the highest bit number for which mmap succeeds. 133 dnl Don't need to test bit 63 (or 31) because we use it as garcol_bit in TYPECODES. 134 AC_CACHE_CHECK([for highest bit number which can be included in mmaped addresses], 135 [cl_cv_func_mmap_highest_bit], 136 [AC_TRY_RUN([ 137 #include <stdlib.h> 138 #ifdef HAVE_UNISTD_H 139 #include <unistd.h> 140 #endif 141 #include <fcntl.h> 142 #include <sys/types.h> 143 #include <sys/mman.h> 144 #ifndef MAP_FILE 145 #define MAP_FILE 0 146 #endif 147 #ifndef MAP_VARIABLE 148 #define MAP_VARIABLE 0 149 #endif 150 int 151 main () 152 { 153 unsigned int my_size = 32768; /* hope that 32768 is a multiple of the page size */ 154 int pos; 155 for (pos = 8*sizeof(void*)-2; pos > 0; pos--) 156 { 157 unsigned long address = (unsigned long)1 << pos; 158 if (address < 4096) 159 break; 160 #ifdef __ia64__ 161 /* On IA64 in 64-bit mode, the executable sits at 0x4000000000000000. 162 An mmap call to this address would either crash the program (on Linux) 163 or fail (on HP-UX). */ 164 if (pos == 62) 165 continue; 166 #endif 167 #ifdef __arm__ 168 /* On Linux/arm64 with CC="arm-linux-gnueabihf-gcc-4.8", 169 some shared libraries may sit at 0x40000000. An mmap call to 170 this address may crash the program. */ 171 if (pos == 30) 172 address += 0x01000000UL; 173 #endif 174 #ifdef __riscv 175 /* On Linux/riscv64, the ld.so and some shared libraries may 176 sit at 0x2000000000. An mmap call to this address may 177 crash the program. */ 178 if (pos == 37) 179 address += 0x01000000UL; 180 #endif 181 { 182 char *p; 183 #if defined HAVE_MMAP_ANON 184 p = (char *) mmap ((void*)address, my_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_VARIABLE, -1, 0); 185 #elif defined HAVE_MMAP_ANONYMOUS 186 p = (char *) mmap ((void*)address, my_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_VARIABLE, -1, 0); 187 #elif defined HAVE_MMAP_DEVZERO 188 int zero_fd = open("/dev/zero", O_RDONLY, 0666); 189 if (zero_fd < 0) 190 return 1; 191 p = (char *) mmap ((void*)address, my_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_FILE | MAP_VARIABLE, zero_fd, 0); 192 #else 193 ?? 194 #endif 195 if (p != (char*) -1) 196 /* mmap succeeded. */ 197 return pos; 198 } 199 } 200 return 0; 201 } 202 ], 203 [cl_cv_func_mmap_highest_bit=none], 204 [cl_cv_func_mmap_highest_bit=$? 205 case "$cl_cv_func_mmap_highest_bit" in 206 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) dnl Most likely a compiler error code. 207 cl_cv_func_mmap_highest_bit=none ;; 208 esac 209 ], 210 [cl_cv_func_mmap_highest_bit="guessing none"]) 211 ]) 212 case "$cl_cv_func_mmap_highest_bit" in 213 *none) value='-1' ;; 214 *) value="$cl_cv_func_mmap_highest_bit" ;; 215 esac 216 ;; 217 *) 218 value='-1' 219 ;; 220 esac 221 AC_DEFINE_UNQUOTED([MMAP_FIXED_ADDRESS_HIGHEST_BIT], [$value], 222 [Define to the highest bit number that can be included in mmaped addresses.]) 223]) 224