Luna/kernel/src/thread/Task.cpp

133 lines
2.6 KiB
C++

#define MODULE "sched"
#include "thread/Task.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "std/assert.h"
#include "std/errno.h"
#include "std/string.h"
void Task::restore_context(Context* context)
{
memcpy(context, &regs, sizeof(Context));
}
void Task::save_context(Context* context)
{
memcpy(&regs, context, sizeof(Context));
}
void Task::save_floating()
{
floating_saved = true;
asm volatile("fxsave (%0)" : : "r"((char*)floating_region));
}
void Task::restore_floating()
{
if (!floating_saved) return;
asm volatile("fxrstor (%0)" : : "r"((char*)floating_region));
}
bool Task::is_user_task()
{
return user_task;
}
int Task::alloc_fd()
{
int fd;
for (fd = 0; fd < TASK_MAX_FDS; fd++)
{
if (!files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS) { return -1; }
return fd;
}
int Task::alloc_fd_greater_than_or_equal(int base_fd)
{
int fd;
if (base_fd >= TASK_MAX_FDS) return -1;
for (fd = base_fd; fd < TASK_MAX_FDS; fd++)
{
if (!files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS) { return -1; }
return fd;
}
void Task::switch_to_address_space()
{
VMM::switch_to_user_address_space(address_space);
VMM::apply_address_space();
}
bool Task::has_died()
{
return state == Exited;
}
void Task::resume_read()
{
regs.rax = files[blocking_read_info.fd].read(blocking_read_info.size, blocking_read_info.buf);
}
bool Task::is_read_still_blocking()
{
return VFS::would_block(files[blocking_read_info.fd].node());
}
void Task::resume()
{
VMM::switch_back_to_kernel_address_space();
VMM::apply_address_space();
VMM::switch_to_previous_user_address_space();
switch (block_reason)
{
case BlockReason::None: ASSERT(false);
case BlockReason::Reading: resume_read(); break;
case BlockReason::Waiting: resume_wait(); break;
default: ASSERT(false);
}
VMM::apply_address_space();
block_reason = BlockReason::None;
state = Running;
}
bool Task::is_still_blocking()
{
switch (block_reason)
{
case BlockReason::None: ASSERT(false);
case BlockReason::Reading: return is_read_still_blocking();
case BlockReason::Waiting: return is_wait_still_blocking();
default: ASSERT(false);
}
}
Descriptor* Task::descriptor_from_fd(int fd, int& error)
{
if (fd < 0 || fd >= TASK_MAX_FDS)
{
error = EBADF;
return nullptr;
}
if (!files[fd].is_open())
{
error = EBADF;
return nullptr;
}
return &files[fd];
}
bool Task::is_superuser()
{
return euid == 0 || egid == 0;
}