Przeglądaj źródła

[contrib/mmap] implements a theoretical dynamic growing mmap
based on Michael Vogts patch in #195018 this commit implements the use
of mmap (as preferred) instead of a static char array. In theory this
made it possible to grow the mmap as needed, but as it is currently
impossible to move the mmap around in the memory the grow is likely
to fail but it improve the memory usage a bit, so it is not totally
useless for now - and maybe we can adjust the pointers in the future...

David Kalnischkies 17 lat temu
rodzic
commit
f1c6a8ca05
3 zmienionych plików z 67 dodań i 21 usunięć
  1. 63 21
      apt-pkg/contrib/mmap.cc
  2. 2 0
      apt-pkg/contrib/mmap.h
  3. 2 0
      debian/changelog

+ 63 - 21
apt-pkg/contrib/mmap.cc

@@ -13,11 +13,6 @@
    libc6 generates warnings -- which should be errors, g++ isn't properly
    strict.
    
-   The configure test notes that some OS's have broken private mmap's
-   so on those OS's we can't use mmap. This means we have to use
-   configure to test mmap and can't rely on the POSIX
-   _POSIX_MAPPED_FILES test.
-   
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
@@ -166,13 +161,23 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace)
 									/*}}}*/
 // DynamicMMap::DynamicMMap - Constructor for a non-file backed map	/*{{{*/
 // ---------------------------------------------------------------------
-/* This is just a fancy malloc really.. */
+/* We try here to use mmap to reserve some space - this is much more
+   cooler than the fallback solution to simply allocate a char array
+   and could come in handy later than we are able to grow such an mmap */
 DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
              MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
 {
    if (_error->PendingError() == true)
       return;
-   
+
+#ifdef _POSIX_MAPPED_FILES
+   // use anonymous mmap() to get the memory
+   Base = (unsigned char*) mmap(0, WorkSpace, PROT_READ|PROT_WRITE,
+			MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+   if(Base != MAP_FAILED)
+      return;
+#endif
+   // fallback to a static allocated space
    Base = new unsigned char[WorkSpace];
    memset(Base,0,WorkSpace);
    iSize = 0;
@@ -185,7 +190,11 @@ DynamicMMap::~DynamicMMap()
 {
    if (Fd == 0)
    {
+#ifdef _POSIX_MAPPED_FILES
+      munmap(Base, WorkSpace);
+#else
       delete [] (unsigned char *)Base;
+#endif
       return;
    }
    
@@ -207,14 +216,16 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
    
    iSize = Result + Size;
    
-   // Just in case error check
-   if (Result + Size > WorkSpace)
+   // try to grow the buffer
+   while(Result + Size > WorkSpace)
    {
-	  _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
-				  "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
-      return 0;
+      if(!Grow())
+      {
+	 _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
+			 "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
+	 return 0;
+      }
    }
-
    return Result;
 }
 									/*}}}*/
@@ -234,7 +245,6 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
       if (I->ItemSize == ItemSize)
 	 break;
    }
-
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
@@ -270,14 +280,17 @@ unsigned long DynamicMMap::WriteString(const char *String,
 				       unsigned long Len)
 {
    unsigned long Result = iSize;
-   // Just in case error check
-   if (Result + Len > WorkSpace)
+   // try to grow the buffer
+   while(Result + Len > WorkSpace)
    {
-	  _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
-				  "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
-      return 0;
-   }   
-   
+      if(!Grow())
+      {
+	 _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
+			 "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
+	 return 0;
+      }
+   }
+
    if (Len == (unsigned long)-1)
       Len = strlen(String);
    iSize += Len + 1;
@@ -286,3 +299,32 @@ unsigned long DynamicMMap::WriteString(const char *String,
    return Result;
 }
 									/*}}}*/
+// DynamicMMap::Grow - Grow the mmap					/*{{{*/
+// ---------------------------------------------------------------------
+/* This method will try to grow the mmap we currently use. This doesn't
+   work most of the time because we can't move the mmap around in the
+   memory for now as this would require to adjust quite a lot of pointers
+   but why we should not at least try to grow it before we give up? */
+bool DynamicMMap::Grow()
+{
+#ifdef _POSIX_MAPPED_FILES
+   unsigned long newSize = WorkSpace + 1024*1024;
+
+   if(Fd != 0)
+   {
+      Fd->Seek(newSize - 1);
+      char C = 0;
+      Fd->Write(&C,sizeof(C));
+   }
+
+   Base = mremap(Base, WorkSpace, newSize, 0);
+   if(Base == MAP_FAILED)
+      return false;
+
+   WorkSpace = newSize;
+   return true;
+#else
+   return false;
+#endif
+}
+									/*}}}*/

+ 2 - 0
apt-pkg/contrib/mmap.h

@@ -84,6 +84,8 @@ class DynamicMMap : public MMap
    unsigned long WorkSpace;
    Pool *Pools;
    unsigned int PoolCount;
+
+   bool Grow();
    
    public:
 

+ 2 - 0
debian/changelog

@@ -34,6 +34,8 @@ apt (0.7.22) UNRELEASED; urgency=low
     correctly when downloading from multiple sites (Closes: #534752)
   * add the various foldmarkers in apt-pkg & cmdline (no code change)
   * versions with a pin of -1 shouldn't be a candidate (Closes: #355237)
+  * prefer mmap as memory allocator in MMap instead of a static char
+    array which can (at least in theory) grow dynamic
 
   [ Michael Vogt ]
   * honor the dpkg hold state in new Marker hooks (closes: #64141)