mmapsup.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: mmapsup.c 31230 2009-11-17 13:39:14Z brun $ */
00002 /* Author: */
00003 
00004 /* Support for an sbrk-like function that uses mmap.
00005    Copyright 1992 Free Software Foundation, Inc.
00006 
00007    Contributed by Fred Fish at Cygnus Support.   fnf@cygnus.com
00008 
00009 This file is part of the GNU C Library.
00010 
00011 The GNU C Library is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU Library General Public License as
00013 published by the Free Software Foundation; either version 2 of the
00014 License, or (at your option) any later version.
00015 
00016 The GNU C Library is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 Library General Public License for more details.
00020 
00021 You should have received a copy of the GNU Library General Public
00022 License along with the GNU C Library; see the file COPYING.LIB.  If
00023 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00024 Boston, MA 02111-1307, USA.  */
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 /* __CYGWIN__ */
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 /* Cache the pagesize for the current host machine.  Note that if the host
00057    does not readily provide a getpagesize() function, we need to emulate it
00058    elsewhere, not clutter up this file with lots of kluges to try to figure
00059    it out. */
00060 
00061 static size_t pagesize;
00062 
00063 #define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + pagesize - 1) & \
00064                                     ~(pagesize - 1))
00065 
00066 /*  Get core for the memory region specified by MDP, using SIZE as the
00067     amount to either add to or subtract from the existing region.  Works
00068     like sbrk(), but using mmap(). */
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;        /* File offset at which new mapping will start */
00077   size_t mapbytes;      /* Number of bytes to map */
00078   caddr_t moveto;       /* Address where we wish to move "break value" to */
00079   caddr_t mapto;        /* Address we actually mapped to */
00080   char buf = 0;         /* Single byte to write to extend mapped file */
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       /* Just return the current "break" value. */
00100       result = mdp -> breakval;
00101     }
00102   else if (size < 0)
00103     {
00104       /* We are deallocating memory.  If the amount requested would cause
00105          us to try to deallocate back past the base of the mmap'd region
00106          then do nothing, and return NULL.  Otherwise, deallocate the
00107          memory and return the old break value. */
00108 
00109       /* only munmap whole mapping, called via mmalloc_detach, smaller size
00110          reductions cause the breakval to be reduced but not the mapping
00111          to be undone (rdm). */
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             /* moveto = PAGE_ALIGN (mdp -> breakval); */
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       /* We are allocating memory.  Make sure we have an open file
00133          descriptor and then go on to get the memory. */
00134       if (mdp -> fd < 0)
00135         {
00136           result = NULL;
00137         }
00138       else if (mdp -> breakval + size > mdp -> top)
00139         {
00140           /* The request would move us past the end of the currently
00141              mapped memory, so map in enough more memory to satisfy
00142              the request.  This means we also have to grow the mapped-to
00143              file by an appropriate amount, since mmap cannot be used
00144              to extend a file. */
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 //                                          0, foffset,0, (LPVOID)0x1e70000);
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             /*fprintf(stderr, "mmap_morecore: try to extend mapping by %d bytes, use bigger TMapFile\n", mapbytes);*/
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;  // for NT always read-only for the time being
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 //    hMap = OpenFileMapping(FILE_MAP_READ, FALSE, (LPTSTR)mdp->magic);
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 //    hMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, (LPTSTR)mdp->magic);
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    * In case of a read-only mapping, we need to call this routine to
00299    * keep the mapping in sync with the mapping of the writer.
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 //    hMap = OpenFileMapping(FILE_MAP_READ, FALSE, (LPTSTR)mdp->magic);
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   /* defined(R__HAVE_MMAP) */
00352 
00353 int
00354 mmalloc_update_mapping(md)
00355   PTR md;
00356 {
00357    return 0;
00358 }
00359 
00360 #endif  /* defined(R__HAVE_MMAP) */

Generated on Tue Jul 5 14:11:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1