casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
HostInfoSolaris.h
Go to the documentation of this file.
00001 //# HostInfo_solaris.h: Solaris specific memory, swap, and CPU code.
00002 //# $Id: HostInfoSolaris.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $
00003 
00004  /*
00005  **  This is a greatly MODIFIED version of a "top" machine dependent file.
00006  **  The only resemblance it bears to the original is with respect to the
00007  **  mechanics of finding various system details. The copyright details
00008  **  follow.
00009  **
00010  **  --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
00011  **
00012  **  Top users/processes display for Unix
00013  **  Version 3
00014  **
00015  **  This program may be freely redistributed,
00016  **  but this entire comment MUST remain intact.
00017  **
00018  **  Copyright (c) 1984, 1989, William LeFebvre, Rice University
00019  **  Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
00020  **  Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
00021  **  Copyright (c) 1996, William LeFebvre, Group sys Consulting
00022  **  Copyright (c) 2002, Associated Universities Inc.
00023  */
00024 
00025 #ifndef CASA_HOSTINFOSOLARIS_H
00026 #define CASA_HOSTINFOSOLARIS_H
00027 
00028 # if defined(HOSTINFO_DO_IMPLEMENT)
00029 
00030 /*
00031  *
00032  * LIBS: -lkstat
00033  *
00034  *          AUTHOR:       Darrell Schiebel  <drs@nrao.edu>
00035  *
00036  * ORIGINAL AUTHORS:      Torsten Kasch     <torsten@techfak.uni-bielefeld.de>
00037  *                        Robert Boucher    <boucher@sofkin.ca>
00038  * ORIGINAL CONTRIBUTORS: Marc Cohen        <marc@aai.com>
00039  *                        Charles Hedrick   <hedrick@geneva.rutgers.edu>
00040  *                        William L. Jones  <jones@chpc>
00041  *                        Petri Kutvonen    <kutvonen@cs.helsinki.fi>
00042  *                        Casper Dik        <casper.dik@sun.com>
00043  *                        Tim Pugh          <tpugh@oce.orst.edu>
00044  */
00045 
00046 #include <stdio.h>
00047 #include <unistd.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <kvm.h>
00051 #include <sys/types.h>
00052 #include <sys/sysinfo.h>
00053 #include <sys/swap.h>
00054 
00055 #include <kstat.h>
00056 
00057 namespace casa { //# NAMESPACE CASA - BEGIN
00058 
00059 // <summary>
00060 // HostInfo for Solaris machines.
00061 // </summary>
00062 
00063 // <use visibility=local>
00064 
00065 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00066 // </reviewed>
00067 
00068 // <prerequisite>
00069 //   <li> <linkto class=HostInfo>HostInfo</linkto>
00070 // </prerequisite>
00071 
00072 // <synopsis> 
00073 // This file provides the Solaris specific functions for HostInfo.
00074 // It is selectively included by HostInfo.cc.
00075 // </synopsis>
00076 //
00077 // <group name="HostInfo">
00078 
00079 /*
00080  * Some kstats are fixed at 32 bits, these will be specified as ui32; some
00081  * are "natural" size (32 bit on 32 bit Solaris, 64 on 64 bit Solaris
00082  * we'll make those unsigned long)
00083  * Older Solaris doesn't define KSTAT_DATA_UINT32, those are always 32 bit.
00084  */
00085 # ifndef KSTAT_DATA_UINT32
00086 #  define ui32 ul
00087 # endif
00088 
00089 #ifdef SC_AINFO
00090 #undef USE_ANONINFO                             /* Use swapctl() instead */
00091 #endif
00092 
00093 #define NO_NPROC
00094 
00095 /* pagetok function is really a pointer to an appropriate function */
00096 #define pagetok(size) ((*p_pagetok)(size))
00097 
00098 #ifndef USE_ANONINFO
00099 static void get_swapinfo(int *total, int *fr);
00100 #endif
00101 
00102 class HostMachineInfo {
00103 friend class HostInfo;
00104 
00105     void kupdate( );
00106     HostMachineInfo( );
00107     ~HostMachineInfo( );
00108     void update_info( );
00109 
00110     static int pageshift;
00111     int (*p_pagetok) (int);
00112 
00113     static inline int pagetok_none(int size) { return(size); }
00114     static inline int pagetok_left(int size) { return(size << pageshift); }
00115     static inline int pagetok_right(int size) { return(size >> pageshift); }
00116 
00117     int valid;
00118     kstat_ctl_t *kc;
00119 
00120     int cpus;
00121 
00122     ssize_t memory_total;
00123     ssize_t memory_used;
00124     ssize_t memory_free;
00125 
00126     ssize_t swap_total;
00127     ssize_t swap_used;
00128     ssize_t swap_free;
00129 };
00130 
00131 // </group>
00132 
00133 
00134 int HostMachineInfo::pageshift = 0;
00135 
00136 HostMachineInfo::~HostMachineInfo( ) { if ( kc ) kstat_close(kc); }
00137 
00138 HostMachineInfo::HostMachineInfo( ) : valid(1), kc(NULL)
00139 {
00140     int i;
00141 
00142     /* calculate pageshift value */
00143     i = sysconf(_SC_PAGESIZE);
00144     pageshift = 0;
00145     while ((i >>= 1) > 0) pageshift++;
00146 
00147     /* calculate an amount to shift to K values */
00148     /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
00149     pageshift -= 10;
00150 
00151     /* now determine which pageshift function is appropriate for the 
00152        result (have to because x << y is undefined for y < 0) */
00153     if (pageshift > 0)
00154     {
00155         /* this is the most likely */
00156         p_pagetok = pagetok_left;
00157     }
00158     else if (pageshift == 0)
00159     {
00160         p_pagetok = pagetok_none;
00161     }
00162     else
00163     {
00164         p_pagetok = pagetok_right;
00165         pageshift = -pageshift;
00166     }
00167 
00168     long maxmem = sysconf(_SC_PHYS_PAGES);
00169     memory_total = pagetok (maxmem);
00170 
00171     /* use kstat to update all processor information */
00172     kupdate( );
00173 
00174     kstat_t *ks = kstat_lookup(kc, "unix", 0, "system_misc");
00175     if (kstat_read(kc, ks, 0) == -1) {
00176         perror("kstat_read");
00177         valid = 0;
00178     } 
00179     kstat_named_t *kn = (kstat_named_t*) kstat_data_lookup(ks, "ncpus");
00180     cpus = kn->value.ui32;
00181 }
00182 
00183 void HostMachineInfo::kupdate( )
00184 {
00185     kid_t nkcid;
00186     int i;
00187     static kid_t kcid = 0;
00188 
00189     /*
00190      * 0. kstat_open
00191      */
00192 
00193     if (!kc)
00194     {
00195         kc = kstat_open();
00196         if (!kc)
00197         {
00198             perror("kstat_open ");
00199             valid = 0;
00200         }
00201         kcid = kc->kc_chain_id;
00202     }
00203 
00204     /* keep doing it until no more changes */
00205   kcid_changed:
00206 
00207     /*
00208      * 1.  kstat_chain_update
00209      */
00210     nkcid = kstat_chain_update(kc);
00211     if (nkcid)
00212     {
00213         /* UPDKCID will abort if nkcid is -1, so no need to check */
00214         kcid = nkcid;
00215     }
00216     if (nkcid == -1) {
00217         perror("kstat_read ");
00218         valid = 0;
00219     }
00220     if (nkcid != 0)
00221         goto kcid_changed;
00222 }
00223 
00224 
00225 void HostMachineInfo::update_info( )
00226 {
00227   static long freemem;
00228   static int swaptotal;
00229   static int swapfree;
00230   kstat_t *ks;
00231   kstat_named_t *kn;
00232 
00233   ks = kstat_lookup(kc, "unix", 0, "system_pages");
00234   if (kstat_read(kc, ks, 0) == -1) {
00235       perror("kstat_read");
00236       valid = 0;
00237   }
00238   kn = (kstat_named_t*) kstat_data_lookup(ks, "freemem");
00239   if (kn)
00240       freemem = kn->value.ul;
00241 
00242   memory_free = pagetok (freemem);
00243   memory_used = memory_total - memory_free;
00244 
00245   get_swapinfo(&swaptotal, &swapfree);
00246   swap_total = pagetok(swaptotal);
00247   swap_used = pagetok(swaptotal - swapfree);
00248   swap_free = pagetok(swapfree);
00249 }
00250 
00251 #ifndef USE_ANONINFO
00252 void get_swapinfo(int *total, int *fr)
00253 
00254 {
00255 #ifdef SC_AINFO
00256     struct anoninfo anon;
00257 
00258     if (swapctl(SC_AINFO, &anon) == -1) {
00259         *total = *fr = 0;
00260         return;
00261     }
00262     *total = anon.ani_max;
00263     *fr = anon.ani_max - anon.ani_resv;
00264 #else
00265     int cnt, i;
00266     int t, f;
00267     struct swaptable *swt;
00268     struct swapent *ste;
00269     static char path[256];
00270 
00271     /* get total number of swap entries */
00272     cnt = swapctl(SC_GETNSWP, 0);
00273 
00274     /* allocate enough space to hold count + n swapents */
00275     swt = (struct swaptable *)malloc(sizeof(int) +
00276                                      cnt * sizeof(struct swapent));
00277     if (swt == NULL)
00278     {
00279         *total = 0;
00280         *fr = 0;
00281         return;
00282     }
00283     swt->swt_n = cnt;
00284 
00285     /* fill in ste_path pointers: we don't care about the paths, so we point
00286        them all to the same buffer */
00287     ste = &(swt->swt_ent[0]);
00288     i = cnt;
00289     while (--i >= 0)
00290     {
00291         ste++->ste_path = path;
00292     }
00293 
00294     /* grab all swap info */
00295     swapctl(SC_LIST, swt);
00296 
00297     /* walk thru the structs and sum up the fields */
00298     t = f = 0;
00299     ste = &(swt->swt_ent[0]);
00300     i = cnt;
00301     while (--i >= 0)
00302     {
00303         /* dont count slots being deleted */
00304         if (!(ste->ste_flags & ST_INDEL) &&
00305             !(ste->ste_flags & ST_DOINGDEL))
00306         {
00307             t += ste->ste_pages;
00308             f += ste->ste_free;
00309         }
00310         ste++;
00311     }
00312 
00313     /* fill in the results */
00314     *total = t;
00315     *fr = f;
00316     free(swt);
00317 #endif /* SC_AINFO */
00318 }
00319 #endif /* USE_ANONINFO */
00320 
00321 
00322 } //# NAMESPACE CASA - END
00323 
00324 # endif
00325 #endif