1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <sys/types.h> 20 #include <unistd.h> 21 22 #include <set> 23 #include <string> 24 #include <vector> 25 #include <unordered_map> 26 27 namespace android { 28 namespace dmabufinfo { 29 30 struct DmaBuffer { 31 public: DmaBufferDmaBuffer32 DmaBuffer(ino_t inode, uint64_t size, uint64_t count, const std::string& exporter, 33 const std::string& name) 34 : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) { 35 total_refs_ = 0; 36 } 37 DmaBuffer() = default; 38 ~DmaBuffer() = default; 39 40 // Adds one file descriptor reference for the given pid AddFdRefDmaBuffer41 void AddFdRef(pid_t pid) { 42 AddRefToPidMap(pid, &fdrefs_); 43 total_refs_++; 44 } 45 46 // Adds one map reference for the given pid AddMapRefDmaBuffer47 void AddMapRef(pid_t pid) { 48 AddRefToPidMap(pid, &maprefs_); 49 total_refs_++; 50 } 51 52 // Getters for each property sizeDmaBuffer53 uint64_t size() const { return size_; } fdrefsDmaBuffer54 const std::unordered_map<pid_t, int>& fdrefs() const { return fdrefs_; } maprefsDmaBuffer55 const std::unordered_map<pid_t, int>& maprefs() const { return maprefs_; } inodeDmaBuffer56 ino_t inode() const { return inode_; } total_refsDmaBuffer57 uint64_t total_refs() const { return total_refs_; } countDmaBuffer58 uint64_t count() const { return count_; }; pidsDmaBuffer59 const std::set<pid_t>& pids() const { return pids_; } nameDmaBuffer60 const std::string& name() const { return name_; } exporterDmaBuffer61 const std::string& exporter() const { return exporter_; } SetNameDmaBuffer62 void SetName(const std::string& name) { name_ = name; } SetExporterDmaBuffer63 void SetExporter(const std::string& exporter) { exporter_ = exporter; } SetCountDmaBuffer64 void SetCount(uint64_t count) { count_ = count; } PssDmaBuffer65 uint64_t Pss(pid_t pid) const { return maprefs_.count(pid) > 0 ? size_ / maprefs_.size() : 0; } 66 67 bool operator==(const DmaBuffer& rhs) { 68 return (inode_ == rhs.inode()) && (size_ == rhs.size()) && (name_ == rhs.name()) && 69 (exporter_ == rhs.exporter()); 70 } 71 72 private: 73 ino_t inode_; 74 uint64_t size_; 75 uint64_t count_; 76 uint64_t total_refs_; 77 std::set<pid_t> pids_; 78 std::string exporter_; 79 std::string name_; 80 std::unordered_map<pid_t, int> fdrefs_; 81 std::unordered_map<pid_t, int> maprefs_; AddRefToPidMapDmaBuffer82 void AddRefToPidMap(pid_t pid, std::unordered_map<pid_t, int>* map) { 83 // The first time we find a ref, we set the ref count to 1 84 // otherwise, increment the existing ref count 85 auto [it, inserted] = map->insert(std::make_pair(pid, 1)); 86 if (!inserted) 87 it->second++; 88 pids_.insert(pid); 89 } 90 }; 91 92 // Read and return current dma buf objects from 93 // DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not 94 // populated here and will return an empty vector. 95 // Returns false if something went wrong with the function, true otherwise. 96 bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs, 97 const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo"); 98 99 100 // Read and return dmabuf objects for a given process without the help 101 // of DEBUGFS 102 // Returns false if something went wrong with the function, true otherwise. 103 bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs, bool read_fdrefs = true); 104 105 // Append new dmabuf objects from a given process to an existing vector. 106 // When the vector contains an existing element with a matching inode, 107 // the reference counts will be updated. 108 // Does not depend on DEBUGFS. 109 // Returns false if something went wrong with the function, true otherwise. 110 bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs, bool read_fdrefs = true); 111 112 } // namespace dmabufinfo 113 } // namespace android 114