Kernel: Fix most of mutex + block race conditions
All block functions now take an optional mutex parameter that is atomically unlocked instead of having the user unlock it before hand. This prevents a ton of race conditions everywhere in the code!
This commit is contained in:
@@ -46,54 +46,54 @@ namespace Kernel
|
||||
void DevFileSystem::initialize_device_updater()
|
||||
{
|
||||
Process::create_kernel(
|
||||
[](void*)
|
||||
[](void* _devfs)
|
||||
{
|
||||
auto* devfs = static_cast<DevFileSystem*>(_devfs);
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
LockGuard _(s_instance->m_device_lock);
|
||||
for (auto& device : s_instance->m_devices)
|
||||
LockGuard _(devfs->m_device_lock);
|
||||
for (auto& device : devfs->m_devices)
|
||||
device->update();
|
||||
}
|
||||
SystemTimer::get().sleep_ms(10);
|
||||
}
|
||||
}, nullptr
|
||||
}, s_instance
|
||||
);
|
||||
|
||||
auto* sync_process = Process::create_kernel();
|
||||
|
||||
sync_process->add_thread(MUST(Thread::create_kernel(
|
||||
[](void*)
|
||||
[](void* _devfs)
|
||||
{
|
||||
auto* devfs = static_cast<DevFileSystem*>(_devfs);
|
||||
while (true)
|
||||
{
|
||||
LockGuard _(s_instance->m_device_lock);
|
||||
while (!s_instance->m_should_sync)
|
||||
{
|
||||
LockFreeGuard _(s_instance->m_device_lock);
|
||||
s_instance->m_sync_thread_blocker.block_indefinite();
|
||||
}
|
||||
LockGuard _(devfs->m_device_lock);
|
||||
while (!devfs->m_should_sync)
|
||||
devfs->m_sync_thread_blocker.block_indefinite(&devfs->m_device_lock);
|
||||
|
||||
for (auto& device : s_instance->m_devices)
|
||||
for (auto& device : devfs->m_devices)
|
||||
if (device->is_storage_device())
|
||||
if (auto ret = static_cast<StorageDevice*>(device.ptr())->sync_disk_cache(); ret.is_error())
|
||||
dwarnln("disk sync: {}", ret.error());
|
||||
|
||||
s_instance->m_should_sync = false;
|
||||
s_instance->m_sync_done.unblock();
|
||||
devfs->m_should_sync = false;
|
||||
devfs->m_sync_done.unblock();
|
||||
}
|
||||
}, nullptr, sync_process
|
||||
}, s_instance, sync_process
|
||||
)));
|
||||
|
||||
sync_process->add_thread(MUST(Kernel::Thread::create_kernel(
|
||||
[](void*)
|
||||
[](void* _devfs)
|
||||
{
|
||||
auto* devfs = static_cast<DevFileSystem*>(_devfs);
|
||||
while (true)
|
||||
{
|
||||
SystemTimer::get().sleep_ms(10'000);
|
||||
s_instance->initiate_sync(false);
|
||||
devfs->initiate_sync(false);
|
||||
}
|
||||
}, nullptr, sync_process
|
||||
}, s_instance, sync_process
|
||||
)));
|
||||
|
||||
sync_process->register_to_scheduler();
|
||||
@@ -101,13 +101,11 @@ namespace Kernel
|
||||
|
||||
void DevFileSystem::initiate_sync(bool should_block)
|
||||
{
|
||||
{
|
||||
LockGuard _(m_device_lock);
|
||||
m_should_sync = true;
|
||||
m_sync_thread_blocker.unblock();
|
||||
}
|
||||
if (should_block)
|
||||
m_sync_done.block_indefinite();
|
||||
LockGuard _(m_device_lock);
|
||||
m_should_sync = true;
|
||||
m_sync_thread_blocker.unblock();
|
||||
while (should_block && m_should_sync)
|
||||
m_sync_done.block_indefinite(&m_device_lock);
|
||||
}
|
||||
|
||||
void DevFileSystem::add_device(BAN::RefPtr<Device> device)
|
||||
|
||||
@@ -278,14 +278,14 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> Inode::add_epoll(class Epoll* epoll)
|
||||
{
|
||||
LockGuard _(m_epoll_mutex);
|
||||
SpinLockGuard _(m_epoll_lock);
|
||||
TRY(m_epolls.push_back(epoll));
|
||||
return {};
|
||||
}
|
||||
|
||||
void Inode::del_epoll(class Epoll* epoll)
|
||||
{
|
||||
LockGuard _(m_epoll_mutex);
|
||||
SpinLockGuard _(m_epoll_lock);
|
||||
for (auto it = m_epolls.begin(); it != m_epolls.end(); it++)
|
||||
{
|
||||
if (*it != epoll)
|
||||
@@ -297,7 +297,7 @@ namespace Kernel
|
||||
|
||||
void Inode::epoll_notify(uint32_t event)
|
||||
{
|
||||
LockGuard _(m_epoll_mutex);
|
||||
SpinLockGuard _(m_epoll_lock);
|
||||
for (auto* epoll : m_epolls)
|
||||
epoll->notify(this, event);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace Kernel
|
||||
|
||||
void Pipe::on_close(int status_flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
if (status_flags & O_WRONLY)
|
||||
{
|
||||
auto old_writing_count = m_writing_count.fetch_sub(1);
|
||||
@@ -71,8 +73,7 @@ namespace Kernel
|
||||
{
|
||||
if (m_writing_count == 0)
|
||||
return 0;
|
||||
LockFreeGuard lock_free(m_mutex);
|
||||
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
}
|
||||
|
||||
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
|
||||
@@ -108,8 +109,7 @@ namespace Kernel
|
||||
Thread::current().add_signal(SIGPIPE);
|
||||
return BAN::Error::from_errno(EPIPE);
|
||||
}
|
||||
LockFreeGuard lock_free(m_mutex);
|
||||
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
}
|
||||
|
||||
const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer.size() - m_buffer_size);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||
#include <kernel/FS/ProcFS/Inode.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user