OpenSolaris_b135/cmd/prstat/prsort.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "prstat.h"
#include "prutil.h"
#include "prsort.h"

void
list_alloc(list_t *list, int size)
{
	if (size > 0) {
		list->l_size = size;
		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
	}
}

void
list_free(list_t *list)
{
	if (list && list->l_ptrs) {
		free(list->l_ptrs);
		list->l_ptrs = NULL;
	}
}

/*
 * Sorting routines
 */
static ulong_t
get_cpu_from_psinfo(void *lwp)
{
	return ((ulong_t)
	    FRC2PCT((((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pctcpu)*1000));
}

static ulong_t
get_cpu_from_usage(void *lwp)
{
	lwp_info_t *p = (lwp_info_t *)lwp;
	float cpu = 0;
	cpu += p->li_usr;
	cpu += p->li_sys;
	cpu *= 1000;
	return ((ulong_t)cpu);
}

static ulong_t
get_time(void *lwp)
{
	return ((ulong_t)TIME2SEC(((lwp_info_t *)lwp)->li_info.pr_lwp.pr_time));
}

static ulong_t
get_size(void *lwp)
{
	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_size);
}

static ulong_t
get_rssize(void *lwp)
{
	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_rssize);
}

static ulong_t
get_pri(void *lwp)
{
	return ((ulong_t)((lwp_info_t *)lwp)->li_info.pr_lwp.pr_pri);
}

static ulong_t
get_idkey(void *id)
{
	return (((id_info_t *)id)->id_key);
}

void
list_setkeyfunc(char *arg, optdesc_t *opt, list_t *list, int type)
{
	if (list == NULL)
		return;

	list->l_sortorder = opt->o_sortorder;
	list->l_type = type;
	if (arg == NULL) {	/* special case for id_infos */
		list->l_func = get_idkey;
		return;
	}
	if (strcmp("cpu", arg) == 0) {
		if (opt->o_outpmode & OPT_MSACCT)
			list->l_func = get_cpu_from_usage;
		else
			list->l_func = get_cpu_from_psinfo;
		return;
	}
	if (strcmp("time", arg) == 0) {
		list->l_func = get_time;
		return;
	}
	if (strcmp("size", arg) == 0) {
		list->l_func = get_size;
		return;
	}
	if (strcmp("rss", arg) == 0) {
		list->l_func = get_rssize;
		return;
	}
	if (strcmp("pri", arg) == 0) {
		list->l_func = get_pri;
		return;
	}
	Die(gettext("invalid sort key -- %s\n"), arg);
}

ulong_t
list_getkeyval(list_t *list, void *ptr)
{
	return (list->l_func(ptr));
}

static int
compare_keys(list_t *list, ulong_t key1, ulong_t key2)
{
	if (key1 == key2)
		return (0);
	if (key1 < key2)
		return (1 * list->l_sortorder);
	else
		return (-1 * list->l_sortorder);
}

static void
list_insert(list_t *list, void *ptr)
{
	int i, j;
	long k1, k2;

	for (i = 0; i < list->l_used; i++) {	/* insert in the middle */
		k1 = list_getkeyval(list, ptr);
		k2 = list_getkeyval(list, list->l_ptrs[i]);
		if (compare_keys(list, k1, k2) >= 0) {
			for (j = list->l_used - 1; j >= i; j--)
				list->l_ptrs[j+1] = list->l_ptrs[j];
			list->l_ptrs[i] = ptr;
			if (list->l_used < list->l_size)
				list->l_used++;
			return;
		}
	}
	if (i + 1 <= list->l_size) {		/* insert at the tail */
		list->l_ptrs[list->l_used] = ptr;

		list->l_used++;
	}
}

static void
list_preinsert(list_t *list, void *ptr)
{
	ulong_t	k1, k2;

	if (list->l_used < list->l_size) {	/* just add */
		list_insert(list, ptr);
		return;
	}
	k1 = list_getkeyval(list, list->l_ptrs[list->l_used - 1]);
	k2 = list_getkeyval(list, ptr);
	if (compare_keys(list, k1, k2) >= 0)	/* skip insertion */
		return;
	k1 = list_getkeyval(list, list->l_ptrs[0]);
	if (compare_keys(list, k2, k1) >= 0) {	/* add at the head */
		list_insert(list, ptr);
		return;
	}
	list_insert(list, ptr);
}

void
list_sort(list_t *list)
{
	(void) memset(list->l_ptrs, 0, sizeof (void *) * list->l_size);
	list->l_used = 0;

	if (list->l_type == LT_LWPS) {
		lwp_info_t *lwp = list->l_head;

		while (lwp) {
			list_preinsert(list, (void *)lwp);
			lwp = lwp->li_next;
		}
	} else {
		id_info_t *id = list->l_head;

		while (id) {
			list_preinsert(list, (void *)id);
			id = id->id_next;
		}
	}
}