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