sq AD TYPE
[metze/wireshark/wip.git] / epan / app_mem_usage.c
1 /*
2  * app_mem_usage.c
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #if defined(__linux__)
12  #define _XOPEN_SOURCE 500
13 #endif
14
15 #include "config.h"
16
17 #include <stdio.h>
18
19 #include <glib.h>
20
21 #ifdef _WIN32
22 #include <windows.h>
23 #include <psapi.h>
24 #endif /*  _WIN32 */
25
26 #if defined(__linux__)
27 # include <sys/types.h>
28 # include <sys/stat.h>
29 # include <unistd.h>
30 # include <fcntl.h>
31 #endif
32
33 #include "wsutil/file_util.h"
34 #include "app_mem_usage.h"
35
36 #define MAX_COMPONENTS 16
37
38 #if defined(_WIN32)
39
40 static gsize
41 win32_get_total_mem_used_by_app(void)
42 {
43         HANDLE pHandle;
44         PROCESS_MEMORY_COUNTERS pmc;
45         SIZE_T workingSize = 0;
46
47         pHandle = GetCurrentProcess();
48
49         if (GetProcessMemoryInfo(pHandle, &pmc, sizeof(pmc))){
50                 workingSize = pmc.WorkingSetSize;
51         }
52
53         CloseHandle(pHandle);
54
55         if(workingSize == 0){
56                 return -1;
57         }else{
58                 return (int)workingSize;
59         }
60 }
61
62 static const ws_mem_usage_t total_usage = { "Total", win32_get_total_mem_used_by_app, NULL };
63
64 static const ws_mem_usage_t *memory_components[MAX_COMPONENTS] = {
65         &total_usage,
66 };
67
68 static guint memory_register_num = 1;
69
70 #elif defined(__linux__)
71
72 static gboolean
73 linux_get_memory(gsize *ptotal, gsize *prss)
74 {
75         static int fd = -1;
76         static intptr_t pagesize = 0;
77
78         char buf[128];
79         unsigned long total, rss;
80         ssize_t ret;
81
82         if (!pagesize)
83                 pagesize = sysconf(_SC_PAGESIZE);
84
85         if (pagesize == -1)
86                 return FALSE;
87
88         if (fd < 0) {
89                 char path[64];
90
91                 g_snprintf(path, sizeof(path), "/proc/%d/statm", getpid());
92
93                 fd = ws_open(path, O_RDONLY);
94
95                 /* XXX, fallback to some other /proc file ? */
96         }
97
98         if (fd < 0)
99                 return FALSE;
100
101         ret = pread(fd, buf, sizeof(buf)-1, 0);
102         if (ret <= 0)
103                 return FALSE;
104
105         buf[ret] = '\0';
106
107         if (sscanf(buf, "%lu %lu", &total, &rss) != 2)
108                 return FALSE;
109
110         if (ptotal)
111                 *ptotal = pagesize * (gsize) total;
112         if (prss)
113                 *prss = pagesize * (gsize) rss;
114
115         return TRUE;
116 }
117
118 static gsize
119 linux_get_total_mem_used_by_app(void)
120 {
121         gsize total;
122
123         if (!linux_get_memory(&total, NULL))
124                 total = 0;
125
126         return total;
127 }
128
129 static gsize
130 linux_get_rss_mem_used_by_app(void)
131 {
132         gsize rss;
133
134         if (!linux_get_memory(NULL, &rss))
135                 rss = 0;
136
137         return rss;
138 }
139
140 static const ws_mem_usage_t total_usage = { "Total", linux_get_total_mem_used_by_app, NULL };
141 static const ws_mem_usage_t rss_usage = { "RSS", linux_get_rss_mem_used_by_app, NULL };
142
143 static const ws_mem_usage_t *memory_components[MAX_COMPONENTS] = {
144         &total_usage,
145         &rss_usage,
146 };
147
148 static guint memory_register_num = 2;
149
150 #else
151
152 /*
153  * macOS: task_info()?
154  *
155  * *BSD: getrusage() -> ru_ixrss ?  Note that there are three
156  * current-RSS components in struct rusage, but those date
157  * back to the days when you had just text, data, and stack,
158  * and kernels might not even bother supplying them.
159  */
160
161 static const ws_mem_usage_t *memory_components[MAX_COMPONENTS];
162
163 static guint memory_register_num = 0;
164
165 #endif
166
167 /* public API */
168
169 void
170 memory_usage_component_register(const ws_mem_usage_t *component)
171 {
172         if (memory_register_num >= MAX_COMPONENTS)
173                 return;
174
175         memory_components[memory_register_num++] = component;
176 }
177
178 const char *
179 memory_usage_get(guint idx, gsize *value)
180 {
181         if (idx >= memory_register_num)
182                 return NULL;
183
184         if (value)
185                 *value = memory_components[idx]->fetch();
186
187         return memory_components[idx]->name;
188 }
189
190 void
191 memory_usage_gc(void)
192 {
193         guint i;
194
195         for (i = 0; i < memory_register_num; i++) {
196                 if (memory_components[i]->gc)
197                         memory_components[i]->gc();
198         }
199 }
200
201
202 /*
203  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
204  *
205  * Local variables:
206  * c-basic-offset: 8
207  * tab-width: 8
208  * indent-tabs-mode: t
209  * End:
210  *
211  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
212  * :indentSize=8:tabSize=8:noTabs=false:
213  */