mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-02 07:28:21 +00:00
scheduler: make idle cpus steal work
This commit is contained in:
@@ -58,6 +58,7 @@ thread_t *sched_select_next_thread(void);
|
|||||||
void sched_insert_in_cpu_queue(struct cpu_t *cpu, thread_t *thread);
|
void sched_insert_in_cpu_queue(struct cpu_t *cpu, thread_t *thread);
|
||||||
void sched_preempt_cpu(struct cpu_t *cpu);
|
void sched_preempt_cpu(struct cpu_t *cpu);
|
||||||
thread_t *sched_steal_work_from_cpu(struct cpu_t *cpu);
|
thread_t *sched_steal_work_from_cpu(struct cpu_t *cpu);
|
||||||
|
bool sched_idle_steal_work(void);
|
||||||
|
|
||||||
static inline int sched_thread_run_queue_index(int interactivity) {
|
static inline int sched_thread_run_queue_index(int interactivity) {
|
||||||
return min(interactivity * SCHED_RUN_QUEUE_SIZE / SCHED_MAX_INTERACTIVITY, SCHED_RUN_QUEUE_SIZE - 1);
|
return min(interactivity * SCHED_RUN_QUEUE_SIZE / SCHED_MAX_INTERACTIVITY, SCHED_RUN_QUEUE_SIZE - 1);
|
||||||
|
|||||||
@@ -195,11 +195,61 @@ thread_t *sched_steal_work_from_cpu(cpu_t *cpu) {
|
|||||||
thread = steal_from_run_queue(&cpu->idle_queue);
|
thread = steal_from_run_queue(&cpu->idle_queue);
|
||||||
found:
|
found:
|
||||||
|
|
||||||
|
if (thread == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
--cpu->thread_count;
|
--cpu->thread_count;
|
||||||
--cpu->stealable_thread_count;
|
--cpu->stealable_thread_count;
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sched_idle_steal_work(void) {
|
||||||
|
bool intstatus = interrupt_set(false);
|
||||||
|
cpu_t *destination = current_cpu();
|
||||||
|
bool work = false;
|
||||||
|
|
||||||
|
spinlock_acquire(&destination->sched_lock);
|
||||||
|
work = destination->thread_count != 0;
|
||||||
|
spinlock_release(&destination->sched_lock);
|
||||||
|
if (work)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
size_t cpu_count = arch_smp_get_cpu_count();
|
||||||
|
if (cpu_count == 1 || unlikely(arch_smp_cpusawake != cpu_count))
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
for (size_t offset = 1; offset < cpu_count; ++offset) {
|
||||||
|
cpu_t *source = smp_cpus[(destination->internal_id + offset) % cpu_count];
|
||||||
|
cpu_t *first = source->internal_id < destination->internal_id ? source : destination;
|
||||||
|
cpu_t *second = first == source ? destination : source;
|
||||||
|
|
||||||
|
if (!spinlock_try(&first->sched_lock))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!spinlock_try(&second->sched_lock)) {
|
||||||
|
spinlock_release(&first->sched_lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
work = destination->thread_count != 0;
|
||||||
|
if (!work && source->stealable_thread_count) {
|
||||||
|
thread_t *thread = sched_steal_work_from_cpu(source);
|
||||||
|
__assert(thread);
|
||||||
|
sched_insert_in_cpu_queue(destination, thread);
|
||||||
|
work = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&second->sched_lock);
|
||||||
|
spinlock_release(&first->sched_lock);
|
||||||
|
if (work)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
interrupt_set(intstatus);
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
|
||||||
// requires cpu queue to be locked
|
// requires cpu queue to be locked
|
||||||
thread_t *sched_select_next_thread(void) {
|
thread_t *sched_select_next_thread(void) {
|
||||||
thread_t *thread = pop_from_run_queue(¤t_cpu()->rt_queue);
|
thread_t *thread = pop_from_run_queue(¤t_cpu()->rt_queue);
|
||||||
|
|||||||
@@ -274,8 +274,12 @@ void sched_preempt_cpu(cpu_t *cpu) {
|
|||||||
|
|
||||||
static void idle_thread(void) {
|
static void idle_thread(void) {
|
||||||
interrupt_set(true);
|
interrupt_set(true);
|
||||||
while (1)
|
while (1) {
|
||||||
|
if (sched_idle_steal_work())
|
||||||
|
sched_yield();
|
||||||
|
else
|
||||||
CPU_HALT();
|
CPU_HALT();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_target_cpu(cpu_t *cpu) {
|
void sched_target_cpu(cpu_t *cpu) {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
name=astral
|
name=astral
|
||||||
revision=32
|
revision=33
|
||||||
from_source=astral
|
from_source=astral
|
||||||
imagedeps="build-essential nasm"
|
imagedeps="build-essential nasm"
|
||||||
hostdeps="xgcc xbinutils limine"
|
hostdeps="xgcc xbinutils limine"
|
||||||
|
|||||||
Reference in New Issue
Block a user