summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2009-07-08 01:03:15 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2009-07-08 01:03:15 +0200
commitf1c6a8ca0511c623a16bb804ed2c5b6c26c83d78 (patch)
tree92ba34080e48a63c143fffba58da3b79698025f6
parentc3a85f49fd8c82326707ce870c2b11b587fd0bd1 (diff)
[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...
-rw-r--r--apt-pkg/contrib/mmap.cc84
-rw-r--r--apt-pkg/contrib/mmap.h2
-rw-r--r--debian/changelog2
3 files changed, 67 insertions, 21 deletions
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index 04a45811b..073bc9eb3 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/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
+}
+ /*}}}*/
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index 19cf7582d..bde62217d 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -84,6 +84,8 @@ class DynamicMMap : public MMap
unsigned long WorkSpace;
Pool *Pools;
unsigned int PoolCount;
+
+ bool Grow();
public:
diff --git a/debian/changelog b/debian/changelog
index 412435fad..27b798fe5 100644
--- a/debian/changelog
+++ b/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)