attach.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: attach.c 27502 2009-02-19 01:09:07Z rdm $ */
00002 /* Author: */
00003 
00004 /* Initialization for access to a mmap'd malloc managed region.
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 
00027 #include <stdio.h>
00028 #include <errno.h>
00029 #include <sys/types.h>
00030 #include <fcntl.h> /* After sys/types.h, at least for dpx/2.  */
00031 #include <sys/stat.h>
00032 #include <string.h>
00033 #include "mmprivate.h"
00034 
00035 #ifndef WIN32
00036 #  include <sys/mman.h>
00037 #else
00038 #  include <io.h>
00039 #endif
00040 
00041 #ifndef SEEK_SET
00042 #define SEEK_SET 0
00043 #endif
00044 
00045 
00046 #if defined(R__HAVE_MMAP)
00047 
00048 /* Forward declarations/prototypes for local functions */
00049 
00050 #ifndef WIN32
00051   static struct mdesc *reuse PARAMS ((int));
00052 #else
00053   static struct mdesc *reuse PARAMS ((HANDLE));
00054 #endif
00055 
00056 /* Initialize access to a mmalloc managed region.
00057 
00058    If FD is a valid file descriptor for an open file then data for the
00059    mmalloc managed region is mapped to that file, otherwise "/dev/zero"
00060    is used and the data will not exist in any filesystem object.
00061 
00062    If the open file corresponding to FD is from a previous use of
00063    mmalloc and passes some basic sanity checks to ensure that it is
00064    compatible with the current mmalloc package, then it's data is
00065    mapped in and is immediately accessible at the same addresses in
00066    the current process as the process that created the file.
00067 
00068    If BASEADDR is not NULL, the mapping is established starting at the
00069    specified address in the process address space.  If BASEADDR is NULL,
00070    the mmalloc package chooses a suitable address at which to start the
00071    mapped region, which will be the value of the previous mapping if
00072    opening an existing file which was previously built by mmalloc, or
00073    for new files will be a value chosen by mmap.
00074 
00075    Specifying BASEADDR provides more control over where the regions
00076    start and how big they can be before bumping into existing mapped
00077    regions or future mapped regions.
00078 
00079    On success, returns a "malloc descriptor" which is used in subsequent
00080    calls to other mmalloc package functions.  It is explicitly "void *"
00081    ("char *" for systems that don't fully support void) so that users
00082    of the package don't have to worry about the actual implementation
00083    details.
00084 
00085    On failure returns NULL. */
00086 
00087 PTR
00088 mmalloc_attach (fd, baseaddr, minsize)
00089 #ifndef WIN32
00090   int fd;
00091 #else
00092   HANDLE fd;
00093 #endif
00094   PTR baseaddr;
00095   int minsize;
00096 {
00097   struct mdesc mtemp;
00098   struct mdesc *mdp;
00099   PTR mbase;
00100   int coresize;
00101 #ifndef WIN32
00102   struct stat sbuf;
00103 #else
00104   BY_HANDLE_FILE_INFORMATION sbuf;
00105 #endif
00106 
00107   /* First check to see if FD is a valid file descriptor, and if so, see
00108      if the file has any current contents (size > 0).  If it does, then
00109      attempt to reuse the file.  If we can't reuse the file, either
00110      because it isn't a valid mmalloc produced file, was produced by an
00111      obsolete version, or any other reason, then we fail to attach to
00112      this file. */
00113 
00114 #ifndef WIN32
00115   if (fd >= 0)
00116     {
00117       if (fstat (fd, &sbuf) < 0)
00118         {
00119           return (NULL);
00120         }
00121       else if (sbuf.st_size > 0)
00122         {
00123           return ((PTR) reuse (fd));
00124         }
00125     }
00126 #else
00127   if (fd != INVALID_HANDLE_VALUE)
00128     {
00129       if ( !GetFileInformationByHandle(fd, &sbuf) )
00130         {
00131           return (NULL);
00132         }
00133       else if (sbuf.nFileSizeLow || sbuf.nFileSizeHigh )
00134         {
00135           return ((PTR) reuse (fd));
00136         }
00137     }
00138 #endif /* WIN32 */
00139 
00140   /* We start off with the malloc descriptor allocated on the stack, until
00141      we build it up enough to call _mmalloc_mmap_morecore() to allocate the
00142      first page of the region and copy it there.  Ensure that it is zero'd and
00143      then initialize the fields that we know values for. */
00144 
00145   mdp = &mtemp;
00146   memset ((char *) mdp, 0, sizeof (mtemp));
00147   strncpy (mdp -> magic, MMALLOC_MAGIC, MMALLOC_MAGIC_SIZE);
00148   mdp -> headersize = sizeof (mtemp);
00149   mdp -> version = MMALLOC_VERSION;
00150   mdp -> morecore = __mmalloc_mmap_morecore;
00151   mdp -> fd = fd;
00152   mdp -> base = mdp -> breakval = mdp -> top = baseaddr;
00153 
00154   /* If we have not been passed a valid open file descriptor for the file
00155      to map to, then open /dev/zero and use that to map to. */
00156 
00157 #ifndef WIN32
00158   if (mdp -> fd < 0)
00159     {
00160       if ((mdp -> fd = open ("/dev/zero", O_RDWR)) < 0)
00161         {
00162           return (NULL);
00163         }
00164       else
00165         {
00166           mdp -> flags |= MMALLOC_DEVZERO;
00167         }
00168     }
00169 #else
00170   if (mdp -> fd == (HANDLE)0xffffffff) mdp -> flags |= MMALLOC_DEVZERO;
00171 #endif /* WIN32 */
00172 
00173   /*  Now try to map in the first page, copy the malloc descriptor structure
00174       there, and arrange to return a pointer to this new copy.  If the mapping
00175       fails, then close the file descriptor if it was opened by us, and arrange
00176       to return a NULL. */
00177 
00178   if (minsize)
00179      coresize = minsize;
00180   else
00181      coresize = sizeof(mtemp);
00182 
00183   if ((mbase = mdp -> morecore (mdp, coresize)) != NULL)
00184     {
00185       mdp->breakval = mdp->base + sizeof(mtemp);
00186       memcpy (mbase, mdp, sizeof (mtemp));
00187 #ifndef WIN32
00188 #  ifndef VMS
00189 #  ifndef R__LYNXOS
00190 #  ifndef R__HURD
00191       /* We should really test for _POSIX_SYNCRONIZED_IO here */
00192       msync(mbase, sizeof(mtemp), MS_ASYNC);
00193 #  endif
00194 #  endif
00195 #  endif
00196 #endif
00197       mdp = (struct mdesc *) mbase;
00198     }
00199   else
00200     {
00201       if (mdp -> flags & MMALLOC_DEVZERO)
00202         {
00203 #ifndef WIN32
00204           close (mdp -> fd);
00205 #else
00206           CloseHandle (mdp -> fd);
00207 #endif
00208         }
00209       mdp = NULL;
00210     }
00211 
00212   return ((PTR) mdp);
00213 }
00214 
00215 /* Given an valid file descriptor on an open file, test to see if that file
00216    is a valid mmalloc produced file, and if so, attempt to remap it into the
00217    current process at the same address to which it was previously mapped.
00218 
00219    Note that we have to update the file descriptor number in the malloc-
00220    descriptor read from the file to match the current valid one, before
00221    trying to map the file in, and again after a successful mapping and
00222    after we've switched over to using the mapped in malloc descriptor
00223    rather than the temporary one on the stack.
00224 
00225    Once we've switched over to using the mapped in malloc descriptor, we
00226    have to update the pointer to the morecore function, since it almost
00227    certainly will be at a different address if the process reusing the
00228    mapped region is from a different executable.
00229 
00230    Also note that if the heap being remapped previously used the mmcheck()
00231    routines, we need to update the hooks since their target functions
00232    will have certainly moved if the executable has changed in any way.
00233    We do this by calling mmcheck() internally.
00234 
00235    Returns a pointer to the malloc descriptor if successful, or NULL if
00236    unsuccessful for some reason. */
00237 
00238 static struct mdesc *
00239 reuse (cfd)
00240 #ifndef WIN32
00241   int cfd;
00242 #else
00243   HANDLE cfd;
00244 #endif
00245 {
00246   struct mdesc *mtemp = (struct mdesc*) malloc(sizeof(struct mdesc));
00247   struct mdesc *mdp = NULL;
00248 
00249 #ifdef WIN32
00250   int rdonly = 0;
00251   BY_HANDLE_FILE_INFORMATION FileInformation;
00252   DWORD lbuf;
00253   long fd = _get_osfhandle((int)cfd);
00254   if (!GetFileInformationByHandle(cfd,&FileInformation))
00255   {
00256      fprintf(stderr, "reuse: error calling GetFileInformationByHandle(%d)\n", GetLastError());
00257      free(mtemp);
00258      return (mdp);
00259   }
00260   if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) rdonly = 1;
00261   rdonly = 1;
00262   if ((SetFilePointer(cfd,0,NULL,FILE_BEGIN) != 0xFFFFFFFF) &&
00263       (ReadFile (cfd, (char *) mtemp, sizeof (*mtemp),&lbuf,NULL) && lbuf == sizeof (*mtemp)) &&
00264       (mtemp->headersize == sizeof (*mtemp)) &&
00265       (strcmp (mtemp->magic, MMALLOC_MAGIC) == 0) &&
00266       (mtemp->version <= MMALLOC_VERSION))
00267 #else
00268   int val, rdonly = 0;
00269   int fd = cfd;
00270 
00271   if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
00272      fprintf(stderr, "reuse: error calling fcntl(%d)\n", errno);
00273      free(mtemp);
00274      return (mdp);
00275   }
00276   if ((val & O_ACCMODE) == O_RDONLY) rdonly = 1;
00277 
00278   if ((lseek (fd, 0L, SEEK_SET) == 0) &&
00279       (read (fd, (char *) mtemp, sizeof (*mtemp)) == sizeof (*mtemp)) &&
00280       (mtemp->headersize == sizeof (*mtemp)) &&
00281       (strcmp (mtemp->magic, MMALLOC_MAGIC) == 0) &&
00282       (mtemp->version <= MMALLOC_VERSION))
00283 #endif
00284     {
00285       mtemp->fd = cfd;
00286       if (__mmalloc_remap_core (mtemp) != (char*)-1)
00287         {
00288           if (rdonly) {
00289             mdp = mtemp;
00290             /* mmalloc_update_mapping(mdp); no need to call since mapping will not change */
00291           } else {
00292             /* cannot continue using mapped file when not mapped on original address */
00293             if (mtemp->offset != 0) goto end;
00294             mdp = (struct mdesc *) mtemp->base;
00295             mdp -> fd = cfd;
00296 #ifndef WIN32
00297 #  ifndef VMS
00298 #  ifndef R__LYNXOS
00299 #  ifndef R__HURD
00300             /* We should really test for _POSIX_SYNCRONIZED_IO here */
00301             msync((void *)mdp, sizeof(*mtemp), MS_ASYNC);
00302 #  endif
00303 #  endif
00304 #  endif
00305 #endif
00306             free(mtemp);
00307           }
00308           mdp -> morecore = __mmalloc_mmap_morecore;
00309           if (mdp -> mfree_hook != NULL)
00310             {
00311               mmcheck ((PTR) mdp, (void (*) PARAMS ((void))) NULL);
00312             }
00313         }
00314     }
00315 end:
00316   if (mdp == NULL) free(mtemp);
00317   return (mdp);
00318 }
00319 
00320 #else   /* !defined (R__HAVE_MMAP) */
00321 
00322 /* For systems without mmap, the library still supplies an entry point
00323    to link to, but trying to initialize access to an mmap'd managed region
00324    always fails. */
00325 
00326 /* ARGSUSED */
00327 #ifdef VMS
00328   PTR
00329   mmalloc_attach (fd,baseaddr,minsize)
00330 #else
00331   PTR
00332   mmalloc_attach (fd, baseaddr)
00333 #endif
00334 
00335 #ifndef WIN32
00336   int fd;
00337 #else
00338   HANDLE fd;
00339 #endif
00340   PTR baseaddr;
00341 {
00342    return (NULL);
00343 }
00344 
00345 #endif  /* defined (R__HAVE_MMAP) */
00346 

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