Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

ProcessDescriptor.cpp

Go to the documentation of this file.
00001 //====================================================================
00002 //  ProcStat.cpp
00003 //--------------------------------------------------------------------
00004 //
00005 //  Package    : System (The LHCb System service)
00006 //
00007 //  Description: Invoke interactively the ProcStat from a
00008 //               running application
00009 //
00010 //  Author     : M.Frank
00011 //  Created    : 13/11/00
00012 //  Changes    :
00013 //
00014 //====================================================================
00015 #define GAUDIKERNEL_PROCSTAT_CPP
00016 
00017 static const long TICK_TO_100NSEC = 100000;
00018 
00019 namespace System    {
00020   enum ProcessInfoCommand {
00021       ProcessBasicInformation,
00022       ProcessQuotaLimits,
00023       ProcessIoCounters,
00024       ProcessVmCounters,
00025       ProcessTimes,
00026       ProcessBasePriority,
00027       ProcessRaisePriority,
00028       ProcessDebugPort,
00029       ProcessExceptionPort,
00030       ProcessAccessToken,
00031       ProcessLdtInformation,
00032       ProcessLdtSize,
00033       ProcessDefaultHardErrorMode,
00034       ProcessIoPortHandlers,          // Note: this is kernel mode only
00035       ProcessPooledUsageAndLimits,
00036       ProcessWorkingSetWatch,
00037       ProcessUserModeIOPL,
00038       ProcessEnableAlignmentFaultFixup,
00039       ProcessPriorityClass,
00040       ProcessWx86Information,
00041       ProcessHandleCount,
00042       ProcessAffinityMask,
00043       ProcessPriorityBoost,
00044       MaxProcessInfoClass,  //
00045       ProcessEllapsedTime
00046   };
00047 }
00048 #ifdef _WIN32
00049   #  define strcasecmp _stricmp
00050   #  define strncasecmp _strnicmp
00051   #define NOMSG
00052   #define NOGDI
00053   #include "process.h"
00054   #include "windows.h"
00055   #define getpid _getpid
00056 namespace NtApi {
00057 //__declspec(dllimport) long __stdcall NtQueryInformationProcess(
00058 //  typedef __declspec(dllimport) long __stdcall (*__NtQueryInformationProcess)(
00059 //  extern "C" long __cdecl NtQueryInformationProcess(
00060 
00061     typedef long (WINAPI *__NtQueryInformationProcess)(
00062 
00063     void* ProcessHandle,
00064     long ProcessInformationClass,
00065     void* ProcessInformation,
00066     unsigned long ProcessInformationLength,
00067     unsigned long* ReturnLength
00068     );
00069   __NtQueryInformationProcess NtQueryInformationProcess;
00070 };
00071 #else  // UNIX...: first the EGCS stuff, then the OS dependent includes
00072 #define WINVER 0
00073 #include <errno.h>
00074 #include <string>
00075 #include "unistd.h"
00076 #include "libgen.h"
00077 #include <cstdio>
00078 #include <unistd.h>
00079 #include <sstream>
00080 #include <iostream>
00081 #include <fcntl.h>
00082 #include "sys/times.h"
00083 #include <sys/types.h>
00084 #include <sys/signal.h>
00085 #include <sys/syscall.h>
00086 #ifndef __APPLE__
00087 #include <sys/procfs.h>
00088 #endif
00089 #include <sys/time.h>
00090 #include <sys/resource.h>
00091 #include <cstdio>
00092 
00093 /* Format of the Linux proc/stat (man 5 proc, kernel 2.6.35):
00094  pid %d      The process ID.
00095 
00096  comm %s     The  filename  of the executable, in parentheses.  This is visible
00097              whether or not the executable is swapped out.
00098 
00099  state %c    One character from the string "RSDZTW" where R is  running,  S  is
00100              sleeping in an interruptible wait, D is waiting in uninterruptible
00101              disk sleep, Z is zombie, T is traced or stopped (on a signal), and
00102              W is paging.
00103 
00104  ppid %d     The PID of the parent.
00105 
00106  pgrp %d     The process group ID of the process.
00107 
00108  session %d  The session ID of the process.
00109 
00110  tty_nr %d   The controlling terminal of the process.  (The minor device number
00111              is contained in the combination of bits 31 to 20 and 7 to  0;  the
00112              major device number is in bits 15 t0 8.)
00113 
00114  tpgid %d    The ID of the foreground process group of the controlling terminal
00115              of the process.
00116 
00117  flags %u (%lu before Linux 2.6.22)
00118              The kernel flags word of the process.  For bit meanings,  see  the
00119              PF_*  defines  in  <linux/sched.h>.   Details depend on the kernel
00120              version.
00121 
00122  minflt %lu  The number of minor faults the process has  made  which  have  not
00123              required loading a memory page from disk.
00124 
00125  cminflt %lu The  number of minor faults that the process's waited-for children
00126              have made.
00127 
00128  majflt %lu  The number of  major  faults  the  process  has  made  which  have
00129              required loading a memory page from disk.
00130 
00131  cmajflt %lu The  number of major faults that the process's waited-for children
00132              have made.
00133 
00134  utime %lu   Amount of time that this process has been scheduled in user  mode,
00135              measured  in  clock  ticks  (divide by sysconf(_SC_CLK_TCK).  This
00136              includes guest time, guest_time (time spent running a virtual CPU,
00137              see  below),  so that applications that are not aware of the guest
00138              time field do not lose that time from their calculations.
00139 
00140  stime %lu   Amount of time that this process  has  been  scheduled  in  kernel
00141              mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK).
00142 
00143  cutime %ld  Amount  of  time that this process's waited-for children have been
00144              scheduled in  user  mode,  measured  in  clock  ticks  (divide  by
00145              sysconf(_SC_CLK_TCK).   (See  also times(2).)  This includes guest
00146              time, cguest_time (time spent running a virtual CPU, see below).
00147 
00148  cstime %ld  Amount of time that this process's waited-for children  have  been
00149              scheduled  in  kernel  mode,  measured  in  clock ticks (divide by
00150              sysconf(_SC_CLK_TCK).
00151 
00152  priority %ld
00153              (Explanation for Linux 2.6)  For  processes  running  a  real-time
00154              scheduling  policy (policy below; see sched_setscheduler(2)), this
00155              is the negated scheduling priority, minus one; that is,  a  number
00156              in  the  range -2 to -100, corresponding to real-time priorities 1
00157              to 99.  For processes running  under  a  non-real-time  scheduling
00158              policy, this is the raw nice value (setpriority(2)) as represented
00159              in the kernel.  The kernel stores nice values as  numbers  in  the
00160              range 0 (high) to 39 (low), corresponding to the user-visible nice
00161              range of -20 to 19.
00162 
00163              Before Linux 2.6, this was a scaled value based on  the  scheduler
00164              weighting given to this process.
00165 
00166  nice %ld    The  nice value (see setpriority(2)), a value in the range 19 (low
00167              priority) to -20 (high priority).
00168 
00169  num_threads %ld
00170              Number of threads in this process (since Linux 2.6).  Before  ker‐
00171              nel  2.6,  this  field was hard coded to 0 as a placeholder for an
00172              earlier removed field.
00173 
00174  itrealvalue %ld
00175              The time in jiffies before the next SIGALRM is sent to the process
00176              due  to  an interval timer.  Since kernel 2.6.17, this field is no
00177              longer maintained, and is hard coded as 0.
00178 
00179  starttime %llu (was %lu before Linux 2.6)
00180              The time in jiffies the process started after system boot.
00181 
00182  vsize %lu   Virtual memory size in bytes.
00183 
00184  rss %ld     Resident Set Size: number of pages the process has in real memory.
00185              This  is  just  the pages which count towards text, data, or stack
00186              space.  This does not include pages which have  not  been  demand-
00187              loaded in, or which are swapped out.
00188 
00189  rsslim %lu  Current  soft  limit  in  bytes on the rss of the process; see the
00190              description of RLIMIT_RSS in getpriority(2).
00191 
00192  startcode %lu
00193              The address above which program text can run.
00194 
00195  endcode %lu The address below which program text can run.
00196 
00197  startstack %lu
00198              The address of the start (i.e., bottom) of the stack.
00199 
00200  kstkesp %lu The current value of ESP (stack pointer), as found in  the  kernel
00201              stack page for the process.
00202 
00203  kstkeip %lu The current EIP (instruction pointer).
00204 
00205  signal %lu  The  bitmap  of  pending  signals,  displayed as a decimal number.
00206              Obsolete, because it does not  provide  information  on  real-time
00207              signals; use /proc/[pid]/status instead.
00208 
00209  blocked %lu The  bitmap  of  blocked  signals,  displayed as a decimal number.
00210              Obsolete, because it does not  provide  information  on  real-time
00211              signals; use /proc/[pid]/status instead.
00212 
00213  sigignore %lu
00214              The  bitmap  of  ignored  signals,  displayed as a decimal number.
00215              Obsolete, because it does not  provide  information  on  real-time
00216              signals; use /proc/[pid]/status instead.
00217 
00218  sigcatch %lu
00219              The  bitmap  of  caught  signals,  displayed  as a decimal number.
00220              Obsolete, because it does not  provide  information  on  real-time
00221              signals; use /proc/[pid]/status instead.
00222 
00223  wchan %lu   This  is the "channel" in which the process is waiting.  It is the
00224              address of a system call, and can be looked up in  a  namelist  if
00225              you   need   a   textual   name.    (If  you  have  an  up-to-date
00226              /etc/psdatabase, then try ps -l to see the WCHAN field in action.)
00227 
00228  nswap %lu   Number of pages swapped (not maintained).
00229 
00230  cnswap %lu  Cumulative nswap for child processes (not maintained).
00231 
00232  exit_signal %d (since Linux 2.1.22)
00233              Signal to be sent to parent when we die.
00234 
00235  processor %d (since Linux 2.2.8)
00236              CPU number last executed on.
00237 
00238  rt_priority %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
00239              Real-time scheduling priority, a number in the range 1 to  99  for
00240              processes  scheduled under a real-time policy, or 0, for non-real-
00241              time processes (see sched_setscheduler(2)).
00242 
00243  policy %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
00244              Scheduling policy (see sched_setscheduler(2)).  Decode  using  the
00245              SCHED_* constants in linux/sched.h.
00246 
00247  delayacct_blkio_ticks %llu (since Linux 2.6.18)
00248              Aggregated  block  I/O  delays, measured in clock ticks (centisec‐
00249              onds).
00250 
00251  guest_time %lu (since Linux 2.6.24)
00252              Guest time of the process (time spent running a virtual CPU for  a
00253              guest  operating  system),  measured  in  clock  ticks  (divide by
00254              sysconf(_SC_CLK_TCK).
00255 
00256  cguest_time %ld (since Linux 2.6.24)
00257              Guest time of the process's  children,  measured  in  clock  ticks
00258              (divide by sysconf(_SC_CLK_TCK).
00259 */
00260 struct linux_proc {
00261   int pid;
00262   char comm[400];
00263   char state;
00264   int ppid;
00265   int pgrp;
00266   int session;
00267   int tty;
00268   int tpgid;
00269   unsigned long flags;
00270   unsigned long minflt;
00271   unsigned long cminflt;
00272   unsigned long majflt;
00273   unsigned long cmajflt;
00274   unsigned long utime;
00275   unsigned long stime;
00276   long cutime;
00277   long cstime;
00278   long priority;
00279   long nice;
00280   long num_threads;
00281   long itrealvalue;
00282   unsigned long long starttime;
00283   unsigned long vsize;
00284   long rss;
00285   unsigned long rlim;
00286   unsigned long startcode;
00287   unsigned long endcode;
00288   unsigned long startstack;
00289   unsigned long kstkesp;
00290   unsigned long kstkeip;
00291   unsigned long signal;
00292   unsigned long blocked;
00293   unsigned long sigignore;
00294   unsigned long sigcatch;
00295   unsigned long wchan;
00296 };
00297 
00298 #ifdef __APPLE__
00299 // static long  pg_size = 0;
00300 #else
00301 static long  pg_size = sysconf(_SC_PAGESIZE); // getpagesize();
00302 #endif
00303 void readProcStat(long pid, linux_proc& pinfo) {
00304 
00305   int cnt, fd;
00306   char buf[512];
00307 
00308   std::ostringstream ost;
00309 
00310   ost << "/proc/" << pid << "/stat";
00311   std::string fname = ost.str();
00312   if((fd=open(fname.c_str(),O_RDONLY))<0)  {
00313     std::cerr << "Failed to open " << ost.str() << std::endl;
00314     return;
00315   }
00316 
00317   lseek(fd,0,SEEK_SET);
00318   if((cnt=read(fd,buf,sizeof(buf)))<0) {
00319     std::cout << "LINUX Read of Proc file failed:" << std::endl;
00320     close(fd);
00321     return;
00322   }
00323 
00324   // Format
00325   if(cnt>0) {
00326     buf[cnt]='\0';
00327     sscanf(buf,
00328            //1  2  3  4  5  6  7  8  9  10  1   2   3   4   5   6   7   8   9   20  1   2   3   4   5   6   7   8   9   30  1   2   3   4   5
00329            "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
00330            &pinfo.pid,
00331            pinfo.comm,
00332            &pinfo.state,
00333            &pinfo.ppid,
00334            &pinfo.pgrp,
00335            &pinfo.session,
00336            &pinfo.tty,
00337            &pinfo.tpgid,
00338            &pinfo.flags,
00339            &pinfo.minflt,
00340            &pinfo.cminflt,
00341            &pinfo.majflt,
00342            &pinfo.cmajflt,
00343            &pinfo.utime,
00344            &pinfo.stime,
00345            &pinfo.cutime,
00346            &pinfo.cstime,
00347            &pinfo.priority,
00348            &pinfo.nice,
00349            &pinfo.num_threads,
00350            &pinfo.itrealvalue,
00351            &pinfo.starttime,
00352            &pinfo.vsize,
00353            &pinfo.rss,
00354            &pinfo.rlim,
00355            &pinfo.startcode,
00356            &pinfo.endcode,
00357            &pinfo.startstack,
00358            &pinfo.kstkesp,
00359            &pinfo.kstkeip,
00360            &pinfo.signal,
00361            &pinfo.blocked,
00362            &pinfo.sigignore,
00363            &pinfo.sigcatch,
00364            &pinfo.wchan
00365            );
00366   }
00367   close(fd);
00368 }
00369 #endif
00370 
00371 //static long s_myPid  = ::getpid();
00372 // In order to properly support e.g. fork() calls, we cannot keep a copy of the pid!
00373 #define s_myPid (::getpid())
00374 static inline long processID(long pid) {
00375   long thePid = (pid>0) ? pid : s_myPid;
00376   return thePid;
00377 }
00378 
00379 // Framework include files
00380 #include "ProcessDescriptor.h"
00381 #include "GaudiKernel/ModuleInfo.h"
00382 #include "GaudiKernel/System.h"
00383 
00384 System::ProcessDescriptor* System::getProcess()   {
00385   static ProcessDescriptor p;
00386 #ifdef _WIN32
00387   static bool first = true;
00388   if ( first )    {
00389     first = false;
00390     void* mh = ::LoadLibrary("NTDll.dll");
00391     if ( mh )  {
00392       NtApi::NtQueryInformationProcess = (NtApi::__NtQueryInformationProcess)
00393         ::GetProcAddress((HINSTANCE)mh, "NtQueryInformationProcess");
00394     }
00395   }
00396 #endif
00397   return &p;
00398 }
00399 
00400 System::ProcessDescriptor::ProcessHandle::ProcessHandle(long pid)   {
00401   if ( pid > 0 )    {
00402     if ( pid != s_myPid )    {
00403 #ifdef _WIN32
00404       m_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
00405                                pid);
00406 #else
00407       m_handle = (void*)s_myPid;
00408 #endif
00409       m_needRelease = true;
00410       return;
00411     }
00412   }
00413   m_handle = processHandle();
00414   m_needRelease = false;
00415 }
00416 
00417 System::ProcessDescriptor::ProcessHandle::~ProcessHandle()   {
00418   if ( m_needRelease )    {
00419 #ifdef _WIN32
00420     ::CloseHandle(m_handle);
00421 #else
00422       m_handle = 0;
00423 #endif
00424   }
00425 }
00426 
00427 System::ProcessDescriptor::ProcessDescriptor()
00428 {
00429 }
00430 
00431 System::ProcessDescriptor::~ProcessDescriptor()   {
00432 }
00433 
00434 long System::ProcessDescriptor::query(long pid,
00435                                       InfoType fetch,
00436                                       IO_COUNTERS* info) {
00437   long status = 1;
00438   ProcessHandle h(pid);
00439   IO_COUNTERS* vb = &m_IO_COUNTERS[h.item()];
00440   if ( fetch == IO )   {
00441 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00442     status = NtApi::NtQueryInformationProcess(h.handle(),
00443                                               ProcessIoCounters,
00444                                               vb,
00445                                               sizeof(IO_COUNTERS),
00446                                               0);
00447     status = (status==0) ? 1 : 0;
00448 #elif defined(_WIN32)                     // Windows 95,98...
00449 #elif defined(linux)
00450     linux_proc prc;
00451     readProcStat(processID(pid), prc);
00452     rusage usage;
00453     getrusage(RUSAGE_SELF, &usage);
00454     vb->ReadOperationCount    = usage.ru_inblock;
00455     vb->WriteOperationCount   = usage.ru_oublock;
00456     vb->OtherOperationCount   = 0;
00457     vb->ReadTransferCount     = usage.ru_inblock;
00458     vb->WriteTransferCount    = usage.ru_oublock;
00459     vb->OtherTransferCount    = 0;
00460 #else                                     // All Other
00461 #endif                                    // End ALL OS
00462   }
00463   if ( info ) *info = *vb;
00464   return status;
00465 }
00466 
00467 long System::ProcessDescriptor::query(long pid,
00468                                       InfoType fetch,
00469                                       POOLED_USAGE_AND_LIMITS* info)    {
00470   long status = 1;
00471   ProcessHandle h(pid);
00472   POOLED_USAGE_AND_LIMITS* vb = &m_POOLED_USAGE_AND_LIMITS[h.item()];
00473   if ( fetch == Quota )   {
00474 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00475     status = NtApi::NtQueryInformationProcess(h.handle(),
00476                                               ProcessPooledUsageAndLimits,
00477                                               vb,
00478                                               sizeof(POOLED_USAGE_AND_LIMITS),
00479                                               0);
00480     status = (status==0) ? 1 : 0;
00481 #elif defined(_WIN32)                     // Windows 95,98...
00482 #elif defined(linux)                      // Linux
00483     //rusage usage;
00484     //getrusage(RUSAGE_SELF, &usage);
00485     rlimit lim;
00486 
00487     getrlimit(RLIMIT_DATA, &lim);
00488     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00489     vb->PeakPagedPoolUsage = lim.rlim_cur;
00490     vb->PagedPoolUsage     = lim.rlim_cur;
00491     vb->PagedPoolLimit     = lim.rlim_max;
00492 
00493     getrlimit(RLIMIT_STACK, &lim);
00494     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00495     vb->PeakNonPagedPoolUsage = lim.rlim_cur;
00496     vb->NonPagedPoolUsage     = lim.rlim_cur;
00497     vb->NonPagedPoolLimit     = lim.rlim_max;
00498 
00499     linux_proc prc;
00500     readProcStat(processID(pid), prc);
00501     vb->PeakPagefileUsage     = prc.rss * pg_size;
00502     vb->PagefileUsage         = prc.rss * pg_size;
00503     vb->PagefileLimit         = 0xFFFFFFFF;
00504 #elif defined(__APPLE__)
00505 #else                                     // All Other
00506 #endif                                    // End ALL OS
00507   }
00508   if ( info ) *info = *vb;
00509   return status;
00510 }
00511 
00512 long System::ProcessDescriptor::query(long pid, InfoType fetch, long* info)    {
00513   long status = 1, *vb = &status;
00514   ProcessHandle h(pid);
00515   vb = &m_PRIORITYBOOST[h.item()];
00516   *vb = 0;
00517   switch ( fetch )    {
00518   case PriorityBoost:
00519 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00520     status = NtApi::NtQueryInformationProcess(h.handle(),
00521                                               ProcessPriorityBoost,
00522                                               vb,
00523                                               sizeof(long),
00524                                               0);
00525 #elif defined(_WIN32)                     // Windows 95,98...
00526 #else
00527     // Not applicable
00528     status = 0;
00529     *vb = 0;
00530 #endif                                    // End ALL OS
00531     status = (status==0) ? 1 : 0;
00532     break;
00533   default:
00534     status = -1;
00535     vb = &status;
00536     break;
00537   }
00538   if ( info ) *info = *vb;
00539   return status;
00540 }
00541 
00542 long System::ProcessDescriptor::query(long pid,
00543                                       InfoType fetch,
00544                                       VM_COUNTERS* info)    {
00545   long status = 1;
00546   ProcessHandle h(pid);
00547   VM_COUNTERS* vb = &m_VM_COUNTERS[h.item()];
00548   if ( fetch == Memory )   {
00549 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00550     status = NtApi::NtQueryInformationProcess(h.handle(),
00551                                               ProcessVmCounters,
00552                                               vb,
00553                                               sizeof(VM_COUNTERS),
00554                                               0);
00555     status = (status==0) ? 1 : 0;
00556 #elif defined(_WIN32)                     // Windows 95,98...
00557 #elif defined(linux)                      // Linux
00558     const ssize_t bufsize = 1024;
00559     char buf[bufsize];
00560     sprintf(buf,"/proc/%ld/statm", processID(pid));
00561     long size, resident, share, trs, lrs, drs, dt;
00562     int fd = open(buf,O_RDONLY);
00563     ssize_t nread = read(fd, buf, bufsize);
00564     close(fd);
00565     if ( nread < bufsize && nread >= 0 )
00566       buf[nread]='\0';
00567     fd = sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld",
00568                      &size, &resident, &share, &trs, &drs, &lrs, &dt);
00569     linux_proc prc;
00570     readProcStat( processID(pid), prc);
00571     vb->PeakVirtualSize            = prc.vsize;
00572     vb->VirtualSize                = prc.vsize;
00573     vb->PeakWorkingSetSize         = resident * pg_size;
00574     vb->WorkingSetSize             = resident * pg_size;
00575     vb->QuotaPeakPagedPoolUsage    = share    * pg_size;
00576     vb->QuotaPagedPoolUsage        = share    * pg_size;
00577     vb->QuotaNonPagedPoolUsage     = (trs+drs)* pg_size;// drs = data/stack size
00578     vb->QuotaPeakNonPagedPoolUsage = (trs+drs)* pg_size;// trs = VmExe size
00579     vb->PageFaultCount             = prc.majflt + prc.minflt;
00580     vb->PagefileUsage              = prc.vsize-resident*pg_size;
00581     vb->PeakPagefileUsage          = prc.vsize-resident*pg_size;
00582 #elif defined(__APPLE__)
00583 #else                                     // All Other
00584 #endif                                    // End ALL OS
00585   }
00586   if ( info ) *info = *vb;
00587   return status;
00588 }
00589 
00590 long System::ProcessDescriptor::query(long pid,
00591                                       InfoType fetch,
00592                                       QUOTA_LIMITS* info)    {
00593   long status = 1;
00594   ProcessHandle h(pid);
00595   QUOTA_LIMITS* vb = &m_QUOTA_LIMITS[h.item()];
00596   if ( fetch == Quota )   {
00597 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00598     status = NtApi::NtQueryInformationProcess(h.handle(),
00599                                               ProcessQuotaLimits,
00600                                               vb,
00601                                               sizeof(QUOTA_LIMITS),
00602                                               0);
00603     status = (status==0) ? 1 : 0;
00604 #elif defined(_WIN32)                     // Windows 95,98...
00605 #elif defined(linux)                      // Linux
00606     // On linux all this stuff typically is not set
00607     // (ie. rlim_max=RLIM_INFINITY...)
00608     rlimit lim;
00609     getrlimit(RLIMIT_DATA, &lim);
00610     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00611     vb->PagedPoolLimit        = lim.rlim_max;
00612 
00613     getrlimit(RLIMIT_STACK, &lim);
00614     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00615     vb->NonPagedPoolLimit     = lim.rlim_max;
00616     vb->MinimumWorkingSetSize = 0;
00617 
00618     getrlimit(RLIMIT_RSS, &lim);
00619     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00620     vb->MaximumWorkingSetSize = lim.rlim_max;
00621 
00622     getrlimit(RLIMIT_AS, &lim);
00623     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00624     vb->PagefileLimit         = lim.rlim_max;
00625 
00626     getrlimit(RLIMIT_CPU, &lim);
00627     if ( lim.rlim_max == RLIM_INFINITY ) lim.rlim_max = 0xFFFFFFFF;
00628     vb->TimeLimit             = lim.rlim_max;
00629 #elif defined(__APPLE__)
00630 #else                                     // All Other
00631 #endif                                    // End ALL OS
00632   }
00633   if ( info ) *info = *vb;
00634   return status;
00635 }
00636 
00637 long System::ProcessDescriptor::query(long pid,
00638                                       InfoType fetch,
00639                                       PROCESS_BASIC_INFORMATION* info)    {
00640   long status = 1;
00641   ProcessHandle h(pid);
00642   PROCESS_BASIC_INFORMATION* vb = &m_PROCESS_BASIC_INFORMATION[h.item()];
00643   if ( fetch == ProcessBasics )   {
00644 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00645     status = NtApi::NtQueryInformationProcess(h.handle(),
00646                                               ProcessBasicInformation,
00647                                               vb,
00648                                               sizeof(PROCESS_BASIC_INFORMATION),
00649                                               0);
00650     status = (status==0) ? 1 : 0;
00651 #elif defined(_WIN32)                     // Windows 95,98...
00652 #elif defined(linux)                      // Linux
00653     linux_proc prc;
00654     readProcStat( processID(pid), prc);
00655     vb->ExitStatus                   = 0;
00656     vb->PebBaseAddress               = (PPEB)prc.startcode;
00657     vb->BasePriority                 = 2*15-prc.priority;
00658     // std::cout << "Base Priority=" << vb->BasePriority << "|"
00659     // << prc.priority << std::endl;
00660     vb->AffinityMask                 = prc.flags;
00661     // std::cout << "Flags        =" << vb->AffinityMask << "|"
00662     // << prc.flags << std::endl;
00663     vb->UniqueProcessId              = processID(pid);
00664     vb->InheritedFromUniqueProcessId = prc.ppid;
00665 #else                                     // All Other
00666 #endif                                    // End ALL OS
00667   }
00668   if ( info ) *info = *vb;
00669   return status;
00670 }
00671 
00672 long System::ProcessDescriptor::query(long pid,
00673                                       InfoType fetch,
00674                                       KERNEL_USER_TIMES* info)   {
00675   long status = 1;
00676   ProcessHandle h(pid);
00677   KERNEL_USER_TIMES* tb = &m_KERNEL_USER_TIMES[h.item()];;
00678   if ( fetch == Times )   {
00679 #if defined(_WIN32) && WINVER>=0x0400     // Windows NT
00680     status = NtApi::NtQueryInformationProcess(h.handle(),
00681                                               ProcessTimes,
00682                                               tb,
00683                                               sizeof(KERNEL_USER_TIMES),
00684                                               0);
00685     status = (status==0) ? 1 : 0;
00686 #elif defined(_WIN32)                     // Windows 95,98...
00687 #elif defined(linux)                      // Linux
00688     // prc.startup is in ticks since system start :
00689     // need to offset for absolute time
00690     tms tmsb;
00691     static longlong prc_start = 0;
00692     //    static longlong offset = 100*longlong(time(0)) - longlong(times(0));
00693     static longlong offset = 100*longlong(time(0)) - longlong(times(&tmsb));
00694     if ( processID(pid) == s_myPid && prc_start == 0 ) {
00695       linux_proc prc;
00696       readProcStat( processID(pid), prc);
00697       prc_start = prc.starttime+offset;
00698     }
00699 
00700     if ( processID(pid) == s_myPid ) {
00701       struct rusage r;
00702       getrusage( RUSAGE_SELF, &r );
00703       tb->UserTime   = (static_cast<long long>(r.ru_utime.tv_sec) * 1000000 +
00704                         r.ru_utime.tv_usec) * 10;
00705       tb->KernelTime = (static_cast<long long>(r.ru_stime.tv_sec) * 1000000 +
00706                         r.ru_stime.tv_usec) * 10;
00707       tb->CreateTime = prc_start;
00708     }
00709     else {
00710       linux_proc prc;
00711       readProcStat( processID(pid), prc );
00712 
00713       tms t;
00714       times(&t);
00715       tb->UserTime   = t.tms_utime * TICK_TO_100NSEC;
00716       tb->KernelTime = t.tms_stime * TICK_TO_100NSEC;
00717       tb->CreateTime = (prc.starttime+offset);
00718     }
00719     tb->CreateTime *= TICK_TO_100NSEC;
00720     tb->ExitTime    = 0;
00721 
00722     status = 1;
00723 
00724 #elif defined(__APPLE__)
00725     // FIXME (MCl): Make an alternative function get timing on OSX
00726     // times() seems to cause a segmentation fault
00727 #else  // no /proc file system: assume sys_start for the first call
00728     tms tmsb;
00729     static clock_t sys_start = times(0);
00730     static longlong offset = 100*longlong(time(0)) - sys_start;
00731     clock_t now = times(&tmsb);
00732     tb->CreateTime    = offset + now;
00733     tb->UserTime      = tmsb.tms_utime;
00734     tb->KernelTime    = tmsb.tms_stime;
00735     tb->CreateTime   *= TICK_TO_100NSEC;
00736     tb->UserTime     *= TICK_TO_100NSEC;
00737     tb->KernelTime   *= TICK_TO_100NSEC;
00738     tb->ExitTime      = 0;
00739     status = 1;
00740 #endif
00741   }
00742   if ( info ) *info = *tb;
00743   return status;
00744 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:24:44 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004