#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, ®s, sizeof(Context)); } void Task::save_context(Context* context) { memcpy(®s, 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; }