2
* Copyright (C) Tildeslash Ltd. All rights reserved.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU Affero General Public License version 3.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU General Public License for more details.
12
* You should have received a copy of the GNU Affero General Public License
13
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15
* In addition, as a special exception, the copyright holders give
16
* permission to link the code of portions of this program with the
17
* OpenSSL library under certain conditions as described in each
18
* individual source file, and distribute linked combinations
21
* You must obey the GNU Affero General Public License in all respects
22
* for all of the code used other than OpenSSL.
48
#ifdef HAVE_SYS_PARAM_H
49
#include <sys/param.h>
52
#ifdef HAVE_SYS_PROC_H
56
#ifdef HAVE_SYS_USER_H
60
#ifdef HAVE_SYS_VMMETER_H
61
#include <sys/vmmeter.h>
64
#ifdef HAVE_SYS_SYSCTL_H
65
#include <sys/sysctl.h>
68
#ifdef HAVE_SYS_DKSTAT_H
69
#include <sys/dkstat.h>
74
#include "process_sysdep.h"
78
* System dependent resource gathering code for FreeBSD.
84
/* ----------------------------------------------------------------- Private */
88
static int pagesize_kbyte;
89
static long total_old = 0;
90
static long cpu_user_old = 0;
91
static long cpu_syst_old = 0;
94
/* ------------------------------------------------------------------ Public */
97
int init_process_info_sysdep(void) {
100
struct clockinfo clock;
103
mib[1] = KERN_CLOCKRATE;
105
if (sysctl(mib, 2, &clock, &len, NULL, 0) == -1) {
106
DEBUG("system statistic error -- cannot get clock rate: %s\n", STRERROR);
113
len = sizeof(systeminfo.cpus);
114
if (sysctl(mib, 2, &systeminfo.cpus, &len, NULL, 0) == -1) {
115
DEBUG("system statistic error -- cannot get cpu count: %s\n", STRERROR);
120
len = sizeof(systeminfo.mem_kbyte_max);
121
if (sysctl(mib, 2, &systeminfo.mem_kbyte_max, &len, NULL, 0) == -1) {
122
DEBUG("system statistic error -- cannot get real memory amount: %s\n", STRERROR);
125
systeminfo.mem_kbyte_max /= 1024;
127
mib[1] = HW_PAGESIZE;
128
len = sizeof(pagesize_kbyte);
129
if (sysctl(mib, 2, &pagesize_kbyte, &len, NULL, 0) == -1) {
130
DEBUG("system statistic error -- cannot get memory page size: %s\n", STRERROR);
133
pagesize_kbyte /= 1024;
140
* Read all processes to initialize the information tree.
141
* @param reference reference of ProcessTree
142
* @return treesize>0 if succeeded otherwise =0.
144
int initprocesstree_sysdep(ProcessTree_T **reference) {
146
static kvm_t *kvm_handle;
148
struct kinfo_proc *pinfo;
150
if (!(kvm_handle = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, prog))) {
151
LogError("system statistic error -- cannot initialize kvm interface\n");
155
pinfo = kvm_getprocs(kvm_handle, KERN_PROC_PROC, 0, &treesize);
156
if (!pinfo || (treesize < 1)) {
157
LogError("system statistic error -- cannot get process tree\n");
158
kvm_close(kvm_handle);
162
pt = CALLOC(sizeof(ProcessTree_T), treesize);
164
for (int i = 0; i < treesize; i++) {
165
StringBuffer_T cmdline = StringBuffer_create(64);
166
pt[i].pid = pinfo[i].ki_pid;
167
pt[i].ppid = pinfo[i].ki_ppid;
168
pt[i].uid = pinfo[i].ki_ruid;
169
pt[i].euid = pinfo[i].ki_uid;
170
pt[i].gid = pinfo[i].ki_rgid;
171
pt[i].starttime = pinfo[i].ki_start.tv_sec;
172
pt[i].cputime = (long)(pinfo[i].ki_runtime / 100000);
173
pt[i].mem_kbyte = (unsigned long)(pinfo[i].ki_rssize * pagesize_kbyte);
174
int flags = pinfo[i].ki_stat;
175
char * procname = pinfo[i].ki_comm;
177
pt[i].status_flag |= PROCESS_ZOMBIE;
178
pt[i].cpu_percent = 0;
179
pt[i].time = get_float_time();
181
if ((args = kvm_getargv(kvm_handle, &pinfo[i], 0))) {
182
for (int j = 0; args[j]; j++)
183
StringBuffer_append(cmdline, args[j + 1] ? "%s " : "%s", args[j]);
184
pt[i].cmdline = Str_dup(StringBuffer_toString(StringBuffer_trim(cmdline)));
186
StringBuffer_free(&cmdline);
187
if (! pt[i].cmdline || ! *pt[i].cmdline) {
189
pt[i].cmdline = Str_dup(procname);
194
kvm_close(kvm_handle);
201
* This routine returns 'nelem' double precision floats containing
202
* the load averages in 'loadv'; at most 3 values will be returned.
203
* @param loadv destination of the load averages
204
* @param nelem number of averages
205
* @return: 0 if successful, -1 if failed (and all load averages are 0).
207
int getloadavg_sysdep(double *loadv, int nelem) {
208
return getloadavg(loadv, nelem);
213
* This routine returns kbyte of real memory in use.
214
* @return: TRUE if successful, FALSE if failed (or not available)
216
int used_system_memory_sysdep(SystemInfo_T *si) {
220
int pagesize = getpagesize();
224
unsigned long long total = 0ULL;
225
unsigned long long used = 0ULL;
228
len = sizeof(v_active_count);
229
if (sysctlbyname("vm.stats.vm.v_active_count", &v_active_count, &len, NULL, 0) == -1) {
230
LogError("system statistic error -- cannot get for real memory usage: %s\n", STRERROR);
233
if (len != sizeof(v_active_count)) {
234
LogError("system statistic error -- real memory usage statics error\n");
237
si->total_mem_kbyte = v_active_count * pagesize_kbyte;
240
memset(mib, 0, sizeof(mib));
241
miblen = sizeof(mib) / sizeof(mib[0]);
242
if (sysctlnametomib("vm.swap_info", mib, &miblen) == -1) {
243
LogError("system statistic error -- cannot get swap usage: %s\n", STRERROR);
244
si->swap_kbyte_max = 0;
249
len = sizeof(struct xswdev);
250
if (sysctl(mib, miblen + 1, &xsw, &len, NULL, 0) == -1)
252
if (xsw.xsw_version != XSWDEV_VERSION) {
253
LogError("system statistic error -- cannot get swap usage: xswdev version mismatch\n");
254
si->swap_kbyte_max = 0;
257
total += xsw.xsw_nblks;
258
used += xsw.xsw_used;
261
si->swap_kbyte_max = (unsigned long)(double)total * (double)pagesize / 1024.;
262
si->total_swap_kbyte = (unsigned long)(double)used * (double)pagesize / 1024.;
268
* This routine returns system/user CPU time in use.
269
* @return: TRUE if successful, FALSE if failed
271
int used_system_cpu_sysdep(SystemInfo_T *si) {
274
long cp_time[CPUSTATES];
280
if (sysctlnametomib("kern.cp_time", mib, &len) == -1) {
281
LogError("system statistic error -- cannot get cpu time handler: %s\n", STRERROR);
285
len = sizeof(cp_time);
286
if (sysctl(mib, 2, &cp_time, &len, NULL, 0) == -1) {
287
LogError("system statistic error -- cannot get cpu time: %s\n", STRERROR);
291
for (i = 0; i < CPUSTATES; i++)
292
total_new += cp_time[i];
294
total = total_new - total_old;
295
total_old = total_new;
297
si->total_cpu_user_percent = (total > 0) ? (int)(1000 * (double)(cp_time[CP_USER] - cpu_user_old) / total) : -10;
298
si->total_cpu_syst_percent = (total > 0) ? (int)(1000 * (double)(cp_time[CP_SYS] - cpu_syst_old) / total) : -10;
299
si->total_cpu_wait_percent = 0; /* there is no wait statistic available */
301
cpu_user_old = cp_time[CP_USER];
302
cpu_syst_old = cp_time[CP_SYS];