* configure.ac: Check for sys/mman.h and mmap. Check for mremap
authorIan Lance Taylor <ian@airs.com>
Tue, 12 Apr 2011 18:06:16 +0000 (18:06 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 12 Apr 2011 18:06:16 +0000 (18:06 +0000)
with MREMAP_MAYMOVE.
* output.h (class Output_file): Add map_is_allocated_ field.
* output.cc: Only #include <sys/mman.h> if it exists.  If mmap is
not available, provide stubs.  If mremap is not available, #define
it to gold_mremap.
(MREMAP_MAYMOVE): Define if not defined.
(Output_file::Output_file): Initialize map_is_allocated_.
(Output_file::resize): Check map_is_allocated_.
(Output_file::map_anonymous): If mmap fails, use malloc.
(Output_file::unmap): Don't do anything for an anonymous map.
* fileread.cc: Only #include <sys/mman.h> if it exists.  If mmap
is not available, provide stubs.
(File_read::View::~View): Use free rather than delete[].
(File_read::make_view): Use malloc rather than new[].  If mmap
fails, use malloc.
(File_read::find_or_make_view): Use malloc rather than new[].
* gold.h: Remove HAVE_REMAP code.
* mremap.c: #include <errno.h>.  Only #include <sys/mman.h> if it
exists.  Rename mremap to gold_mremap.  If mmap is not available
don't do anything.
* configure, config.in: Rebuild.

gold/ChangeLog
gold/config.in
gold/configure
gold/configure.ac
gold/fileread.cc
gold/gold.h
gold/mremap.c
gold/output.cc
gold/output.h

index cb4cdfa880542db092ce20fffedbdeb0678bc7be..bb29127f9e3a8563fb9de63bdecf15d14cdcf6c2 100644 (file)
@@ -1,3 +1,28 @@
+2011-04-12  Ian Lance Taylor  <iant@google.com>
+
+       * configure.ac: Check for sys/mman.h and mmap.  Check for mremap
+       with MREMAP_MAYMOVE.
+       * output.h (class Output_file): Add map_is_allocated_ field.
+       * output.cc: Only #include <sys/mman.h> if it exists.  If mmap is
+       not available, provide stubs.  If mremap is not available, #define
+       it to gold_mremap.
+       (MREMAP_MAYMOVE): Define if not defined.
+       (Output_file::Output_file): Initialize map_is_allocated_.
+       (Output_file::resize): Check map_is_allocated_.
+       (Output_file::map_anonymous): If mmap fails, use malloc.
+       (Output_file::unmap): Don't do anything for an anonymous map.
+       * fileread.cc: Only #include <sys/mman.h> if it exists.  If mmap
+       is not available, provide stubs.
+       (File_read::View::~View): Use free rather than delete[].
+       (File_read::make_view): Use malloc rather than new[].  If mmap
+       fails, use malloc.
+       (File_read::find_or_make_view): Use malloc rather than new[].
+       * gold.h: Remove HAVE_REMAP code.
+       * mremap.c: #include <errno.h>.  Only #include <sys/mman.h> if it
+       exists.  Rename mremap to gold_mremap.  If mmap is not available
+       don't do anything.
+       * configure, config.in: Rebuild.
+
 2011-04-11  Ian Lance Taylor  <iant@google.com>
 
        * incremental.cc (Sized_incr_relobj::do_add_symbols): Always
index 7a824b045a04860856d77e66d9ace2d7b5749c92..86113763d9ba16bcd33e0d2966398d8e2059d8da 100644 (file)
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
-/* Define to 1 if you have the `mremap' function. */
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the mremap function with MREMAP_MAYMOVE support */
 #undef HAVE_MREMAP
 
 /* Define if compiler supports #pragma omp threadprivate */
 /* Define to 1 if you have the `sysconf' function. */
 #undef HAVE_SYSCONF
 
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
index 1a0d47d03a0215019eb1f08cb95cb8ad96d0fbaf..5a7268d3494eb2cbd3d55a2ed537dd9ad559a092 100755 (executable)
@@ -6486,18 +6486,32 @@ WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmi
 LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 
 
-for ac_func in chsize
+for ac_header in sys/mman.h
 do :
-  ac_fn_c_check_func "$LINENO" "chsize" "ac_cv_func_chsize"
-if test "x$ac_cv_func_chsize" = x""yes; then :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CHSIZE 1
+#define HAVE_SYS_MMAN_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in chsize mmap
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
 
 fi
 done
 
-for ac_func in pread ftruncate mremap ffsll
+for ac_func in pread ftruncate ffsll
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -6519,6 +6533,49 @@ done
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking mremap with MREMAP_MAYMOVE" >&5
+$as_echo_n "checking mremap with MREMAP_MAYMOVE... " >&6; }
+if test "${gold_cv_lib_mremap_maymove+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#include <sys/mman.h>
+void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); }
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  gold_cv_lib_mremap_maymove=yes
+else
+  gold_cv_lib_mremap_maymove=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_lib_mremap_maymove" >&5
+$as_echo "$gold_cv_lib_mremap_maymove" >&6; }
+if test "$gold_cv_lib_mremap_maymove" = "yes"; then
+
+$as_echo "#define HAVE_MREMAP 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" mremap.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS mremap.$ac_objext"
+ ;;
+esac
+
+fi
+
 # Link in zlib if we can.  This allows us to write compressed sections.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing zlibVersion" >&5
 $as_echo_n "checking for library containing zlibVersion... " >&6; }
index 60243d0709e69e314378c82f5d2db017337eaec6..7757d8c55ac53b4a73debf9ca1a11b074be3ad01 100644 (file)
@@ -393,8 +393,22 @@ dnl host dependent.  If build == host, we can check getconf LFS_CFLAGS.
 LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
 AC_SUBST(LFS_CFLAGS)
 
-AC_CHECK_FUNCS(chsize)
-AC_REPLACE_FUNCS(pread ftruncate mremap ffsll)
+AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_FUNCS(chsize mmap)
+AC_REPLACE_FUNCS(pread ftruncate ffsll)
+
+AC_CACHE_CHECK([mremap with MREMAP_MAYMOVE], [gold_cv_lib_mremap_maymove],
+[AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[
+#include <sys/mman.h>
+void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); }
+]])], [gold_cv_lib_mremap_maymove=yes], [gold_cv_lib_mremap_maymove=no])])
+if test "$gold_cv_lib_mremap_maymove" = "yes"; then
+  AC_DEFINE(HAVE_MREMAP, 1,
+    [Define to 1 if you have the mremap function with MREMAP_MAYMOVE support])
+else
+  AC_LIBOBJ(mremap)
+fi
 
 # Link in zlib if we can.  This allows us to write compressed sections.
 AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)])
index 2ae0a43ec5b7f33b2cd340d9fbfc884cf21ea683..232473470a9c5fd4adeb77d735f255881f5b05b9 100644 (file)
 #include <climits>
 #include <fcntl.h>
 #include <unistd.h>
+
+#ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
+#endif
 
 #ifdef HAVE_READV
 #include <sys/uio.h>
 #include "gold-threads.h"
 #include "fileread.h"
 
+// For systems without mmap support.
+#ifndef HAVE_MMAP
+# define mmap gold_mmap
+# define munmap gold_munmap
+# ifndef MAP_FAILED
+#  define MAP_FAILED (reinterpret_cast<void*>(-1))
+# endif
+# ifndef PROT_READ
+#  define PROT_READ 0
+# endif
+# ifndef MAP_PRIVATE
+#  define MAP_PRIVATE 0
+# endif
+
+# ifndef ENOSYS
+#  define ENOSYS EINVAL
+# endif
+
+static void *
+gold_mmap(void *, size_t, int, int, int, off_t)
+{
+  errno = ENOSYS;
+  return MAP_FAILED;
+}
+
+static int
+gold_munmap(void *, size_t)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+#endif
+
 #ifndef HAVE_READV
 struct iovec { void* iov_base; size_t iov_len; };
 ssize_t
