diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index a4227a6c3c..10b1a06464 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -258,3 +258,50 @@ void Scheduler::initialize() current = nullptr; load_task_register(s_redirection.selector); } + +void Scheduler::timer_tick(RegisterDump& regs) +{ + if (!current) + return; + + system.uptime++; + + if (current->tick()) + return; + + current->tss().gs = regs.gs; + current->tss().fs = regs.fs; + current->tss().es = regs.es; + current->tss().ds = regs.ds; + current->tss().edi = regs.edi; + current->tss().esi = regs.esi; + current->tss().ebp = regs.ebp; + current->tss().ebx = regs.ebx; + current->tss().edx = regs.edx; + current->tss().ecx = regs.ecx; + current->tss().eax = regs.eax; + current->tss().eip = regs.eip; + current->tss().cs = regs.cs; + current->tss().eflags = regs.eflags; + + // Compute process stack pointer. + // Add 12 for CS, EIP, EFLAGS (interrupt mechanic) + current->tss().esp = regs.esp + 12; + current->tss().ss = regs.ss; + + if ((current->tss().cs & 3) != 0) { + current->tss().ss = regs.ss_if_crossRing; + current->tss().esp = regs.esp_if_crossRing; + } + + if (!pick_next()) + return; + prepare_for_iret_to_new_process(); + + // Set the NT (nested task) flag. + asm( + "pushf\n" + "orl $0x00004000, (%esp)\n" + "popf\n" + ); +} diff --git a/Kernel/Scheduler.h b/Kernel/Scheduler.h index c4be384fe3..466de2bbe4 100644 --- a/Kernel/Scheduler.h +++ b/Kernel/Scheduler.h @@ -1,20 +1,24 @@ #pragma once #include + class Process; +struct RegisterDump; extern Process* current; class Scheduler { public: static void initialize(); + static void timer_tick(RegisterDump&); static bool pick_next(); static void pick_next_and_switch_now(); static void switch_now(); static bool yield(); static bool context_switch(Process&); - static void prepare_for_iret_to_new_process(); static void prepare_to_modify_tss(Process&); +private: + static void prepare_for_iret_to_new_process(); }; int sched_yield(); diff --git a/Kernel/i8253.cpp b/Kernel/i8253.cpp index 5efbda30a9..5dee910113 100644 --- a/Kernel/i8253.cpp +++ b/Kernel/i8253.cpp @@ -1,24 +1,16 @@ #include "i8253.h" #include "i386.h" #include "IO.h" -#include "VGA.h" -#include "Process.h" -#include "system.h" #include "PIC.h" #include "Scheduler.h" #define IRQ_TIMER 0 extern "C" void tick_ISR(); -extern "C" void clock_handle(); - -extern volatile DWORD state_dump; +extern "C" void clock_handle(RegisterDump&); asm( ".globl tick_ISR \n" - ".globl state_dump \n" - "state_dump: \n" - ".long 0\n" "tick_ISR: \n" " pusha\n" " pushw %ds\n" @@ -34,7 +26,7 @@ asm( " popw %es\n" " popw %fs\n" " popw %gs\n" - " mov %esp, state_dump\n" + " mov %esp, %eax\n" " call clock_handle\n" " popw %gs\n" " popw %gs\n" @@ -66,54 +58,10 @@ asm( /* Miscellaneous */ #define BASE_FREQUENCY 1193182 -void clock_handle() +void clock_handle(RegisterDump& regs) { IRQHandlerScope scope(IRQ_TIMER); - - if (!current) - return; - - system.uptime++; - - if (current->tick()) - return; - - auto& regs = *reinterpret_cast(state_dump); - current->tss().gs = regs.gs; - current->tss().fs = regs.fs; - current->tss().es = regs.es; - current->tss().ds = regs.ds; - current->tss().edi = regs.edi; - current->tss().esi = regs.esi; - current->tss().ebp = regs.ebp; - current->tss().ebx = regs.ebx; - current->tss().edx = regs.edx; - current->tss().ecx = regs.ecx; - current->tss().eax = regs.eax; - current->tss().eip = regs.eip; - current->tss().cs = regs.cs; - current->tss().eflags = regs.eflags; - - // Compute process stack pointer. - // Add 12 for CS, EIP, EFLAGS (interrupt mechanic) - current->tss().esp = regs.esp + 12; - current->tss().ss = regs.ss; - - if ((current->tss().cs & 3) != 0) { - current->tss().ss = regs.ss_if_crossRing; - current->tss().esp = regs.esp_if_crossRing; - } - - if (!Scheduler::pick_next()) - return; - Scheduler::prepare_for_iret_to_new_process(); - - // Set the NT (nested task) flag. - asm( - "pushf\n" - "orl $0x00004000, (%esp)\n" - "popf\n" - ); + Scheduler::timer_tick(regs); } namespace PIT { @@ -126,8 +74,6 @@ void initialize() timer_reload = (BASE_FREQUENCY / TICKS_PER_SECOND); - /* Send LSB and MSB of timer reload value. */ - kprintf("PIT(i8253): %u Hz, square wave (%x)\n", TICKS_PER_SECOND, timer_reload); IO::out8(TIMER0_CTL, LSB(timer_reload));