kernel: Use local APIC timer for preemption on APs, not an IPI

This commit is contained in:
K. Lange 2021-11-14 17:16:20 +09:00
parent 8994db92f3
commit f7a29b90af
3 changed files with 30 additions and 5 deletions

View File

@ -256,19 +256,27 @@ void arch_tick_others(void);
static uint64_t time_slice_basis = 0; static uint64_t time_slice_basis = 0;
int cmos_time_stuff(struct regs *r) { static spin_lock_t clock_lock = { 0 };
void arch_update_clock(void) {
uint64_t clock_ticks = read_tsc() / tsc_mhz; uint64_t clock_ticks = read_tsc() / tsc_mhz;
uint64_t timer_ticks, timer_subticks; uint64_t timer_ticks, timer_subticks;
spin_lock(clock_lock);
update_ticks(clock_ticks, &timer_ticks, &timer_subticks); update_ticks(clock_ticks, &timer_ticks, &timer_subticks);
wakeup_sleepers(timer_ticks, timer_subticks);
irq_ack(0);
if (time_slice_basis + SUBSECONDS_PER_SECOND/4 <= clock_ticks) { if (time_slice_basis + SUBSECONDS_PER_SECOND/4 <= clock_ticks) {
update_process_usage(clock_ticks - time_slice_basis, tsc_mhz); update_process_usage(clock_ticks - time_slice_basis, tsc_mhz);
time_slice_basis = clock_ticks; time_slice_basis = clock_ticks;
} }
spin_unlock(clock_lock);
wakeup_sleepers(timer_ticks, timer_subticks);
}
int cmos_time_stuff(struct regs *r) {
arch_update_clock();
irq_ack(0);
arch_tick_others();
switch_task(1); switch_task(1);
asm volatile ( asm volatile (
".global _ret_from_preempt_source\n" ".global _ret_from_preempt_source\n"

View File

@ -339,6 +339,8 @@ struct regs * isr_handler(struct regs * r) {
return r; return r;
} }
case 123: { case 123: {
extern void arch_update_clock(void);
arch_update_clock();
switch_task(1); switch_task(1);
return r; return r;
} }

View File

@ -10,6 +10,7 @@
#include <kernel/printf.h> #include <kernel/printf.h>
#include <kernel/misc.h> #include <kernel/misc.h>
#include <kernel/args.h> #include <kernel/args.h>
#include <kernel/time.h>
#include <kernel/multiboot.h> #include <kernel/multiboot.h>
#include <kernel/arch/x86_64/acpi.h> #include <kernel/arch/x86_64/acpi.h>
#include <kernel/arch/x86_64/mmu.h> #include <kernel/arch/x86_64/mmu.h>
@ -123,6 +124,20 @@ void ap_main(void) {
/* Enable our spurious vector register */ /* Enable our spurious vector register */
*((volatile uint32_t*)(lapic_final + 0x0F0)) = 0x127; *((volatile uint32_t*)(lapic_final + 0x0F0)) = 0x127;
*((volatile uint32_t*)(lapic_final + 0x320)) = 0x7b;
*((volatile uint32_t*)(lapic_final + 0x3e0)) = 1;
uint64_t before = arch_perf_timer();
*((volatile uint32_t*)(lapic_final + 0x380)) = 1000000;
while (*((volatile uint32_t*)(lapic_final + 0x390)));
uint64_t after = arch_perf_timer();
uint64_t ms = (after-before)/arch_cpu_mhz();
uint64_t target = 10000000000UL / ms;
*((volatile uint32_t*)(lapic_final + 0x3e0)) = 1;
*((volatile uint32_t*)(lapic_final + 0x320)) = 0x7b | 0x20000;
*((volatile uint32_t*)(lapic_final + 0x380)) = target;
/* Set our pml pointers */ /* Set our pml pointers */
this_core->current_pml = &init_page_region[0]; this_core->current_pml = &init_page_region[0];