Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/procstat/procstat_rusage.c
/*- | /*- | ||||
* Copyright (c) 2012 Hudson River Trading LLC | * Copyright (c) 2012 Hudson River Trading LLC | ||||
* Written by: John H. Baldwin <jhb@FreeBSD.org> | * Written by: John H. Baldwin <jhb@FreeBSD.org> | ||||
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org> | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
Show All 18 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/user.h> | #include <sys/user.h> | ||||
#include <libprocstat.h> | #include <libprocstat.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | |||||
#include <libutil.h> | #include <libutil.h> | ||||
#include "procstat.h" | #include "procstat.h" | ||||
static struct { | static struct { | ||||
const char *ri_name; | const char *ri_name; | ||||
bool ri_humanize; | bool ri_humanize; | ||||
int ri_scale; | int ri_scale; | ||||
Show All 28 Lines | format_time(struct timeval *tv) | ||||
days = hours / 24; | days = hours / 24; | ||||
hours %= 24; | hours %= 24; | ||||
used = 0; | used = 0; | ||||
if (days == 1) | if (days == 1) | ||||
used += snprintf(buffer, sizeof(buffer), "1 day "); | used += snprintf(buffer, sizeof(buffer), "1 day "); | ||||
else if (days > 0) | else if (days > 0) | ||||
used += snprintf(buffer, sizeof(buffer), "%u days ", days); | used += snprintf(buffer, sizeof(buffer), "%u days ", days); | ||||
snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u ", | snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u", | ||||
hours, minutes, seconds, (unsigned int)tv->tv_usec); | hours, minutes, seconds, (unsigned int)tv->tv_usec); | ||||
return (buffer); | return (buffer); | ||||
} | } | ||||
static const char * | static const char * | ||||
format_value(long value, bool humanize, int scale) | format_value(long value, bool humanize, int scale) | ||||
{ | { | ||||
static char buffer[14]; | static char buffer[14]; | ||||
if (scale != 0) | if (scale != 0) | ||||
value <<= scale * 10; | value <<= scale * 10; | ||||
if (humanize) | if (humanize) | ||||
humanize_number(buffer, sizeof(buffer), value, "B", | humanize_number(buffer, sizeof(buffer), value, "B", | ||||
scale, HN_DECIMAL); | scale, HN_DECIMAL); | ||||
else | else | ||||
snprintf(buffer, sizeof(buffer), "%ld ", value); | snprintf(buffer, sizeof(buffer), "%ld ", value); | ||||
return (buffer); | return (buffer); | ||||
} | } | ||||
static void | static void | ||||
print_prefix(struct kinfo_proc *kipp) | print_prefix(struct kinfo_proc *kipp) | ||||
{ | { | ||||
printf("%5d ", kipp->ki_pid); | xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid); | ||||
if (Hflag) | if (Hflag) | ||||
printf("%6d ", kipp->ki_tid); | xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid); | ||||
printf("%-16s ", kipp->ki_comm); | xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm); | ||||
} | } | ||||
static void | static void | ||||
print_rusage(struct kinfo_proc *kipp) | print_rusage(struct kinfo_proc *kipp) | ||||
{ | { | ||||
long *lp; | long *lp; | ||||
unsigned int i; | unsigned int i; | ||||
char *field, *threadid; | |||||
print_prefix(kipp); | print_prefix(kipp); | ||||
printf("%-14s %32s\n", "user time", | xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "user time", | ||||
format_time(&kipp->ki_rusage.ru_utime)); | format_time(&kipp->ki_rusage.ru_utime)); | ||||
print_prefix(kipp); | print_prefix(kipp); | ||||
printf("%-14s %32s\n", "system time", | xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "system time", | ||||
format_time(&kipp->ki_rusage.ru_stime)); | format_time(&kipp->ki_rusage.ru_stime)); | ||||
if (Hflag) { | |||||
asprintf(&threadid, "%d", kipp->ki_tid); | |||||
xo_open_container(threadid); | |||||
xo_emit("{e:thread_id/%d}", kipp->ki_tid); | |||||
} else { | |||||
xo_emit("{e:process_id/%d}", kipp->ki_pid); | |||||
xo_emit("{e:command/%s}", kipp->ki_comm); | |||||
} | |||||
xo_emit("{e:user time/%s}", format_time(&kipp->ki_rusage.ru_utime)); | |||||
xo_emit("{e:system time/%s}", format_time(&kipp->ki_rusage.ru_stime)); | |||||
lp = &kipp->ki_rusage.ru_maxrss; | lp = &kipp->ki_rusage.ru_maxrss; | ||||
for (i = 0; i < nitems(rusage_info); i++) { | for (i = 0; i < nitems(rusage_info); i++) { | ||||
print_prefix(kipp); | print_prefix(kipp); | ||||
printf("%-32s %14s\n", rusage_info[i].ri_name, | asprintf(&field, "{e:%s/%%D}", rusage_info[i].ri_name); | ||||
xo_emit(field, *lp); | |||||
free(field); | |||||
xo_emit("{d:resource/%-32s} {d:usage/%14s}\n", rusage_info[i].ri_name, | |||||
format_value(*lp, rusage_info[i].ri_humanize, | format_value(*lp, rusage_info[i].ri_humanize, | ||||
rusage_info[i].ri_scale)); | rusage_info[i].ri_scale)); | ||||
lp++; | lp++; | ||||
} | } | ||||
if (Hflag) { | |||||
xo_close_container(threadid); | |||||
free(threadid); | |||||
} | } | ||||
} | |||||
void | void | ||||
procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp) | procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp) | ||||
{ | { | ||||
struct kinfo_proc *kip; | struct kinfo_proc *kip; | ||||
unsigned int count, i; | unsigned int count, i; | ||||
if (!hflag) { | if (!hflag) { | ||||
printf("%5s ", "PID"); | xo_emit("{d:ta/%5s} ", "PID"); | ||||
if (Hflag) | if (Hflag) | ||||
printf("%6s ", "TID"); | xo_emit("{d:tb/%6s} ", "TID"); | ||||
printf("%-16s %-32s %14s\n", "COMM", "RESOURCE", | xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE", | ||||
"VALUE "); | "VALUE "); | ||||
} | } | ||||
if (!Hflag) { | if (!Hflag) { | ||||
print_rusage(kipp); | print_rusage(kipp); | ||||
return; | return; | ||||
} | } | ||||
xo_emit("{e:process_id/%d}", kipp->ki_pid); | |||||
xo_emit("{e:command/%s}", kipp->ki_comm); | |||||
xo_open_container("threads"); | |||||
kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, | kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, | ||||
kipp->ki_pid, &count); | kipp->ki_pid, &count); | ||||
if (kip == NULL) | if (kip == NULL) | ||||
return; | return; | ||||
kinfo_proc_sort(kip, count); | kinfo_proc_sort(kip, count); | ||||
for (i = 0; i < count; i++) | for (i = 0; i < count; i++) { | ||||
print_rusage(&kip[i]); | print_rusage(&kip[i]); | ||||
} | |||||
xo_close_container("threads"); | |||||
procstat_freeprocs(procstat, kip); | procstat_freeprocs(procstat, kip); | ||||
} | } |