mirror of
https://github.com/opnsense/src.git
synced 2026-06-14 19:20:18 -04:00
runq: runq_not_empty() to support racy lookups again
The 4BSD assumes that its sched_runnable(), which then calls
runq_not_empty(), can be called racily (another CPU may be grabbing
a thread from the global queue at the same time).
This makes runq_not_empty() trip on an assertion in runq_find()
detecting a mismatch between some bit in the status word and the state
of the corresponding queue (empty/not empty).
Re-implement runq_not_empty() in an independent and simpler way as an
alternative to removing the assertion, which remains useful to detect
races when removing or adding a thread in some runqueue.
Fixes: 79f68322c892 ("runq: runq_check(): Re-implement on top of runq_findq()")
MFC after: 1 month
Event: Kitchener-Waterloo Hackathon 202506
Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
3e5aeb2064
commit
be8e84c2e9
1 changed files with 15 additions and 8 deletions
|
|
@ -493,7 +493,7 @@ int
|
|||
runq_findq(struct runq *const rq, const int lvl_min, const int lvl_max,
|
||||
runq_pred_t *const pred, void *const pred_data)
|
||||
{
|
||||
rqsw_t const (*const rqsw)[RQSW_NB] = &rq->rq_status.rq_sw;
|
||||
const rqsw_t (*const rqsw)[RQSW_NB] = &rq->rq_status.rq_sw;
|
||||
rqsw_t w;
|
||||
int i, last, idx;
|
||||
|
||||
|
|
@ -568,20 +568,27 @@ runq_first_thread(struct runq *const rq)
|
|||
|
||||
/*
|
||||
* Return true if there are some processes of any priority on the run queue,
|
||||
* false otherwise. Has no side effects.
|
||||
* false otherwise. Has no side effects. Supports racy lookups (required by
|
||||
* 4BSD).
|
||||
*/
|
||||
bool
|
||||
runq_not_empty(struct runq *rq)
|
||||
{
|
||||
struct thread *const td = runq_first_thread(rq);
|
||||
const rqsw_t (*const rqsw)[RQSW_NB] = &rq->rq_status.rq_sw;
|
||||
int sw_idx;
|
||||
|
||||
if (td != NULL) {
|
||||
CTR2(KTR_RUNQ, "runq_not_empty: idx=%d, td=%p",
|
||||
td->td_rqindex, td);
|
||||
return (true);
|
||||
for (sw_idx = 0; sw_idx < RQSW_NB; ++sw_idx) {
|
||||
const rqsw_t w = (*rqsw)[sw_idx];
|
||||
|
||||
if (w != 0) {
|
||||
CTR3(KTR_RUNQ, "runq_not_empty: not empty; "
|
||||
"rq=%p, sw_idx=%d, bits=" RQSW_PRI,
|
||||
rq, sw_idx, w);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
CTR0(KTR_RUNQ, "runq_not_empty: empty");
|
||||
CTR1(KTR_RUNQ, "runq_not_empty: empty; rq=%p", rq);
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue