sched: add a thread flag to indicate when a thread is scheduled on a runqueue

this prevents runqueue corruption that can occur if rq_enqueue is called on
a thread that's already on a runqueue.
This commit is contained in:
2026-03-14 22:22:05 +00:00
parent 7c630ece54
commit 89dac0c951
2 changed files with 19 additions and 1 deletions

View File

@@ -14,8 +14,11 @@ enum thread_state {
};
enum thread_flags {
/* this thread has exhausted its quantum and is due to be re-scheduled.
*/
THREAD_F_NEED_RESCHED = 0x01u,
THREAD_F_NO_PREEMPT = 0x02u,
/* this thread is currently scheduled (i.e. is present on a runqueue) */
THREAD_F_SCHEDULED = 0x04u,
};
struct thread {

View File

@@ -1,6 +1,7 @@
#include <kernel/cpu.h>
#include <kernel/percpu.h>
#include <kernel/sched.h>
#include <kernel/task.h>
#include <kernel/thread.h>
#define PRIO_MASK(p) (((uint32_t)1) << (p))
@@ -20,6 +21,7 @@ struct thread *rq_dequeue(struct runqueue *rq)
}
struct queue *q = &rq->rq_queues[prio];
struct queue_entry *qe = queue_pop_front(q);
if (!qe) {
rq->rq_readybits &= ~PRIO_MASK(prio);
@@ -27,6 +29,7 @@ struct thread *rq_dequeue(struct runqueue *rq)
}
struct thread *thr = QUEUE_CONTAINER(struct thread, tr_rqentry, qe);
thr->tr_flags &= ~THREAD_F_SCHEDULED;
if (rq->rq_nthreads > 0) {
rq->rq_nthreads--;
@@ -41,17 +44,24 @@ struct thread *rq_dequeue(struct runqueue *rq)
void rq_enqueue(struct runqueue *rq, struct thread *thr)
{
if (thr->tr_flags & THREAD_F_SCHEDULED) {
return;
}
int prio = thread_priority(thr);
if (prio < 0 || prio > PRIO_MAX) {
return;
}
struct queue *q = &rq->rq_queues[prio];
queue_push_back(q, &thr->tr_rqentry);
rq->rq_nthreads++;
rq->rq_readybits |= PRIO_MASK(thread_priority(thr));
thr->tr_rq = rq;
thr->tr_flags |= THREAD_F_SCHEDULED;
}
struct runqueue *cpu_rq(unsigned int cpu)
@@ -65,6 +75,10 @@ struct runqueue *cpu_rq(unsigned int cpu)
void rq_remove_thread(struct runqueue *rq, struct thread *thr)
{
if (!(thr->tr_flags & THREAD_F_SCHEDULED)) {
return;
}
int prio = thread_priority(thr);
if (prio < 0 || prio > PRIO_MAX) {
return;
@@ -72,6 +86,7 @@ void rq_remove_thread(struct runqueue *rq, struct thread *thr)
struct queue *q = &rq->rq_queues[prio];
queue_delete(q, &thr->tr_rqentry);
thr->tr_flags &= ~THREAD_F_SCHEDULED;
if (rq->rq_nthreads > 0) {
rq->rq_nthreads--;