@@ -96,7 +133,7 @@ File_read::View::~View()
   switch (this->data_ownership_)
     {
     case DATA_ALLOCATED_ARRAY:
-      delete[] this->data_;
+      free(const_cast<unsigned char*>(this->data_));
       break;
     case DATA_MMAPPED:
       if (::munmap(const_cast<unsigned char*>(this->data_), this->size_) != 0)
@@ -440,34 +477,40 @@ File_read::make_view(off_t start, section_size_type size,
       gold_assert(psize >= size);
     }
 
-  File_read::View* v;
+  void* p;
+  View::Data_ownership ownership;
   if (byteshift != 0)
     {
-      unsigned char* p = new unsigned char[psize + byteshift];
+      p = malloc(psize + byteshift);
+      if (p == NULL)
+       gold_nomem();
       memset(p, 0, byteshift);
-      this->do_read(poff, psize, p + byteshift);
-      v = new File_read::View(poff, psize, p, byteshift, cache,
-                              View::DATA_ALLOCATED_ARRAY);
+      this->do_read(poff, psize, static_cast<unsigned char*>(p) + byteshift);
+      ownership = View::DATA_ALLOCATED_ARRAY;
     }
   else
     {
       this->reopen_descriptor();
-      void* p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE,
-                       this->descriptor_, poff);
-      if (p == MAP_FAILED)
-       gold_fatal(_("%s: mmap offset %lld size %lld failed: %s"),
-                  this->filename().c_str(),
-                  static_cast<long long>(poff),
-                  static_cast<long long>(psize),
-                  strerror(errno));
-
-      this->mapped_bytes_ += psize;
-
-      const unsigned char* pbytes = static_cast<const unsigned char*>(p);
-      v = new File_read::View(poff, psize, pbytes, 0, cache,
-                              View::DATA_MMAPPED);
+      p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE, this->descriptor_, poff);
+      if (p != MAP_FAILED)
+       {
+         ownership = View::DATA_MMAPPED;
+         this->mapped_bytes_ += psize;
+       }
+      else
+       {
+         p = malloc(psize);
+         if (p == NULL)
+           gold_nomem();
+         this->do_read(poff, psize, p);
+         ownership = View::DATA_ALLOCATED_ARRAY;
+       }
     }
 
+  const unsigned char* pbytes = static_cast<const unsigned char*>(p);
+  File_read::View* v = new File_read::View(poff, psize, pbytes, byteshift,
+                                          cache, ownership);
+
   this->add_view(v);
 
   return v;
