1dnl mmap.m4 -- Probe for mmap properties. 2dnl $Id: mmap.m4 10397 2020-11-12 20:22:51Z iulius $ 3dnl 4dnl The mmap macro that comes with Autoconf doesn't do anything useful. 5dnl Define a new INN_FUNC_MMAP that probes for a working mmap that supports 6dnl shared, non-fixed maps. This function defines HAVE_MMAP if mmap appears 7dnl to work, and takes an action if found argument that can be used to make 8dnl other probes. 9dnl 10dnl Provide INN_FUNC_MMAP_NEEDS_MSYNC, which defines MMAP_NEEDS_MSYNC if 11dnl reading from an open file doesn't see changes made to that file through 12dnl mmap without an intervening msync. 13dnl 14dnl Provide INN_FUNC_MMAP_MISSES_WRITES, which defines MMAP_MISSES_WRITES if 15dnl changes to a file made with write aren't seen in an mmaped region without 16dnl an intervening msync. 17dnl 18dnl (The above two macros together in essence probe for whether the operating 19dnl system has a unified page cache.) 20dnl 21dnl Finally, provide AC_FUNC_MSYNC_ARGS, which defines HAVE_MSYNC_3_ARGS if 22dnl msync takes three arguments (as on Solaris and Linux) rather than two 23dnl (most other operating systems). 24 25dnl Source used by INN_FUNC_MMAP. 26define([_INN_FUNC_MMAP_SOURCE], 27[AC_LANG_SOURCE([[ 28#include <fcntl.h> 29#include <stdlib.h> 30#include <sys/mman.h> 31#include <sys/stat.h> 32#if HAVE_UNISTD_H 33# include <unistd.h> 34#endif 35 36int 37main() 38{ 39 int *data, *data2; 40 int i, fd; 41 42 /* First, make a file with some known garbage in it. Use something 43 larger than one page but still an odd page size. */ 44 data = malloc (20000); 45 if (!data) 46 return 1; 47 for (i = 0; i < 20000 / sizeof (int); i++) 48 data[i] = rand(); 49 umask (0); 50 fd = creat ("conftestmmaps", 0600); 51 if (fd < 0) 52 return 1; 53 if (write (fd, data, 20000) != 20000) 54 return 1; 55 close (fd); 56 57 /* Next, try to mmap the file and make sure we see the same garbage. */ 58 fd = open ("conftestmmaps", O_RDWR); 59 if (fd < 0) 60 return 1; 61 data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 62 if (data2 == (int *) -1) 63 return 1; 64 for (i = 0; i < 20000 / sizeof (int); i++) 65 if (data[i] != data2[i]) 66 return 1; 67 68 close (fd); 69 unlink ("conftestmmaps"); 70 return 0; 71} 72]])]) 73 74dnl This portion is similar to what AC_FUNC_MMAP does, only it tests shared, 75dnl non-fixed mmaps. 76AC_DEFUN([INN_FUNC_MMAP], 77[AC_CACHE_CHECK([for working mmap], [inn_cv_func_mmap], 78[AC_RUN_IFELSE([_INN_FUNC_MMAP_SOURCE], 79 [inn_cv_func_mmap=yes], 80 [inn_cv_func_mmap=no], 81 [inn_cv_func_mmap=no])]) 82 if test $inn_cv_func_mmap = yes ; then 83 AC_DEFINE([HAVE_MMAP], 1, 84 [Define if mmap exists and works for shared, non-fixed maps.]) 85 $1 86 else 87 : 88 $2 89 fi]) 90 91dnl Source used by INN_FUNC_MMAP_NEEDS_MSYNC. 92define([_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE], 93[AC_LANG_SOURCE([[ 94#include <fcntl.h> 95#include <stdlib.h> 96#include <sys/mman.h> 97#include <sys/stat.h> 98#include <sys/types.h> 99#if HAVE_UNISTD_H 100# include <unistd.h> 101#endif 102 103int 104main() 105{ 106 int *data, *data2; 107 int i, fd; 108 109 /* First, make a file with some known garbage in it. Use something 110 larger than one page but still an odd page size. */ 111 data = malloc (20000); 112 if (!data) 113 return 1; 114 for (i = 0; i < 20000 / sizeof (int); i++) 115 data[i] = rand(); 116 umask (0); 117 fd = creat ("conftestmmaps", 0600); 118 if (fd < 0) 119 return 1; 120 if (write (fd, data, 20000) != 20000) 121 return 1; 122 close (fd); 123 124 /* Next, try to mmap the file and make sure we see the same garbage. */ 125 fd = open ("conftestmmaps", O_RDWR); 126 if (fd < 0) 127 return 1; 128 data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 129 if (data2 == (int *) -1) 130 return 1; 131 132 /* Finally, see if changes made to the mmaped region propagate back to 133 the file as seen by read (meaning that msync isn't needed). */ 134 for (i = 0; i < 20000 / sizeof (int); i++) 135 data2[i]++; 136 if (read (fd, data, 20000) != 20000) 137 return 1; 138 for (i = 0; i < 20000 / sizeof (int); i++) 139 if (data[i] != data2[i]) 140 return 1; 141 142 close (fd); 143 unlink ("conftestmmapm"); 144 return 0; 145} 146]])]) 147 148dnl Check whether the data read from an open file sees the changes made to an 149dnl mmaped region, or if msync has to be called for other applications to see 150dnl those changes. 151AC_DEFUN([INN_FUNC_MMAP_NEEDS_MSYNC], 152[AC_CACHE_CHECK([whether msync is needed], [inn_cv_func_mmap_need_msync], 153[AC_RUN_IFELSE([_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE], 154 [inn_cv_func_mmap_need_msync=no], 155 [inn_cv_func_mmap_need_msync=yes], 156 [inn_cv_func_mmap_need_msync=yes])]) 157 if test $inn_cv_func_mmap_need_msync = yes ; then 158 AC_DEFINE([MMAP_NEEDS_MSYNC], 1, 159 [Define if you need to call msync for calls to read to see changes.]) 160 fi]) 161 162dnl Source used by INN_FUNC_MMAP_SEES_WRITES. 163define([_INN_FUNC_MMAP_SEES_WRITES_SOURCE], 164[AC_LANG_SOURCE([[ 165#include <stdlib.h> 166#include <sys/types.h> 167#include <sys/stat.h> 168#include <fcntl.h> 169#if HAVE_UNISTD_H 170# include <unistd.h> 171#endif 172#include <sys/mman.h> 173 174/* Fractional page is probably worst case. */ 175static char zbuff[1024]; 176static char fname[] = "conftestw"; 177 178int 179main () 180{ 181 char *map; 182 int i, fd; 183 184 fd = open (fname, O_RDWR | O_CREAT, 0660); 185 if (fd < 0) 186 return 1; 187 unlink (fname); 188 write (fd, zbuff, sizeof (zbuff)); 189 lseek (fd, 0, SEEK_SET); 190 map = mmap (0, sizeof (zbuff), PROT_READ, MAP_SHARED, fd, 0); 191 if (map == (char *) -1) 192 return 2; 193 for (i = 0; fname[i]; i++) 194 { 195 if (write (fd, &fname[i], 1) != 1) 196 return 3; 197 if (map[i] != fname[i]) 198 return 4; 199 } 200 return 0; 201} 202]])]) 203 204dnl Check if an mmaped region will see writes made to the underlying file 205dnl without an intervening msync. 206AC_DEFUN([INN_FUNC_MMAP_SEES_WRITES], 207[AC_CACHE_CHECK([whether mmap sees writes], [inn_cv_func_mmap_sees_writes], 208[AC_RUN_IFELSE([_INN_FUNC_MMAP_SEES_WRITES_SOURCE], 209 [inn_cv_func_mmap_sees_writes=yes], 210 [inn_cv_func_mmap_sees_writes=no], 211 [inn_cv_func_mmap_sees_writes=no])]) 212 if test $inn_cv_func_mmap_sees_writes = no ; then 213 AC_DEFINE([MMAP_MISSES_WRITES], 1, 214 [Define if you need to call msync after writes.]) 215 fi]) 216 217dnl Check whether msync takes three arguments. (It takes three arguments on 218dnl Solaris and Linux, two arguments on BSDI.) 219AC_DEFUN([INN_FUNC_MSYNC_ARGS], 220[AC_CACHE_CHECK([how many arguments msync takes], [inn_cv_func_msync_args], 221[AC_COMPILE_IFELSE( 222[AC_LANG_PROGRAM([[ 223#include <sys/types.h> 224#include <sys/mman.h>]], 225 [[char *p; int psize; msync (p, psize, MS_ASYNC);]])], 226 [inn_cv_func_msync_args=3], 227 [inn_cv_func_msync_args=2])]) 228 if test $inn_cv_func_msync_args = 3 ; then 229 AC_DEFINE([HAVE_MSYNC_3_ARG], 1, 230 [Define if your msync function takes three arguments.]) 231 fi]) 232