sysdep_FREEBSD.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2003 by Contributors to the monit codebase. 
00003  * All Rights Reserved.
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018  */
00019 
00020 
00021 #include <config.h>
00022 
00023 #ifdef HAVE_SYS_TYPES_H
00024 #include <sys/types.h>
00025 #endif
00026 
00027 #include <unistd.h>
00028 
00029 #ifdef HAVE_SYS_STAT_H
00030 #include <sys/stat.h>
00031 #endif
00032 
00033 #ifdef HAVE_FCNTL_H
00034 #include <fcntl.h>
00035 #endif
00036 
00037 #ifdef HAVE_STDLIB_H
00038 #include <stdlib.h>
00039 #endif
00040 
00041 #ifdef TIME_WITH_SYS_TIME
00042 #include <time.h>
00043 
00044 #ifdef HAVE_SYS_TIME_H
00045 #include <sys/time.h>
00046 #endif
00047 #else
00048 #include <time.h>
00049 #endif
00050 
00051 #ifdef HAVE_STRING_H
00052 #include <string.h>
00053 #endif
00054 
00055 #include <stdio.h>
00056 #include <kvm.h>
00057 #include <sys/param.h>
00058 #include <sys/proc.h>
00059 #include <sys/resource.h>
00060 #include <sys/resourcevar.h>
00061 #include <sys/lock.h>
00062 #include <sys/user.h>
00063 #include <vm/vm.h>
00064 #include <vm/vm_object.h>
00065 #include <vm/pmap.h>
00066 #include <machine/pmap.h>
00067 #include <machine/vmparam.h>
00068 #include <vm/vm_map.h>
00069 #include <sys/vmmeter.h>
00070 #include <sys/sysctl.h>
00071 
00072 #include "process.h"
00073 #include "sysdep.h"
00074 
00087 #define pagetok(size) ((size) << pageshift)
00088 #define tv2sec(tv) (((u_int64_t) tv.tv_sec * 1000000) + (u_int64_t) tv.tv_usec)
00089 
00090 static int pageshift;
00091 static long mem_kbyte_max;
00092 
00093 #ifndef LOG1024
00094 #define LOG1024         10
00095 #endif
00096 
00097 static kvm_t * kvm_handle;
00098 
00099 static void calcru(struct proc *p, struct timeval *up, struct timeval *sp,
00100            struct timeval *ip)
00101 {
00102   quad_t totusec;
00103   u_quad_t u, st, ut, it, tot;
00104 #if (__FreeBSD_version < 300003)
00105   long sec, usec;
00106 #endif 
00107   
00108   st = p->p_sticks;
00109   ut = p->p_uticks;
00110   it = p->p_iticks;
00111   
00112   tot = st + ut + it;
00113   if (tot == 0)
00114     {
00115       st = 1;
00116       tot = 1;
00117     }
00118   
00119 #if (defined __FreeBSD__) && (__FreeBSD_version >= 300003)
00120   totusec = (u_quad_t) p->p_runtime;
00121 #else
00122   sec = p->p_rtime.tv_usec;
00123   usec = p->p_rtime.tv_usec;
00124   
00125   totusec = (quad_t)sec * 1000000 + usec;
00126 #endif
00127   
00128   if(totusec < 0)
00129     {
00130       fprintf (stderr, "calcru: negative time: %ld usec\n",
00131            (long)totusec);
00132       totusec = 0;
00133     }
00134   
00135   u = totusec;
00136   st = (u * st) / tot;
00137   sp->tv_sec = st / 1000000;
00138   sp->tv_usec = st % 1000000;
00139   ut = (u * ut) / tot;
00140   up->tv_sec = ut / 1000000;
00141   up->tv_usec = ut % 1000000;
00142   
00143   if(ip != NULL)
00144     {
00145       it = (u * it) / tot;
00146       ip->tv_sec = it / 1000000;
00147       ip->tv_usec = it % 1000000;
00148     }
00149 }
00150 
00151 int init_process_info_sysdep(void) {
00152 
00153   register int pagesize;
00154   struct vmmeter vmm;
00155   int mib[2];
00156   size_t len;
00157   
00158   struct nlist nlst [] = {
00159       { "_bufspace"},
00160       { "_cnt" },
00161       { 0 }
00162   };
00163 
00164   if(getuid()!=0) {
00165 
00166     return FALSE;
00167 
00168   }
00169 
00170   mib[0] = CTL_HW;
00171   mib[1] = HW_NCPU;
00172   len = sizeof(num_cpus);
00173   sysctl(mib, 2, &num_cpus, &len, NULL, 0);
00174 
00175   kvm_handle = kvm_open(NULL, NULL, NULL, O_RDONLY, "monit");
00176   
00177   if ( kvm_handle == NULL ) {
00178     
00179     return FALSE;
00180     
00181   }
00182   
00183   /* ----------------------------- INIT MEM -----------------------------*/
00184   /* Got it from libgtop/sysdep/freebsd/mem.c */
00185 
00186   /* Initialize nlist structure */
00187   if (kvm_nlist (kvm_handle, nlst) < 0)
00188   {
00189     return FALSE;
00190   }
00191 
00192   /* get the page size with "getpagesize" and calculate pageshift
00193    * from it */
00194 
00195   pagesize = getpagesize ();
00196   pageshift = 0;
00197   while (pagesize > 1) {
00198 
00199     pageshift++;
00200     pagesize >>= 1;
00201 
00202   }
00203 
00204   /* we only need the amount of log(2)1024 for our conversion */
00205   pageshift -= LOG1024;
00206 
00207   /* Get the data from kvm_* */
00208   if (kvm_read (kvm_handle, nlst[1].n_value,
00209         &vmm, sizeof (vmm)) != sizeof (vmm)) {
00210     return FALSE;
00211 
00212   }
00213 
00214   mem_kbyte_max= vmm.v_pageout_free_min +
00215     vmm.v_free_count + vmm.v_wire_count +
00216     vmm.v_active_count + vmm.v_inactive_count;
00217 
00218   return TRUE;
00219 
00220 }
00221 
00222 int get_process_info_sysdep(ProcInfo_T p) {
00223 
00224   struct kinfo_proc *pinfo;
00225 
00226   /* Only needed for older versions of BSD that use kvm_uread */
00227   /* struct user *u_addr = (struct user *)USRSTACK; */
00228   struct pstats pstats;
00229   struct plimit plimit;
00230   struct vmspace *vms;
00231   register struct rusage *rup;
00232   long stat_utime;
00233   long stat_stime;
00234   long stat_cutime;
00235   long stat_cstime;
00236 
00237   u_int64_t rss_lim;
00238 
00239   int count;
00240 
00241   /* Got it from libgtop */
00242 
00243   pinfo = kvm_getprocs(kvm_handle, KERN_PROC_PID, p->pid, &count);
00244 
00245   if ((pinfo == NULL) || (count < 1)) {
00246 
00247     return FALSE;
00248 
00249   }
00250 
00251   /* ----------------------------- CPU TIMING ----------------------------*/
00252   /* Got it from libgtop/sysdep/freebsd/proctime.c */
00253   
00254   if (kvm_read (kvm_handle, 
00255         (unsigned long) pinfo [0].kp_proc.p_stats,
00256         &pstats, sizeof (pstats)) == sizeof (pstats)) {
00257     
00258     /* Need to fix for different versions of BSD - I think older ones
00259        use kvm_uread, and newer use kvm_read */
00260 
00261   /*  if ((pinfo [0].kp_proc.p_flag & P_INMEM) &&
00262       kvm_uread (kvm_handle, &(pinfo [0]).kp_proc,
00263          (unsigned long) &u_addr->u_stats,
00264          (char *) &pstats, sizeof (pstats)) == sizeof (pstats)) {
00265   */
00266     rup = &pstats.p_ru;
00267     calcru(&(pinfo [0]).kp_proc,
00268        &rup->ru_utime, &rup->ru_stime, NULL);
00269 
00270     stat_utime = tv2sec (pstats.p_ru.ru_utime);
00271     stat_stime = tv2sec (pstats.p_ru.ru_stime);
00272 
00273     stat_cutime = tv2sec (pstats.p_cru.ru_utime);
00274     stat_cstime = tv2sec (pstats.p_cru.ru_stime);
00275 
00276   } else {
00277 
00278     return FALSE;
00279 
00280   }
00281 
00282   p->cputime_prev= p->cputime;
00283   p->cputime= (int)(( stat_utime + stat_stime ) / 1000);
00284 
00285   if( include_children ) {
00286 
00287     p->cputime+= (int)(( stat_cutime + stat_cstime ) / 1000);
00288 
00289   }
00290 
00291   /* first run ? */
00292 
00293   if ( p->time_prev == 0.0 ) {
00294 
00295     p->cputime_prev= p->cputime;
00296 
00297   }
00298 
00299   /* ----------------------------- MEMORY --------------------------------*/
00300   /* Got it from libgtop/sysdep/freebsd/procmem.c */
00301 
00302   if (kvm_read (kvm_handle,
00303         (unsigned long) pinfo [0].kp_proc.p_limit,
00304         (char *) &plimit, sizeof (plimit)) != sizeof (plimit)) {
00305 
00306     return FALSE;
00307 
00308   }
00309 
00310   rss_lim = (u_int64_t)
00311     (plimit.pl_rlimit [RLIMIT_RSS].rlim_cur);
00312 
00313   vms = &pinfo [0].kp_eproc.e_vm;
00314 
00315   p->mem_kbyte= (u_int64_t) pagetok (vms->vm_rssize);
00316              /* <<LOG1024 removed, we wanna have kb */
00317 
00318   /* ----------------------------- STATE ---------------------------------*/
00319   /* Got it from libgtop/sysdep/freebsd/procstate.c */
00320 
00321   if ( pinfo [0].kp_proc.p_stat == SZOMB ) {
00322 
00323     p->status_flag |= PROCESS_ZOMBIE;
00324 
00325   }
00326 
00327   p->mem_percent = (int) ((double) p->mem_kbyte * 1000.0 / mem_kbyte_max);
00328 
00329   return TRUE;
00330 
00331 }