xref: /illumos-gate/usr/src/cmd/prstat/prsort.c (revision f3041bfa)
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  * Copyright 2012 Joyent, Inc.  All rights reserved.
26  */
27 
28 #include <libintl.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 
33 #include "prstat.h"
34 #include "prutil.h"
35 #include "prsort.h"
36 
37 void
38 list_alloc(list_t *list, int size)
39 {
40 	list->l_size = size;
41 	if (size > 0)
42 		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
43 	else
44 		list->l_ptrs = NULL;
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 	list->l_used = 0;
212 	if (list->l_size == 0)
213 		return;
214 
215 	(void) memset(list->l_ptrs, 0, sizeof (void *) * list->l_size);
216 
217 	if (list->l_type == LT_LWPS) {
218 		lwp_info_t *lwp = list->l_head;
219 
220 		while (lwp) {
221 			list_preinsert(list, (void *)lwp);
222 			lwp = lwp->li_next;
223 		}
224 	} else {
225 		id_info_t *id = list->l_head;
226 
227 		while (id) {
228 			list_preinsert(list, (void *)id);
229 			id = id->id_next;
230 		}
231 	}
232 }
233