00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "mmprivate.h"
00027
00028 #if defined(R__HAVE_MMAP)
00029
00030 #include <stdio.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 #include <sys/types.h>
00034 #ifdef WIN32
00035 typedef char* caddr_t;
00036 #else
00037 # include <unistd.h>
00038 # include <sys/mman.h>
00039 #endif
00040
00041 #ifdef __CYGWIN__
00042 #include <cygwin/version.h>
00043 #endif
00044
00045 #if defined(R__LINUX) && !defined(R__GLIBC) && !defined(__CYGWIN__) \
00046 || (defined(__CYGWIN__) && (CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR < 213))
00047 extern size_t getpagesize PARAMS ((void));
00048 #else
00049 extern int getpagesize PARAMS ((void));
00050 #endif
00051
00052 #ifndef SEEK_SET
00053 #define SEEK_SET 0
00054 #endif
00055
00056
00057
00058
00059
00060
00061 static size_t pagesize;
00062
00063 #define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + pagesize - 1) & \
00064 ~(pagesize - 1))
00065
00066
00067
00068
00069
00070 PTR
00071 __mmalloc_mmap_morecore (mdp, size)
00072 struct mdesc *mdp;
00073 int size;
00074 {
00075 PTR result = NULL;
00076 off_t foffset;
00077 size_t mapbytes;
00078 caddr_t moveto;
00079 caddr_t mapto;
00080 char buf = 0;
00081 #ifdef WIN32
00082 HANDLE hMap;
00083 #endif
00084
00085 if (pagesize == 0)
00086 {
00087 #ifdef _SC_PAGE_SIZE
00088 pagesize = sysconf(_SC_PAGE_SIZE);
00089 #else
00090 # ifdef _SC_PAGESIZE
00091 pagesize = sysconf(_SC_PAGESIZE);
00092 # else
00093 pagesize = getpagesize();
00094 # endif
00095 #endif
00096 }
00097 if (size == 0)
00098 {
00099
00100 result = mdp -> breakval;
00101 }
00102 else if (size < 0)
00103 {
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 if (mdp -> breakval + size >= mdp -> base)
00114 {
00115 result = (PTR) mdp -> breakval;
00116 mdp -> breakval += size;
00117
00118 if (mdp -> breakval == mdp -> base) {
00119
00120 moveto = PAGE_ALIGN (mdp -> base);
00121 #ifndef WIN32
00122 munmap (moveto, (size_t) (mdp -> top - moveto));
00123 #else
00124 UnmapViewOfFile(moveto);
00125 #endif
00126 mdp -> top = moveto;
00127 }
00128 }
00129 }
00130 else
00131 {
00132
00133
00134 if (mdp -> fd < 0)
00135 {
00136 result = NULL;
00137 }
00138 else if (mdp -> breakval + size > mdp -> top)
00139 {
00140
00141
00142
00143
00144
00145 moveto = PAGE_ALIGN (mdp -> breakval + size);
00146 mapbytes = moveto - mdp -> top;
00147 foffset = mdp -> top - mdp -> base;
00148 #ifndef WIN32
00149 if (lseek (mdp -> fd, foffset + mapbytes - 1, SEEK_SET) == -1) {
00150 fprintf(stderr, "mmap_morecore: error in lseek (%d)\n", errno);
00151 return (result);
00152 }
00153 if (write (mdp -> fd, &buf, 1) == -1) {
00154 fprintf(stderr,
00155 "mmap_morecore: error extending memory mapped file (%d)\n",
00156 errno);
00157 return (result);
00158 }
00159 if (!mdp->base) {
00160 mapto = mmap (0, mapbytes, PROT_READ | PROT_WRITE,
00161 MAP_SHARED, mdp -> fd, foffset);
00162 #else
00163 if (!mdp->base) {
00164 hMap = CreateFileMapping(mdp -> fd, NULL, PAGE_READWRITE,
00165 0, mapbytes, NULL);
00166 mapto = (char *) -1;
00167 if (hMap != NULL)
00168 {
00169 mapto = MapViewOfFileEx(hMap, FILE_MAP_READ | FILE_MAP_WRITE,
00170 0, foffset,0, (LPVOID)0);
00171
00172 if (!mapto) mapto = (char *)-1;
00173 }
00174 #endif
00175 if (mapto != (char *)-1) {
00176 mdp->base = mapto;
00177 mdp->top = mapto + mapbytes;
00178 mdp->breakval = mapto + size;
00179 result = (PTR) mapto;
00180 }
00181 } else {
00182
00183 #ifndef WIN32
00184 mapto = mmap (mdp -> top, mapbytes, PROT_READ | PROT_WRITE,
00185 MAP_SHARED | MAP_FIXED, mdp -> fd, foffset);
00186 #else
00187 hMap = CreateFileMapping(mdp -> fd, NULL, PAGE_READWRITE,
00188 0, mapbytes, NULL);
00189 mapto = (char *) -1;
00190 if (hMap != NULL)
00191 mapto = MapViewOfFileEx(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, foffset,0, mdp -> top);
00192 #endif
00193 if (mapto == mdp -> top)
00194 {
00195 mdp -> top = moveto;
00196 result = (PTR) mdp -> breakval;
00197 mdp -> breakval += size;
00198 }
00199 }
00200 }
00201 else
00202 {
00203 result = (PTR) mdp -> breakval;
00204 mdp -> breakval += size;
00205 }
00206 }
00207 return (result);
00208 }
00209
00210 PTR
00211 __mmalloc_remap_core (mdp)
00212 struct mdesc *mdp;
00213 {
00214 caddr_t base;
00215 int rdonly = 0;
00216
00217 #ifndef WIN32
00218 int val;
00219 if ((val = fcntl(mdp->fd, F_GETFL, 0)) < 0) {
00220 fprintf(stderr, "__mmalloc_remap_core: error calling fcntl(%d)\n", errno);
00221 return ((PTR)-1);
00222 }
00223 if ((val & O_ACCMODE) == O_RDONLY) rdonly = 1;
00224 #else
00225 BY_HANDLE_FILE_INFORMATION FileInformation;
00226 if (!GetFileInformationByHandle(mdp->fd,&FileInformation))
00227 {
00228 fprintf(stderr, "__mmalloc_remap_core: error calling GetFileInformationByHandle(%d)\n",
00229 GetLastError());
00230 return ((PTR)-1);
00231 }
00232 if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) rdonly = 1;
00233 rdonly = 1;
00234 #endif
00235
00236 if (rdonly) {
00237 #ifndef WIN32
00238 base = mmap (mdp -> base, mdp -> top - mdp -> base,
00239 PROT_READ, MAP_SHARED | MAP_FIXED,
00240 mdp -> fd, 0);
00241 if (base == (char *)-1)
00242 base = mmap (0, mdp -> top - mdp -> base,
00243 PROT_READ, MAP_SHARED, mdp -> fd, 0);
00244 #else
00245 HANDLE hMap;
00246 hMap = CreateFileMapping(mdp -> fd, NULL, PAGE_READONLY,
00247 0, mdp -> top - mdp -> base, NULL);
00248
00249
00250
00251 base = (char *)-1;
00252 if (hMap != NULL)
00253 {
00254 base = MapViewOfFileEx(hMap, FILE_MAP_READ, 0, 0, 0, 0);
00255 if (!base)
00256 fprintf(stderr, "__mmalloc_remap_core: can't get base address %x to map. Error code %d.\n",
00257 mdp -> base,GetLastError());
00258 }
00259 else
00260 {
00261 fprintf(stderr, "__mmalloc_remap_core: can't map file. Error code %d.\n",GetLastError());
00262 }
00263 #endif
00264 if (base != mdp->base) mdp->offset = base - mdp->base;
00265 } else {
00266 #ifndef WIN32
00267 base = mmap (mdp -> base, mdp -> top - mdp -> base,
00268 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
00269 mdp -> fd, 0);
00270 #else
00271 HANDLE hMap;
00272 hMap = CreateFileMapping(mdp -> fd, NULL, PAGE_READWRITE,
00273 0, mdp -> top - mdp -> base, NULL);
00274
00275
00276
00277 base = (char *)-1;
00278 if (hMap != NULL)
00279 {
00280 base = MapViewOfFileEx(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, mdp -> base);
00281 if (!base)
00282 fprintf(stderr, "__mmalloc_remap_core: can't get base address %x to map. Error code %d.\n",
00283 mdp -> base,GetLastError());
00284 }
00285 else {
00286 fprintf(stderr, "__mmalloc_remap_core: can't map file. Error code %d.\n",GetLastError());
00287 }
00288 #endif
00289 }
00290 return ((PTR) base);
00291 }
00292
00293 int
00294 mmalloc_update_mapping(md)
00295 PTR md;
00296 {
00297
00298
00299
00300
00301
00302 struct mdesc *mdp = (struct mdesc *)md;
00303 caddr_t oldtop, top, mapto;
00304 size_t mapbytes;
00305 off_t foffset;
00306 int result;
00307 #ifdef WIN32
00308 HANDLE hMap;
00309 #endif
00310
00311 oldtop = mdp->top;
00312 top = ((struct mdesc *)mdp->base)->top;
00313
00314 if (oldtop == top) return 0;
00315
00316 if (top < oldtop) {
00317
00318 #ifndef WIN32
00319 munmap (top, (size_t) (oldtop - top));
00320 #else
00321 UnmapViewOfFile((LPCVOID)top);
00322 #endif
00323 result = 0;
00324
00325 } else {
00326
00327 mapbytes = top - oldtop;
00328 foffset = oldtop - mdp->base;
00329 #ifndef WIN32
00330 mapto = mmap (oldtop, mapbytes, PROT_READ,
00331 MAP_SHARED | MAP_FIXED, mdp -> fd, foffset);
00332 #else
00333
00334 hMap = CreateFileMapping(mdp -> fd, NULL, PAGE_READWRITE,
00335 0, mapbytes, NULL);
00336
00337 mapto = (char *) -1;
00338 if (hMap != NULL)
00339 mapto = MapViewOfFileEx(hMap, FILE_MAP_READ,(DWORD)0, (DWORD)foffset, 0, (LPVOID)oldtop);
00340 #endif
00341 if (mapto == oldtop)
00342 result = 0;
00343 else
00344 result = -1;
00345 }
00346 mdp->top = top;
00347
00348 return (result);
00349 }
00350
00351 #else
00352
00353 int
00354 mmalloc_update_mapping(md)
00355 PTR md;
00356 {
00357 return 0;
00358 }
00359
00360 #endif