sched: schedule() no longer switches threads when preempt_count > 0

This commit is contained in:
2023-05-01 08:27:18 +01:00
parent 40762ffb95
commit fbbe339f72

View File

@@ -70,6 +70,8 @@ void context_switch(struct thread *old, struct thread *new)
void __schedule(enum sched_mode mode) void __schedule(enum sched_mode mode)
{ {
ml_int_disable();
struct cpu_data *this_cpu = get_this_cpu(); struct cpu_data *this_cpu = get_this_cpu();
struct runqueue *rq = &this_cpu->c_rq; struct runqueue *rq = &this_cpu->c_rq;
@@ -78,6 +80,10 @@ void __schedule(enum sched_mode mode)
unsigned long flags; unsigned long flags;
rq_lock(rq, &flags); rq_lock(rq, &flags);
/* subtrace one to compensate for the fact that get_this_cpu()
increases preempt_count */
int preempt = READ_ONCE(this_cpu->c_preempt_count) - 1;
put_cpu(this_cpu); put_cpu(this_cpu);
struct thread *prev = rq->rq_cur; struct thread *prev = rq->rq_cur;
@@ -86,6 +92,11 @@ void __schedule(enum sched_mode mode)
prev->tr_quantum_cycles = 0; prev->tr_quantum_cycles = 0;
} }
if (preempt > 0) {
rq_unlock(rq, flags);
return;
}
enum thread_state prev_state = READ_ONCE(prev->tr_state); enum thread_state prev_state = READ_ONCE(prev->tr_state);
if ((mode == SCHED_IRQ || prev_state == THREAD_READY) && prev != rq->rq_idle) { if ((mode == SCHED_IRQ || prev_state == THREAD_READY) && prev != rq->rq_idle) {
@@ -108,6 +119,8 @@ void __schedule(enum sched_mode mode)
if (prev != next) { if (prev != next) {
context_switch(prev, next); context_switch(prev, next);
} }
ml_int_enable();
} }
void schedule(enum sched_mode mode) void schedule(enum sched_mode mode)