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
16 #include <iostream>
17 #include <map>
18 #include <string>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <securec.h>
22 #include "hc_mutex.h"
23 #include "memory_monitor.h"
24
25 using namespace std;
26
27 #define MAX_MALLOC_SIZE 8192
28 #define MALLOC_MAX_LINE_STR_LEN 11
29
30 static const int MALLOC_SIZE[] = { 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
31
GetRealMallocSize(int size)32 static int GetRealMallocSize(int size)
33 {
34 for (unsigned int i = 0; i < sizeof(MALLOC_SIZE) / sizeof(int); ++i) {
35 if (size <= MALLOC_SIZE[i]) {
36 return MALLOC_SIZE[i];
37 }
38 }
39 return MAX_MALLOC_SIZE;
40 }
41
42 typedef struct {
43 uint32_t id;
44 uint32_t size;
45 uint32_t realSize;
46 string str;
47 } MemoryBlock;
48
49 static map<void*, MemoryBlock> gMemoryMap;
50
51 static bool g_isInit = false;
52
53 static int g_mallocCount = 0;
54 static int g_maxCount = 0;
55 static int g_maxSingleCount = 0;
56 static int g_count = 0;
57
58 static HcMutex *g_mutex = NULL;
59
HcMonitorMalloc(void * addr,uint32_t size,const char * strFile,int nLine)60 void HcMonitorMalloc(void *addr, uint32_t size, const char *strFile, int nLine)
61 {
62 if (!g_isInit) {
63 return;
64 }
65 g_mutex->lock(g_mutex);
66 map<void *, MemoryBlock>::iterator iter = gMemoryMap.find(addr);
67 if (iter != gMemoryMap.end()) {
68 cout << "############## Monitor Malloc error, addr is alread exist!" << endl;
69 } else {
70 int realSize = GetRealMallocSize(size);
71 MemoryBlock mb;
72 mb.size = size;
73 mb.realSize = realSize;
74 mb.id = g_count++;
75 char strLine[MALLOC_MAX_LINE_STR_LEN];
76 if (sprintf_s(strLine, MALLOC_MAX_LINE_STR_LEN, "%d", nLine) <= 0) {
77 g_mutex->unlock(g_mutex);
78 return;
79 }
80 mb.str = strFile;
81 mb.str += ":";
82 mb.str += strLine;
83 gMemoryMap[addr] = mb;
84 g_mallocCount += realSize;
85 if (g_maxCount < g_mallocCount) {
86 g_maxCount = g_mallocCount;
87 }
88 if (g_maxSingleCount < realSize) {
89 g_maxSingleCount = realSize;
90 }
91 }
92 g_mutex->unlock(g_mutex);
93 }
94
HcMonitorFree(void * addr)95 void HcMonitorFree(void *addr)
96 {
97 if (!g_isInit) {
98 return;
99 }
100 g_mutex->lock(g_mutex);
101 map<void *, MemoryBlock>::iterator iter = gMemoryMap.find(addr);
102 if (iter != gMemoryMap.end()) {
103 g_mallocCount -= GetRealMallocSize(iter->second.size);
104 gMemoryMap.erase(iter);
105 } else {
106 cout << "############## Monitor Free error, addr is not exist!" << endl;
107 }
108 g_mutex->unlock(g_mutex);
109 }
110
ReportMonitor(void)111 void ReportMonitor(void)
112 {
113 if (!g_isInit) {
114 return;
115 }
116 g_mutex->lock(g_mutex);
117 printf("\n############## Monitor Report ##############\nMemoryBlock Num: %zu\nMemory Used Size: %d\n"
118 "Memory Max Used Size: %d\nMemory Max Single Size: %d\n",
119 gMemoryMap.size(), g_mallocCount, g_maxCount, g_maxSingleCount);
120 for (map<void *, MemoryBlock>::iterator iter = gMemoryMap.begin(); iter != gMemoryMap.end(); ++iter) {
121 printf("\n############## Memory Block ##############\nMemoryBlock Id: %d\nMemoryBlock Size: %d\n"
122 "MemoryBlock Size: %d\nMemoryBlock Location: %s\n",
123 iter->second.id, iter->second.size, iter->second.realSize, iter->second.str.c_str());
124 }
125 g_mutex->unlock(g_mutex);
126 }
127
IsMemoryLeak(void)128 bool IsMemoryLeak(void)
129 {
130 return g_mallocCount > 0;
131 }
132
HcInitMallocMonitor(void)133 void HcInitMallocMonitor(void)
134 {
135 if (g_isInit) {
136 return;
137 }
138 g_isInit = true;
139 g_mutex = static_cast<HcMutex *>(malloc(sizeof(HcMutex)));
140 InitHcMutex(g_mutex);
141 }
142
HcDestroyMallocMonitor(void)143 void HcDestroyMallocMonitor(void)
144 {
145 if (!g_isInit) {
146 return;
147 }
148 g_isInit = false;
149 g_mutex->lock(g_mutex);
150 gMemoryMap.clear();
151 g_mallocCount = 0;
152 g_maxCount = 0;
153 g_maxSingleCount = 0;
154 g_count = 0;
155 g_mutex->unlock(g_mutex);
156 DestroyHcMutex(g_mutex);
157 free(g_mutex);
158 g_mutex = NULL;
159 }
160