1 /*
2  * Copyright (c) 2001-2008 Willem Dijkstra
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *    - Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    - Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30 
31 /*
32  * Get current memory statistics in bytes; reports them back in symon_buf as
33  *
34  * real active : real total : free : [swap used : swap total]
35  */
36 
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
39 #include <sys/swap.h>
40 
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <limits.h>
46 
47 #include "error.h"
48 #include "symon.h"
49 #include "xmalloc.h"
50 
51 #define pagetob(size) (((u_int64_t)size) << me_pageshift)
52 
53 /* Globals for this module all start with me_ */
54 static u_int64_t me_pageshift;
55 static u_int64_t me_stats[5];
56 static int me_vm_mib[] = {CTL_VM, VM_METER};
57 static struct vmtotal me_vmtotal;
58 static size_t me_vmsize;
59 static u_int64_t me_pagesize;
60 static u_int64_t me_nswap;
61 struct swapent *me_swdev = NULL;
62 
63 void
init_mem(struct stream * st)64 init_mem(struct stream *st)
65 {
66     me_pagesize = sysconf(_SC_PAGESIZE);
67     me_pageshift = 0;
68     while (me_pagesize > 1) {
69         me_pageshift++;
70         me_pagesize >>= 1;
71     }
72 
73     /* get total -- systemwide main memory usage structure */
74     me_vmsize = sizeof(me_vmtotal);
75 
76     /* determine number of swap entries */
77     me_nswap = swapctl(SWAP_NSWAP, 0, 0);
78 
79     if (me_swdev) {
80         xfree(me_swdev);
81     }
82 
83     if (me_nswap != 0) {
84         me_swdev = xmalloc(me_nswap * sizeof(*me_swdev));
85     } else {
86         me_swdev = NULL;
87     }
88 
89     if (me_swdev == NULL && me_nswap != 0) {
90         me_nswap = 0;
91     }
92 
93     if (st != NULL) {
94         info("started module mem(%.200s)", st->arg);
95     }
96 }
97 
98 void
gets_mem()99 gets_mem()
100 {
101     int i, rnswap;
102 
103     if (sysctl(me_vm_mib, 2, &me_vmtotal, &me_vmsize, NULL, 0) < 0) {
104         warning("%s:%d: sysctl failed", __FILE__, __LINE__);
105         bzero(&me_vmtotal, sizeof(me_vmtotal));
106     }
107 
108     /* convert memory stats to Kbytes */
109     me_stats[0] = pagetob(me_vmtotal.t_arm);
110     me_stats[1] = pagetob(me_vmtotal.t_rm);
111     me_stats[2] = pagetob(me_vmtotal.t_free);
112 
113     rnswap = swapctl(SWAP_STATS, me_swdev, me_nswap);
114     if (rnswap == -1) {
115         /* A swap device may have been added; increase and retry */
116         init_mem(NULL);
117         rnswap = swapctl(SWAP_STATS, me_swdev, me_nswap);
118     }
119 
120     me_stats[3] = me_stats[4] = 0;
121     if (rnswap == me_nswap) {   /* Read swap successfully */
122         /* Total things up */
123         for (i = 0; i < me_nswap; i++) {
124             if (me_swdev[i].se_flags & SWF_ENABLE) {
125                 me_stats[3] += ((u_int64_t)me_swdev[i].se_inuse * DEV_BSIZE);
126                 me_stats[4] += ((u_int64_t)me_swdev[i].se_nblks * DEV_BSIZE);
127             }
128         }
129     }
130 }
131 
132 int
get_mem(char * symon_buf,int maxlen,struct stream * st)133 get_mem(char *symon_buf, int maxlen, struct stream *st)
134 {
135     return snpack(symon_buf, maxlen, st->arg, MT_MEM2,
136                   me_stats[0], me_stats[1], me_stats[2],
137                   me_stats[3], me_stats[4]);
138 }
139