From 89dac0c95125ec71c62443ac315c05713c162c0e Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 14 Mar 2026 22:22:05 +0000 Subject: [PATCH] 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. --- include/kernel/thread.h | 5 ++++- sched/runqueue.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/kernel/thread.h b/include/kernel/thread.h index 619fe17..7608c62 100644 --- a/include/kernel/thread.h +++ b/include/kernel/thread.h @@ -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 { diff --git a/sched/runqueue.c b/sched/runqueue.c index ca076b3..38c6da9 100644 --- a/sched/runqueue.c +++ b/sched/runqueue.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #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--;