diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp index 41ecc5195ad83f581d6063555f8686a63ba30a13..b4ad6678a44c411abebcb79fa5b07df3e7e901cf 100644 --- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp +++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp @@ -119,9 +119,23 @@ static bool ReadDmaBufFdRefs(pid_t pid, std::vector* dmabufs) { return false; } - DmaBuffer& buf = + uint64_t inode = sb.st_ino; + auto buf = std::find_if(dmabufs->begin(), dmabufs->end(), + [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; }); + if (buf != dmabufs->end()) { + if (buf->name() == "" || buf->name() == "") + buf->SetName(name); + if (buf->exporter() == "" || buf->exporter() == "") + buf->SetExporter(exporter); + if (buf->count() == 0) + buf->SetCount(count); + buf->AddFdRef(pid); + return true; + } + + DmaBuffer& db = dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name); - buf.AddFdRef(pid); + db.AddFdRef(pid); } return true; @@ -225,6 +239,10 @@ bool ReadDmaBufInfo(std::vector* dmabufs, const std::string& path) { bool ReadDmaBufInfo(pid_t pid, std::vector* dmabufs) { dmabufs->clear(); + return AppendDmaBufInfo(pid, dmabufs); +} + +bool AppendDmaBufInfo(pid_t pid, std::vector* dmabufs) { if (!ReadDmaBufFdRefs(pid, dmabufs)) { LOG(ERROR) << "Failed to read dmabuf fd references"; return false; diff --git a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp index aa5f16c22d89269f1af366fdd6db80434e2a9c13..95aa2c79938aa0326aaed264cdc5107a38577c47 100644 --- a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp +++ b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -61,18 +62,16 @@ struct ion_heap_data { #define EXPECT_PID_IN_FDREFS(_bufptr, _pid, _expect) \ do { \ - const std::vector& _fdrefs = _bufptr->fdrefs(); \ - auto _ref = std::find_if(_fdrefs.begin(), _fdrefs.end(), \ - [&](const pid_t& p) { return p == _pid; }); \ - EXPECT_EQ((_ref == _fdrefs.end()), _expect); \ + const std::unordered_map& _fdrefs = _bufptr->fdrefs(); \ + auto _ref = _fdrefs.find(_pid); \ + EXPECT_EQ((_ref != _fdrefs.end()), _expect); \ } while (0) #define EXPECT_PID_IN_MAPREFS(_bufptr, _pid, _expect) \ do { \ - const std::vector& _maprefs = _bufptr->maprefs(); \ - auto _ref = std::find_if(_maprefs.begin(), _maprefs.end(), \ - [&](const pid_t& p) { return p == _pid; }); \ - EXPECT_EQ((_ref == _maprefs.end()), _expect); \ + const std::unordered_map& _maprefs = _bufptr->maprefs(); \ + auto _ref = _maprefs.find(_pid); \ + EXPECT_EQ((_ref != _maprefs.end()), _expect); \ } while (0) TEST(DmaBufInfoParser, TestReadDmaBufInfo) { diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h index 29ce4d0bd22a973e5a04299678ec18da30234a64..74eff3ccac711fe8964f1b5e8073bb219ebf79b0 100644 --- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h +++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h @@ -21,6 +21,7 @@ #include #include +#include namespace android { namespace dmabufinfo { @@ -33,20 +34,27 @@ struct DmaBuffer { ~DmaBuffer() = default; // Adds one file descriptor reference for the given pid - void AddFdRef(pid_t pid) { fdrefs_.emplace_back(pid); } + void AddFdRef(pid_t pid) { + AddRefToPidMap(pid, &fdrefs_); + } // Adds one map reference for the given pid - void AddMapRef(pid_t pid) { maprefs_.emplace_back(pid); } + void AddMapRef(pid_t pid) { + AddRefToPidMap(pid, &maprefs_); + } // Getters for each property uint64_t size() { return size_; } - const std::vector& fdrefs() const { return fdrefs_; } - const std::vector& maprefs() const { return maprefs_; } + const std::unordered_map& fdrefs() const { return fdrefs_; } + const std::unordered_map& maprefs() const { return maprefs_; } ino_t inode() const { return inode_; } uint64_t total_refs() const { return fdrefs_.size() + maprefs_.size(); } uint64_t count() const { return count_; }; const std::string& name() const { return name_; } const std::string& exporter() const { return exporter_; } + void SetName(const std::string& name) { name_ = name; } + void SetExporter(const std::string& exporter) { exporter_ = exporter; } + void SetCount(uint64_t count) { count_ = count; } private: ino_t inode_; @@ -54,20 +62,37 @@ struct DmaBuffer { uint64_t count_; std::string exporter_; std::string name_; - std::vector fdrefs_; - std::vector maprefs_; + std::unordered_map fdrefs_; + std::unordered_map maprefs_; + void AddRefToPidMap(pid_t pid, std::unordered_map* map) { + // The first time we find a ref, we set the ref count to 1 + // otherwise, increment the existing ref count + auto [it, inserted] = map->insert(std::make_pair(pid, 1)); + if (!inserted) + it->second++; + } }; // Read and return current dma buf objects from // DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not // populated here and will return an empty vector. +// // Returns false if something went wrong with the function, true otherwise. bool ReadDmaBufInfo(std::vector* dmabufs, const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo"); + // Read and return dmabuf objects for a given process without the help // of DEBUGFS +// +// Returns false if something went wrong with the function, true otherwise. bool ReadDmaBufInfo(pid_t pid, std::vector* dmabufs); +// Append dmabuf objects for a given process without the help +// of DEBUGFS to an existing vector +// +// Returns false if something went wrong with the function, true otherwise. +bool AppendDmaBufInfo(pid_t pid, std::vector* dmabufs); + } // namespace dmabufinfo } // namespace android