Home | History | Annotate | Download | only in prstat
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <libintl.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <strings.h>
     33 
     34 #include "prstat.h"
     35 #include "prutil.h"
     36 #include "prsort.h"
     37 
     38 void
     39 list_alloc(list_t *list, int size)
     40 {
     41 	if (size > 0) {
     42 		list->l_size = size;
     43 		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
     44 	}
     45 }
     46 
     47 void
     48 list_free(list_t *list)
     49 {
     50 	if (list && list->l_ptrs) {
     51 		free(list->l_ptrs);
     52 		list->l_ptrs = NULL;
     53 	}
     54 }
     55 
     56 /*
     57  * Sorting routines
     58  */
     59 static ulong_t
     60 get_cpu_from_psinfo(void *lwp)
     61 {
     62 	return ((ulong_t)
     63 	    FRC2PCT((((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pctcpu)*1000));
     64 }
     65 
     66 static ulong_t
     67 get_cpu_from_usage(void *lwp)
     68 {
     69 	lwp_info_t *p = (lwp_info_t *)lwp;
     70 	float cpu = 0;
     71 	cpu += p->li_usr;
     72 	cpu += p->li_sys;
     73 	cpu *= 1000;
     74 	return ((ulong_t)cpu);
     75 }
     76 
     77 static ulong_t
     78 get_time(void *lwp)
     79 {
     80 	return ((ulong_t)TIME2SEC(((lwp_info_t *)lwp)->li_info.pr_lwp.pr_time));
     81 }
     82 
     83 static ulong_t
     84 get_size(void *lwp)
     85 {
     86 	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_size);
     87 }
     88 
     89 static ulong_t
     90 get_rssize(void *lwp)
     91 {
     92 	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_rssize);
     93 }
     94 
     95 static ulong_t
     96 get_pri(void *lwp)
     97 {
     98 	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pri);
     99 }
    100 
    101 static ulong_t
    102 get_idkey(void *id)
    103 {
    104 	return (((id_info_t *)id)->id_key);
    105 }
    106 
    107 void
    108 list_setkeyfunc(char *arg, optdesc_t *opt, list_t *list, int type)
    109 {
    110 	if (list == NULL)
    111 		return;
    112 
    113 	list->l_sortorder = opt->o_sortorder;
    114 	list->l_type = type;
    115 	if (arg == NULL) {	/* special case for id_infos */
    116 		list->l_func = get_idkey;
    117 		return;
    118 	}
    119 	if (strcmp("cpu", arg) == 0) {
    120 		if (opt->o_outpmode & OPT_MSACCT)
    121 			list->l_func = get_cpu_from_usage;
    122 		else
    123 			list->l_func = get_cpu_from_psinfo;
    124 		return;
    125 	}
    126 	if (strcmp("time", arg) == 0) {
    127 		list->l_func = get_time;
    128 		return;
    129 	}
    130 	if (strcmp("size", arg) == 0) {
    131 		list->l_func = get_size;
    132 		return;
    133 	}
    134 	if (strcmp("rss", arg) == 0) {
    135 		list->l_func = get_rssize;
    136 		return;
    137 	}
    138 	if (strcmp("pri", arg) == 0) {
    139 		list->l_func = get_pri;
    140 		return;
    141 	}
    142 	Die(gettext("invalid sort key -- %s\n"), arg);
    143 }
    144 
    145 ulong_t
    146 list_getkeyval(list_t *list, void *ptr)
    147 {
    148 	return (list->l_func(ptr));
    149 }
    150 
    151 static int
    152 compare_keys(list_t *list, ulong_t key1, ulong_t key2)
    153 {
    154 	if (key1 == key2)
    155 		return (0);
    156 	if (key1 < key2)
    157 		return (1 * list->l_sortorder);
    158 	else
    159 		return (-1 * list->l_sortorder);
    160 }
    161 
    162 static void
    163 list_insert(list_t *list, void *ptr)
    164 {
    165 	int i, j;
    166 	long k1, k2;
    167 
    168 	for (i = 0; i < list->l_used; i++) {	/* insert in the middle */
    169 		k1 = list_getkeyval(list, ptr);
    170 		k2 = list_getkeyval(list, list->l_ptrs[i]);
    171 		if (compare_keys(list, k1, k2) >= 0) {
    172 			for (j = list->l_used - 1; j >= i; j--)
    173 				list->l_ptrs[j+1] = list->l_ptrs[j];
    174 			list->l_ptrs[i] = ptr;
    175 			if (list->l_used < list->l_size)
    176 				list->l_used++;
    177 			return;
    178 		}
    179 	}
    180 	if (i + 1 <= list->l_size) {		/* insert at the tail */
    181 		list->l_ptrs[list->l_used] = ptr;
    182 
    183 		list->l_used++;
    184 	}
    185 }
    186 
    187 static void
    188 list_preinsert(list_t *list, void *ptr)
    189 {
    190 	ulong_t	k1, k2;
    191 
    192 	if (list->l_used < list->l_size) {	/* just add */
    193 		list_insert(list, ptr);
    194 		return;
    195 	}
    196 	k1 = list_getkeyval(list, list->l_ptrs[list->l_used - 1]);
    197 	k2 = list_getkeyval(list, ptr);
    198 	if (compare_keys(list, k1, k2) >= 0)	/* skip insertion */
    199 		return;
    200 	k1 = list_getkeyval(list, list->l_ptrs[0]);
    201 	if (compare_keys(list, k2, k1) >= 0) {	/* add at the head */
    202 		list_insert(list, ptr);
    203 		return;
    204 	}
    205 	list_insert(list, ptr);
    206 }
    207 
    208 void
    209 list_sort(list_t *list)
    210 {
    211 	(void) memset(list->l_ptrs, 0, sizeof (void *) * list->l_size);
    212 	list->l_used = 0;
    213 
    214 	if (list->l_type == LT_LWPS) {
    215 		lwp_info_t *lwp = list->l_head;
    216 
    217 		while (lwp) {
    218 			list_preinsert(list, (void *)lwp);
    219 			lwp = lwp->li_next;
    220 		}
    221 	} else {
    222 		id_info_t *id = list->l_head;
    223 
    224 		while (id) {
    225 			list_preinsert(list, (void *)id);
    226 			id = id->id_next;
    227 		}
    228 	}
    229 }
    230