* [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map @ 2020-02-13 1:13 Ivan Zakharyaschev 2020-02-13 2:19 ` Vladislav Zavjalov 2020-02-13 5:34 ` Ivan Zakharyaschev 0 siblings, 2 replies; 5+ messages in thread From: Ivan Zakharyaschev @ 2020-02-13 1:13 UTC (permalink / raw) To: darktemplar, devel [-- Attachment #1: Type: text/plain, Size: 14924 bytes --] Со временем я замечаю больше тонкостей про memory management в APT, например, обратил-таки когда-то внимание на следующее место в mmap.h: /* This should be a 32 bit type, larger tyes use too much ram and smaller types are too small. Where ever possible 'unsigned long' should be used instead of this internal type */ typedef unsigned int map_ptrloc; Я пытался догадаться, что имели в виду авторы, и подумал, что когда нам нужно хранить указатель в структуре, попадающей в область памяти, отмапленную в файл ("кеш" информации о всех пакетах), то мы хотим чтобы это всё занимало поменьше места и вместо указателя храним в структуре "индекс" (offset) в массиве, соответствующем этой области, и делаем его 32-битным (грубо говоря). (На LP64-платформах, таких как x86_64, int 32битный.) При этом авторы призывают где возможно использовать unsigned long (64-бита, как и указатели, на x86_64). "Где возможно" -- это, наверное, до тех пор, пока мы индекс не записываем в структуру, которая будет сохранена в этом мапе. Т.е. когда нам просто надо поработать с данными. Я не очень понимаю, к каким местам кода в программе этот призыв применим. Но всё же меня озадачивает, что следующий патч идёт как бы вразрез с этим призывом -- он изживает unsigned long из всех методов класса DynamicMMap, которые возвращают такие индексы. Хотелось бы понять: авторы APT хотели бессмысленного или у их задумки был какой-то смысл и этот патч её нарушает? Связанный вопрос, о котором я задумался: в тех местах, где эти "индексы" (offsets) вычисляются (чтобы их вернуть), какие гарантии, что они не выйдут за пределы 32 бит? Возможно, с такими гарантиями лучше в тех местах в коде, где эти значения окончательно попадают в поля структур типа map_ptrloc, которые будут хранится в мапе ("кеше")? Что всё же лучше (и почему): оставить, как было, или перейти на 32 бита в соответствии с этим патчем? Если перейти, мне кажется, их комментарий с призывом к unsigned long хорошо бы тоже заменить на обоснование новой концепции (а то он будет противоречить тому, что мы видим в коде, и сбивать с толку ещё сильнее, хотя и раньше он был загадочным). В ветке sisyphus_one_more_time в git://git.altlinux.org/people/darktemplar/packages/apt.git коммит commit 971eae5c0248f6f849e1e989cab7244e33fbaf67 Author: Aleksei Nikiforov <darktemplar@altlinux.org> Date: Mon Jul 22 14:18:13 2019 +0300 dynamic memory management: Use same type for all offsets to dynamically allocated map Conformance update Change-Id: I5efcdb9e6604ad4e3f7329e590ab0b48e5400664 diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc index 5e9cfbce9..743e35723 100644 --- a/apt/apt-pkg/contrib/mmap.cc +++ b/apt/apt-pkg/contrib/mmap.cc @@ -215,7 +215,7 @@ DynamicMMap::~DynamicMMap() // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/ // --------------------------------------------------------------------- /* This allocates a block of memory aligned to the given size */ -std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) +std::experimental::optional<map_ptrloc> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) { unsigned long long Result = iSize; if (Aln != 0) @@ -231,25 +231,25 @@ std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned lon "Current values are: %llu, %llu. (man 5 apt.conf)"), (unsigned long long) _config->FindI("APT::Cache-Start", 24*1024*1024), (unsigned long long) _config->FindI("APT::Cache-Limit", 0)); - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); } } iSize = Result + Size; - return std::experimental::optional<unsigned long>(Result); + return std::experimental::optional<map_ptrloc>(Result); } /*}}}*/ // DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/ // --------------------------------------------------------------------- /* This allocates an Item of size ItemSize so that it is aligned to its size in the file. */ -std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long ItemSize) +std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long ItemSize) { if (ItemSize == 0) { _error->Error("Can't allocate an item of size zero"); - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); } // Look for a matching pool entry @@ -286,7 +286,7 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I if (Empty == 0) { _error->Error("Ran out of allocation pools"); - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); } I = Empty; @@ -316,13 +316,13 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I I->Count--; I->Start += ItemSize; - return std::experimental::optional<unsigned long>(Result/ItemSize); + return std::experimental::optional<map_ptrloc>(Result/ItemSize); } /*}}}*/ // DynamicMMap::WriteString - Write a string to the file /*{{{*/ // --------------------------------------------------------------------- /* Strings are not aligned to anything */ -std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char *String, +std::experimental::optional<map_ptrloc> DynamicMMap::WriteString(const char *String, unsigned long Len) { if (Len == std::numeric_limits<unsigned long>::max()) @@ -331,7 +331,7 @@ std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char * auto Result = RawAllocate(Len+1,0); if (Base == NULL || !Result) - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); memcpy((char *)Base + *Result,String,Len); ((char *)Base)[*Result + Len] = 0; diff --git a/apt/apt-pkg/contrib/mmap.h b/apt/apt-pkg/contrib/mmap.h index cfeec12b1..e4f289a5c 100644 --- a/apt/apt-pkg/contrib/mmap.h +++ b/apt/apt-pkg/contrib/mmap.h @@ -101,10 +101,10 @@ class DynamicMMap : public MMap public: // Allocation - std::experimental::optional<unsigned long> RawAllocate(unsigned long long Size,unsigned long Aln = 0); - std::experimental::optional<unsigned long> Allocate(unsigned long ItemSize); - std::experimental::optional<unsigned long> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; + std::experimental::optional<map_ptrloc> RawAllocate(unsigned long long Size,unsigned long Aln = 0); + std::experimental::optional<map_ptrloc> Allocate(unsigned long ItemSize); + std::experimental::optional<map_ptrloc> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;}; DynamicMMap(FileFd &F,unsigned long Flags,unsigned long long WorkSpace = 2*1024*1024, diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc index 36d54504e..4940ec6e5 100644 --- a/apt/apt-pkg/pkgcachegen.cc +++ b/apt/apt-pkg/pkgcachegen.cc @@ -525,15 +525,15 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, // CacheGenerator::NewVersion - Create a new Version /*{{{*/ // --------------------------------------------------------------------- /* This puts a version structure in the linked list */ -std::experimental::optional<unsigned long> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, +std::experimental::optional<map_ptrloc> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, const string &VerStr, - unsigned long Next) + map_ptrloc Next) { // Get a structure const auto Version = AllocateInMap(sizeof(pkgCache::Version)); const auto idxVerStr = WriteStringInMap(VerStr); if ((!Version) || (!idxVerStr)) - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); // Fill it in Ver = pkgCache::VerIterator(Cache,Cache.VerP + *Version); @@ -710,7 +710,7 @@ bool pkgCacheGenerator::SelectFile(const string &File, const string &Site, // --------------------------------------------------------------------- /* This is used to create handles to strings. Given the same text it always returns the same number */ -std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(const char *S, +std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const char *S, unsigned int Size) { /* We use a very small transient hash table here, this speeds up generation @@ -718,7 +718,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)]; if (Bucket != 0 && stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0) - return std::experimental::optional<unsigned long>(Bucket->String); + return std::experimental::optional<map_ptrloc>(Bucket->String); // Search for an insertion point pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList; @@ -736,7 +736,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co if (Res == 0) { Bucket = I; - return std::experimental::optional<unsigned long>(I->String); + return std::experimental::optional<map_ptrloc>(I->String); } // Get a structure @@ -744,7 +744,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co const auto Item = AllocateInMap(sizeof(pkgCache::StringItem)); const auto idxString = WriteStringInMap(S, Size); if ((!Item) || (!idxString)) - return std::experimental::optional<unsigned long>(); + return std::experimental::optional<map_ptrloc>(); if (oldMap != Map.Data()) { @@ -760,7 +760,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co ItemP->String = *idxString; Bucket = ItemP; - return std::experimental::optional<unsigned long>(ItemP->String); + return std::experimental::optional<map_ptrloc>(ItemP->String); } /*}}}*/ diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h index dfcadbf8e..8a66765cc 100644 --- a/apt/apt-pkg/pkgcachegen.h +++ b/apt/apt-pkg/pkgcachegen.h @@ -116,15 +116,15 @@ class pkgCacheGenerator bool FoundFileDeps; bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); - std::experimental::optional<unsigned long> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next); + std::experimental::optional<map_ptrloc> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr, map_ptrloc Next); public: // CNC:2003-02-27 - We need this in rpmListParser. bool NewPackage(pkgCache::PkgIterator &PkgI,const string &Pkg); - std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size); - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; + std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size); + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; void DropProgress() {Progress = 0;}; bool SelectFile(const string &File,const string &Site,pkgIndexFile const &Index, @@ -162,10 +162,10 @@ class pkgCacheGenerator::ListParser pkgCacheGenerator *Owner; friend class pkgCacheGenerator; - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; - inline std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; - inline std::experimental::optional<unsigned long> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; + inline std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; + inline std::experimental::optional<map_ptrloc> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; bool NewDepends(pkgCache::VerIterator &Ver, const string &Package, const string &Version,unsigned int Op, unsigned int Type); diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc index 0cbb5f750..ea27d11c5 100644 --- a/apt/apt-pkg/rpm/rpmlistparser.cc +++ b/apt/apt-pkg/rpm/rpmlistparser.cc @@ -75,7 +75,7 @@ rpmListParser::~rpmListParser() // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ // --------------------------------------------------------------------- /* */ -std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int Tag) +std::experimental::optional<map_ptrloc> rpmListParser::UniqFindTagWrite(int Tag) { char *Start; char *Stop; @@ -90,7 +90,7 @@ std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int T * But since cacheiterators treat zero as special value, * just pass it instead of failing */ - return std::experimental::optional<unsigned long>(0); + return std::experimental::optional<map_ptrloc>(0); } if (type == RPM_STRING_TYPE) diff --git a/apt/apt-pkg/rpm/rpmlistparser.h b/apt/apt-pkg/rpm/rpmlistparser.h index 6767d106d..22a90a0a5 100644 --- a/apt/apt-pkg/rpm/rpmlistparser.h +++ b/apt/apt-pkg/rpm/rpmlistparser.h @@ -45,7 +45,7 @@ class rpmListParser : public pkgCacheGenerator::ListParser bool Duplicated; - std::experimental::optional<unsigned long> UniqFindTagWrite(int Tag); + std::experimental::optional<map_ptrloc> UniqFindTagWrite(int Tag); bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); bool ParseDepends(pkgCache::VerIterator &Ver, char **namel, char **verl, int32_t *flagl, -- Best regards, Ivan ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map 2020-02-13 1:13 [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map Ivan Zakharyaschev @ 2020-02-13 2:19 ` Vladislav Zavjalov 2020-02-13 5:34 ` Ivan Zakharyaschev 1 sibling, 0 replies; 5+ messages in thread From: Vladislav Zavjalov @ 2020-02-13 2:19 UTC (permalink / raw) To: ALT Linux Team development discussions On Thu, Feb 13, 2020 at 04:13:17AM +0300, Ivan Zakharyaschev wrote: > Со временем я замечаю больше тонкостей про memory management в APT, > например, обратил-таки когда-то внимание на следующее место в mmap.h: > > /* This should be a 32 bit type, larger tyes use too much ram and smaller > types are too small. Where ever possible 'unsigned long' should be used > instead of this internal type */ > typedef unsigned int map_ptrloc; > > Я пытался догадаться, что имели в виду авторы, и подумал, что когда > нам нужно хранить указатель в структуре, попадающей в область памяти, > отмапленную в файл ("кеш" информации о всех пакетах), то мы хотим > чтобы это всё занимало поменьше места и вместо указателя храним в > структуре "индекс" (offset) в массиве, соответствующем этой области, и > делаем его 32-битным (грубо говоря). (На LP64-платформах, таких как > x86_64, int 32битный.) > > При этом авторы призывают где возможно использовать unsigned long > (64-бита, как и указатели, на x86_64). "Где возможно" -- это, наверное, > до тех пор, пока мы индекс не записываем в структуру, которая будет > сохранена в этом мапе. Т.е. когда нам просто надо поработать с > данными. > > Я не очень понимаю, к каким местам кода в программе этот призыв > применим. > > Но всё же меня озадачивает, что следующий патч идёт как бы вразрез с этим > призывом -- он изживает unsigned long из всех методов класса DynamicMMap, > которые возвращают такие индексы. > > Хотелось бы понять: авторы APT хотели бессмысленного или у их задумки > был какой-то смысл и этот патч её нарушает? > > Связанный вопрос, о котором я задумался: в тех местах, где эти > "индексы" (offsets) вычисляются (чтобы их вернуть), какие гарантии, > что они не выйдут за пределы 32 бит? Возможно, с такими гарантиями > лучше в тех местах в коде, где эти значения окончательно попадают в > поля структур типа map_ptrloc, которые будут хранится в мапе ("кеше")? > > Что всё же лучше (и почему): оставить, как было, или перейти на 32 > бита в соответствии с этим патчем? > > Если перейти, мне кажется, их комментарий с призывом к unsigned long > хорошо бы тоже заменить на обоснование новой концепции (а то он будет > противоречить тому, что мы видим в коде, и сбивать с толку ещё > сильнее, хотя и раньше он был загадочным). > Из общих соображений кажется, что такую задачу надо решать, сделав get_* и set_* методы в этой структуре. Пусть они принимают int64_t (и снаружи пусть все работают с этим типом), а внутри (если хочется экономить место) пусть хранят private int32_t. И переполнение пусть проверяют. Снаружи могло быть полезно использовать int64_t потому, что где-то могут вычисляться суммы/разности таких чисел и авторы боятся переполнения в таких местах. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map 2020-02-13 1:13 [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map Ivan Zakharyaschev 2020-02-13 2:19 ` Vladislav Zavjalov @ 2020-02-13 5:34 ` Ivan Zakharyaschev 2020-02-13 12:33 ` Aleksei Nikiforov 1 sibling, 1 reply; 5+ messages in thread From: Ivan Zakharyaschev @ 2020-02-13 5:34 UTC (permalink / raw) To: ALT Linux Team development discussions; +Cc: darktemplar [-- Attachment #1: Type: text/plain, Size: 15084 bytes --] On Thu, 13 Feb 2020, Ivan Zakharyaschev wrote: > Со временем я замечаю больше тонкостей про memory management в APT, > например, обратил-таки когда-то внимание на следующее место в mmap.h: > > /* This should be a 32 bit type, larger tyes use too much ram and smaller > types are too small. Where ever possible 'unsigned long' should be used > instead of this internal type */ > typedef unsigned int map_ptrloc; > > Я пытался догадаться, что имели в виду авторы, и подумал, что когда > нам нужно хранить указатель в структуре, попадающей в область памяти, > отмапленную в файл ("кеш" информации о всех пакетах), то мы хотим > чтобы это всё занимало поменьше места и вместо указателя храним в > структуре "индекс" (offset) в массиве, соответствующем этой области, и > делаем его 32-битным (грубо говоря). (На LP64-платформах, таких как > x86_64, int 32битный.) > > При этом авторы призывают где возможно использовать unsigned long > (64-бита, как и указатели, на x86_64). "Где возможно" -- это, наверное, > до тех пор, пока мы индекс не записываем в структуру, которая будет > сохранена в этом мапе. Т.е. когда нам просто надо поработать с > данными. > Но всё же меня озадачивает, что следующий патч идёт как бы вразрез с этим > призывом -- он изживает unsigned long из всех методов класса DynamicMMap, > которые возвращают такие индексы. > В ветке sisyphus_one_more_time в > git://git.altlinux.org/people/darktemplar/packages/apt.git коммит > > commit 971eae5c0248f6f849e1e989cab7244e33fbaf67 > Author: Aleksei Nikiforov <darktemplar@altlinux.org> > Date: Mon Jul 22 14:18:13 2019 +0300 > > dynamic memory management: Use same type for all offsets to dynamically allocated map > > Conformance update > > Change-Id: I5efcdb9e6604ad4e3f7329e590ab0b48e5400664 Тем самым, с одной стороны, это изменение не является по виду просто эквивалентным переписыванием имевшегося кода, которое однозначно не меняет поведение. (Когда раньше смотрел этот патч, я этого не осознавал, потому что не обращал внимание, что это два типа разного размера.) С другой стороны, если поведение программы в каких-то местах может поменяться, из коммита непонятно, чем потенциальное новое поведение лучше старого. > diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc > index 5e9cfbce9..743e35723 100644 > --- a/apt/apt-pkg/contrib/mmap.cc > +++ b/apt/apt-pkg/contrib/mmap.cc > @@ -215,7 +215,7 @@ DynamicMMap::~DynamicMMap() > // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/ > // --------------------------------------------------------------------- > /* This allocates a block of memory aligned to the given size */ > -std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) > +std::experimental::optional<map_ptrloc> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) > { > unsigned long long Result = iSize; > if (Aln != 0) > @@ -231,25 +231,25 @@ std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned lon > "Current values are: %llu, %llu. (man 5 apt.conf)"), > (unsigned long long) _config->FindI("APT::Cache-Start", 24*1024*1024), > (unsigned long long) _config->FindI("APT::Cache-Limit", 0)); > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > } > } > > iSize = Result + Size; > > - return std::experimental::optional<unsigned long>(Result); > + return std::experimental::optional<map_ptrloc>(Result); > } > /*}}}*/ > // DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/ > // --------------------------------------------------------------------- > /* This allocates an Item of size ItemSize so that it is aligned to its > size in the file. */ > -std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long ItemSize) > +std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long ItemSize) > { > if (ItemSize == 0) > { > _error->Error("Can't allocate an item of size zero"); > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > } > > // Look for a matching pool entry > @@ -286,7 +286,7 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I > if (Empty == 0) > { > _error->Error("Ran out of allocation pools"); > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > } > > I = Empty; > @@ -316,13 +316,13 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I > > I->Count--; > I->Start += ItemSize; > - return std::experimental::optional<unsigned long>(Result/ItemSize); > + return std::experimental::optional<map_ptrloc>(Result/ItemSize); > } > /*}}}*/ > // DynamicMMap::WriteString - Write a string to the file /*{{{*/ > // --------------------------------------------------------------------- > /* Strings are not aligned to anything */ > -std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char *String, > +std::experimental::optional<map_ptrloc> DynamicMMap::WriteString(const char *String, > unsigned long Len) > { > if (Len == std::numeric_limits<unsigned long>::max()) > @@ -331,7 +331,7 @@ std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char * > auto Result = RawAllocate(Len+1,0); > > if (Base == NULL || !Result) > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > > memcpy((char *)Base + *Result,String,Len); > ((char *)Base)[*Result + Len] = 0; > diff --git a/apt/apt-pkg/contrib/mmap.h b/apt/apt-pkg/contrib/mmap.h > index cfeec12b1..e4f289a5c 100644 > --- a/apt/apt-pkg/contrib/mmap.h > +++ b/apt/apt-pkg/contrib/mmap.h > @@ -101,10 +101,10 @@ class DynamicMMap : public MMap > public: > > // Allocation > - std::experimental::optional<unsigned long> RawAllocate(unsigned long long Size,unsigned long Aln = 0); > - std::experimental::optional<unsigned long> Allocate(unsigned long ItemSize); > - std::experimental::optional<unsigned long> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); > - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; > + std::experimental::optional<map_ptrloc> RawAllocate(unsigned long long Size,unsigned long Aln = 0); > + std::experimental::optional<map_ptrloc> Allocate(unsigned long ItemSize); > + std::experimental::optional<map_ptrloc> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); > + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; > void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;}; > > DynamicMMap(FileFd &F,unsigned long Flags,unsigned long long WorkSpace = 2*1024*1024, > diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc > index 36d54504e..4940ec6e5 100644 > --- a/apt/apt-pkg/pkgcachegen.cc > +++ b/apt/apt-pkg/pkgcachegen.cc > @@ -525,15 +525,15 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, > // CacheGenerator::NewVersion - Create a new Version /*{{{*/ > // --------------------------------------------------------------------- > /* This puts a version structure in the linked list */ > -std::experimental::optional<unsigned long> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, > +std::experimental::optional<map_ptrloc> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, > const string &VerStr, > - unsigned long Next) > + map_ptrloc Next) > { > // Get a structure > const auto Version = AllocateInMap(sizeof(pkgCache::Version)); > const auto idxVerStr = WriteStringInMap(VerStr); > if ((!Version) || (!idxVerStr)) > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > > // Fill it in > Ver = pkgCache::VerIterator(Cache,Cache.VerP + *Version); > @@ -710,7 +710,7 @@ bool pkgCacheGenerator::SelectFile(const string &File, const string &Site, > // --------------------------------------------------------------------- > /* This is used to create handles to strings. Given the same text it > always returns the same number */ > -std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(const char *S, > +std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const char *S, > unsigned int Size) > { > /* We use a very small transient hash table here, this speeds up generation > @@ -718,7 +718,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co > pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)]; > if (Bucket != 0 && > stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0) > - return std::experimental::optional<unsigned long>(Bucket->String); > + return std::experimental::optional<map_ptrloc>(Bucket->String); > > // Search for an insertion point > pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList; > @@ -736,7 +736,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co > if (Res == 0) > { > Bucket = I; > - return std::experimental::optional<unsigned long>(I->String); > + return std::experimental::optional<map_ptrloc>(I->String); > } > > // Get a structure > @@ -744,7 +744,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co > const auto Item = AllocateInMap(sizeof(pkgCache::StringItem)); > const auto idxString = WriteStringInMap(S, Size); > if ((!Item) || (!idxString)) > - return std::experimental::optional<unsigned long>(); > + return std::experimental::optional<map_ptrloc>(); > > if (oldMap != Map.Data()) > { > @@ -760,7 +760,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co > ItemP->String = *idxString; > > Bucket = ItemP; > - return std::experimental::optional<unsigned long>(ItemP->String); > + return std::experimental::optional<map_ptrloc>(ItemP->String); > } > /*}}}*/ > > diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h > index dfcadbf8e..8a66765cc 100644 > --- a/apt/apt-pkg/pkgcachegen.h > +++ b/apt/apt-pkg/pkgcachegen.h > @@ -116,15 +116,15 @@ class pkgCacheGenerator > bool FoundFileDeps; > > bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); > - std::experimental::optional<unsigned long> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next); > + std::experimental::optional<map_ptrloc> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr, map_ptrloc Next); > > public: > > // CNC:2003-02-27 - We need this in rpmListParser. > bool NewPackage(pkgCache::PkgIterator &PkgI,const string &Pkg); > > - std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size); > - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; > + std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size); > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; > > void DropProgress() {Progress = 0;}; > bool SelectFile(const string &File,const string &Site,pkgIndexFile const &Index, > @@ -162,10 +162,10 @@ class pkgCacheGenerator::ListParser > pkgCacheGenerator *Owner; > friend class pkgCacheGenerator; > > - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; > - inline std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; > - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; > - inline std::experimental::optional<unsigned long> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; > + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; > + inline std::experimental::optional<map_ptrloc> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; > bool NewDepends(pkgCache::VerIterator &Ver, const string &Package, > const string &Version,unsigned int Op, > unsigned int Type); > diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc > index 0cbb5f750..ea27d11c5 100644 > --- a/apt/apt-pkg/rpm/rpmlistparser.cc > +++ b/apt/apt-pkg/rpm/rpmlistparser.cc > @@ -75,7 +75,7 @@ rpmListParser::~rpmListParser() > // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ > // --------------------------------------------------------------------- > /* */ > -std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int Tag) > +std::experimental::optional<map_ptrloc> rpmListParser::UniqFindTagWrite(int Tag) > { > char *Start; > char *Stop; > @@ -90,7 +90,7 @@ std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int T > * But since cacheiterators treat zero as special value, > * just pass it instead of failing > */ > - return std::experimental::optional<unsigned long>(0); > + return std::experimental::optional<map_ptrloc>(0); > } > > if (type == RPM_STRING_TYPE) > diff --git a/apt/apt-pkg/rpm/rpmlistparser.h b/apt/apt-pkg/rpm/rpmlistparser.h > index 6767d106d..22a90a0a5 100644 > --- a/apt/apt-pkg/rpm/rpmlistparser.h > +++ b/apt/apt-pkg/rpm/rpmlistparser.h > @@ -45,7 +45,7 @@ class rpmListParser : public pkgCacheGenerator::ListParser > > bool Duplicated; > > - std::experimental::optional<unsigned long> UniqFindTagWrite(int Tag); > + std::experimental::optional<map_ptrloc> UniqFindTagWrite(int Tag); > bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); > bool ParseDepends(pkgCache::VerIterator &Ver, > char **namel, char **verl, int32_t *flagl, > > -- > Best regards, > Ivan ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map 2020-02-13 5:34 ` Ivan Zakharyaschev @ 2020-02-13 12:33 ` Aleksei Nikiforov 2020-02-13 14:05 ` Ivan Zakharyaschev 0 siblings, 1 reply; 5+ messages in thread From: Aleksei Nikiforov @ 2020-02-13 12:33 UTC (permalink / raw) To: Ivan Zakharyaschev; +Cc: ALT Linux Team development discussions 13.02.2020 08:34, Ivan Zakharyaschev пишет: > > On Thu, 13 Feb 2020, Ivan Zakharyaschev wrote: > >> Со временем я замечаю больше тонкостей про memory management в APT, >> например, обратил-таки когда-то внимание на следующее место в mmap.h: >> >> /* This should be a 32 bit type, larger tyes use too much ram and smaller >> types are too small. Where ever possible 'unsigned long' should be used >> instead of this internal type */ >> typedef unsigned int map_ptrloc; >> >> Я пытался догадаться, что имели в виду авторы, и подумал, что когда >> нам нужно хранить указатель в структуре, попадающей в область памяти, >> отмапленную в файл ("кеш" информации о всех пакетах), то мы хотим >> чтобы это всё занимало поменьше места и вместо указателя храним в >> структуре "индекс" (offset) в массиве, соответствующем этой области, и >> делаем его 32-битным (грубо говоря). (На LP64-платформах, таких как >> x86_64, int 32битный.) >> >> При этом авторы призывают где возможно использовать unsigned long >> (64-бита, как и указатели, на x86_64). "Где возможно" -- это, наверное, >> до тех пор, пока мы индекс не записываем в структуру, которая будет >> сохранена в этом мапе. Т.е. когда нам просто надо поработать с >> данными. > >> Но всё же меня озадачивает, что следующий патч идёт как бы вразрез с этим >> призывом -- он изживает unsigned long из всех методов класса DynamicMMap, >> которые возвращают такие индексы. > >> В ветке sisyphus_one_more_time в >> git://git.altlinux.org/people/darktemplar/packages/apt.git коммит >> >> commit 971eae5c0248f6f849e1e989cab7244e33fbaf67 >> Author: Aleksei Nikiforov <darktemplar@altlinux.org> >> Date: Mon Jul 22 14:18:13 2019 +0300 >> >> dynamic memory management: Use same type for all offsets to dynamically allocated map >> >> Conformance update >> >> Change-Id: I5efcdb9e6604ad4e3f7329e590ab0b48e5400664 > > Тем самым, с одной стороны, это изменение не является по виду просто > эквивалентным переписыванием имевшегося кода, которое однозначно не меняет > поведение. (Когда раньше смотрел этот патч, я этого не осознавал, потому > что не обращал внимание, что это два типа разного размера.) > > С другой стороны, если поведение программы в каких-то местах может > поменяться, из коммита непонятно, чем потенциальное новое поведение лучше > старого. > Здравствуй. По поводу мыслей и замыслов других авторов, в том числе из Debian, я ничего сказать не могу. Такие вопросы точно не по адресу. Далее по поводу данного патча и некоторых предыдущих патчей из серии. Портируемые из Debian изменения, как и сделанные на их основе мной изменения, содержали unsigned long как до изменений, так и после. Поэтому я решил это не менять там. Поскольку индексы map_ptrloc и 'unsigned long' указывают на смещение в одном и том же файле, делать их разными типами смысла никакого нет. Соответственно, я привёл в этом патче их к единому виду: map_ptrloc. Сейчас это typedef на 'unsigned int'. Делать map_ptrloc более длинным типом я причин пока что не вижу. Как минимум, пока файлы кэша не подходят близко к отметке в 4Гб. А вот минусы от такого изменения быть могут, и скорее всего будут, в виде увеличения потребления ресурсов. Только что посмотрел код apt свежей версии из Debian. Там map_ptrloc заменили на map_stringitem_t, а unsigned long в данных случаях - на map_pointer_t, который является typedef на тот же самый map_stringitem_t, который в свою очередь всё ещё является typedef на 32-битный int, который правда прописали как uint32_t. >> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc >> index 5e9cfbce9..743e35723 100644 >> --- a/apt/apt-pkg/contrib/mmap.cc >> +++ b/apt/apt-pkg/contrib/mmap.cc >> @@ -215,7 +215,7 @@ DynamicMMap::~DynamicMMap() >> // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/ >> // --------------------------------------------------------------------- >> /* This allocates a block of memory aligned to the given size */ >> -std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) >> +std::experimental::optional<map_ptrloc> DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) >> { >> unsigned long long Result = iSize; >> if (Aln != 0) >> @@ -231,25 +231,25 @@ std::experimental::optional<unsigned long> DynamicMMap::RawAllocate(unsigned lon >> "Current values are: %llu, %llu. (man 5 apt.conf)"), >> (unsigned long long) _config->FindI("APT::Cache-Start", 24*1024*1024), >> (unsigned long long) _config->FindI("APT::Cache-Limit", 0)); >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> } >> } >> >> iSize = Result + Size; >> >> - return std::experimental::optional<unsigned long>(Result); >> + return std::experimental::optional<map_ptrloc>(Result); >> } >> /*}}}*/ >> // DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/ >> // --------------------------------------------------------------------- >> /* This allocates an Item of size ItemSize so that it is aligned to its >> size in the file. */ >> -std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long ItemSize) >> +std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long ItemSize) >> { >> if (ItemSize == 0) >> { >> _error->Error("Can't allocate an item of size zero"); >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> } >> >> // Look for a matching pool entry >> @@ -286,7 +286,7 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I >> if (Empty == 0) >> { >> _error->Error("Ran out of allocation pools"); >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> } >> >> I = Empty; >> @@ -316,13 +316,13 @@ std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned long I >> >> I->Count--; >> I->Start += ItemSize; >> - return std::experimental::optional<unsigned long>(Result/ItemSize); >> + return std::experimental::optional<map_ptrloc>(Result/ItemSize); >> } >> /*}}}*/ >> // DynamicMMap::WriteString - Write a string to the file /*{{{*/ >> // --------------------------------------------------------------------- >> /* Strings are not aligned to anything */ >> -std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char *String, >> +std::experimental::optional<map_ptrloc> DynamicMMap::WriteString(const char *String, >> unsigned long Len) >> { >> if (Len == std::numeric_limits<unsigned long>::max()) >> @@ -331,7 +331,7 @@ std::experimental::optional<unsigned long> DynamicMMap::WriteString(const char * >> auto Result = RawAllocate(Len+1,0); >> >> if (Base == NULL || !Result) >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> >> memcpy((char *)Base + *Result,String,Len); >> ((char *)Base)[*Result + Len] = 0; >> diff --git a/apt/apt-pkg/contrib/mmap.h b/apt/apt-pkg/contrib/mmap.h >> index cfeec12b1..e4f289a5c 100644 >> --- a/apt/apt-pkg/contrib/mmap.h >> +++ b/apt/apt-pkg/contrib/mmap.h >> @@ -101,10 +101,10 @@ class DynamicMMap : public MMap >> public: >> >> // Allocation >> - std::experimental::optional<unsigned long> RawAllocate(unsigned long long Size,unsigned long Aln = 0); >> - std::experimental::optional<unsigned long> Allocate(unsigned long ItemSize); >> - std::experimental::optional<unsigned long> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); >> - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; >> + std::experimental::optional<map_ptrloc> RawAllocate(unsigned long long Size,unsigned long Aln = 0); >> + std::experimental::optional<map_ptrloc> Allocate(unsigned long ItemSize); >> + std::experimental::optional<map_ptrloc> WriteString(const char *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); >> + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return WriteString(S.c_str(),S.length());}; >> void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;}; >> >> DynamicMMap(FileFd &F,unsigned long Flags,unsigned long long WorkSpace = 2*1024*1024, >> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc >> index 36d54504e..4940ec6e5 100644 >> --- a/apt/apt-pkg/pkgcachegen.cc >> +++ b/apt/apt-pkg/pkgcachegen.cc >> @@ -525,15 +525,15 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, >> // CacheGenerator::NewVersion - Create a new Version /*{{{*/ >> // --------------------------------------------------------------------- >> /* This puts a version structure in the linked list */ >> -std::experimental::optional<unsigned long> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, >> +std::experimental::optional<map_ptrloc> pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, >> const string &VerStr, >> - unsigned long Next) >> + map_ptrloc Next) >> { >> // Get a structure >> const auto Version = AllocateInMap(sizeof(pkgCache::Version)); >> const auto idxVerStr = WriteStringInMap(VerStr); >> if ((!Version) || (!idxVerStr)) >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> >> // Fill it in >> Ver = pkgCache::VerIterator(Cache,Cache.VerP + *Version); >> @@ -710,7 +710,7 @@ bool pkgCacheGenerator::SelectFile(const string &File, const string &Site, >> // --------------------------------------------------------------------- >> /* This is used to create handles to strings. Given the same text it >> always returns the same number */ >> -std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(const char *S, >> +std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const char *S, >> unsigned int Size) >> { >> /* We use a very small transient hash table here, this speeds up generation >> @@ -718,7 +718,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co >> pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)]; >> if (Bucket != 0 && >> stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0) >> - return std::experimental::optional<unsigned long>(Bucket->String); >> + return std::experimental::optional<map_ptrloc>(Bucket->String); >> >> // Search for an insertion point >> pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList; >> @@ -736,7 +736,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co >> if (Res == 0) >> { >> Bucket = I; >> - return std::experimental::optional<unsigned long>(I->String); >> + return std::experimental::optional<map_ptrloc>(I->String); >> } >> >> // Get a structure >> @@ -744,7 +744,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co >> const auto Item = AllocateInMap(sizeof(pkgCache::StringItem)); >> const auto idxString = WriteStringInMap(S, Size); >> if ((!Item) || (!idxString)) >> - return std::experimental::optional<unsigned long>(); >> + return std::experimental::optional<map_ptrloc>(); >> >> if (oldMap != Map.Data()) >> { >> @@ -760,7 +760,7 @@ std::experimental::optional<unsigned long> pkgCacheGenerator::WriteUniqString(co >> ItemP->String = *idxString; >> >> Bucket = ItemP; >> - return std::experimental::optional<unsigned long>(ItemP->String); >> + return std::experimental::optional<map_ptrloc>(ItemP->String); >> } >> /*}}}*/ >> >> diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h >> index dfcadbf8e..8a66765cc 100644 >> --- a/apt/apt-pkg/pkgcachegen.h >> +++ b/apt/apt-pkg/pkgcachegen.h >> @@ -116,15 +116,15 @@ class pkgCacheGenerator >> bool FoundFileDeps; >> >> bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); >> - std::experimental::optional<unsigned long> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next); >> + std::experimental::optional<map_ptrloc> NewVersion(pkgCache::VerIterator &Ver,const string &VerStr, map_ptrloc Next); >> >> public: >> >> // CNC:2003-02-27 - We need this in rpmListParser. >> bool NewPackage(pkgCache::PkgIterator &PkgI,const string &Pkg); >> >> - std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size); >> - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; >> + std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size); >> + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return WriteUniqString(S.c_str(),S.length());}; >> >> void DropProgress() {Progress = 0;}; >> bool SelectFile(const string &File,const string &Site,pkgIndexFile const &Index, >> @@ -162,10 +162,10 @@ class pkgCacheGenerator::ListParser >> pkgCacheGenerator *Owner; >> friend class pkgCacheGenerator; >> >> - inline std::experimental::optional<unsigned long> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; >> - inline std::experimental::optional<unsigned long> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; >> - inline std::experimental::optional<unsigned long> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; >> - inline std::experimental::optional<unsigned long> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; >> + inline std::experimental::optional<map_ptrloc> WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; >> + inline std::experimental::optional<map_ptrloc> WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; >> + inline std::experimental::optional<map_ptrloc> WriteString(const string &S) {return Owner->WriteStringInMap(S);}; >> + inline std::experimental::optional<map_ptrloc> WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; >> bool NewDepends(pkgCache::VerIterator &Ver, const string &Package, >> const string &Version,unsigned int Op, >> unsigned int Type); >> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc >> index 0cbb5f750..ea27d11c5 100644 >> --- a/apt/apt-pkg/rpm/rpmlistparser.cc >> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc >> @@ -75,7 +75,7 @@ rpmListParser::~rpmListParser() >> // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ >> // --------------------------------------------------------------------- >> /* */ >> -std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int Tag) >> +std::experimental::optional<map_ptrloc> rpmListParser::UniqFindTagWrite(int Tag) >> { >> char *Start; >> char *Stop; >> @@ -90,7 +90,7 @@ std::experimental::optional<unsigned long> rpmListParser::UniqFindTagWrite(int T >> * But since cacheiterators treat zero as special value, >> * just pass it instead of failing >> */ >> - return std::experimental::optional<unsigned long>(0); >> + return std::experimental::optional<map_ptrloc>(0); >> } >> >> if (type == RPM_STRING_TYPE) >> diff --git a/apt/apt-pkg/rpm/rpmlistparser.h b/apt/apt-pkg/rpm/rpmlistparser.h >> index 6767d106d..22a90a0a5 100644 >> --- a/apt/apt-pkg/rpm/rpmlistparser.h >> +++ b/apt/apt-pkg/rpm/rpmlistparser.h >> @@ -45,7 +45,7 @@ class rpmListParser : public pkgCacheGenerator::ListParser >> >> bool Duplicated; >> >> - std::experimental::optional<unsigned long> UniqFindTagWrite(int Tag); >> + std::experimental::optional<map_ptrloc> UniqFindTagWrite(int Tag); >> bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); >> bool ParseDepends(pkgCache::VerIterator &Ver, >> char **namel, char **verl, int32_t *flagl, >> >> -- >> Best regards, >> Ivan >> >> _______________________________________________ >> Devel mailing list >> Devel@lists.altlinux.org >> https://lists.altlinux.org/mailman/listinfo/devel ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map 2020-02-13 12:33 ` Aleksei Nikiforov @ 2020-02-13 14:05 ` Ivan Zakharyaschev 0 siblings, 0 replies; 5+ messages in thread From: Ivan Zakharyaschev @ 2020-02-13 14:05 UTC (permalink / raw) To: ALT Linux Team development discussions [-- Attachment #1: Type: text/plain, Size: 19254 bytes --] On Thu, 13 Feb 2020, Aleksei Nikiforov wrote: > 13.02.2020 08:34, Ivan Zakharyaschev пишет: > > > > On Thu, 13 Feb 2020, Ivan Zakharyaschev wrote: > > > > > Со временем я замечаю больше тонкостей про memory management в APT, > > > например, обратил-таки когда-то внимание на следующее место в mmap.h: > > > > > > /* This should be a 32 bit type, larger tyes use too much ram and smaller > > > types are too small. Where ever possible 'unsigned long' should be > > > used > > > instead of this internal type */ > > > typedef unsigned int map_ptrloc; > > > > > > Я пытался догадаться, что имели в виду авторы, и подумал, что когда > > > нам нужно хранить указатель в структуре, попадающей в область памяти, > > > отмапленную в файл ("кеш" информации о всех пакетах), то мы хотим > > > чтобы это всё занимало поменьше места и вместо указателя храним в > > > структуре "индекс" (offset) в массиве, соответствующем этой области, и > > > делаем его 32-битным (грубо говоря). (На LP64-платформах, таких как > > > x86_64, int 32битный.) > > > > > > При этом авторы призывают где возможно использовать unsigned long > > > (64-бита, как и указатели, на x86_64). "Где возможно" -- это, наверное, > > > до тех пор, пока мы индекс не записываем в структуру, которая будет > > > сохранена в этом мапе. Т.е. когда нам просто надо поработать с > > > данными. > > > > > Но всё же меня озадачивает, что следующий патч идёт как бы вразрез с этим > > > призывом -- он изживает unsigned long из всех методов класса DynamicMMap, > > > которые возвращают такие индексы. > > > > > В ветке sisyphus_one_more_time в > > > git://git.altlinux.org/people/darktemplar/packages/apt.git коммит > > > > > > commit 971eae5c0248f6f849e1e989cab7244e33fbaf67 > > > Author: Aleksei Nikiforov <darktemplar@altlinux.org> > > > Date: Mon Jul 22 14:18:13 2019 +0300 > > > > > > dynamic memory management: Use same type for all offsets to > > > dynamically allocated map > > > > > > Conformance update > > > > > > Change-Id: I5efcdb9e6604ad4e3f7329e590ab0b48e5400664 > > > > Тем самым, с одной стороны, это изменение не является по виду просто > > эквивалентным переписыванием имевшегося кода, которое однозначно не меняет > > поведение. (Когда раньше смотрел этот патч, я этого не осознавал, потому > > что не обращал внимание, что это два типа разного размера.) > > > > С другой стороны, если поведение программы в каких-то местах может > > поменяться, из коммита непонятно, чем потенциальное новое поведение лучше > > старого. > Далее по поводу данного патча и некоторых предыдущих патчей из серии. > > Портируемые из Debian изменения, как и сделанные на их основе мной изменения, > содержали unsigned long как до изменений, так и после. Поэтому я решил это не > менять там. Согласен, что так лучше, когда это неочевидное по последствиям изменение отделено от других в отдельном коммите. > Поскольку индексы map_ptrloc и 'unsigned long' указывают на > смещение в одном и том же файле, делать их разными типами смысла никакого нет. Это не ясно до конца, потому что до этого изменения часть работы с ними делалась в виде unsigned long. Только часть этих индексов могла доехать до того места, где мы сохраняем их в мап в виде 32-битного числа. Вот эта часть работы может измениться. (А может быть и нет.) Это неясно из commit message. Оно немного вводит в заблуждение, называя это conformance change, как будто бы нет потенциального изменения поведения, которое требует обоснования. (Чем новое поведение, именно в run-time, а не по warning-ам от компилятора, лучше старого?) > Соответственно, я привёл в этом патче их к единому виду: map_ptrloc. Сейчас > это typedef на 'unsigned int'. Делать map_ptrloc более длинным типом я причин > пока что не вижу. Как минимум, пока файлы кэша не подходят близко к отметке в > 4Гб. А вот минусы от такого изменения быть могут, и скорее всего будут, в виде > увеличения потребления ресурсов. Согласен, что хранить в мапе в 64-битном виде не надо, раз пока и так справлялись. Менять ещё и эту часть я не предлагал и не хотел. > Только что посмотрел код apt свежей версии из Debian. Там map_ptrloc заменили > на map_stringitem_t, а unsigned long в данных случаях - на map_pointer_t, > который является typedef на тот же самый map_stringitem_t, который в свою > очередь всё ещё является typedef на 32-битный int, который правда прописали > как uint32_t. Интересная информация, которая может стать хоть каким-то обоснованием этих изменений. > > > diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc > > > index 5e9cfbce9..743e35723 100644 > > > --- a/apt/apt-pkg/contrib/mmap.cc > > > +++ b/apt/apt-pkg/contrib/mmap.cc > > > @@ -215,7 +215,7 @@ DynamicMMap::~DynamicMMap() > > > // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space > > > /*{{{*/ > > > // --------------------------------------------------------------------- > > > /* This allocates a block of memory aligned to the given size */ > > > -std::experimental::optional<unsigned long> > > > DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln) > > > +std::experimental::optional<map_ptrloc> DynamicMMap::RawAllocate(unsigned > > > long long Size,unsigned long Aln) > > > { > > > unsigned long long Result = iSize; > > > if (Aln != 0) > > > @@ -231,25 +231,25 @@ std::experimental::optional<unsigned long> > > > DynamicMMap::RawAllocate(unsigned lon > > > "Current values are: %llu, %llu. (man 5 > > > apt.conf)"), > > > (unsigned long long) > > > _config->FindI("APT::Cache-Start", 24*1024*1024), > > > (unsigned long long) > > > _config->FindI("APT::Cache-Limit", 0)); > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > } > > > } > > > > > > iSize = Result + Size; > > > - return std::experimental::optional<unsigned long>(Result); > > > + return std::experimental::optional<map_ptrloc>(Result); > > > } > > > /*}}}*/ > > > // DynamicMMap::Allocate - Pooled aligned allocation > > > /*{{{*/ > > > // --------------------------------------------------------------------- > > > /* This allocates an Item of size ItemSize so that it is aligned to its > > > size in the file. */ > > > -std::experimental::optional<unsigned long> DynamicMMap::Allocate(unsigned > > > long ItemSize) > > > +std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned > > > long ItemSize) > > > { > > > if (ItemSize == 0) > > > { > > > _error->Error("Can't allocate an item of size zero"); > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > } > > > > > > // Look for a matching pool entry > > > @@ -286,7 +286,7 @@ std::experimental::optional<unsigned long> > > > DynamicMMap::Allocate(unsigned long I > > > if (Empty == 0) > > > { > > > _error->Error("Ran out of allocation pools"); > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > } > > > > > > I = Empty; > > > @@ -316,13 +316,13 @@ std::experimental::optional<unsigned long> > > > DynamicMMap::Allocate(unsigned long I > > > > > > I->Count--; > > > I->Start += ItemSize; > > > - return std::experimental::optional<unsigned long>(Result/ItemSize); > > > + return std::experimental::optional<map_ptrloc>(Result/ItemSize); > > > } > > > /*}}}*/ > > > // DynamicMMap::WriteString - Write a string to the file > > > /*{{{*/ > > > // --------------------------------------------------------------------- > > > /* Strings are not aligned to anything */ > > > -std::experimental::optional<unsigned long> DynamicMMap::WriteString(const > > > char *String, > > > +std::experimental::optional<map_ptrloc> DynamicMMap::WriteString(const > > > char *String, > > > unsigned long Len) > > > { > > > if (Len == std::numeric_limits<unsigned long>::max()) > > > @@ -331,7 +331,7 @@ std::experimental::optional<unsigned long> > > > DynamicMMap::WriteString(const char * > > > auto Result = RawAllocate(Len+1,0); > > > > > > if (Base == NULL || !Result) > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > > > > memcpy((char *)Base + *Result,String,Len); > > > ((char *)Base)[*Result + Len] = 0; > > > diff --git a/apt/apt-pkg/contrib/mmap.h b/apt/apt-pkg/contrib/mmap.h > > > index cfeec12b1..e4f289a5c 100644 > > > --- a/apt/apt-pkg/contrib/mmap.h > > > +++ b/apt/apt-pkg/contrib/mmap.h > > > @@ -101,10 +101,10 @@ class DynamicMMap : public MMap > > > public: > > > > > > // Allocation > > > - std::experimental::optional<unsigned long> RawAllocate(unsigned long > > > long Size,unsigned long Aln = 0); > > > - std::experimental::optional<unsigned long> Allocate(unsigned long > > > ItemSize); > > > - std::experimental::optional<unsigned long> WriteString(const char > > > *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); > > > - inline std::experimental::optional<unsigned long> WriteString(const > > > string &S) {return WriteString(S.c_str(),S.length());}; > > > + std::experimental::optional<map_ptrloc> RawAllocate(unsigned long long > > > Size,unsigned long Aln = 0); > > > + std::experimental::optional<map_ptrloc> Allocate(unsigned long > > > ItemSize); > > > + std::experimental::optional<map_ptrloc> WriteString(const char > > > *String,unsigned long Len = std::numeric_limits<unsigned long>::max()); > > > + inline std::experimental::optional<map_ptrloc> WriteString(const > > > string &S) {return WriteString(S.c_str(),S.length());}; > > > void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = > > > Count;}; > > > > > > DynamicMMap(FileFd &F,unsigned long Flags,unsigned long long > > > WorkSpace = 2*1024*1024, > > > diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc > > > index 36d54504e..4940ec6e5 100644 > > > --- a/apt/apt-pkg/pkgcachegen.cc > > > +++ b/apt/apt-pkg/pkgcachegen.cc > > > @@ -525,15 +525,15 @@ bool > > > pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, > > > // CacheGenerator::NewVersion - Create a new Version > > > /*{{{*/ > > > // --------------------------------------------------------------------- > > > /* This puts a version structure in the linked list */ > > > -std::experimental::optional<unsigned long> > > > pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, > > > +std::experimental::optional<map_ptrloc> > > > pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, > > > const string &VerStr, > > > - unsigned long Next) > > > + map_ptrloc Next) > > > { > > > // Get a structure > > > const auto Version = AllocateInMap(sizeof(pkgCache::Version)); > > > const auto idxVerStr = WriteStringInMap(VerStr); > > > if ((!Version) || (!idxVerStr)) > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > > > > // Fill it in > > > Ver = pkgCache::VerIterator(Cache,Cache.VerP + *Version); > > > @@ -710,7 +710,7 @@ bool pkgCacheGenerator::SelectFile(const string &File, > > > const string &Site, > > > // --------------------------------------------------------------------- > > > /* This is used to create handles to strings. Given the same text it > > > always returns the same number */ > > > -std::experimental::optional<unsigned long> > > > pkgCacheGenerator::WriteUniqString(const char *S, > > > +std::experimental::optional<map_ptrloc> > > > pkgCacheGenerator::WriteUniqString(const char *S, > > > unsigned int Size) > > > { > > > /* We use a very small transient hash table here, this speeds up > > > generation > > > @@ -718,7 +718,7 @@ std::experimental::optional<unsigned long> > > > pkgCacheGenerator::WriteUniqString(co > > > pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % > > > _count(UniqHash)]; > > > if (Bucket != 0 && > > > stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0) > > > - return std::experimental::optional<unsigned long>(Bucket->String); > > > + return std::experimental::optional<map_ptrloc>(Bucket->String); > > > > > > // Search for an insertion point > > > pkgCache::StringItem *I = Cache.StringItemP + > > > Cache.HeaderP->StringList; > > > @@ -736,7 +736,7 @@ std::experimental::optional<unsigned long> > > > pkgCacheGenerator::WriteUniqString(co > > > if (Res == 0) > > > { > > > Bucket = I; > > > - return std::experimental::optional<unsigned long>(I->String); > > > + return std::experimental::optional<map_ptrloc>(I->String); > > > } > > > > > > // Get a structure > > > @@ -744,7 +744,7 @@ std::experimental::optional<unsigned long> > > > pkgCacheGenerator::WriteUniqString(co > > > const auto Item = AllocateInMap(sizeof(pkgCache::StringItem)); > > > const auto idxString = WriteStringInMap(S, Size); > > > if ((!Item) || (!idxString)) > > > - return std::experimental::optional<unsigned long>(); > > > + return std::experimental::optional<map_ptrloc>(); > > > > > > if (oldMap != Map.Data()) > > > { > > > @@ -760,7 +760,7 @@ std::experimental::optional<unsigned long> > > > pkgCacheGenerator::WriteUniqString(co > > > ItemP->String = *idxString; > > > > > > Bucket = ItemP; > > > - return std::experimental::optional<unsigned long>(ItemP->String); > > > + return std::experimental::optional<map_ptrloc>(ItemP->String); > > > } > > > /*}}}*/ > > > diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h > > > index dfcadbf8e..8a66765cc 100644 > > > --- a/apt/apt-pkg/pkgcachegen.h > > > +++ b/apt/apt-pkg/pkgcachegen.h > > > @@ -116,15 +116,15 @@ class pkgCacheGenerator > > > bool FoundFileDeps; > > > > > > bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); > > > - std::experimental::optional<unsigned long> > > > NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long > > > Next); > > > + std::experimental::optional<map_ptrloc> > > > NewVersion(pkgCache::VerIterator &Ver,const string &VerStr, map_ptrloc > > > Next); > > > > > > public: > > > > > > // CNC:2003-02-27 - We need this in rpmListParser. > > > bool NewPackage(pkgCache::PkgIterator &PkgI,const string &Pkg); > > > - std::experimental::optional<unsigned long> WriteUniqString(const > > > char *S,unsigned int Size); > > > - inline std::experimental::optional<unsigned long> > > > WriteUniqString(const string &S) {return > > > WriteUniqString(S.c_str(),S.length());}; > > > + std::experimental::optional<map_ptrloc> WriteUniqString(const char > > > *S,unsigned int Size); > > > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const > > > string &S) {return WriteUniqString(S.c_str(),S.length());}; > > > > > > void DropProgress() {Progress = 0;}; > > > bool SelectFile(const string &File,const string &Site,pkgIndexFile > > > const &Index, > > > @@ -162,10 +162,10 @@ class pkgCacheGenerator::ListParser > > > pkgCacheGenerator *Owner; > > > friend class pkgCacheGenerator; > > > - inline std::experimental::optional<unsigned long> > > > WriteUniqString(const string &S) {return Owner->WriteUniqString(S);}; > > > - inline std::experimental::optional<unsigned long> > > > WriteUniqString(const char *S,unsigned int Size) {return > > > Owner->WriteUniqString(S,Size);}; > > > - inline std::experimental::optional<unsigned long> WriteString(const > > > string &S) {return Owner->WriteStringInMap(S);}; > > > - inline std::experimental::optional<unsigned long> WriteString(const > > > char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; > > > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const > > > string &S) {return Owner->WriteUniqString(S);}; > > > + inline std::experimental::optional<map_ptrloc> WriteUniqString(const > > > char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; > > > + inline std::experimental::optional<map_ptrloc> WriteString(const > > > string &S) {return Owner->WriteStringInMap(S);}; > > > + inline std::experimental::optional<map_ptrloc> WriteString(const char > > > *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; > > > bool NewDepends(pkgCache::VerIterator &Ver, const string &Package, > > > const string &Version,unsigned int Op, > > > unsigned int Type); > > > diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc > > > b/apt/apt-pkg/rpm/rpmlistparser.cc > > > index 0cbb5f750..ea27d11c5 100644 > > > --- a/apt/apt-pkg/rpm/rpmlistparser.cc > > > +++ b/apt/apt-pkg/rpm/rpmlistparser.cc > > > @@ -75,7 +75,7 @@ rpmListParser::~rpmListParser() > > > // ListParser::UniqFindTagWrite - Find the tag and write a unq string > > > /*{{{*/ > > > // --------------------------------------------------------------------- > > > /* */ > > > -std::experimental::optional<unsigned long> > > > rpmListParser::UniqFindTagWrite(int Tag) > > > +std::experimental::optional<map_ptrloc> > > > rpmListParser::UniqFindTagWrite(int Tag) > > > { > > > char *Start; > > > char *Stop; > > > @@ -90,7 +90,7 @@ std::experimental::optional<unsigned long> > > > rpmListParser::UniqFindTagWrite(int T > > > * But since cacheiterators treat zero as special value, > > > * just pass it instead of failing > > > */ > > > - return std::experimental::optional<unsigned long>(0); > > > + return std::experimental::optional<map_ptrloc>(0); > > > } > > > > > > if (type == RPM_STRING_TYPE) > > > diff --git a/apt/apt-pkg/rpm/rpmlistparser.h > > > b/apt/apt-pkg/rpm/rpmlistparser.h > > > index 6767d106d..22a90a0a5 100644 > > > --- a/apt/apt-pkg/rpm/rpmlistparser.h > > > +++ b/apt/apt-pkg/rpm/rpmlistparser.h > > > @@ -45,7 +45,7 @@ class rpmListParser : public > > > pkgCacheGenerator::ListParser > > > > > > bool Duplicated; > > > > > > - std::experimental::optional<unsigned long> UniqFindTagWrite(int Tag); > > > + std::experimental::optional<map_ptrloc> UniqFindTagWrite(int Tag); > > > bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator > > > &Ver); > > > bool ParseDepends(pkgCache::VerIterator &Ver, > > > char **namel, char **verl, int32_t *flagl, > > > > > > -- > > > Best regards, > > > Ivan > > > > > > _______________________________________________ > > > Devel mailing list > > > Devel@lists.altlinux.org > > > https://lists.altlinux.org/mailman/listinfo/devel > _______________________________________________ > Devel mailing list > Devel@lists.altlinux.org > https://lists.altlinux.org/mailman/listinfo/devel > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-02-13 14:05 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-02-13 1:13 [devel] re APT patch: Use same [32bit] type for all offsets to dynamically allocated map Ivan Zakharyaschev 2020-02-13 2:19 ` Vladislav Zavjalov 2020-02-13 5:34 ` Ivan Zakharyaschev 2020-02-13 12:33 ` Aleksei Nikiforov 2020-02-13 14:05 ` Ivan Zakharyaschev
ALT Linux Team development discussions This inbox may be cloned and mirrored by anyone: git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \ devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru public-inbox-index devel Example config snippet for mirrors. Newsgroup available over NNTP: nntp://lore.altlinux.org/org.altlinux.lists.devel AGPL code for this site: git clone https://public-inbox.org/public-inbox.git