1266293Sjhb/*- 2266293Sjhb * Copyright (c) 2012 Advanced Computing Technologies LLC 3266293Sjhb * Written by: John H. Baldwin <jhb@FreeBSD.org> 4266293Sjhb * All rights reserved. 5266293Sjhb * 6266293Sjhb * Redistribution and use in source and binary forms, with or without 7266293Sjhb * modification, are permitted provided that the following conditions 8266293Sjhb * are met: 9266293Sjhb * 1. Redistributions of source code must retain the above copyright 10266293Sjhb * notice, this list of conditions and the following disclaimer. 11266293Sjhb * 2. Redistributions in binary form must reproduce the above copyright 12266293Sjhb * notice, this list of conditions and the following disclaimer in the 13266293Sjhb * documentation and/or other materials provided with the distribution. 14266293Sjhb * 15266293Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16266293Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17266293Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18266293Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19266293Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20266293Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21266293Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22266293Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23266293Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24266293Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25266293Sjhb * SUCH DAMAGE. 26266293Sjhb */ 27266293Sjhb 28266293Sjhb#include <sys/cdefs.h> 29266293Sjhb__FBSDID("$FreeBSD$"); 30266293Sjhb 31266293Sjhb#include <sys/param.h> 32266293Sjhb#include <sys/sysctl.h> 33266293Sjhb#include <sys/user.h> 34266293Sjhb 35266293Sjhb#include <libprocstat.h> 36266293Sjhb#include <stdbool.h> 37266293Sjhb#include <stdio.h> 38266293Sjhb#include <libutil.h> 39266293Sjhb 40266293Sjhb#include "procstat.h" 41266293Sjhb 42266293Sjhbstatic struct { 43266293Sjhb const char *ri_name; 44266293Sjhb bool ri_humanize; 45266293Sjhb int ri_scale; 46266293Sjhb} rusage_info[] = { 47266293Sjhb { "maximum RSS", true, 1 }, 48266293Sjhb { "integral shared memory", true, 1 }, 49266293Sjhb { "integral unshared data", true, 1 }, 50266293Sjhb { "integral unshared stack", true, 1 }, 51266293Sjhb { "page reclaims", false, 0 }, 52266293Sjhb { "page faults", false, 0 }, 53266293Sjhb { "swaps", false, 0 }, 54266293Sjhb { "block reads", false, 0 }, 55266293Sjhb { "block writes", false, 0 }, 56266293Sjhb { "messages sent", false, 0 }, 57266293Sjhb { "messages received", false, 0 }, 58266293Sjhb { "signals received", false, 0 }, 59266293Sjhb { "voluntary context switches", false, 0 }, 60266293Sjhb { "involuntary context switches", false, 0 } 61266293Sjhb}; 62266293Sjhb 63266293Sjhb/* xxx days hh:mm:ss.uuuuuu */ 64266293Sjhbstatic const char * 65266293Sjhbformat_time(struct timeval *tv) 66266293Sjhb{ 67266293Sjhb static char buffer[32]; 68266293Sjhb int days, hours, minutes, seconds, used; 69266293Sjhb 70266293Sjhb minutes = tv->tv_sec / 60; 71266293Sjhb seconds = tv->tv_sec % 60; 72266293Sjhb hours = minutes / 60; 73266293Sjhb minutes %= 60; 74266293Sjhb days = hours / 24; 75266293Sjhb hours %= 24; 76266293Sjhb used = 0; 77266293Sjhb if (days == 1) 78266293Sjhb used += snprintf(buffer, sizeof(buffer), "1 day "); 79266293Sjhb else if (days > 0) 80266293Sjhb used += snprintf(buffer, sizeof(buffer), "%u days ", days); 81266293Sjhb 82266293Sjhb snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u ", 83266293Sjhb hours, minutes, seconds, (unsigned int)tv->tv_usec); 84266293Sjhb return (buffer); 85266293Sjhb} 86266293Sjhb 87266293Sjhbstatic const char * 88266293Sjhbformat_value(long value, bool humanize, int scale) 89266293Sjhb{ 90266293Sjhb static char buffer[14]; 91266293Sjhb 92266293Sjhb if (scale != 0) 93266293Sjhb value <<= scale * 10; 94266293Sjhb if (humanize) 95266293Sjhb humanize_number(buffer, sizeof(buffer), value, "B", 96266293Sjhb scale, HN_DECIMAL); 97266293Sjhb else 98266293Sjhb snprintf(buffer, sizeof(buffer), "%ld ", value); 99266293Sjhb return (buffer); 100266293Sjhb} 101266293Sjhb 102266293Sjhbstatic void 103266293Sjhbprint_prefix(struct kinfo_proc *kipp) 104266293Sjhb{ 105266293Sjhb 106266293Sjhb printf("%5d ", kipp->ki_pid); 107266293Sjhb if (Hflag) 108266293Sjhb printf("%6d ", kipp->ki_tid); 109266293Sjhb printf("%-16s ", kipp->ki_comm); 110266293Sjhb} 111266293Sjhb 112266293Sjhbstatic void 113266293Sjhbprint_rusage(struct kinfo_proc *kipp) 114266293Sjhb{ 115266293Sjhb long *lp; 116266293Sjhb unsigned int i; 117266293Sjhb 118266293Sjhb print_prefix(kipp); 119266293Sjhb printf("%-14s %32s\n", "user time", 120266293Sjhb format_time(&kipp->ki_rusage.ru_utime)); 121266293Sjhb print_prefix(kipp); 122266293Sjhb printf("%-14s %32s\n", "system time", 123266293Sjhb format_time(&kipp->ki_rusage.ru_stime)); 124266293Sjhb lp = &kipp->ki_rusage.ru_maxrss; 125266293Sjhb for (i = 0; i < nitems(rusage_info); i++) { 126266293Sjhb print_prefix(kipp); 127266293Sjhb printf("%-32s %14s\n", rusage_info[i].ri_name, 128266293Sjhb format_value(*lp, rusage_info[i].ri_humanize, 129266293Sjhb rusage_info[i].ri_scale)); 130266293Sjhb lp++; 131266293Sjhb } 132266293Sjhb} 133266293Sjhb 134266293Sjhbvoid 135266293Sjhbprocstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp) 136266293Sjhb{ 137266293Sjhb struct kinfo_proc *kip; 138266293Sjhb unsigned int count, i; 139266293Sjhb 140266293Sjhb if (!hflag) { 141266293Sjhb printf("%5s ", "PID"); 142266293Sjhb if (Hflag) 143266293Sjhb printf("%6s ", "TID"); 144268108Sjhb printf("%-16s %-32s %14s\n", "COMM", "RESOURCE", 145268108Sjhb "VALUE "); 146266293Sjhb } 147266293Sjhb 148266293Sjhb if (!Hflag) { 149266293Sjhb print_rusage(kipp); 150266293Sjhb return; 151266293Sjhb } 152266293Sjhb 153266293Sjhb kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, 154266293Sjhb kipp->ki_pid, &count); 155266293Sjhb if (kip == NULL) 156266293Sjhb return; 157266293Sjhb kinfo_proc_sort(kip, count); 158266293Sjhb for (i = 0; i < count; i++) 159266293Sjhb print_rusage(&kip[i]); 160266293Sjhb procstat_freeprocs(procstat, kip); 161266293Sjhb} 162