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