diff --git a/kernel/src/kernel/logger/logger.cpp b/kernel/src/kernel/logger/logger.cpp index 32dadb71..23c881a8 100644 --- a/kernel/src/kernel/logger/logger.cpp +++ b/kernel/src/kernel/logger/logger.cpp @@ -19,12 +19,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "shared/logger/logger.hpp" -#include "kernel/system/interrupts/interrupts.hpp" -#include "kernel/system/smp.hpp" -#include "shared/system/mutex.hpp" #include "shared/system/spinlock.hpp" -#include "shared/utils/string.hpp" -#include "shared/video/console_video.hpp" +#include "kernel/system/interrupts/interrupts.hpp" g_spinlock loggerLock = 0; diff --git a/kernel/src/kernel/system/interrupts/interrupts.cpp b/kernel/src/kernel/system/interrupts/interrupts.cpp index caa0abb3..a9bf07cf 100644 --- a/kernel/src/kernel/system/interrupts/interrupts.cpp +++ b/kernel/src/kernel/system/interrupts/interrupts.cpp @@ -104,6 +104,8 @@ extern "C" volatile g_processor_state* _interruptHandler(volatile g_processor_st auto newTask = taskingGetCurrentTask(); if(!newTask || !newTask->state) panic("%! attempted to switch to null task (%x) or state (%x)", "system", newTask, newTask->state); + if(newTask != task) + taskingRestoreState(newTask); return newTask->state; } diff --git a/kernel/src/kernel/tasking/task.hpp b/kernel/src/kernel/tasking/task.hpp index 646cb951..c4a07447 100644 --- a/kernel/src/kernel/tasking/task.hpp +++ b/kernel/src/kernel/tasking/task.hpp @@ -74,6 +74,7 @@ struct g_task g_task_status status; g_task_type type; g_mutex lock; + int interruptionLevel; /** * Flag that is only relevant when this task is spawned from an executable. After the task has diff --git a/kernel/src/kernel/tasking/tasking.cpp b/kernel/src/kernel/tasking/tasking.cpp index c6d17281..2d3b352a 100644 --- a/kernel/src/kernel/tasking/tasking.cpp +++ b/kernel/src/kernel/tasking/tasking.cpp @@ -280,8 +280,11 @@ void taskingSaveState(g_task* task, g_processor_state* state) // Save latest pointer to interrupt stack top task->state = state; + // Increase interruption counter + task->interruptionLevel++; + // Save FPU state - if(task->fpu.state) + if(task->interruptionLevel == 0 && task->fpu.state) { processorSaveFpuState(task->fpu.state); task->fpu.stored = true; @@ -289,13 +292,13 @@ void taskingSaveState(g_task* task, g_processor_state* state) } -void taskingApplySwitch() +void taskingRestoreState(g_task* task) { - g_task* task = taskingGetCurrentTask(); if(!task) - { panic("%! tried to restore without a current task", "tasking"); - } + + // Decrease interruption counter + task->interruptionLevel--; // Switch to process address space if(task->overridePageDirectory) @@ -314,7 +317,7 @@ void taskingApplySwitch() gdtSetTssEsp0(task->interruptStack.end); // Restore FPU state - if(task->fpu.stored) + if(task->interruptionLevel == 0 && task->fpu.stored) { processorRestoreFpuState(task->fpu.state); } @@ -322,9 +325,7 @@ void taskingApplySwitch() void taskingSchedule() { - auto local = taskingGetLocal(); - schedulerSchedule(local); - taskingApplySwitch(); + schedulerSchedule(taskingGetLocal()); } g_process* taskingCreateProcess(g_security_level securityLevel) @@ -461,6 +462,7 @@ void taskingInitializeTask(g_task* task, g_process* process, g_security_level le task->process = process; task->securityLevel = level; task->status = G_TASK_STATUS_RUNNING; + task->interruptionLevel = 1; waitQueueInitialize(&task->waitersJoin); mutexInitializeNonInterruptible(&task->lock, __func__); } diff --git a/kernel/src/kernel/tasking/tasking.hpp b/kernel/src/kernel/tasking/tasking.hpp index 8ad033ef..218a1a83 100644 --- a/kernel/src/kernel/tasking/tasking.hpp +++ b/kernel/src/kernel/tasking/tasking.hpp @@ -191,7 +191,7 @@ void taskingSaveState(g_task* task, g_processor_state* state); * Applies the context switch to the task which is the current one for this core. This sets * the correct page directory and TLS variables. */ -void taskingApplySwitch(); +void taskingRestoreState(g_task* task); /** * Yields control to the next task. This can only be called while no mutexes