Kernel: Fix wait syscall with atomics
This commit is contained in:
parent
d2cf7c7a5c
commit
5001fa58e0
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Atomic.h>
|
||||||
#include <BAN/Iteration.h>
|
#include <BAN/Iteration.h>
|
||||||
#include <BAN/String.h>
|
#include <BAN/String.h>
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
|
@ -173,7 +174,7 @@ namespace Kernel
|
||||||
// Load elf from a file
|
// Load elf from a file
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, Kernel::PageTable&);
|
static BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, Kernel::PageTable&);
|
||||||
|
|
||||||
int block_until_exit();
|
BAN::ErrorOr<int> block_until_exit(pid_t pid);
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
|
@ -183,10 +184,10 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
struct ExitStatus
|
struct ExitStatus
|
||||||
{
|
{
|
||||||
Semaphore semaphore;
|
Semaphore semaphore;
|
||||||
int exit_code { 0 };
|
int exit_code { 0 };
|
||||||
bool exited { false };
|
BAN::Atomic<bool> exited { false };
|
||||||
int waiting { 0 };
|
BAN::Atomic<int> waiting { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
Credentials m_credentials;
|
Credentials m_credentials;
|
||||||
|
|
|
@ -202,24 +202,22 @@ namespace Kernel
|
||||||
|
|
||||||
void Process::cleanup_function()
|
void Process::cleanup_function()
|
||||||
{
|
{
|
||||||
s_process_lock.lock();
|
{
|
||||||
for (size_t i = 0; i < s_processes.size(); i++)
|
LockGuard _(s_process_lock);
|
||||||
if (s_processes[i] == this)
|
for (size_t i = 0; i < s_processes.size(); i++)
|
||||||
s_processes.remove(i);
|
if (s_processes[i] == this)
|
||||||
s_process_lock.unlock();
|
s_processes.remove(i);
|
||||||
|
}
|
||||||
|
|
||||||
ProcFileSystem::get().on_process_delete(*this);
|
ProcFileSystem::get().on_process_delete(*this);
|
||||||
|
|
||||||
m_lock.lock();
|
|
||||||
m_exit_status.exited = true;
|
m_exit_status.exited = true;
|
||||||
|
m_exit_status.semaphore.unblock();
|
||||||
|
|
||||||
while (m_exit_status.waiting > 0)
|
while (m_exit_status.waiting > 0)
|
||||||
{
|
|
||||||
m_exit_status.semaphore.unblock();
|
|
||||||
while (m_lock.is_locked())
|
|
||||||
m_lock.unlock();
|
|
||||||
Scheduler::get().reschedule();
|
Scheduler::get().reschedule();
|
||||||
m_lock.lock();
|
|
||||||
}
|
m_lock.lock();
|
||||||
|
|
||||||
m_open_file_descriptors.close_all();
|
m_open_file_descriptors.close_all();
|
||||||
|
|
||||||
|
@ -241,6 +239,7 @@ namespace Kernel
|
||||||
|
|
||||||
thread.setup_process_cleanup();
|
thread.setup_process_cleanup();
|
||||||
Scheduler::get().execute_current_thread();
|
Scheduler::get().execute_current_thread();
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_threads.size(); i++)
|
for (size_t i = 0; i < m_threads.size(); i++)
|
||||||
|
@ -547,44 +546,17 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::block_until_exit()
|
BAN::ErrorOr<int> Process::block_until_exit(pid_t pid)
|
||||||
{
|
{
|
||||||
ASSERT(this != &Process::current());
|
ASSERT(this->pid() != pid);
|
||||||
|
|
||||||
m_lock.lock();
|
|
||||||
m_exit_status.waiting++;
|
|
||||||
while (!m_exit_status.exited)
|
|
||||||
{
|
|
||||||
m_lock.unlock();
|
|
||||||
m_exit_status.semaphore.block();
|
|
||||||
m_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = m_exit_status.exit_code;
|
|
||||||
m_exit_status.waiting--;
|
|
||||||
m_lock.unlock();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_wait(pid_t pid, int* stat_loc, int options)
|
|
||||||
{
|
|
||||||
Process* target = nullptr;
|
Process* target = nullptr;
|
||||||
|
|
||||||
{
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
TRY(validate_pointer_access(stat_loc, sizeof(int)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: support options
|
|
||||||
if (options)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
|
|
||||||
for_each_process(
|
for_each_process(
|
||||||
[&](Process& process)
|
[pid, &target](Process& process)
|
||||||
{
|
{
|
||||||
if (process.pid() == pid)
|
if (process.pid() == pid)
|
||||||
{
|
{
|
||||||
|
process.m_exit_status.waiting++;
|
||||||
target = &process;
|
target = &process;
|
||||||
return BAN::Iteration::Break;
|
return BAN::Iteration::Break;
|
||||||
}
|
}
|
||||||
|
@ -595,13 +567,31 @@ namespace Kernel
|
||||||
if (target == nullptr)
|
if (target == nullptr)
|
||||||
return BAN::Error::from_errno(ECHILD);
|
return BAN::Error::from_errno(ECHILD);
|
||||||
|
|
||||||
pid_t ret = target->pid();
|
while (!target->m_exit_status.exited)
|
||||||
|
TRY(Thread::current().block_or_eintr(target->m_exit_status.semaphore));
|
||||||
|
|
||||||
int stat = target->block_until_exit();
|
int exit_status = target->m_exit_status.exit_code;
|
||||||
|
target->m_exit_status.waiting--;
|
||||||
|
|
||||||
|
return exit_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_wait(pid_t pid, int* stat_loc, int options)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
TRY(validate_pointer_access(stat_loc, sizeof(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: support options
|
||||||
|
if (options)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
int stat = TRY(block_until_exit(pid));
|
||||||
if (stat_loc)
|
if (stat_loc)
|
||||||
*stat_loc = stat;
|
*stat_loc = stat;
|
||||||
|
|
||||||
return ret;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
||||||
|
|
Loading…
Reference in New Issue