mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
scheduler: sched_reschedule_on_cpu
This commit is contained in:
@@ -167,6 +167,7 @@ thread_t *sched_newthread(void *ip, size_t kstacksize, int priority, proc_t *pro
|
||||
void sched_destroyproc(proc_t *);
|
||||
void sched_destroythread(thread_t *);
|
||||
void sched_targetcpu(struct cpu_t *cpu);
|
||||
void sched_reschedule_on_cpu(struct cpu_t *cpu, bool target);
|
||||
void sched_sleepus(size_t us);
|
||||
void sched_apentry();
|
||||
void sched_inactiveproc(proc_t *proc);
|
||||
|
||||
@@ -30,16 +30,11 @@ void itimer_pause(itimer_t *itimer, uintmax_t *remainingus, uintmax_t *repeatus)
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
|
||||
|
||||
while (itimer->cpu && itimer->cpu != current_cpu()) {
|
||||
// schedule on the itimer cpu
|
||||
sched_targetcpu(itimer->cpu);
|
||||
spinlock_release(&itimer->lock);
|
||||
// allow interrupts to be handled (such as a tlb shootdown)
|
||||
// as the other cpu could be busy waiting for this one
|
||||
interrupt_set(true);
|
||||
interrupt_set(false);
|
||||
sched_yield();
|
||||
sched_targetcpu(NULL);
|
||||
sched_reschedule_on_cpu(itimer->cpu, false);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <kernel/jobctl.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/auth.h>
|
||||
#include <arch/smp.h>
|
||||
|
||||
#define QUANTUM_US 100000
|
||||
#define SCHEDULER_STACK_SIZE PAGE_SIZE * 16
|
||||
@@ -714,6 +715,52 @@ void sched_targetcpu(cpu_t *cpu) {
|
||||
interrupt_set(intstatus);
|
||||
}
|
||||
|
||||
// yields the current thread and sends an reschedule ipi to a specific cpu
|
||||
static void reschedule_yield(context_t *context, void *_cpu) {
|
||||
thread_t *thread = current_thread();
|
||||
cpu_t *cpu = _cpu;
|
||||
|
||||
spinlock_acquire(&runqueuelock);
|
||||
|
||||
thread_t *next = runqueuenext(0x0fffffff);
|
||||
|
||||
ARCH_CONTEXT_THREADSAVE(thread, context);
|
||||
|
||||
thread->flags &= ~SCHED_THREAD_FLAGS_RUNNING;
|
||||
runqueueinsert(thread);
|
||||
|
||||
if (next == NULL)
|
||||
next = current_cpu()->idlethread;
|
||||
|
||||
arch_smp_sendipi(cpu, cpu->reschedule_isr, ARCH_SMP_IPI_TARGET, false);
|
||||
|
||||
spinlock_release(&runqueuelock);
|
||||
switchthread(next);
|
||||
}
|
||||
|
||||
void sched_reschedule_on_cpu(cpu_t *cpu, bool target) {
|
||||
cpu_t *old_target = current_thread()->cputarget;
|
||||
current_thread()->cputarget = cpu;
|
||||
|
||||
bool status = interrupt_set(false);
|
||||
|
||||
// already on the cpu
|
||||
if (cpu == current_cpu())
|
||||
goto leave;
|
||||
|
||||
long old_priority = current_thread()->priority;
|
||||
current_thread()->priority = 0;
|
||||
|
||||
arch_context_saveandcall(reschedule_yield, current_cpu()->schedulerstack, cpu);
|
||||
|
||||
current_thread()->priority = old_priority;
|
||||
|
||||
leave:
|
||||
interrupt_set(status);
|
||||
if (target == false)
|
||||
current_thread()->cputarget = old_target;
|
||||
}
|
||||
|
||||
static void timeout(context_t *, dpcarg_t arg) {
|
||||
thread_t *thread = arg;
|
||||
sched_wakeup(thread, 0);
|
||||
|
||||
Reference in New Issue
Block a user