00001
00002
00003
00004
00005
00006
00007
00009 #include "LeakChecker/LeaMemMonitor.h"
00010
00011 #include <sys/types.h>
00012 #include <stdio.h>
00013 #include <fcntl.h>
00014 #include <unistd.h>
00015 #include <stdlib.h>
00016 #include <time.h>
00017 #include <sys/stat.h>
00018
00019 #define PROCFS "/proc"
00020 #define PROCSTATUS "/proc/self/status"
00021
00022 #include "MessageService/MsgService.h"
00023 CVSID("$Id: LeaMemMonitor.cxx,v 1.6 2007/02/08 17:03:42 rhatcher Exp $");
00024
00025 void LeaMemMonitor::FillMemStat(LeaMemMonitor::memstat_t& result)
00026 {
00027
00028
00029 #ifndef linux
00030 MSG("Lea",Msg::kFatal)
00031 << "Not supported for any OS other than Linux" << endl;
00032 result.ms_total.mu_sizex = 0;
00033 #else
00034 char buffer[4096+1];
00035
00036 int fd = open(PROCSTATUS,O_RDONLY);
00037 int len = read(fd,buffer,sizeof(buffer)-1);
00038 close(fd);
00039 buffer[len] = '\0';
00040
00041
00042 int nskip = 0;
00043 char *p = buffer;
00044 char *pend = buffer+len;
00045 while (p<pend) {
00046 if (*p == '\n') nskip++;
00047 p++;
00048 if (nskip == 10) break;
00049 }
00050
00051
00052 int nexpect = 14;
00053 int ndatum = sscanf(p,"VmSize: %u %cB \
00054 VmLck: %u %cB \
00055 VmRSS: %u %cB \
00056 VmData: %u %cB \
00057 VmStk: %u %cB \
00058 VmExe: %u %cB \
00059 VmLib: %u %cB",
00060 &result.ms_total.mu_sizex,&result.ms_total.mu_sizeu,
00061 &result.ms_lck.mu_sizex,&result.ms_lck.mu_sizeu,
00062 &result.ms_rss.mu_sizex,&result.ms_rss.mu_sizeu,
00063 &result.ms_data.mu_sizex,&result.ms_data.mu_sizeu,
00064 &result.ms_stk.mu_sizex,&result.ms_stk.mu_sizeu,
00065 &result.ms_exe.mu_sizex,&result.ms_exe.mu_sizeu,
00066 &result.ms_lib.mu_sizex,&result.ms_lib.mu_sizeu);
00067
00068 if (ndatum != nexpect)
00069 MSG("Lea",Msg::kWarning)
00070 << " sscanf only returned " << ndatum << " of "
00071 << nexpect << " items " << endl;
00072
00073
00074 LeaMemMonitor::CalcBytes(result.ms_total);
00075 LeaMemMonitor::CalcBytes(result.ms_lck);
00076 LeaMemMonitor::CalcBytes(result.ms_rss);
00077 LeaMemMonitor::CalcBytes(result.ms_data);
00078 LeaMemMonitor::CalcBytes(result.ms_stk);
00079 LeaMemMonitor::CalcBytes(result.ms_exe);
00080 LeaMemMonitor::CalcBytes(result.ms_lib);
00081
00082 #endif
00083
00084 }
00085
00086 void LeaMemMonitor::PrintMemStat(const char* tag)
00087 {
00088
00089
00090
00091 #ifndef linux
00092 MSG("Lea",Msg::kFatal)
00093 << "Not supported for any OS other than Linux: "
00094 << tag
00095 << endl;
00096 #else
00097 memstat_t result;
00098 LeaMemMonitor::FillMemStat(result);
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 if (tag) MSG("Lea",Msg::kInfo) << tag << endl;
00109 MSG("Lea",Msg::kInfo)
00110 << "Memory:"
00111 << " Total " << result.ms_total.mu_sizex << result.ms_total.mu_sizeu
00112
00113 << ", RSS " << result.ms_rss.mu_sizex << result.ms_rss.mu_sizeu
00114 << ", Data " << result.ms_data.mu_sizex << result.ms_data.mu_sizeu
00115 << ", Stack " << result.ms_stk.mu_sizex << result.ms_stk.mu_sizeu
00116 << ", Exe " << result.ms_exe.mu_sizex << result.ms_exe.mu_sizeu
00117 << ", Lib " << result.ms_lib.mu_sizex << result.ms_lib.mu_sizeu
00118 << endl;
00119 #endif
00120 }
00121
00122 void LeaMemMonitor::CalcBytes(memusage_t& usage)
00123 {
00124 switch (usage.mu_sizeu) {
00125 case 'k':
00126 case 'K':
00127 usage.mu_size = 1024 * usage.mu_sizex;
00128 break;
00129 case 'm':
00130 case 'M':
00131 usage.mu_size = 1024 * 1024 * usage.mu_sizex;
00132 break;
00133 default:
00134 usage.mu_size = usage.mu_sizex;
00135 MSG("Lea",Msg::kWarning)
00136 << "unit designator \"" << usage.mu_sizeu
00137 << "\" not recognized" << endl;
00138
00139 }
00140 }