diff options
author | David Kalnischkies <kalnischkies@gmail.com> | 2009-07-08 01:03:15 +0200 |
---|---|---|
committer | David Kalnischkies <kalnischkies@gmail.com> | 2009-07-08 01:03:15 +0200 |
commit | f1c6a8ca0511c623a16bb804ed2c5b6c26c83d78 (patch) | |
tree | 92ba34080e48a63c143fffba58da3b79698025f6 | |
parent | c3a85f49fd8c82326707ce870c2b11b587fd0bd1 (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.cc | 84 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.h | 2 | ||||
-rw-r--r-- | debian/changelog | 2 |
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) |