1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "executor/memory/dma_info.h"
16 #include "util/file_utils.h"
17 #include "securec.h"
18 
19 using namespace std;
20 
21 namespace OHOS {
22 namespace HiviewDFX {
23 static constexpr int BYTE_PER_KB = 1024;
DmaInfo()24 DmaInfo::DmaInfo()
25 {
26 }
27 
~DmaInfo()28 DmaInfo::~DmaInfo()
29 {
30 }
31 
32 /**
33  * @description: create dma info
34  * @param {string} &str-string to be inserted into result
35  * @return void
36  */
CreateDmaInfo(const string & str)37 void DmaInfo::CreateDmaInfo(const string &str)
38 {
39     /*
40         Dma-buf objects usage of processes:
41         Process          pid              fd               size_bytes       ino              exp_pid          exp_task_comm    buf_name          exp_name
42         composer_host    552              11               3686400          7135             552              composer_host    NULL      rockchipdrm
43         composer_host    552              18               3686400          30235            543              allocator_host   NULL      rockchipdrm
44         Total dmabuf size of composer_host: 29491200 bytes
45         render_service   575              28               3686400          28052            543              allocator_host   NULL      rockchipdrm
46         render_service   575              31               3686400          31024            543              allocator_host   NULL      rockchipdrm
47         Total dmabuf size of render_service: 35520512 bytes
48     */
49     MemInfoData::DmaInfo dmaInfo;
50     char name[256] = {0}; // 256: max size of name
51     if (sscanf_s(str.c_str(), "%255s %llu %*llu %llu %llu %*n %*s %*s %*s",
52                  name, sizeof(name), &dmaInfo.pid, &dmaInfo.size, &dmaInfo.ino) == 0) {
53         return;
54     }
55     dmaInfo.name = name;
56     dmaInfo.size /= BYTE_PER_KB;
57     auto it = dmaInfos_.find(dmaInfo.ino);
58     if (it == dmaInfos_.end()) {
59         dmaInfos_.insert(pair<uint64_t, MemInfoData::DmaInfo>(dmaInfo.ino, dmaInfo));
60     } else if ((dmaInfo.name != "composer_host" && dmaInfo.name != "render_service") ||
61                (dmaInfo.name == "render_service" && it->second.name == "composer_host")) {
62         it->second.pid = dmaInfo.pid;
63     }
64 }
65 
66 /**
67  * @description: parse dma info
68  * @param void
69  * @return {bool}-the result of
70  */
ParseDmaInfo()71 bool DmaInfo::ParseDmaInfo()
72 {
73     if (initialized_) {
74         return true;
75     }
76     initialized_ = true;
77     string path = "/proc/process_dmabuf_info";
78     bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, false, true, [&](const string &line) -> void {
79         CreateDmaInfo(line);
80     });
81     for (const auto &it : dmaInfos_) {
82         auto dma = dmaMap_.find(it.second.pid);
83         if (dma != dmaMap_.end()) {
84             dma->second += it.second.size;
85         } else {
86             dmaMap_.insert(pair<uint32_t, uint64_t>(it.second.pid, it.second.size));
87         }
88     }
89     return ret;
90 }
91 
92 /**
93  * @description: get dma total
94  * @param void
95  * @return {uint64_t} dma total
96  */
GetTotalDma()97 uint64_t DmaInfo::GetTotalDma()
98 {
99     uint64_t totalDma = 0;
100     for (const auto &it : dmaMap_) {
101         totalDma += it.second;
102     }
103     return totalDma;
104 }
105 
106 /**
107  * @description: get dma by pid
108  * @param {int32_t} &pid-process id
109  * @return dma value of process
110  */
GetDmaByPid(const int32_t & pid) const111 uint64_t DmaInfo::GetDmaByPid(const int32_t &pid) const
112 {
113     auto it = dmaMap_.find(pid);
114     if (it != dmaMap_.end()) {
115         return it->second;
116     }
117     return 0;
118 }
119 } // namespace HiviewDFX
120 } // namespace OHOS
121