Kernel: optimize yielding

Doing a yield no longer raises a software interrupt. Instead it just
saves all the callee saved registers, ip, sp and return value. Because
yield is only called in the kernel, it can just restore registers and
jump to the target address. There is never a need to use iret :)
This commit is contained in:
2026-01-11 01:31:09 +02:00
parent 83e5cb81e8
commit 35c97e2ff8
13 changed files with 109 additions and 118 deletions

View File

@@ -22,9 +22,8 @@ namespace Kernel
#if ARCH(i686)
constexpr uint8_t IRQ_SYSCALL = 0xF0;
#endif
constexpr uint8_t IRQ_YIELD = 0xF1;
constexpr uint8_t IRQ_IPI = 0xF2;
constexpr uint8_t IRQ_TIMER = 0xF3;
constexpr uint8_t IRQ_IPI = 0xF1;
constexpr uint8_t IRQ_TIMER = 0xF2;
#if ARCH(x86_64)
struct GateDescriptor

View File

@@ -27,7 +27,6 @@ namespace Kernel
uintptr_t r10;
uintptr_t r9;
uintptr_t r8;
uintptr_t rdi;
uintptr_t rsi;
uintptr_t rbp;
@@ -36,6 +35,18 @@ namespace Kernel
uintptr_t rcx;
uintptr_t rax;
};
struct YieldRegisters
{
uintptr_t r15;
uintptr_t r14;
uintptr_t r13;
uintptr_t r12;
uintptr_t rbp;
uintptr_t rbx;
uintptr_t ret;
uintptr_t sp;
uintptr_t ip;
};
#elif ARCH(i686)
struct InterruptRegisters
{
@@ -48,6 +59,16 @@ namespace Kernel
uintptr_t ecx;
uintptr_t eax;
};
struct YieldRegisters
{
uintptr_t ebp;
uintptr_t edi;
uintptr_t esi;
uintptr_t ebx;
uintptr_t ret;
uintptr_t sp;
uintptr_t ip;
};
#endif
}

View File

@@ -57,7 +57,7 @@ namespace Kernel
static BAN::ErrorOr<Scheduler*> create();
BAN::ErrorOr<void> initialize();
void reschedule(InterruptStack*, InterruptRegisters*);
void reschedule(YieldRegisters*);
void reschedule_if_idle();
void timer_interrupt();

View File

@@ -132,8 +132,7 @@ namespace Kernel
size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); }
size_t physical_page_count() const { return virtual_page_count(); }
InterruptStack& interrupt_stack() { return m_interrupt_stack; }
InterruptRegisters& interrupt_registers() { return m_interrupt_registers; }
YieldRegisters& yield_registers() { return m_yield_registers; }
void save_sse();
void load_sse();
@@ -173,8 +172,7 @@ namespace Kernel
SchedulerQueue::Node* m_scheduler_node { nullptr };
InterruptStack m_interrupt_stack { };
InterruptRegisters m_interrupt_registers { };
YieldRegisters m_yield_registers { };
siginfo_t m_signal_infos[_SIGMAX + 1] { };
uint64_t m_signal_pending_mask { 0 };