@@ -525,7 +568,10 @@ File_read::find_or_make_view(off_t offset, off_t start,
     {
       gold_assert(aligned);
 
-      unsigned char* pbytes = new unsigned char[v->size() + byteshift];
+      unsigned char* pbytes;
+      pbytes = static_cast<unsigned char*>(malloc(v->size() + byteshift));
+      if (pbytes == NULL)
+       gold_nomem();
       memset(pbytes, 0, byteshift);
       memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size());
 
index 158f63b012f105870dba61bc5e01d3a292732a43..133a64ef25110c1bb62d58655ea4ec1e5347248b 100644 (file)
@@ -1,6 +1,6 @@
 // gold.h -- general definitions for gold   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -135,11 +135,6 @@ extern "C" ssize_t pread(int, void*, size_t, off_t);
 extern "C" int ftruncate(int, off_t);
 #endif
 
-#ifndef HAVE_MREMAP
-#define MREMAP_MAYMOVE 1
-extern "C" void *mremap(void *, size_t, size_t, int, ...);
-#endif
-
 #ifndef HAVE_FFSLL
 extern "C" int ffsll(long long);
 #endif
index 332fded11c9dc39a2ef0c3db0c5c613177d396d0..e16563412a5ab4a130c40faf4e1ba085714a7004 100644 (file)
@@ -1,6 +1,6 @@
 /* mremap.c -- version of mremap for gold.  */
 
-/* Copyright 2009 Free Software Foundation, Inc.
+/* Copyright 2009, 2011 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <iant@google.com>.
 
    This file is part of gold.
 #include "config.h"
 #include "ansidecl.h"
 
+#include <errno.h>
 #include <string.h>
 #include <sys/types.h>
+
+#ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
+#endif
+
+extern void *gold_mremap (void *, size_t, size_t, int);
+
+#ifdef HAVE_MMAP
 
 /* This file implements mremap for systems which don't have it.  The
    gold code requires support for mmap.  However, there are systems
 # define MAP_ANONYMOUS MAP_ANON
 #endif
 
-extern void *mremap (void *, size_t, size_t, int, ...);
-
 void *
-mremap (void *old_address, size_t old_size, size_t new_size,
-       int flags ATTRIBUTE_UNUSED, ...)
+gold_mremap (void *old_address, size_t old_size, size_t new_size,
+            int flags ATTRIBUTE_UNUSED)
 {
   void *ret;
 
@@ -57,3 +63,25 @@ mremap (void *old_address, size_t old_size, size_t new_size,
   (void) munmap (old_address, old_size);
   return ret;
 }
+
+#else /* !defined(HAVE_MMAP) */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+void *
+gold_mremap (void *old_address ATTRIBUTE_UNUSED,
+            size_t old_size ATTRIBUTE_UNUSED,
+            size_t new_size ATTRIBUTE_UNUSED,
+            int flags ATTRIBUTE_UNUSED)
+{
+  errno = ENOSYS;
+  return MAP_FAILED;
+}
+
+#endif /* !defined(HAVE_MMAP) */
index 5c1fae9aa9f20488f53270995e52d32bed24612d..26f843c60d3af03b1c4094e0996f44241c41159c 100644 (file)
@@ -1,6 +1,6 @@
 // output.cc -- manage the output file for gold
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
 #include <cerrno>
 #include <fcntl.h>
 #include <unistd.h>
-#include <sys/mman.h>
 #include <sys/stat.h>
 #include <algorithm>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 #include "libiberty.h"
 
 #include "parameters.h"
 #include "descriptors.h"
 #include "output.h"
 
+// For systems without mmap support.
+#ifndef HAVE_MMAP
+# define mmap gold_mmap
+# define munmap gold_munmap
+# define mremap gold_mremap
+# ifndef MAP_FAILED
+#  define MAP_FAILED (reinterpret_cast<void*>(-1))
+# endif
+# ifndef PROT_READ
+#  define PROT_READ 0
+# endif
+# ifndef PROT_WRITE
+#  define PROT_WRITE 0
+# endif
+# ifndef MAP_PRIVATE
+#  define MAP_PRIVATE 0
+# endif
+# ifndef MAP_ANONYMOUS
+#  define MAP_ANONYMOUS 0
+# endif
+# ifndef MAP_SHARED
+#  define MAP_SHARED 0
+# endif
+
+# ifndef ENOSYS
+#  define ENOSYS EINVAL
+# endif
+
+static void *
+gold_mmap(void *, size_t, int, int, int, off_t)
+{
+  errno = ENOSYS;
+  return MAP_FAILED;
+}
+
+static int
+gold_munmap(void *, size_t)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+static void *
+gold_mremap(void *, size_t, size_t, int)
+{
+  errno = ENOSYS;
+  return MAP_FAILED;
+}
+
+#endif
+
+#if defined(HAVE_MMAP) && !defined(HAVE_MREMAP)
+# define mremap gold_mremap
+extern "C" void *gold_mremap(void *, size_t, size_t, int);
+#endif
+
 // Some BSD systems still use MAP_ANON instead of MAP_ANONYMOUS
 #ifndef MAP_ANONYMOUS
 # define MAP_ANONYMOUS  MAP_ANON
 #endif
 
+#ifndef MREMAP_MAYMOVE
+# define MREMAP_MAYMOVE 1
+#endif
+
 #ifndef HAVE_POSIX_FALLOCATE
 // A dummy, non general, version of posix_fallocate.  Here we just set
 // the file size and hope that there is enough disk space.  FIXME: We
@@ -4415,6 +4479,7 @@ Output_file::Output_file(const char* name)
     file_size_(0),
     base_(NULL),
     map_is_anonymous_(false),
+    map_is_allocated_(false),
     is_temporary_(false)
 {
 }
@@ -4522,10 +4587,23 @@ Output_file::resize(off_t file_size)
   // to unmap to flush to the file, then remap after growing the file.
   if (this->map_is_anonymous_)
     {
-      void* base = ::mremap(this->base_, this->file_size_, file_size,
-                            MREMAP_MAYMOVE);
-      if (base == MAP_FAILED)
-        gold_fatal(_("%s: mremap: %s"), this->name_, strerror(errno));
+      void* base;
+      if (!this->map_is_allocated_)
+       {
+         base = ::mremap(this->base_, this->file_size_, file_size,
+                         MREMAP_MAYMOVE);
+         if (base == MAP_FAILED)
+           gold_fatal(_("%s: mremap: %s"), this->name_, strerror(errno));
+       }
+      else
+       {
+         base = realloc(this->base_, file_size);
+         if (base == NULL)
+           gold_nomem();
+         if (file_size > this->file_size_)
+           memset(static_cast<char*>(base) + this->file_size_, 0,
+                  file_size - this->file_size_);
+       }
       this->base_ = static_cast<unsigned char*>(base);
       this->file_size_ = file_size;
     }
@@ -4546,13 +4624,17 @@ Output_file::map_anonymous()
 {
   void* base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  if (base != MAP_FAILED)
+  if (base == MAP_FAILED)
     {
-      this->map_is_anonymous_ = true;
-      this->base_ = static_cast<unsigned char*>(base);
-      return true;
+      base = malloc(this->file_size_);
+      if (base == NULL)
+       return false;
+      memset(base, 0, this->file_size_);
+      this->map_is_allocated_ = true;
     }
-  return false;
+  this->base_ = static_cast<unsigned char*>(base);
+  this->map_is_anonymous_ = true;
+  return true;
 }
 
 // Map the file into memory.  Return whether the mapping succeeded.
@@ -4624,8 +4706,16 @@ Output_file::map()
 void
 Output_file::unmap()
 {
-  if (::munmap(this->base_, this->file_size_) < 0)
-    gold_error(_("%s: munmap: %s"), this->name_, strerror(errno));
+  if (this->map_is_anonymous_)
+    {
+      // We've already written out the data, so there is no reason to
+      // waste time unmapping or freeing the memory.
+    }
+  else
+    {
+      if (::munmap(this->base_, this->file_size_) < 0)
+       gold_error(_("%s: munmap: %s"), this->name_, strerror(errno));
+    }
   this->base_ = NULL;
 }
 
index d62ae73b76d82906b329f18ef61e785b855a7e61..f47c72413c9b369b9d0d9ba08214231103fd7a03 100644 (file)
@@ -1,6 +1,6 @@
 // output.h -- manage the output file for gold   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -4221,6 +4221,8 @@ class Output_file
   unsigned char* base_;
   // True iff base_ points to a memory buffer rather than an output file.
   bool map_is_anonymous_;
+  // True if base_ was allocated using new rather than mmap.
+  bool map_is_allocated_;
   // True if this is a temporary file which should not be output.
   bool is_temporary_;
 };