kernel/sched: Don't touch deadline values on queued threads
k_thread_deadline_set() would modify the thread's deadline and then, if it was in the run queue, requeue it to put it at the right spot. Sounds right, right? It's wrong. The deadline field is part of the thread priority, so this results in a mis-ordered list. For dlist backends, that's benign as the removal works anyway, but if CONFIG_SCHED_SCALABLE=y we've now broken the sorting order of an in-tree item and corrupted the rbtree! Fixes #69935 Signed-off-by: Andy Ross <andyross@google.com>
This commit is contained in:
parent
238b9be5ee
commit
f2280d119d
|
@ -1280,12 +1280,21 @@ static inline void z_vrfy_k_thread_priority_set(k_tid_t thread, int prio)
|
|||
void z_impl_k_thread_deadline_set(k_tid_t tid, int deadline)
|
||||
{
|
||||
struct k_thread *thread = tid;
|
||||
int32_t newdl = k_cycle_get_32() + deadline;
|
||||
|
||||
/* The prio_deadline field changes the sorting order, so can't
|
||||
* change it while the thread is in the run queue (dlists
|
||||
* actually are benign as long as we requeue it before we
|
||||
* release the lock, but an rbtree will blow up if we break
|
||||
* sorting!)
|
||||
*/
|
||||
K_SPINLOCK(&_sched_spinlock) {
|
||||
thread->base.prio_deadline = k_cycle_get_32() + deadline;
|
||||
if (z_is_thread_queued(thread)) {
|
||||
dequeue_thread(thread);
|
||||
thread->base.prio_deadline = newdl;
|
||||
queue_thread(thread);
|
||||
} else {
|
||||
thread->base.prio_deadline = newdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue