1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<table class="head">
<tr>
<td class="head-ltitle">RUNQUEUE(9)</td>
<td class="head-vol">Kernel Developer's Manual</td>
<td class="head-rtitle">RUNQUEUE(9)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">choosethread</code>,
<code class="Nm">procrunnable</code>, <code class="Nm">remrunqueue</code>,
<code class="Nm">setrunqueue</code> — <span class="Nd">manage the
queue of runnable processes</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp"><code class="In">#include
<<a class="In">sys/param.h</a>></code>
<br/>
<code class="In">#include <<a class="In">sys/proc.h</a>></code></p>
<p class="Pp"><var class="Vt">extern struct rq itqueues[]</var>;
<br/>
<var class="Vt">extern struct rq rtqueues[]</var>;
<br/>
<var class="Vt">extern struct rq queues[]</var>;
<br/>
<var class="Vt">extern struct rq idqueues[]</var>;</p>
<p class="Pp"><var class="Ft">struct thread *</var>
<br/>
<code class="Fn">choosethread</code>(<var class="Fa" style="white-space: nowrap;">void</var>);</p>
<p class="Pp"><var class="Ft">int</var>
<br/>
<code class="Fn">procrunnable</code>(<var class="Fa" style="white-space: nowrap;">void</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">remrunqueue</code>(<var class="Fa" style="white-space: nowrap;">struct
thread *td</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">setrunqueue</code>(<var class="Fa" style="white-space: nowrap;">struct
thread *td</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">The run queue consists of four priority queues:
<var class="Va">itqueues</var> for interrupt threads,
<var class="Va">rtqueues</var> for realtime priority processes,
<var class="Va">queues</var> for time sharing processes, and
<var class="Va">idqueues</var> for idle priority processes. Each priority
queue consists of an array of <code class="Dv">NQS</code> queue header
structures. Each queue header identifies a list of runnable processes of
equal priority. Each queue also has a single word that contains a bit mask
identifying non-empty queues to assist in selecting a process quickly. These
are named <var class="Va">itqueuebits</var>,
<var class="Va">rtqueuebits</var>, <var class="Va">queuebits</var>, and
<var class="Va">idqueuebits</var>. The run queues are protected by the
<var class="Va">sched_lock</var> mutex.</p>
<p class="Pp" id="procrunnable"><a class="permalink" href="#procrunnable"><code class="Fn">procrunnable</code></a>()
returns zero if there are no runnable processes other than the idle process.
If there is at least one runnable process other than the idle process, it
will return a non-zero value. Note that the <var class="Va">sched_lock</var>
mutex does
<a class="permalink" href="#not"><i class="Em" id="not">not</i></a> need to
be held when this function is called. There is a small race window where one
CPU may place a process on the run queue when there are currently no other
runnable processes while another CPU is calling this function. In that case
the second CPU will simply travel through the idle loop one additional time
before noticing that there is a runnable process. This works because idle
CPUs are not halted in SMP systems. If idle CPUs are halted in SMP systems,
then this race condition might have more serious repercussions in the losing
case, and <code class="Fn">procrunnable</code>() may have to require that
the <var class="Va">sched_lock</var> mutex be acquired.</p>
<p class="Pp" id="choosethread"><a class="permalink" href="#choosethread"><code class="Fn">choosethread</code></a>()
returns the highest priority runnable thread. If there are no runnable
threads, then the idle thread is returned. This function is called by
<a class="permalink" href="#cpu_switch"><code class="Fn" id="cpu_switch">cpu_switch</code></a>()
and
<a class="permalink" href="#cpu_throw"><code class="Fn" id="cpu_throw">cpu_throw</code></a>()
to determine which thread to switch to.
<code class="Fn">choosethread</code>() must be called with the
<var class="Va">sched_lock</var> mutex held.</p>
<p class="Pp" id="setrunqueue"><a class="permalink" href="#setrunqueue"><code class="Fn">setrunqueue</code></a>()
adds the thread <var class="Fa">td</var> to the tail of the appropriate
queue in the proper priority queue. The thread must be runnable, i.e.
<var class="Va">p_stat</var> must be set to <code class="Dv">SRUN</code>.
This function must be called with the <var class="Va">sched_lock</var> mutex
held.</p>
<p class="Pp" id="remrunqueue"><a class="permalink" href="#remrunqueue"><code class="Fn">remrunqueue</code></a>()
removes thread <var class="Fa">td</var> from its run queue. If
<var class="Fa">td</var> is not on a run queue, then the kernel will
<a class="Xr">panic(9)</a>. This function must be called with the
<var class="Va">sched_lock</var> mutex held.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<p class="Pp"><a class="Xr">cpu_switch(9)</a>, <a class="Xr">scheduler(9)</a>,
<a class="Xr">sleepqueue(9)</a></p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">August 15, 2010</td>
<td class="foot-os">FreeBSD 15.0</td>
</tr>
</table>
|