diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 48ebb8e5..2ca21953 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -30,9 +30,14 @@ typedef struct cpu_t { thread_t *idlethread; timerentry_t schedtimerentry; void *schedulerstack; + isr_t *isrqueue; - dpc_t *dpcqueue; + isr_t *dpcisr; + dpc_t *dpcqueue; + + dpc_t reschedule_dpc; + isr_t *reschedule_isr; } cpu_t; #define CPU_HALT() asm volatile("hlt") diff --git a/kernel-src/sys/scheduler.c b/kernel-src/sys/scheduler.c index b57aa921..612647ae 100644 --- a/kernel-src/sys/scheduler.c +++ b/kernel-src/sys/scheduler.c @@ -602,6 +602,7 @@ bool sched_wakeup(thread_t *thread, int reason) { thread->flags &= ~(SCHED_THREAD_FLAGS_SLEEP | SCHED_THREAD_FLAGS_INTERRUPTIBLE); thread->wakeupreason = reason; + // TODO send IPI to idle cores sched_queue(thread); spinlock_release(&thread->sleeplock); interrupt_set(intstate); @@ -672,7 +673,7 @@ static void dopreempt() { switchthread(next); } -static void timerhook(context_t *context, dpcarg_t arg) { +static void preempt_dpc(context_t *context, dpcarg_t arg) { thread_t* current = current_thread(); interrupt_set(false); @@ -688,6 +689,16 @@ static void timerhook(context_t *context, dpcarg_t arg) { CTX_IP(context) = (uintptr_t)dopreempt; } +// IPL_DPC +static void reschedule_timer_dpc(context_t *context, dpcarg_t arg) { + dpc_enqueue(¤t_cpu()->reschedule_dpc, preempt_dpc, NULL); +} + +// IPL_MAX +static void reschedule_ipi(isr_t *, context_t *) { + dpc_enqueue(¤t_cpu()->reschedule_dpc, preempt_dpc, NULL); +} + static void cpuidlethread() { sched_targetcpu(current_cpu()); interrupt_set(true); @@ -724,7 +735,10 @@ void sched_apentry() { current_cpu()->idlethread = sched_newthread(cpuidlethread, PAGE_SIZE * 4, 3, NULL, NULL); __assert(current_cpu()->idlethread); - timer_insert(current_cpu()->timer, ¤t_cpu()->schedtimerentry, timerhook, NULL, QUANTUM_US, true); + current_cpu()->reschedule_isr = interrupt_allocate(reschedule_ipi, ARCH_EOI, IPL_MAX); + __assert(current_cpu()->reschedule_isr); + + timer_insert(current_cpu()->timer, ¤t_cpu()->schedtimerentry, reschedule_timer_dpc, NULL, QUANTUM_US, true); timer_resume(current_cpu()->timer); sched_stopcurrentthread(); } @@ -749,7 +763,10 @@ void sched_init() { current_cpu()->thread = sched_newthread(NULL, PAGE_SIZE * 32, 0, NULL, NULL); __assert(current_thread()); - timer_insert(current_cpu()->timer, ¤t_cpu()->schedtimerentry, timerhook, NULL, QUANTUM_US, true); + current_cpu()->reschedule_isr = interrupt_allocate(reschedule_ipi, ARCH_EOI, IPL_MAX); + __assert(current_cpu()->reschedule_isr); + + timer_insert(current_cpu()->timer, ¤t_cpu()->schedtimerentry, reschedule_timer_dpc, NULL, QUANTUM_US, true); // XXX move this resume to a more appropriate place timer_resume(current_cpu()->timer); }