git: 000ffb6f24c4 - stable/14 - runq: More macros; Better and more consistent naming
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 28 Jul 2025 13:31:13 UTC
The branch stable/14 has been updated by olce:
URL: https://cgit.FreeBSD.org/src/commit/?id=000ffb6f24c498bc665b887fafdd1bd4e96f598f
commit 000ffb6f24c498bc665b887fafdd1bd4e96f598f
Author: Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2024-04-23 11:33:02 +0000
Commit: Olivier Certner <olce@FreeBSD.org>
CommitDate: 2025-07-28 13:28:06 +0000
runq: More macros; Better and more consistent naming
Most existing macros have ambiguous names regarding which index they
operate on (queue, word, bit?), so have been renamed to improve clarity.
Use the 'RQSW_' prefix for all macros related to status words, and
change the status word type name accordingly.
Rename RQB_FFS() to RQSW_BSF() to remove confusion about the return
value (ffs*() return bit indices starting at 1, or 0 if the input is 0,
whereas BSF on x86 returns 0-based indices, which is what the current
code assumes). While here, add a check (under INVARIANTS) that
RQSW_BSF() isn't called with 0 as an argument.
Also, rename 'rqb_bits_t' to the more concise 'rqsw_t', 'struct rqbits'
to 'struct rq_status', its 'rqb_bits' field to 'rq_sw' (it designates an
array of words, not bits), and the type 'rqhead' to 'rq_queue'
Add macros computing a queue index from a status word index and a bit in
order to factorize code. If the precise index of the bit is known,
callers can use RQSW_TO_QUEUE_IDX() to get the corresponding queue
index, whereas if they want the one corresponding to the first
(least-significant): set bit in a given status word (corresponding to
the non-empty queue with lower index in the status word), they can use
RQSW_FIRST_QUEUE_IDX() instead.
Add RQSW_BIT_IDX(), which computes the correspond bit's index in the
corresponding status word. This allows more code factorization (even if
most uses will be eliminated in a later commit) and makes what is
computed clearer.
Reviewed by: kib
MFC after: 1 month
Event: Kitchener-Waterloo Hackathon 202506
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D45387
(cherry picked from commit 7e2502e3dec989ea31e5300ade759a721718548d)
---
sys/kern/kern_switch.c | 114 ++++++++++++++++++++++++-------------------------
sys/kern/sched_4bsd.c | 2 +-
sys/kern/sched_ule.c | 56 ++++++++++++------------
sys/sys/runq.h | 40 ++++++++++-------
4 files changed, 111 insertions(+), 101 deletions(-)
diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c
index 906efca4bb51..9e63709d0acc 100644
--- a/sys/kern/kern_switch.c
+++ b/sys/kern/kern_switch.c
@@ -281,15 +281,15 @@ runq_init(struct runq *rq)
static __inline void
runq_clrbit(struct runq *rq, int idx)
{
- struct rqbits *rqb;
+ struct rq_status *rqs;
CHECK_IDX(idx);
- rqb = &rq->rq_status;
+ rqs = &rq->rq_status;
CTR4(KTR_RUNQ, "runq_clrbit: bits=%#x %#x bit=%#x word=%d",
- rqb->rqb_bits[RQB_WORD(idx)],
- rqb->rqb_bits[RQB_WORD(idx)] & ~RQB_BIT(idx),
- RQB_BIT(idx), RQB_WORD(idx));
- rqb->rqb_bits[RQB_WORD(idx)] &= ~RQB_BIT(idx);
+ rqs->rq_sw[RQSW_IDX(idx)],
+ rqs->rq_sw[RQSW_IDX(idx)] & ~RQSW_BIT(idx),
+ RQSW_BIT(idx), RQSW_IDX(idx));
+ rqs->rq_sw[RQSW_IDX(idx)] &= ~RQSW_BIT(idx);
}
/*
@@ -299,16 +299,16 @@ runq_clrbit(struct runq *rq, int idx)
static __inline int
runq_findbit(struct runq *rq)
{
- struct rqbits *rqb;
+ struct rq_status *rqs;
int idx;
- rqb = &rq->rq_status;
- for (int i = 0; i < RQB_LEN; i++)
- if (rqb->rqb_bits[i] != 0) {
- idx = RQB_FFS(rqb->rqb_bits[i]) + i * RQB_BPW;
+ rqs = &rq->rq_status;
+ for (int i = 0; i < RQSW_NB; i++)
+ if (rqs->rq_sw[i] != 0) {
+ idx = RQSW_FIRST_QUEUE_IDX(i, rqs->rq_sw[i]);
CHECK_IDX(idx);
CTR3(KTR_RUNQ, "runq_findbit: bits=%#x i=%d idx=%d",
- rqb->rqb_bits[i], i, idx);
+ rqs->rq_sw[i], i, idx);
return (idx);
}
@@ -318,20 +318,20 @@ runq_findbit(struct runq *rq)
static __inline int
runq_findbit_from(struct runq *rq, int idx)
{
- struct rqbits *rqb;
- rqb_word_t mask;
+ struct rq_status *rqs;
+ rqsw_t mask;
int i;
CHECK_IDX(idx);
/* Set the mask for the first word so we ignore indices before 'idx'. */
- mask = (rqb_word_t)-1 << (idx & (RQB_BPW - 1));
- rqb = &rq->rq_status;
+ mask = (rqsw_t)-1 << RQSW_BIT_IDX(idx);
+ rqs = &rq->rq_status;
again:
- for (i = RQB_WORD(idx); i < RQB_LEN; mask = -1, i++) {
- mask = rqb->rqb_bits[i] & mask;
+ for (i = RQSW_IDX(idx); i < RQSW_NB; mask = -1, i++) {
+ mask = rqs->rq_sw[i] & mask;
if (mask == 0)
continue;
- idx = RQB_FFS(mask) + i * RQB_BPW;
+ idx = RQSW_FIRST_QUEUE_IDX(i, mask);
CTR3(KTR_RUNQ, "runq_findbit_from: bits=%#x i=%d idx=%d",
mask, i, idx);
return (idx);
@@ -353,15 +353,15 @@ again:
static __inline void
runq_setbit(struct runq *rq, int idx)
{
- struct rqbits *rqb;
+ struct rq_status *rqs;
CHECK_IDX(idx);
- rqb = &rq->rq_status;
+ rqs = &rq->rq_status;
CTR4(KTR_RUNQ, "runq_setbit: bits=%#x %#x bit=%#x word=%d",
- rqb->rqb_bits[RQB_WORD(idx)],
- rqb->rqb_bits[RQB_WORD(idx)] | RQB_BIT(idx),
- RQB_BIT(idx), RQB_WORD(idx));
- rqb->rqb_bits[RQB_WORD(idx)] |= RQB_BIT(idx);
+ rqs->rq_sw[RQSW_IDX(idx)],
+ rqs->rq_sw[RQSW_IDX(idx)] | RQSW_BIT(idx),
+ RQSW_BIT(idx), RQSW_IDX(idx));
+ rqs->rq_sw[RQSW_IDX(idx)] |= RQSW_BIT(idx);
}
/*
@@ -372,13 +372,13 @@ void
runq_add(struct runq *rq, struct thread *td, int flags)
{
- runq_add_idx(rq, td, RQ_PRI_TO_IDX(td->td_priority), flags);
+ runq_add_idx(rq, td, RQ_PRI_TO_QUEUE_IDX(td->td_priority), flags);
}
void
runq_add_idx(struct runq *rq, struct thread *td, int idx, int flags)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
/*
* runq_setbit() asserts 'idx' is non-negative and below 'RQ_NQS', and
@@ -387,13 +387,13 @@ runq_add_idx(struct runq *rq, struct thread *td, int idx, int flags)
*/
td->td_rqindex = idx;
runq_setbit(rq, idx);
- rqh = &rq->rq_queues[idx];
- CTR4(KTR_RUNQ, "runq_add_idx: td=%p pri=%d idx=%d rqh=%p",
- td, td->td_priority, idx, rqh);
+ rqq = &rq->rq_queues[idx];
+ CTR4(KTR_RUNQ, "runq_add_idx: td=%p pri=%d idx=%d rqq=%p",
+ td, td->td_priority, idx, rqq);
if (flags & SRQ_PREEMPTED)
- TAILQ_INSERT_HEAD(rqh, td, td_runq);
+ TAILQ_INSERT_HEAD(rqq, td, td_runq);
else
- TAILQ_INSERT_TAIL(rqh, td, td_runq);
+ TAILQ_INSERT_TAIL(rqq, td, td_runq);
}
/*
@@ -403,13 +403,13 @@ runq_add_idx(struct runq *rq, struct thread *td, int idx, int flags)
bool
runq_not_empty(struct runq *rq)
{
- struct rqbits *rqb;
+ struct rq_status *rqs;
- rqb = &rq->rq_status;
- for (int i = 0; i < RQB_LEN; i++)
- if (rqb->rqb_bits[i] != 0) {
+ rqs = &rq->rq_status;
+ for (int i = 0; i < RQSW_NB; i++)
+ if (rqs->rq_sw[i] != 0) {
CTR2(KTR_RUNQ, "runq_not_empty: bits=%#x i=%d",
- rqb->rqb_bits[i], i);
+ rqs->rq_sw[i], i);
return (true);
}
CTR0(KTR_RUNQ, "runq_not_empty: empty");
@@ -423,13 +423,13 @@ runq_not_empty(struct runq *rq)
struct thread *
runq_choose_fuzz(struct runq *rq, int fuzz)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
struct thread *td;
int idx;
idx = runq_findbit(rq);
if (idx != -1) {
- rqh = &rq->rq_queues[idx];
+ rqq = &rq->rq_queues[idx];
/* fuzz == 1 is normal.. 0 or less are ignored */
if (fuzz > 1) {
/*
@@ -439,7 +439,7 @@ runq_choose_fuzz(struct runq *rq, int fuzz)
int count = fuzz;
int cpu = PCPU_GET(cpuid);
struct thread *td2;
- td2 = td = TAILQ_FIRST(rqh);
+ td2 = td = TAILQ_FIRST(rqq);
while (count-- && td2) {
if (td2->td_lastcpu == cpu) {
@@ -449,10 +449,10 @@ runq_choose_fuzz(struct runq *rq, int fuzz)
td2 = TAILQ_NEXT(td2, td_runq);
}
} else
- td = TAILQ_FIRST(rqh);
+ td = TAILQ_FIRST(rqq);
KASSERT(td != NULL, ("runq_choose_fuzz: no proc on busy queue"));
CTR3(KTR_RUNQ,
- "runq_choose_fuzz: idx=%d thread=%p rqh=%p", idx, td, rqh);
+ "runq_choose_fuzz: idx=%d thread=%p rqq=%p", idx, td, rqq);
return (td);
}
CTR1(KTR_RUNQ, "runq_choose_fuzz: idleproc idx=%d", idx);
@@ -466,17 +466,17 @@ runq_choose_fuzz(struct runq *rq, int fuzz)
struct thread *
runq_choose(struct runq *rq)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
struct thread *td;
int idx;
idx = runq_findbit(rq);
if (idx != -1) {
- rqh = &rq->rq_queues[idx];
- td = TAILQ_FIRST(rqh);
+ rqq = &rq->rq_queues[idx];
+ td = TAILQ_FIRST(rqq);
KASSERT(td != NULL, ("runq_choose: no thread on busy queue"));
CTR3(KTR_RUNQ,
- "runq_choose: idx=%d thread=%p rqh=%p", idx, td, rqh);
+ "runq_choose: idx=%d thread=%p rqq=%p", idx, td, rqq);
return (td);
}
CTR1(KTR_RUNQ, "runq_choose: idlethread idx=%d", idx);
@@ -487,17 +487,17 @@ runq_choose(struct runq *rq)
struct thread *
runq_choose_from(struct runq *rq, int from_idx)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
struct thread *td;
int idx;
if ((idx = runq_findbit_from(rq, from_idx)) != -1) {
- rqh = &rq->rq_queues[idx];
- td = TAILQ_FIRST(rqh);
+ rqq = &rq->rq_queues[idx];
+ td = TAILQ_FIRST(rqq);
KASSERT(td != NULL, ("runq_choose: no thread on busy queue"));
CTR4(KTR_RUNQ,
- "runq_choose_from: idx=%d thread=%p idx=%d rqh=%p",
- idx, td, td->td_rqindex, rqh);
+ "runq_choose_from: idx=%d thread=%p idx=%d rqq=%p",
+ idx, td, td->td_rqindex, rqq);
return (td);
}
CTR1(KTR_RUNQ, "runq_choose_from: idlethread idx=%d", idx);
@@ -513,17 +513,17 @@ runq_choose_from(struct runq *rq, int from_idx)
bool
runq_remove(struct runq *rq, struct thread *td)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
int idx;
KASSERT(td->td_flags & TDF_INMEM, ("runq_remove: Thread swapped out"));
idx = td->td_rqindex;
CHECK_IDX(idx);
- rqh = &rq->rq_queues[idx];
- CTR4(KTR_RUNQ, "runq_remove: td=%p pri=%d idx=%d rqh=%p",
- td, td->td_priority, idx, rqh);
- TAILQ_REMOVE(rqh, td, td_runq);
- if (TAILQ_EMPTY(rqh)) {
+ rqq = &rq->rq_queues[idx];
+ CTR4(KTR_RUNQ, "runq_remove: td=%p pri=%d idx=%d rqq=%p",
+ td, td->td_priority, idx, rqq);
+ TAILQ_REMOVE(rqq, td, td_runq);
+ if (TAILQ_EMPTY(rqq)) {
runq_clrbit(rq, idx);
CTR1(KTR_RUNQ, "runq_remove: queue at idx=%d now empty", idx);
return (true);
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index c6b789d060c3..c204e4a5676e 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -873,7 +873,7 @@ sched_priority(struct thread *td, u_char prio)
if (td->td_priority == prio)
return;
td->td_priority = prio;
- if (TD_ON_RUNQ(td) && td->td_rqindex != RQ_PRI_TO_IDX(prio)) {
+ if (TD_ON_RUNQ(td) && td->td_rqindex != RQ_PRI_TO_QUEUE_IDX(prio)) {
sched_rem(td);
sched_add(td, SRQ_BORING | SRQ_HOLDTD);
}
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 13bef8ca9c1c..8fdc71c21e64 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -387,20 +387,20 @@ SDT_PROBE_DEFINE2(sched, , , surrender, "struct thread *",
static void
runq_print(struct runq *rq)
{
- struct rqhead *rqh;
+ struct rq_queue *rqq;
struct thread *td;
int pri;
int j;
int i;
- for (i = 0; i < RQB_LEN; i++) {
+ for (i = 0; i < RQSW_NB; i++) {
printf("\t\trunq bits %d 0x%zx\n",
- i, rq->rq_status.rqb_bits[i]);
- for (j = 0; j < RQB_BPW; j++)
- if (rq->rq_status.rqb_bits[i] & (1ul << j)) {
- pri = j + i * RQB_BPW;
- rqh = &rq->rq_queues[pri];
- TAILQ_FOREACH(td, rqh, td_runq) {
+ i, rq->rq_status.rq_sw[i]);
+ for (j = 0; j < RQSW_BPW; j++)
+ if (rq->rq_status.rq_sw[i] & (1ul << j)) {
+ pri = RQSW_TO_QUEUE_IDX(i, j);
+ rqq = &rq->rq_queues[pri];
+ TAILQ_FOREACH(td, rqq, td_runq) {
printf("\t\t\ttd %p(%s) priority %d rqindex %d pri %d\n",
td, td->td_name, td->td_priority,
td->td_rqindex, pri);
@@ -1190,26 +1190,26 @@ tdq_notify(struct tdq *tdq, int lowpri)
static struct thread *
runq_steal_from(struct runq *rq, int cpu, u_char start)
{
- struct rqbits *rqb;
- struct rqhead *rqh;
+ struct rq_status *rqs;
+ struct rq_queue *rqq;
struct thread *td, *first;
int bit;
int i;
- rqb = &rq->rq_status;
- bit = start & (RQB_BPW -1);
+ rqs = &rq->rq_status;
+ bit = RQSW_BIT_IDX(start);
first = NULL;
again:
- for (i = RQB_WORD(start); i < RQB_LEN; bit = 0, i++) {
- if (rqb->rqb_bits[i] == 0)
+ for (i = RQSW_IDX(start); i < RQSW_NB; bit = 0, i++) {
+ if (rqs->rq_sw[i] == 0)
continue;
if (bit == 0)
- bit = RQB_FFS(rqb->rqb_bits[i]);
- for (; bit < RQB_BPW; bit++) {
- if ((rqb->rqb_bits[i] & (1ul << bit)) == 0)
+ bit = RQSW_BSF(rqs->rq_sw[i]);
+ for (; bit < RQSW_BPW; bit++) {
+ if ((rqs->rq_sw[i] & (1ul << bit)) == 0)
continue;
- rqh = &rq->rq_queues[bit + i * RQB_BPW];
- TAILQ_FOREACH(td, rqh, td_runq) {
+ rqq = &rq->rq_queues[RQSW_TO_QUEUE_IDX(i, bit)];
+ TAILQ_FOREACH(td, rqq, td_runq) {
if (first) {
if (THREAD_CAN_MIGRATE(td) &&
THREAD_CAN_SCHED(td, cpu))
@@ -1236,21 +1236,21 @@ again:
static struct thread *
runq_steal(struct runq *rq, int cpu)
{
- struct rqhead *rqh;
- struct rqbits *rqb;
+ struct rq_queue *rqq;
+ struct rq_status *rqs;
struct thread *td;
int word;
int bit;
- rqb = &rq->rq_status;
- for (word = 0; word < RQB_LEN; word++) {
- if (rqb->rqb_bits[word] == 0)
+ rqs = &rq->rq_status;
+ for (word = 0; word < RQSW_NB; word++) {
+ if (rqs->rq_sw[word] == 0)
continue;
- for (bit = 0; bit < RQB_BPW; bit++) {
- if ((rqb->rqb_bits[word] & (1ul << bit)) == 0)
+ for (bit = 0; bit < RQSW_BPW; bit++) {
+ if ((rqs->rq_sw[word] & (1ul << bit)) == 0)
continue;
- rqh = &rq->rq_queues[bit + word * RQB_BPW];
- TAILQ_FOREACH(td, rqh, td_runq)
+ rqq = &rq->rq_queues[RQSW_TO_QUEUE_IDX(word, bit)];
+ TAILQ_FOREACH(td, rqq, td_runq)
if (THREAD_CAN_MIGRATE(td) &&
THREAD_CAN_SCHED(td, cpu))
return (td);
diff --git a/sys/sys/runq.h b/sys/sys/runq.h
index 030b4bb370a8..80a1fad0a089 100644
--- a/sys/sys/runq.h
+++ b/sys/sys/runq.h
@@ -47,16 +47,26 @@
/*
* Deduced from the above parameters and machine ones.
*/
-typedef unsigned long rqb_word_t; /* runq's status words type. */
-
#define RQ_NQS (howmany(RQ_MAX_PRIO + 1, RQ_PPQ)) /* Number of run queues. */
-#define RQ_PRI_TO_IDX(pri) ((pri) / RQ_PPQ) /* Priority to queue index. */
-
-#define RQB_BPW (sizeof(rqb_word_t) * NBBY) /* Bits per runq word. */
-#define RQB_LEN (howmany(RQ_NQS, RQB_BPW)) /* Words to cover RQ_NQS queues. */
-#define RQB_WORD(idx) ((idx) / RQB_BPW)
-#define RQB_BIT(idx) (1ul << ((idx) % RQB_BPW))
-#define RQB_FFS(word) (ffsl((long)(word)) - 1) /* Assumes two-complement. */
+#define RQ_PRI_TO_QUEUE_IDX(pri) ((pri) / RQ_PPQ) /* Priority to queue index. */
+
+typedef unsigned long rqsw_t; /* runq's status words type. */
+#define RQSW_BPW (sizeof(rqsw_t) * NBBY) /* Bits per runq word. */
+
+/* Number of status words to cover RQ_NQS queues. */
+#define RQSW_NB (howmany(RQ_NQS, RQSW_BPW))
+#define RQSW_IDX(idx) ((idx) / RQSW_BPW)
+#define RQSW_BIT_IDX(idx) ((idx) % RQSW_BPW)
+#define RQSW_BIT(idx) (1ul << RQSW_BIT_IDX(idx))
+#define RQSW_BSF(word) __extension__ ({ \
+ int _res = ffsl((long)(word)); /* Assumes two-complement. */ \
+ MPASS(_res > 0); \
+ _res - 1; \
+})
+#define RQSW_TO_QUEUE_IDX(word_idx, bit_idx) \
+ (((word_idx) * RQSW_BPW) + (bit_idx))
+#define RQSW_FIRST_QUEUE_IDX(word_idx, word) \
+ RQSW_TO_QUEUE_IDX(word_idx, RQSW_BSF(word))
#ifdef _KERNEL
@@ -66,16 +76,16 @@ typedef unsigned long rqb_word_t; /* runq's status words type. */
struct thread;
/*
- * Head of run queues.
+ * The queue for a given index as a list of threads.
*/
-TAILQ_HEAD(rqhead, thread);
+TAILQ_HEAD(rq_queue, thread);
/*
* Bit array which maintains the status of a run queue. When a queue is
* non-empty the bit corresponding to the queue number will be set.
*/
-struct rqbits {
- rqb_word_t rqb_bits[RQB_LEN];
+struct rq_status {
+ rqsw_t rq_sw[RQSW_NB];
};
/*
@@ -83,8 +93,8 @@ struct rqbits {
* are placed, and a structure to maintain the status of each queue.
*/
struct runq {
- struct rqbits rq_status;
- struct rqhead rq_queues[RQ_NQS];
+ struct rq_status rq_status;
+ struct rq_queue rq_queues[RQ_NQS];
};
void runq_add(struct runq *, struct thread *, int _flags);