casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HostInfoSolaris.h
Go to the documentation of this file.
1 //# HostInfo_solaris.h: Solaris specific memory, swap, and CPU code.
2 //# $Id$
3 
4  /*
5  ** This is a greatly MODIFIED version of a "top" machine dependent file.
6  ** The only resemblance it bears to the original is with respect to the
7  ** mechanics of finding various system details. The copyright details
8  ** follow.
9  **
10  ** --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
11  **
12  ** Top users/processes display for Unix
13  ** Version 3
14  **
15  ** This program may be freely redistributed,
16  ** but this entire comment MUST remain intact.
17  **
18  ** Copyright (c) 1984, 1989, William LeFebvre, Rice University
19  ** Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
20  ** Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
21  ** Copyright (c) 1996, William LeFebvre, Group sys Consulting
22  ** Copyright (c) 2002, Associated Universities Inc.
23  */
24 
25 #ifndef CASA_HOSTINFOSOLARIS_H
26 #define CASA_HOSTINFOSOLARIS_H
27 
28 # if defined(HOSTINFO_DO_IMPLEMENT)
29 
30 /*
31  *
32  * LIBS: -lkstat
33  *
34  * AUTHOR: Darrell Schiebel <drs@nrao.edu>
35  *
36  * ORIGINAL AUTHORS: Torsten Kasch <torsten@techfak.uni-bielefeld.de>
37  * Robert Boucher <boucher@sofkin.ca>
38  * ORIGINAL CONTRIBUTORS: Marc Cohen <marc@aai.com>
39  * Charles Hedrick <hedrick@geneva.rutgers.edu>
40  * William L. Jones <jones@chpc>
41  * Petri Kutvonen <kutvonen@cs.helsinki.fi>
42  * Casper Dik <casper.dik@sun.com>
43  * Tim Pugh <tpugh@oce.orst.edu>
44  */
45 
46 #include <stdio.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <kvm.h>
51 #include <sys/types.h>
52 #include <sys/sysinfo.h>
53 #include <sys/swap.h>
54 
55 #include <kstat.h>
56 
57 namespace casacore { //# NAMESPACE CASACORE - BEGIN
58 
59 // <summary>
60 // HostInfo for Solaris machines.
61 // </summary>
62 
63 // <use visibility=local>
64 
65 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
66 // </reviewed>
67 
68 // <prerequisite>
69 // <li> <linkto class=HostInfo>HostInfo</linkto>
70 // </prerequisite>
71 
72 // <synopsis>
73 // This file provides the Solaris specific functions for HostInfo.
74 // It is selectively included by HostInfo.cc.
75 // </synopsis>
76 //
77 // <group name="HostInfo">
78 
79 /*
80  * Some kstats are fixed at 32 bits, these will be specified as ui32; some
81  * are "natural" size (32 bit on 32 bit Solaris, 64 on 64 bit Solaris
82  * we'll make those unsigned long)
83  * Older Solaris doesn't define KSTAT_DATA_UINT32, those are always 32 bit.
84  */
85 # ifndef KSTAT_DATA_UINT32
86 # define ui32 ul
87 # endif
88 
89 #ifdef SC_AINFO
90 #undef USE_ANONINFO /* Use swapctl() instead */
91 #endif
92 
93 #define NO_NPROC
94 
95 /* pagetok function is really a pointer to an appropriate function */
96 #define pagetok(size) ((*p_pagetok)(size))
97 
98 #ifndef USE_ANONINFO
99 static void get_swapinfo(int *total, int *fr);
100 #endif
101 
102 class HostMachineInfo {
103 friend class HostInfo;
104 
105  void kupdate( );
106  HostMachineInfo( );
107  ~HostMachineInfo( );
108  void update_info( );
109 
110  static int pageshift;
111  int (*p_pagetok) (int);
112 
113  static inline int pagetok_none(int size) { return(size); }
114  static inline int pagetok_left(int size) { return(size << pageshift); }
115  static inline int pagetok_right(int size) { return(size >> pageshift); }
116 
117  int valid;
118  kstat_ctl_t *kc;
119 
120  int cpus;
121 
122  ptrdiff_t memory_total;
123  ptrdiff_t memory_used;
124  ptrdiff_t memory_free;
125 
126  ptrdiff_t swap_total;
127  ptrdiff_t swap_used;
128  ptrdiff_t swap_free;
129 };
130 
131 // </group>
132 
133 
134 int HostMachineInfo::pageshift = 0;
135 
136 HostMachineInfo::~HostMachineInfo( ) { if ( kc ) kstat_close(kc); }
137 
138 HostMachineInfo::HostMachineInfo( ) : valid(1), kc(NULL)
139 {
140  int i;
141 
142  /* calculate pageshift value */
143  i = sysconf(_SC_PAGESIZE);
144  pageshift = 0;
145  while ((i >>= 1) > 0) pageshift++;
146 
147  /* calculate an amount to shift to K values */
148  /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
149  pageshift -= 10;
150 
151  /* now determine which pageshift function is appropriate for the
152  result (have to because x << y is undefined for y < 0) */
153  if (pageshift > 0)
154  {
155  /* this is the most likely */
156  p_pagetok = pagetok_left;
157  }
158  else if (pageshift == 0)
159  {
160  p_pagetok = pagetok_none;
161  }
162  else
163  {
164  p_pagetok = pagetok_right;
165  pageshift = -pageshift;
166  }
167 
168  long maxmem = sysconf(_SC_PHYS_PAGES);
169  memory_total = pagetok (maxmem);
170 
171  /* use kstat to update all processor information */
172  kupdate( );
173 
174  kstat_t *ks = kstat_lookup(kc, "unix", 0, "system_misc");
175  if (kstat_read(kc, ks, 0) == -1) {
176  perror("kstat_read");
177  valid = 0;
178  }
179  kstat_named_t *kn = (kstat_named_t*) kstat_data_lookup(ks, "ncpus");
180  cpus = kn->value.ui32;
181 }
182 
183 void HostMachineInfo::kupdate( )
184 {
185  kid_t nkcid;
186  int i;
187  static kid_t kcid = 0;
188 
189  /*
190  * 0. kstat_open
191  */
192 
193  if (!kc)
194  {
195  kc = kstat_open();
196  if (!kc)
197  {
198  perror("kstat_open ");
199  valid = 0;
200  }
201  kcid = kc->kc_chain_id;
202  }
203 
204  /* keep doing it until no more changes */
205  kcid_changed:
206 
207  /*
208  * 1. kstat_chain_update
209  */
210  nkcid = kstat_chain_update(kc);
211  if (nkcid)
212  {
213  /* UPDKCID will abort if nkcid is -1, so no need to check */
214  kcid = nkcid;
215  }
216  if (nkcid == -1) {
217  perror("kstat_read ");
218  valid = 0;
219  }
220  if (nkcid != 0)
221  goto kcid_changed;
222 }
223 
224 
225 void HostMachineInfo::update_info( )
226 {
227  static long freemem;
228  static int swaptotal;
229  static int swapfree;
230  kstat_t *ks;
231  kstat_named_t *kn;
232 
233  ks = kstat_lookup(kc, "unix", 0, "system_pages");
234  if (kstat_read(kc, ks, 0) == -1) {
235  perror("kstat_read");
236  valid = 0;
237  }
238  kn = (kstat_named_t*) kstat_data_lookup(ks, "freemem");
239  if (kn)
240  freemem = kn->value.ul;
241 
242  memory_free = pagetok (freemem);
243  memory_used = memory_total - memory_free;
244 
245  get_swapinfo(&swaptotal, &swapfree);
246  swap_total = pagetok(swaptotal);
247  swap_used = pagetok(swaptotal - swapfree);
248  swap_free = pagetok(swapfree);
249 }
250 
251 #ifndef USE_ANONINFO
252 void get_swapinfo(int *total, int *fr)
253 
254 {
255 #ifdef SC_AINFO
256  struct anoninfo anon;
257 
258  if (swapctl(SC_AINFO, &anon) == -1) {
259  *total = *fr = 0;
260  return;
261  }
262  *total = anon.ani_max;
263  *fr = anon.ani_max - anon.ani_resv;
264 #else
265  int cnt, i;
266  int t, f;
267  struct swaptable *swt;
268  struct swapent *ste;
269  static char path[256];
270 
271  /* get total number of swap entries */
272  cnt = swapctl(SC_GETNSWP, 0);
273 
274  /* allocate enough space to hold count + n swapents */
275  swt = (struct swaptable *)malloc(sizeof(int) +
276  cnt * sizeof(struct swapent));
277  if (swt == NULL)
278  {
279  *total = 0;
280  *fr = 0;
281  return;
282  }
283  swt->swt_n = cnt;
284 
285  /* fill in ste_path pointers: we don't care about the paths, so we point
286  them all to the same buffer */
287  ste = &(swt->swt_ent[0]);
288  i = cnt;
289  while (--i >= 0)
290  {
291  ste++->ste_path = path;
292  }
293 
294  /* grab all swap info */
295  swapctl(SC_LIST, swt);
296 
297  /* walk thru the structs and sum up the fields */
298  t = f = 0;
299  ste = &(swt->swt_ent[0]);
300  i = cnt;
301  while (--i >= 0)
302  {
303  /* dont count slots being deleted */
304  if (!(ste->ste_flags & ST_INDEL) &&
305  !(ste->ste_flags & ST_DOINGDEL))
306  {
307  t += ste->ste_pages;
308  f += ste->ste_free;
309  }
310  ste++;
311  }
312 
313  /* fill in the results */
314  *total = t;
315  *fr = f;
316  free(swt);
317 #endif /* SC_AINFO */
318 }
319 #endif /* USE_ANONINFO */
320 
321 
322 } //# NAMESPACE CASACORE - END
323 
324 # endif
325 #endif
free(pool)