mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +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_destroyproc(proc_t *);
|
||||||
void sched_destroythread(thread_t *);
|
void sched_destroythread(thread_t *);
|
||||||
void sched_targetcpu(struct cpu_t *cpu);
|
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_sleepus(size_t us);
|
||||||
void sched_apentry();
|
void sched_apentry();
|
||||||
void sched_inactiveproc(proc_t *proc);
|
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);
|
bool intstatus = interrupt_set(false);
|
||||||
spinlock_acquire(&itimer->lock);
|
spinlock_acquire(&itimer->lock);
|
||||||
|
|
||||||
|
|
||||||
while (itimer->cpu && itimer->cpu != current_cpu()) {
|
while (itimer->cpu && itimer->cpu != current_cpu()) {
|
||||||
// schedule on the itimer cpu
|
// schedule on the itimer cpu
|
||||||
sched_targetcpu(itimer->cpu);
|
|
||||||
spinlock_release(&itimer->lock);
|
spinlock_release(&itimer->lock);
|
||||||
// allow interrupts to be handled (such as a tlb shootdown)
|
sched_reschedule_on_cpu(itimer->cpu, false);
|
||||||
// as the other cpu could be busy waiting for this one
|
|
||||||
interrupt_set(true);
|
|
||||||
interrupt_set(false);
|
|
||||||
sched_yield();
|
|
||||||
sched_targetcpu(NULL);
|
|
||||||
spinlock_acquire(&itimer->lock);
|
spinlock_acquire(&itimer->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <kernel/jobctl.h>
|
#include <kernel/jobctl.h>
|
||||||
#include <kernel/cmdline.h>
|
#include <kernel/cmdline.h>
|
||||||
#include <kernel/auth.h>
|
#include <kernel/auth.h>
|
||||||
|
#include <arch/smp.h>
|
||||||
|
|
||||||
#define QUANTUM_US 100000
|
#define QUANTUM_US 100000
|
||||||
#define SCHEDULER_STACK_SIZE PAGE_SIZE * 16
|
#define SCHEDULER_STACK_SIZE PAGE_SIZE * 16
|
||||||
@@ -714,6 +715,52 @@ void sched_targetcpu(cpu_t *cpu) {
|
|||||||
interrupt_set(intstatus);
|
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) {
|
static void timeout(context_t *, dpcarg_t arg) {
|
||||||
thread_t *thread = arg;
|
thread_t *thread = arg;
|
||||||
sched_wakeup(thread, 0);
|
sched_wakeup(thread, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user