Home | History | Annotate | Line # | Download | only in libutil
proc_compare.c revision 1.1.44.3
      1  1.1.44.3    martin /*	$NetBSD: proc_compare.c,v 1.1.44.3 2020/04/21 19:37:51 martin Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*-
      4       1.1  christos  * Copyright (c) 1990, 1993
      5       1.1  christos  *	The Regents of the University of California.  All rights reserved.
      6       1.1  christos  *
      7       1.1  christos  * Redistribution and use in source and binary forms, with or without
      8       1.1  christos  * modification, are permitted provided that the following conditions
      9       1.1  christos  * are met:
     10       1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11       1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12       1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14       1.1  christos  *    documentation and/or other materials provided with the distribution.
     15       1.1  christos  * 3. Neither the name of the University nor the names of its contributors
     16       1.1  christos  *    may be used to endorse or promote products derived from this software
     17       1.1  christos  *    without specific prior written permission.
     18       1.1  christos  *
     19       1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1  christos  * SUCH DAMAGE.
     30       1.1  christos  */
     31       1.1  christos #ifndef _STANDALONE
     32       1.1  christos # ifndef _KERNEL
     33       1.1  christos 
     34       1.1  christos #  if HAVE_NBTOOL_CONFIG_H
     35       1.1  christos #   include "nbtool_config.h"
     36       1.1  christos #  endif
     37       1.1  christos 
     38       1.1  christos #  include <sys/cdefs.h>
     39       1.1  christos #  if defined(LIBC_SCCS) && !defined(lint)
     40  1.1.44.3    martin __RCSID("$NetBSD: proc_compare.c,v 1.1.44.3 2020/04/21 19:37:51 martin Exp $");
     41       1.1  christos #  endif
     42       1.1  christos 
     43       1.1  christos #  include <sys/types.h>
     44       1.1  christos #  include <sys/inttypes.h>
     45       1.1  christos #  include <sys/sysctl.h>
     46       1.1  christos #  include <stdio.h>
     47       1.1  christos #  include <util.h>
     48       1.1  christos #  include <errno.h>
     49       1.1  christos #  define PROC		struct kinfo_proc2
     50       1.1  christos #  define LWP		struct kinfo_lwp
     51       1.1  christos #  define P_RTIME_SEC	p_rtime_sec
     52       1.1  christos #  define P_RTIME_USEC	p_rtime_usec
     53       1.1  christos # else
     54       1.1  christos #  include <sys/cdefs.h>
     55  1.1.44.3    martin __KERNEL_RCSID(0, "$NetBSD: proc_compare.c,v 1.1.44.3 2020/04/21 19:37:51 martin Exp $");
     56       1.1  christos #  include <sys/param.h>
     57       1.1  christos #  include <sys/inttypes.h>
     58       1.1  christos #  include <sys/systm.h>
     59       1.1  christos #  include <sys/proc.h>
     60       1.1  christos #  include <sys/lwp.h>
     61       1.1  christos #  include <lib/libkern/libkern.h>
     62       1.1  christos #  define PROC		struct proc
     63       1.1  christos #  define LWP		struct lwp
     64       1.1  christos #  define P_RTIME_SEC	p_rtime.sec
     65       1.1  christos #  define P_RTIME_USEC	p_rtime.frac
     66       1.1  christos # endif
     67       1.1  christos /*
     68       1.1  christos  * Returns 1 if p2 is "better" than p1
     69       1.1  christos  *
     70       1.1  christos  * The algorithm for picking the "interesting" process is thus:
     71       1.1  christos  *
     72       1.1  christos  *	1) Only foreground processes are eligible - implied.
     73       1.1  christos  *	2) Runnable processes are favored over anything else.  The runner
     74       1.1  christos  *	   with the highest CPU utilization is picked (l_pctcpu).  Ties are
     75       1.1  christos  *	   broken by picking the highest pid.
     76       1.1  christos  *	3) The sleeper with the shortest sleep time is next.  With ties,
     77       1.1  christos  *	   we pick out just "short-term" sleepers (P_SINTR == 0).
     78       1.1  christos  *	4) Further ties are broken by picking the one started last.
     79       1.1  christos  *	5) Finally the one with the biggest pid wins, but that is nonsense
     80       1.1  christos  *	   because of pid randomization.
     81       1.1  christos  */
     82       1.1  christos #define	ISRUN(p)	((p)->p_nrlwps > 0)
     83       1.1  christos #define	TESTAB(a, b)	(((a) << 1) | (b))
     84       1.1  christos #define	ONLYA	2
     85       1.1  christos #define	ONLYB	1
     86       1.1  christos #define	BOTH	3
     87       1.1  christos 
     88       1.1  christos int
     89       1.1  christos proc_compare(const PROC *p1, const LWP *l1, const PROC *p2, const LWP *l2)
     90       1.1  christos {
     91       1.1  christos 	/*
     92  1.1.44.1    martin  	 * weed out zombies
     93  1.1.44.1    martin 	 */
     94  1.1.44.1    martin 	switch (TESTAB(P_ZOMBIE(p1), P_ZOMBIE(p2))) {
     95  1.1.44.1    martin 	case ONLYA:
     96  1.1.44.1    martin 		return 1;
     97  1.1.44.1    martin 	case ONLYB:
     98  1.1.44.1    martin 		return 0;
     99  1.1.44.1    martin 	case BOTH:
    100  1.1.44.1    martin 		goto out;
    101  1.1.44.1    martin 	}
    102  1.1.44.1    martin 	/*
    103       1.1  christos 	 * see if at least one of them is runnable
    104       1.1  christos 	 */
    105       1.1  christos 	switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
    106       1.1  christos 	case ONLYA:
    107       1.1  christos 		return 0;
    108       1.1  christos 	case ONLYB:
    109       1.1  christos 		return 1;
    110       1.1  christos 	case BOTH:
    111       1.1  christos 		/*
    112       1.1  christos 		 * tie - favor one with highest recent CPU utilization
    113       1.1  christos 		 */
    114       1.1  christos 		if (l2->l_pctcpu > l1->l_pctcpu)
    115       1.1  christos 			return 1;
    116       1.1  christos 		goto out;
    117       1.1  christos 	}
    118       1.1  christos 	/*
    119       1.1  christos 	 * pick the one with the smallest sleep time
    120       1.1  christos 	 */
    121       1.1  christos 	if (l1->l_slptime < l2->l_slptime)
    122       1.1  christos 		return 0;
    123       1.1  christos 	if (l2->l_slptime < l1->l_slptime)
    124       1.1  christos 		return 1;
    125       1.1  christos 
    126       1.1  christos 	/*
    127       1.1  christos 	 * favor one sleeping in a non-interruptible sleep
    128       1.1  christos 	 */
    129       1.1  christos 	if ((l1->l_flag & LW_SINTR) && (l2->l_flag & LW_SINTR) == 0)
    130       1.1  christos 		return 0;
    131       1.1  christos 	if ((l2->l_flag & LW_SINTR) && (l1->l_flag & LW_SINTR) == 0)
    132       1.1  christos 		return 1;
    133       1.1  christos out:
    134       1.1  christos 	/* tie, return the one with the smallest realtime */
    135       1.1  christos 	if (p1->P_RTIME_SEC < p2->P_RTIME_SEC)
    136       1.1  christos 		return 0;
    137       1.1  christos 	if (p2->P_RTIME_SEC < p1->P_RTIME_SEC)
    138       1.1  christos 		return 1;
    139       1.1  christos 	if (p1->P_RTIME_USEC < p2->P_RTIME_USEC)
    140       1.1  christos 		return 0;
    141       1.1  christos 	if (p2->P_RTIME_USEC < p1->P_RTIME_USEC)
    142       1.1  christos 		return 1;
    143  1.1.44.1    martin 
    144       1.1  christos 	return p2->p_pid > p1->p_pid;	/* Nonsense */
    145       1.1  christos }
    146       1.1  christos #endif /* STANDALONE */
    147