[gold][patch] Control caching of memory mapped regions

Cary Coutant ccoutant@google.com
Thu Mar 11 00:13:00 GMT 2010


> The patch is OK.  It's also OK if you change the name.

I changed it to is_permanent_view() to eliminate the "!", and added a
comment to the method explaining the connection to DATA_NOT_OWNED.

Here's the patch as committed.

-cary

        * fileread.cc (File_read::~File_read): Don't delete whole_file_view_.
        (File_read::open[1]): Remove initial mapping of whole_file_view_.
        (File_read::open[2]): Add whole_file_view_ to list of views.
        (File_read::make_view): Remove test of whole_file_view_.
        (File_read::find_or_make_view): Create whole_file_view_ if
        necessary.
        (File_read::clear_views): Replace bool parameter with enum;
        adjust all callers.  Don't delete views with permanent data;
        do delete cached views and views from archives if
        --no-keep-files-mapped is set.  Set whole_file_view_ to NULL
        if clearing the corresponding view.
        * fileread.h (File_read::Clear_views_mode): New enum.
        (File_read::View::is_permanent_view): New method.
        (File_read::clear_views): Replace bool parameter
        with enum; adjust all callers.
        * options.h (General_options): Change keep_files_mapped option;
        add map_whole_files.
        * readsyms.cc (Add_symbols::run): Delete sd_ object before
        releasing the file.
        * reloc.cc (Scan_relocs::run): Delete rd_ object before releasing
        the file.
-------------- next part --------------
Index: fileread.cc
===================================================================
RCS file: /cvs/src/src/gold/fileread.cc,v
retrieving revision 1.61
diff -u -p -r1.61 fileread.cc
--- fileread.cc	24 Feb 2010 20:50:59 -0000	1.61
+++ fileread.cc	10 Mar 2010 17:27:50 -0000
@@ -115,9 +115,7 @@ File_read::~File_read()
       this->is_descriptor_opened_ = false;
     }
   this->name_.clear();
-  this->clear_views(true);
-  if (this->whole_file_view_)
-    delete this->whole_file_view_;
+  this->clear_views(CLEAR_VIEWS_ALL);
 }
 
 // Open the file.
@@ -144,23 +142,6 @@ File_read::open(const Task* task, const 
       this->size_ = s.st_size;
       gold_debug(DEBUG_FILES, "Attempt to open %s succeeded",
                  this->name_.c_str());
-
-      // Options may not yet be ready e.g. when reading a version
-      // script.  We then default to --no-keep-files-mapped.
-      if (parameters->options_valid()
-	  && parameters->options().keep_files_mapped())
-        {
-          const unsigned char* contents = static_cast<const unsigned char*>(
-              ::mmap(NULL, this->size_, PROT_READ, MAP_PRIVATE,
-                     this->descriptor_, 0));
-          if (contents == MAP_FAILED)
-            gold_fatal(_("%s: mmap failed: %s"), this->filename().c_str(),
-                       strerror(errno));
-          this->whole_file_view_ = new View(0, this->size_, contents, 0, false,
-                                            View::DATA_MMAPPED);
-          this->mapped_bytes_ += this->size_;
-        }
-
       this->token_.add_writer(task);
     }
 
