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
list_alloc(list_t * list,int size)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
list_free(list_t * list)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
get_cpu_from_psinfo(void * lwp)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
get_cpu_from_usage(void * lwp)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
get_time(void * lwp)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
get_size(void * lwp)84 get_size(void *lwp)
85 {
86 return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_size);
87 }
88
89 static ulong_t
get_rssize(void * lwp)90 get_rssize(void *lwp)
91 {
92 return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_rssize);
93 }
94
95 static ulong_t
get_pri(void * lwp)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
get_idkey(void * id)102 get_idkey(void *id)
103 {
104 return (((id_info_t *)id)->id_key);
105 }
106
107 void
list_setkeyfunc(char * arg,optdesc_t * opt,list_t * list,int type)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
list_getkeyval(list_t * list,void * ptr)146 list_getkeyval(list_t *list, void *ptr)
147 {
148 return (list->l_func(ptr));
149 }
150
151 static int
compare_keys(list_t * list,ulong_t key1,ulong_t key2)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
list_insert(list_t * list,void * ptr)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
list_preinsert(list_t * list,void * ptr)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
list_sort(list_t * list)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