X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fvserver-stat.c;h=60810e1989bee3468443bb52aac6590b104479ac;hb=a917f24ef7b003dcef54a3db2644cf9cb4bc2db2;hp=7ca6504957405010c0ca1f34c07aa7a4244dc4d1;hpb=32be2811337e77a0cf85321909bf603073e1c09a;p=util-vserver.git diff --git a/util-vserver/src/vserver-stat.c b/util-vserver/src/vserver-stat.c index 7ca6504..60810e1 100644 --- a/util-vserver/src/vserver-stat.c +++ b/util-vserver/src/vserver-stat.c @@ -17,19 +17,6 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -/* - vserver-stat help you to see all the active context currently in the kernel - with some useful stat - - Changelog: - - 2003-01-08 Jacques Gelinas: Shows vserver description - 2002-02-28 Jacques Gelinas: Use dynamic system call - 2002-06-05 Martial Rioux : fix memory output error - 2002-12-05 Martial Rioux : fix output glitch - 2001-11-29 added uptime/ctx stat - 2001-11-20 added vmsize, rss, stime and utime stat -*/ #ifdef HAVE_CONFIG_H # include #endif @@ -53,6 +40,7 @@ #include #include #include +#include #define ENSC_WRAPPERS_DIRENT 1 #define ENSC_WRAPPERS_VSERVER 1 @@ -66,24 +54,30 @@ int wrapper_exit_code = 1; +#ifndef AT_CLKTCK +#define AT_CLKTCK 17 /* frequency of times() */ +#endif + +static unsigned long hertz=0x42; + struct XidData { xid_t xid; int process_count; int VmSize_total; int VmRSS_total; - long start_time_oldest; - long stime_total, utime_total; + uint64_t start_time_oldest; + uint64_t stime_total, utime_total; }; struct process_info { - long VmSize; // number of pages of virtual memory - long VmRSS; // resident set size from /proc/#/stat - long start_time; // start time of process -- seconds since 1-1-70 - long stime, utime; // kernel & user-mode CPU time accumulated by process - long cstime, cutime; // cumulative time of process and reaped children - xid_t s_context; + long VmSize; // number of pages of virtual memory + long VmRSS; // resident set size from /proc/#/stat + uint64_t start_time; // start time of process -- milliseconds since 1-1-70 + uint64_t stime, utime; // kernel & user-mode CPU time accumulated by process + uint64_t cstime, cutime; // cumulative time of process and reaped children + xid_t s_context; }; struct ArgInfo { @@ -143,7 +137,7 @@ getUptime() uint32_t msecs=0; // open the /proc/uptime file - fd = Eopen("/proc/uptime", O_RDONLY, 0); + fd = EopenD("/proc/uptime", O_RDONLY, 0); len = Eread(fd, buffer, sizeof buffer); if (len==sizeof(buffer)) { @@ -157,14 +151,24 @@ getUptime() secs = strtol(buffer, &errptr, 10); if (*errptr!='.') errptr = buffer; - else msecs = strtol(errptr+1, &errptr, 10); + else { + unsigned int mult; + switch (strlen(errptr+1)) { + case 0 : mult = 1000; break; + case 1 : mult = 100; break; + case 2 : mult = 10; break; + case 3 : mult = 1; break; + default : mult = 0; break; + } + msecs = strtol(errptr+1, &errptr, 10) * mult; + } if ((*errptr!='\0' && *errptr!=' ') || errptr==buffer) { WRITE_MSG(2, "Bad data in /proc/uptime\n"); exit(1); } - return secs*100 + msecs; + return secs*1000 + msecs; } static int @@ -191,7 +195,7 @@ registerXid(struct Vector *vec, struct process_info *process) res->VmRSS_total = 0; res->utime_total = 0; res->stime_total = 0; - res->start_time_oldest = 0; + res->start_time_oldest = process->start_time; } ++res->process_count; @@ -200,15 +204,41 @@ registerXid(struct Vector *vec, struct process_info *process) res->utime_total += process->utime + process->cutime; res->stime_total += process->stime + process->cstime; - if (res->start_time_oldest == 0) // first entry - res->start_time_oldest = process->start_time; - else - if (res->start_time_oldest > process->start_time) - res->start_time_oldest = process->start_time; + res->start_time_oldest = MIN(res->start_time_oldest, process->start_time); +} + +static inline uint64_t +toMsec(uint64_t v) +{ + return v*1000llu/hertz; +} + + +// shamelessly stolen from procps... +static unsigned long +find_elf_note(unsigned long findme){ + unsigned long *ep = (unsigned long *)environ; + while(*ep++); + while(*ep){ + if(ep[0]==findme) return ep[1]; + ep+=2; + } + return (unsigned long)(-1); +} + +static void initHertz() __attribute__((__constructor__)); + +static void +initHertz() +{ + hertz = find_elf_note(AT_CLKTCK); + if (hertz==(unsigned long)(-1)) + hertz = sysconf(_SC_CLK_TCK); } // open the process's status file to get the ctx number, and other stat -struct process_info *get_process_info(char *pid) +struct process_info * +get_process_info(char *pid) { int fd; char buffer[1024]; @@ -230,6 +260,8 @@ struct process_info *get_process_info(char *pid) WRITE_MSG(2, "): "); WRITE_STR(2, strerror(err)); WRITE_MSG(2, "\n"); + + return 0; } memcpy(buffer, "/proc/", 6); idx = 6; @@ -249,18 +281,19 @@ struct process_info *get_process_info(char *pid) for (idx = 0; idx<12 && *p!='\0'; ++p) if ((*p)==' ') ++idx; - process.utime = strtol(p, &p, 10); - process.stime = strtol(p+1, &p, 10); - process.cutime = strtol(p+1, &p, 10); - process.cstime = strtol(p+1, &p, 10); + process.utime = toMsec(strtol(p, &p, 10)); + process.stime = toMsec(strtol(p+1, &p, 10)); + process.cutime = toMsec(strtol(p+1, &p, 10)); + process.cstime = toMsec(strtol(p+1, &p, 10)); for (idx = 0; idx<5 && *p!='\0'; ++p) if ((*p)==' ') ++idx; - process.start_time = strtol(p, &p, 10); + process.start_time = toMsec(strtol(p, &p, 10)); process.VmSize = strtol(p+1, &p, 10); process.VmRSS = strtol(p+1, &p, 10); - + + //printf("pid=%s, start_time=%llu\n", pid, process.start_time); return &process; } @@ -319,8 +352,8 @@ shortenTime(char *buf, uint64_t t) unsigned long hh, mm, ss, ms; - ms = t % 100; - t /= 100; + ms = t % 1000; + t /= 1000; ss = t%60; t /= 60; @@ -329,7 +362,18 @@ shortenTime(char *buf, uint64_t t) hh = t%60; t /= 24; - if (t>0) { + if (t>999*999) { + memcpy(ptr, "INVALID", 7); + ptr += 7; + } + else if (t>999) { + ptr += utilvserver_fmt_ulong(ptr, t/365); + *ptr++ = 'y'; + ptr += fillUintZero(ptr, t%365, 2); + *ptr++ = 'd'; + ptr += fillUintZero(ptr, hh, 2); + } + else if (t>0) { ptr += utilvserver_fmt_ulong(ptr, t); *ptr++ = 'd'; ptr += fillUintZero(ptr, hh, 2); @@ -358,7 +402,7 @@ shortenTime(char *buf, uint64_t t) static void showContexts(struct Vector *vec) { - uint64_t uptime = getUptime(); + uint64_t uptime = getUptime(); struct XidData const * ptr = Vector_begin_const(vec); struct XidData const * const end_ptr = Vector_end_const(vec); @@ -378,6 +422,7 @@ showContexts(struct Vector *vec) shortenMem (buf+17, ptr->VmRSS_total); shortenTime(buf+24, ptr->utime_total); shortenTime(buf+34, ptr->stime_total); + //printf("%llu, %llu\n", uptime, ptr->start_time_oldest); shortenTime(buf+44, uptime - ptr->start_time_oldest); switch (ptr->xid) { @@ -407,6 +452,7 @@ int main(int argc, char **argv) struct dirent* dir_entry; pid_t my_pid; struct Vector xid_data; + char const * errptr; if (argc==2) { if (strcmp(argv[1], "--help") ==0) showHelp(1, argv[0], 0); @@ -417,16 +463,16 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + if (hertz==0x42) initHertz(); + + //printf("hertz=%lu\n", hertz); // do not include own stat my_pid = getpid(); -#if 1 - // try to switch in context 1 - if (vc_get_task_xid(0)!=1) - Evc_new_s_context(1, 0,0); -#else -# warning Compiling in debug-code -#endif + if (!switchToWatchXid(&errptr)) { + perror(errptr); + exit(1); + } Vector_init(&xid_data, sizeof(struct XidData)); @@ -438,8 +484,11 @@ int main(int argc, char **argv) if (!isdigit(*dir_entry->d_name)) continue; - if (atoi(dir_entry->d_name) != my_pid) - registerXid(&xid_data, get_process_info(dir_entry->d_name)); + if (atoi(dir_entry->d_name) != my_pid) { + struct process_info * info = get_process_info(dir_entry->d_name); + if (info) + registerXid(&xid_data, info); + } } closedir(proc_dir);