17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*156d6b3aSJerry Jelinek * Copyright 2012 Joyent, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <libintl.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include "prstat.h" 347c478bd9Sstevel@tonic-gate #include "prutil.h" 357c478bd9Sstevel@tonic-gate #include "prsort.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate void 387c478bd9Sstevel@tonic-gate list_alloc(list_t *list, int size) 397c478bd9Sstevel@tonic-gate { 407c478bd9Sstevel@tonic-gate list->l_size = size; 41*156d6b3aSJerry Jelinek if (size > 0) 427c478bd9Sstevel@tonic-gate list->l_ptrs = Zalloc(sizeof (void *) * (size + 1)); 43*156d6b3aSJerry Jelinek else 44*156d6b3aSJerry Jelinek list->l_ptrs = NULL; 457c478bd9Sstevel@tonic-gate } 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate void 487c478bd9Sstevel@tonic-gate list_free(list_t *list) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate if (list && list->l_ptrs) { 517c478bd9Sstevel@tonic-gate free(list->l_ptrs); 527c478bd9Sstevel@tonic-gate list->l_ptrs = NULL; 537c478bd9Sstevel@tonic-gate } 547c478bd9Sstevel@tonic-gate } 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * Sorting routines 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate static ulong_t 607c478bd9Sstevel@tonic-gate get_cpu_from_psinfo(void *lwp) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate return ((ulong_t) 637c478bd9Sstevel@tonic-gate FRC2PCT((((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pctcpu)*1000)); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static ulong_t 677c478bd9Sstevel@tonic-gate get_cpu_from_usage(void *lwp) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate lwp_info_t *p = (lwp_info_t *)lwp; 707c478bd9Sstevel@tonic-gate float cpu = 0; 717c478bd9Sstevel@tonic-gate cpu += p->li_usr; 727c478bd9Sstevel@tonic-gate cpu += p->li_sys; 737c478bd9Sstevel@tonic-gate cpu *= 1000; 747c478bd9Sstevel@tonic-gate return ((ulong_t)cpu); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static ulong_t 787c478bd9Sstevel@tonic-gate get_time(void *lwp) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate return ((ulong_t)TIME2SEC(((lwp_info_t *)lwp)->li_info.pr_lwp.pr_time)); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate static ulong_t 847c478bd9Sstevel@tonic-gate get_size(void *lwp) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_size); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static ulong_t 907c478bd9Sstevel@tonic-gate get_rssize(void *lwp) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_rssize); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static ulong_t 967c478bd9Sstevel@tonic-gate get_pri(void *lwp) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pri); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static ulong_t 1027c478bd9Sstevel@tonic-gate get_idkey(void *id) 1037c478bd9Sstevel@tonic-gate { 1047c478bd9Sstevel@tonic-gate return (((id_info_t *)id)->id_key); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate void 1087c478bd9Sstevel@tonic-gate list_setkeyfunc(char *arg, optdesc_t *opt, list_t *list, int type) 1097c478bd9Sstevel@tonic-gate { 1107c478bd9Sstevel@tonic-gate if (list == NULL) 1117c478bd9Sstevel@tonic-gate return; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate list->l_sortorder = opt->o_sortorder; 1147c478bd9Sstevel@tonic-gate list->l_type = type; 1157c478bd9Sstevel@tonic-gate if (arg == NULL) { /* special case for id_infos */ 1167c478bd9Sstevel@tonic-gate list->l_func = get_idkey; 1177c478bd9Sstevel@tonic-gate return; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate if (strcmp("cpu", arg) == 0) { 1207c478bd9Sstevel@tonic-gate if (opt->o_outpmode & OPT_MSACCT) 1217c478bd9Sstevel@tonic-gate list->l_func = get_cpu_from_usage; 1227c478bd9Sstevel@tonic-gate else 1237c478bd9Sstevel@tonic-gate list->l_func = get_cpu_from_psinfo; 1247c478bd9Sstevel@tonic-gate return; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate if (strcmp("time", arg) == 0) { 1277c478bd9Sstevel@tonic-gate list->l_func = get_time; 1287c478bd9Sstevel@tonic-gate return; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate if (strcmp("size", arg) == 0) { 1317c478bd9Sstevel@tonic-gate list->l_func = get_size; 1327c478bd9Sstevel@tonic-gate return; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate if (strcmp("rss", arg) == 0) { 1357c478bd9Sstevel@tonic-gate list->l_func = get_rssize; 1367c478bd9Sstevel@tonic-gate return; 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate if (strcmp("pri", arg) == 0) { 1397c478bd9Sstevel@tonic-gate list->l_func = get_pri; 1407c478bd9Sstevel@tonic-gate return; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate Die(gettext("invalid sort key -- %s\n"), arg); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate ulong_t 1467c478bd9Sstevel@tonic-gate list_getkeyval(list_t *list, void *ptr) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate return (list->l_func(ptr)); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static int 1527c478bd9Sstevel@tonic-gate compare_keys(list_t *list, ulong_t key1, ulong_t key2) 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate if (key1 == key2) 1557c478bd9Sstevel@tonic-gate return (0); 1567c478bd9Sstevel@tonic-gate if (key1 < key2) 1577c478bd9Sstevel@tonic-gate return (1 * list->l_sortorder); 1587c478bd9Sstevel@tonic-gate else 1597c478bd9Sstevel@tonic-gate return (-1 * list->l_sortorder); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static void 1637c478bd9Sstevel@tonic-gate list_insert(list_t *list, void *ptr) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate int i, j; 1667c478bd9Sstevel@tonic-gate long k1, k2; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate for (i = 0; i < list->l_used; i++) { /* insert in the middle */ 1697c478bd9Sstevel@tonic-gate k1 = list_getkeyval(list, ptr); 1707c478bd9Sstevel@tonic-gate k2 = list_getkeyval(list, list->l_ptrs[i]); 1717c478bd9Sstevel@tonic-gate if (compare_keys(list, k1, k2) >= 0) { 1727c478bd9Sstevel@tonic-gate for (j = list->l_used - 1; j >= i; j--) 1737c478bd9Sstevel@tonic-gate list->l_ptrs[j+1] = list->l_ptrs[j]; 1747c478bd9Sstevel@tonic-gate list->l_ptrs[i] = ptr; 1757c478bd9Sstevel@tonic-gate if (list->l_used < list->l_size) 1767c478bd9Sstevel@tonic-gate list->l_used++; 1777c478bd9Sstevel@tonic-gate return; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate if (i + 1 <= list->l_size) { /* insert at the tail */ 1817c478bd9Sstevel@tonic-gate list->l_ptrs[list->l_used] = ptr; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate list->l_used++; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static void 1887c478bd9Sstevel@tonic-gate list_preinsert(list_t *list, void *ptr) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate ulong_t k1, k2; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (list->l_used < list->l_size) { /* just add */ 1937c478bd9Sstevel@tonic-gate list_insert(list, ptr); 1947c478bd9Sstevel@tonic-gate return; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate k1 = list_getkeyval(list, list->l_ptrs[list->l_used - 1]); 1977c478bd9Sstevel@tonic-gate k2 = list_getkeyval(list, ptr); 1987c478bd9Sstevel@tonic-gate if (compare_keys(list, k1, k2) >= 0) /* skip insertion */ 1997c478bd9Sstevel@tonic-gate return; 2007c478bd9Sstevel@tonic-gate k1 = list_getkeyval(list, list->l_ptrs[0]); 2017c478bd9Sstevel@tonic-gate if (compare_keys(list, k2, k1) >= 0) { /* add at the head */ 2027c478bd9Sstevel@tonic-gate list_insert(list, ptr); 2037c478bd9Sstevel@tonic-gate return; 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate list_insert(list, ptr); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate void 2097c478bd9Sstevel@tonic-gate list_sort(list_t *list) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate list->l_used = 0; 212*156d6b3aSJerry Jelinek if (list->l_size == 0) 213*156d6b3aSJerry Jelinek return; 214*156d6b3aSJerry Jelinek 215*156d6b3aSJerry Jelinek (void) memset(list->l_ptrs, 0, sizeof (void *) * list->l_size); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (list->l_type == LT_LWPS) { 2187c478bd9Sstevel@tonic-gate lwp_info_t *lwp = list->l_head; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate while (lwp) { 2217c478bd9Sstevel@tonic-gate list_preinsert(list, (void *)lwp); 2227c478bd9Sstevel@tonic-gate lwp = lwp->li_next; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate } else { 2257c478bd9Sstevel@tonic-gate id_info_t *id = list->l_head; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate while (id) { 2287c478bd9Sstevel@tonic-gate list_preinsert(list, (void *)id); 2297c478bd9Sstevel@tonic-gate id = id->id_next; 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 233