@@ -180,6 +161,7 @@ File_read::open(const Task* task, const 
   this->name_ = name;
   this->whole_file_view_ = new View(0, size, contents, 0, false,
                                     View::DATA_NOT_OWNED);
+  this->add_view(this->whole_file_view_);
   this->size_ = size;
   this->token_.add_writer(task);
   return true;
@@ -226,7 +208,7 @@ File_read::release()
   // for releasing the descriptor.
   if (this->object_count_ <= 1)
     {
-      this->clear_views(false);
+      this->clear_views(CLEAR_VIEWS_NORMAL);
       if (this->is_descriptor_opened_)
 	{
 	  release_descriptor(this->descriptor_, false);
@@ -428,7 +410,7 @@ File_read::make_view(off_t start, sectio
     }
 
   File_read::View* v;
-  if (this->whole_file_view_ != NULL || byteshift != 0)
+  if (byteshift != 0)
     {
       unsigned char* p = new unsigned char[psize + byteshift];
       memset(p, 0, byteshift);
@@ -484,6 +466,15 @@ File_read::find_or_make_view(off_t offse
 	byteshift = (target_size / 8) - byteshift;
     }
 
+  // If --map-whole-files is set, make sure we have a
+  // whole file view.  Options may not yet be ready, e.g.,
+  // when reading a version script.  We then default to
+  // --no-keep-files-mapped.
+  if (this->whole_file_view_ == NULL
+      && parameters->options_valid()
+      && parameters->options().map_whole_files())
+    this->whole_file_view_ = this->make_view(0, this->size_, 0, cache);
+
   // Try to find a View with the required BYTESHIFT.
   File_read::View* vshifted;
   File_read::View* v = this->find_view(offset + start, size,
@@ -691,25 +682,31 @@ File_read::clear_view_cache_marks()
 // the next object.
 
 void
-File_read::clear_views(bool destroying)
+File_read::clear_views(Clear_views_mode mode)
 {
+  bool keep_files_mapped = (parameters->options_valid()
+			    && parameters->options().keep_files_mapped());
   Views::iterator p = this->views_.begin();
   while (p != this->views_.end())
     {
       bool should_delete;
-      if (p->second->is_locked())
+      if (p->second->is_locked() || p->second->is_permanent_view())
 	should_delete = false;
-      else if (destroying)
+      else if (mode == CLEAR_VIEWS_ALL)
 	should_delete = true;
-      else if (p->second->should_cache())
+      else if (p->second->should_cache() && keep_files_mapped)
 	should_delete = false;
-      else if (this->object_count_ > 1 && p->second->accessed())
+      else if (this->object_count_ > 1
+      	       && p->second->accessed()
+      	       && mode != CLEAR_VIEWS_ARCHIVE)
 	should_delete = false;
       else
 	should_delete = true;
 
       if (should_delete)
 	{
+	  if (p->second == this->whole_file_view_)
+	    this->whole_file_view_ = NULL;
 	  delete p->second;
 
 	  // map::erase invalidates only the iterator to the deleted
@@ -720,7 +717,6 @@ File_read::clear_views(bool destroying)
 	}
       else
 	{
-	  gold_assert(!destroying);
 	  p->second->clear_accessed();
 	  ++p;
 	}
@@ -736,7 +732,7 @@ File_read::clear_views(bool destroying)
 	}
       else
 	{
-	  gold_assert(!destroying);
+	  gold_assert(mode != CLEAR_VIEWS_ALL);
 	  ++q;
 	}
     }
Index: fileread.h
===================================================================
RCS file: /cvs/src/src/gold/fileread.h,v
retrieving revision 1.42
diff -u -p -r1.42 fileread.h
--- fileread.h	24 Feb 2010 20:50:59 -0000	1.42
+++ fileread.h	10 Mar 2010 17:27:50 -0000
@@ -170,7 +170,7 @@ class File_read
   // interface, and it would be nice to have something more automatic.
   void
   clear_uncached_views()
-  { this->clear_views(false); }
+  { this->clear_views(CLEAR_VIEWS_ARCHIVE); }
 
   // A struct used to do a multiple read.
   struct Read_multiple_entry
@@ -214,6 +214,17 @@ class File_read
   get_mtime();
 
  private:
+  // Control for what views to clear.
+  enum Clear_views_mode
+  {
+    // Clear uncached views not used by an archive.
+    CLEAR_VIEWS_NORMAL,
+    // Clear all uncached views (including in an archive).
+    CLEAR_VIEWS_ARCHIVE,
+    // Clear all views (i.e., we're destroying the file).
+    CLEAR_VIEWS_ALL
+  };
+
   // This class may not be copied.
   File_read(const File_read&);
   File_read& operator=(const File_read&);
@@ -303,6 +314,12 @@ class File_read
     accessed() const
     { return this->accessed_; }
 
+    // Returns TRUE if this view contains permanent data -- e.g., data that
+    // was supplied by the owner of the File object.
+    bool
+    is_permanent_view() const
+    { return this->data_ownership_ == DATA_NOT_OWNED; }
+
    private:
     View(const View&);
     View& operator=(const View&);
@@ -366,7 +383,7 @@ class File_read
 
   // Clear the file views.
   void
-  clear_views(bool);
+  clear_views(Clear_views_mode);
 
   // The size of a file page for buffering data.
   static const off_t page_size = 8192;
Index: options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.141
diff -u -p -r1.141 options.h
--- options.h	6 Mar 2010 02:34:13 -0000	1.141
+++ options.h	10 Mar 2010 17:27:50 -0000
@@ -774,11 +774,14 @@ class General_options
   DEFINE_special(just_symbols, options::TWO_DASHES, '\0',
                  N_("Read only symbol values from FILE"), N_("FILE"));
 
-  DEFINE_bool(keep_files_mapped, options::TWO_DASHES, '\0',
+  DEFINE_bool(map_whole_files, options::TWO_DASHES, '\0',
 	      sizeof(void*) >= 8,
               N_("Map whole files to memory (default on 64-bit hosts)"),
               N_("Map relevant file parts to memory (default on 32-bit "
                  "hosts)"));
+  DEFINE_bool(keep_files_mapped, options::TWO_DASHES, '\0', true,
+              N_("Keep files mapped across passes (default)"),
+              N_("Release mapped files after each pass"));
 
   DEFINE_special(library, options::TWO_DASHES, 'l',
                  N_("Search for library LIBNAME"), N_("LIBNAME"));
Index: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.40
diff -u -p -r1.40 readsyms.cc
--- readsyms.cc	12 Feb 2010 03:23:26 -0000	1.40
+++ readsyms.cc	10 Mar 2010 17:27:50 -0000
@@ -470,6 +470,8 @@ Add_symbols::run(Workqueue*)
 
   if (!this->input_objects_->add_object(this->object_))
     {
+      delete this->sd_;
+      this->sd_ = NULL;
       this->object_->release();
       delete this->object_;
     }
@@ -477,10 +479,10 @@ Add_symbols::run(Workqueue*)
     {
       this->object_->layout(this->symtab_, this->layout_, this->sd_);
       this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
+      delete this->sd_;
+      this->sd_ = NULL;
       this->object_->release();
     }
-  delete this->sd_;
-  this->sd_ = NULL;
 }
 
 // Class Start_group.
Index: reloc.cc
===================================================================
RCS file: /cvs/src/src/gold/reloc.cc,v
retrieving revision 1.54
diff -u -p -r1.54 reloc.cc
--- reloc.cc	12 Feb 2010 04:33:53 -0000	1.54
+++ reloc.cc	10 Mar 2010 17:27:51 -0000
@@ -179,9 +179,9 @@ void
 Scan_relocs::run(Workqueue*)
 {
   this->object_->scan_relocs(this->symtab_, this->layout_, this->rd_);
-  this->object_->release();
   delete this->rd_;
   this->rd_ = NULL;
+  this->object_->release();
 }
 
 // Return a debugging name for the task.


More information about the Binutils mailing list