ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/memory_stats.c
Revision: 1.27
Committed: Wed Apr 7 21:08:40 2004 UTC (20 years, 1 month ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_10
Changes since 1.26: +20 -8 lines
Log Message:
The rest of the error handling stuff (except the vector code).

I've been extremely unimaginative with the string names in error.c, but
they're all in one place so much easier to tidy up. I'm also beginning to
wonder if we actually needed an SG_ERROR_SYSTEM_CALL to indicate some call
into the system failed - because the majority of our errors are those :-)

Still to do, then:
 - vector code
 - better string names in error.c
 - deal with arg string in some way
 - make use of the error status in statgrab/saidar/examples

File Contents

# User Rev Content
1 tdb 1.18 /*
2 tdb 1.25 * i-scream libstatgrab
3 tdb 1.7 * http://www.i-scream.org
4 tdb 1.18 * Copyright (C) 2000-2004 i-scream
5 pajs 1.1 *
6 tdb 1.18 * This library is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public
8     * License as published by the Free Software Foundation; either
9     * version 2.1 of the License, or (at your option) any later version.
10 pajs 1.1 *
11 tdb 1.18 * This library is distributed in the hope that it will be useful,
12 pajs 1.1 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 tdb 1.18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * Lesser General Public License for more details.
15 pajs 1.1 *
16 tdb 1.18 * You should have received a copy of the GNU Lesser General Public
17     * License along with this library; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19     * 02111-1307 USA
20 tdb 1.19 *
21 tdb 1.27 * $Id: memory_stats.c,v 1.26 2004/04/07 14:53:40 tdb Exp $
22 pajs 1.1 */
23    
24     #ifdef HAVE_CONFIG_H
25     #include "config.h"
26     #endif
27    
28     #include "statgrab.h"
29 ats 1.12 #include "tools.h"
30 pajs 1.1 #ifdef SOLARIS
31     #include <unistd.h>
32     #include <kstat.h>
33     #endif
34 ats 1.17 #if defined(LINUX) || defined(CYGWIN)
35 pajs 1.5 #include <stdio.h>
36     #include <string.h>
37     #endif
38 tdb 1.23 #if defined(FREEBSD) || defined(DFBSD)
39 pajs 1.6 #include <sys/types.h>
40     #include <sys/sysctl.h>
41     #include <unistd.h>
42     #endif
43 tdb 1.21 #if defined(NETBSD) || defined(OPENBSD)
44 tdb 1.20 #include <sys/param.h>
45 ats 1.22 #include <sys/time.h>
46 tdb 1.20 #include <uvm/uvm.h>
47     #endif
48 pajs 1.1
49 ats 1.24 sg_mem_stats *sg_get_mem_stats(){
50 pajs 1.1
51 ats 1.24 static sg_mem_stats mem_stat;
52 pajs 1.1
53     #ifdef SOLARIS
54     kstat_ctl_t *kc;
55     kstat_t *ksp;
56     kstat_named_t *kn;
57     long totalmem;
58     int pagesize;
59     #endif
60 ats 1.17 #if defined(LINUX) || defined(CYGWIN)
61 pajs 1.5 char *line_ptr;
62 ats 1.15 unsigned long long value;
63 pajs 1.5 FILE *f;
64     #endif
65 tdb 1.23 #if defined(FREEBSD) || defined(DFBSD)
66 ats 1.12 int mib[2];
67 ats 1.14 u_long physmem;
68     size_t size;
69 tdb 1.8 u_int free_count;
70     u_int cache_count;
71     u_int inactive_count;
72 ats 1.12 int pagesize;
73     #endif
74 tdb 1.20 #if defined(NETBSD) || defined(OPENBSD)
75 ats 1.12 struct uvmexp *uvm;
76     #endif
77 pajs 1.1
78     #ifdef SOLARIS
79     if((pagesize=sysconf(_SC_PAGESIZE)) == -1){
80 tdb 1.27 sg_set_error(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
81 pajs 1.1 return NULL;
82     }
83    
84     if((totalmem=sysconf(_SC_PHYS_PAGES)) == -1){
85 tdb 1.27 sg_set_error(SG_ERROR_SYSCONF, "_SC_PHYS_PAGES");
86 pajs 1.1 return NULL;
87     }
88    
89     if ((kc = kstat_open()) == NULL) {
90 tdb 1.27 sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
91 pajs 1.1 return NULL;
92     }
93     if((ksp=kstat_lookup(kc, "unix", 0, "system_pages")) == NULL){
94 tdb 1.27 sg_set_error(SG_ERROR_KSTAT_LOOKUP, "unix,0,system_pages");
95 pajs 1.1 return NULL;
96     }
97     if (kstat_read(kc, ksp, 0) == -1) {
98 tdb 1.27 sg_set_error(SG_ERROR_KSTAT_READ, NULL);
99 pajs 1.1 return NULL;
100     }
101     if((kn=kstat_data_lookup(ksp, "freemem")) == NULL){
102 tdb 1.27 sg_set_error(SG_ERROR_KSTAT_DATA_LOOKUP, "freemem");
103 pajs 1.1 return NULL;
104     }
105 tdb 1.26 kstat_close(kc);
106 pajs 1.2
107 pajs 1.1 mem_stat.total = (long long)totalmem * (long long)pagesize;
108     mem_stat.free = ((long long)kn->value.ul) * (long long)pagesize;
109     mem_stat.used = mem_stat.total - mem_stat.free;
110 pajs 1.5 #endif
111    
112 ats 1.17 #if defined(LINUX) || defined(CYGWIN)
113 ats 1.16 if ((f = fopen("/proc/meminfo", "r")) == NULL) {
114 tdb 1.27 sg_set_error(SG_ERROR_OPEN, "/proc/meminfo");
115 pajs 1.5 return NULL;
116     }
117    
118 ats 1.24 while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
119 ats 1.16 if (sscanf(line_ptr, "%*s %llu kB", &value) != 1) {
120 ats 1.15 continue;
121     }
122     value *= 1024;
123    
124     if (strncmp(line_ptr, "MemTotal:", 9) == 0) {
125     mem_stat.total = value;
126     } else if (strncmp(line_ptr, "MemFree:", 8) == 0) {
127     mem_stat.free = value;
128     } else if (strncmp(line_ptr, "Cached:", 7) == 0) {
129     mem_stat.cache = value;
130     }
131 pajs 1.5 }
132    
133     fclose(f);
134 ats 1.15 mem_stat.used = mem_stat.total - mem_stat.free;
135 pajs 1.6 #endif
136    
137 tdb 1.23 #if defined(FREEBSD) || defined(DFBSD)
138 tdb 1.8 /* Returns bytes */
139 ats 1.12 mib[0] = CTL_HW;
140     mib[1] = HW_PHYSMEM;
141 ats 1.11 size = sizeof physmem;
142 ats 1.12 if (sysctl(mib, 2, &physmem, &size, NULL, 0) < 0) {
143 tdb 1.27 sg_set_error(SG_ERROR_SYSCTL, "CTL_HW.HW_PHYSMEM");
144 pajs 1.6 return NULL;
145 ats 1.12 }
146     mem_stat.total = physmem;
147 pajs 1.6
148     /*returns pages*/
149 ats 1.11 size = sizeof free_count;
150 tdb 1.27 if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0){
151     sg_set_error(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_free_count");
152 pajs 1.6 return NULL;
153 tdb 1.27 }
154 pajs 1.6
155 ats 1.11 size = sizeof inactive_count;
156 tdb 1.27 if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0){
157     sg_set_error(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_inactive_count");
158 pajs 1.6 return NULL;
159 tdb 1.27 }
160 pajs 1.6
161 ats 1.11 size = sizeof cache_count;
162 tdb 1.27 if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0){
163     sg_set_error(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_cache_count");
164 pajs 1.6 return NULL;
165 tdb 1.27 }
166 pajs 1.6
167 tdb 1.8 /* Because all the vm.stats returns pages, I need to get the page size.
168 tdb 1.27 * After that I then need to multiple the anything that used vm.stats to
169 tdb 1.8 * get the system statistics by pagesize
170 pajs 1.6 */
171     if ((pagesize=getpagesize()) == -1){
172 tdb 1.27 sg_set_error(SG_ERROR_GETPAGESIZE, "NULL");
173 pajs 1.6 return NULL;
174     }
175    
176 tdb 1.8 mem_stat.cache=cache_count*pagesize;
177    
178     /* Of couse nothing is ever that simple :) And I have inactive pages to
179     * deal with too. So I'm going to add them to free memory :)
180 pajs 1.6 */
181 tdb 1.8 mem_stat.free=(free_count*pagesize)+(inactive_count*pagesize);
182     mem_stat.used=physmem-mem_stat.free;
183 ats 1.12 #endif
184 ats 1.14
185 tdb 1.21 #if defined(NETBSD) || defined(OPENBSD)
186 ats 1.24 if ((uvm = sg_get_uvmexp()) == NULL) {
187 ats 1.12 return NULL;
188     }
189 tdb 1.20
190 ats 1.14 mem_stat.total = uvm->pagesize * uvm->npages;
191 tdb 1.20 #ifdef NETBSD
192 ats 1.12 mem_stat.cache = uvm->pagesize * (uvm->filepages + uvm->execpages);
193 tdb 1.20 #else
194 tdb 1.21 /* Can't find cache memory on OpenBSD */
195 tdb 1.20 mem_stat.cache = 0;
196     #endif
197 ats 1.14 mem_stat.free = uvm->pagesize * (uvm->free + uvm->inactive);
198     mem_stat.used = mem_stat.total - mem_stat.free;
199 pajs 1.1 #endif
200    
201     return &mem_stat;
202     }