1 /*
2 * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 /*
26 get memory usage
27 special versions for FreeBSD,MacOS X and Linux (without checking in autotools)
28 general 'getrusage' version for others
29 */
30
31 #if __FreeBSD__
32 # include <sys/file.h>
33 # include <sys/sysctl.h>
34 # include <sys/user.h>
35 # include <kvm.h>
36 # include <sys/types.h>
37 # include <unistd.h>
38 #elif __APPLE__
39 # include <mach/mach_init.h>
40 # include <mach/task.h>
41 #elif __linux__
42 # include <fcntl.h>
43 # include <sys/types.h>
44 # include <unistd.h>
45 # include <stdlib.h>
46 #elif defined(HAVE_GETRUSAGE) && defined(HAVE_STRUCT_RUSAGE_RU_MAXRSS)
47 # include <sys/types.h>
48 # ifdef HAVE_SYS_RESOURCE_H
49 # include <sys/resource.h>
50 # endif
51 # ifdef HAVE_SYS_RUSAGE_H
52 # include <sys/rusage.h>
53 # endif
54 # ifndef RUSAGE_SELF
55 # define RUSAGE_SELF 0
56 # endif
57 # define MEMORY_USAGE 1
58 #endif
59 #include <inttypes.h>
60
mem_used(uint64_t * rss,uint64_t * virt)61 uint8_t mem_used(uint64_t *rss,uint64_t *virt) {
62 #if defined(__FreeBSD__)
63 static kvm_t* kd = NULL;
64
65 if ( kd == NULL) {
66 kd = kvm_open( NULL, "/dev/null", NULL, O_RDONLY, "kvm_open" ); // open once
67 }
68 if ( kd != NULL ) {
69 // Use FreeBSD kvm function to get the size of resident pages (RSS).
70 int pc = 0;
71 struct kinfo_proc* kp;
72 kp = kvm_getprocs(kd,KERN_PROC_PID,getpid(),&pc); // do not free returned struct
73 if ( (kp != NULL) && (pc >= 1) ) { // in case multiple threads have the same PID
74 *rss = kp->ki_rssize * getpagesize();
75 *virt = kp->ki_size;
76 return 1; // success
77 }
78 }
79 *rss = 0;
80 *virt = 0;
81 return 0; // failed
82 #elif __APPLE__
83 struct task_basic_info machInfo;
84 mach_port_t machTask = mach_task_self();
85 mach_msg_type_number_t machCount = TASK_BASIC_INFO_COUNT;
86 if ( task_info( machTask, TASK_BASIC_INFO, (task_info_t)&machInfo, &machCount ) == KERN_SUCCESS ) {
87 *rss = machInfo.resident_size;
88 *virt = machInfo.virtual_size;
89 return 1;
90 }
91 *rss = 0;
92 *virt = 0;
93 return 0; // error
94 #elif __linux__
95 int fd = open("/proc/self/statm",O_RDONLY);
96 char statbuff[1000],*p;
97 int l,e;
98 e = 0;
99 *rss = 0;
100 *virt = 0;
101 if (fd>=0) {
102 l = read(fd,statbuff,1000);
103 if (l<1000 && l>0) {
104 statbuff[l]=0;
105 *virt = strtoul(statbuff,&p,10) * getpagesize();
106 if (*p==' ') {
107 *rss = strtoul(p+1,&p,10) * getpagesize();
108 if (*p==' ' || *p=='\0') {
109 e = 1;
110 }
111 }
112 }
113 close(fd);
114 }
115 return e;
116 #elif MEMORY_USAGE
117 struct rusage ru;
118 getrusage(RUSAGE_SELF,&ru);
119 *rss = *virt = ru.ru_maxrss * UINT64_C(1024);
120 return 2;
121 #else
122 return 0;
123 #endif
124 }
125