Compare commits

...

6 Commits

Author SHA1 Message Date
Bananymous 6e1825d6b4 Kernel: Add missing TRY() to font loading 2023-09-27 00:49:53 +03:00
Bananymous ec2baeb276 Sync: Add some argument parsing to sync(1)
You can specify --block to make the program wait until sync is
complete.
2023-09-27 00:37:23 +03:00
Bananymous 6cb8bda6e1 LibC: add syncsync() to unistd.h
This is my own WELL NAMED (:D) function that takes a paramemeter
to make the sync operation synchronous.
2023-09-27 00:35:36 +03:00
Bananymous 05e57801e7 Kernel: SYS_SYNC now schedules sync to happen soon
You can pass non-zero argument to the syscall to block until the
sync has finished.
2023-09-27 00:34:00 +03:00
Bananymous b924c85669 Kernel: DiskCache now requires sync to be called from kernel thread
This disables the scenario where user interrupts sync operation
possibly leaving the syncing in invalid state.
2023-09-27 00:32:13 +03:00
Bananymous 09c1aa44d8 Kernel: Allow creationg of empty processes and manual registration
You can now create kernel processes without any threads, add the
needed threads and only then register the process and its threads
to the scheduler.
2023-09-27 00:29:45 +03:00
12 changed files with 160 additions and 48 deletions

View File

@ -2,6 +2,7 @@
#include <kernel/Device/Device.h>
#include <kernel/FS/RamFS/FileSystem.h>
#include <kernel/Semaphore.h>
namespace Kernel
{
@ -19,6 +20,8 @@ namespace Kernel
dev_t get_next_dev();
void initiate_sync(bool should_block);
private:
DevFileSystem(size_t size)
: RamFileSystem(size)
@ -26,6 +29,10 @@ namespace Kernel
private:
SpinLock m_device_lock;
Semaphore m_sync_done;
Semaphore m_sync_semaphore;
volatile bool m_should_sync { false };
};
}

View File

@ -38,11 +38,13 @@ namespace Kernel
};
public:
static Process* create_kernel();
static Process* create_kernel(entry_t, void*);
static BAN::ErrorOr<Process*> create_userspace(const Credentials&, BAN::StringView);
~Process();
void cleanup_function();
void register_to_scheduler();
void exit(int status, int signal);
static void for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback);
@ -107,7 +109,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag);
BAN::ErrorOr<long> sys_stat(const char* path, struct stat* buf, int flag);
BAN::ErrorOr<long> sys_sync();
BAN::ErrorOr<long> sys_sync(bool should_block);
BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);
@ -138,7 +140,6 @@ namespace Kernel
private:
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
static void register_process(Process*);
// Load an elf file to virtual address space of the current page table
static BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd);

View File

@ -36,6 +36,7 @@ namespace Kernel
const size_t m_sector_size;
StorageDevice& m_device;
BAN::Vector<PageCache> m_cache;
BAN::Array<uint8_t, PAGE_SIZE> m_sync_cache;
};
}

View File

@ -5,6 +5,7 @@
#include <kernel/FS/RamFS/Inode.h>
#include <kernel/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Storage/StorageDevice.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
@ -53,6 +54,67 @@ namespace Kernel
}
}, nullptr
);
auto* sync_process = Process::create_kernel();
sync_process->add_thread(MUST(Thread::create_kernel(
[](void*)
{
// NOTE: we lock the device lock here and unlock
// it only while semaphore is blocking
s_instance->m_device_lock.lock();
while (true)
{
while (!s_instance->m_should_sync)
{
s_instance->m_device_lock.unlock();
s_instance->m_sync_semaphore.block();
s_instance->m_device_lock.lock();
}
s_instance->for_each_inode(
[](BAN::RefPtr<RamInode> inode)
{
if (inode->is_device())
if (((Device*)inode.ptr())->is_storage_device())
if (auto ret = ((StorageDevice*)inode.ptr())->sync_disk_cache(); ret.is_error())
dwarnln("disk sync: {}", ret.error());
return BAN::Iteration::Continue;
}
);
s_instance->m_should_sync = false;
s_instance->m_sync_done.unblock();
}
}, nullptr, sync_process
)));
sync_process->add_thread(MUST(Kernel::Thread::create_kernel(
[](void*)
{
while (true)
{
SystemTimer::get().sleep(10000);
LockGuard _(s_instance->m_device_lock);
s_instance->m_should_sync = true;
s_instance->m_sync_semaphore.unblock();
}
}, nullptr, sync_process
)));
sync_process->register_to_scheduler();
}
void DevFileSystem::initiate_sync(bool should_block)
{
{
LockGuard _(m_device_lock);
m_should_sync = true;
m_sync_semaphore.unblock();
}
if (should_block)
m_sync_done.block();
}
void DevFileSystem::add_device(BAN::StringView path, BAN::RefPtr<RamInode> device)

View File

@ -43,7 +43,7 @@ namespace Kernel
BAN::Vector<uint8_t> file_data;
TRY(file_data.resize(inode->size()));
inode->read(0, file_data.data(), file_data.size());
TRY(inode->read(0, file_data.data(), file_data.size()));
if (file_data.size() < 4)
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);

View File

@ -78,22 +78,29 @@ namespace Kernel
return process;
}
void Process::register_process(Process* process)
void Process::register_to_scheduler()
{
s_process_lock.lock();
MUST(s_processes.push_back(process));
MUST(s_processes.push_back(this));
s_process_lock.unlock();
for (auto* thread : process->m_threads)
for (auto* thread : m_threads)
MUST(Scheduler::get().add_thread(thread));
}
Process* Process::create_kernel()
{
auto* process = create_process({ 0, 0, 0, 0 }, 0);
MUST(process->m_working_directory.push_back('/'));
return process;
}
Process* Process::create_kernel(entry_t entry, void* data)
{
auto* process = create_process({ 0, 0, 0, 0 }, 0);
MUST(process->m_working_directory.push_back('/'));
auto* thread = MUST(Thread::create_kernel(entry, data, process));
process->add_thread(thread);
register_process(process);
process->register_to_scheduler();
return process;
}
@ -146,7 +153,7 @@ namespace Kernel
auto* thread = MUST(Thread::create_userspace(process));
process->add_thread(thread);
register_process(process);
process->register_to_scheduler();
return process;
}
@ -353,8 +360,7 @@ namespace Kernel
// FIXME: this should be able to fail
Thread* thread = MUST(Thread::current().clone(forked, rsp, rip));
forked->add_thread(thread);
register_process(forked);
forked->register_to_scheduler();
return forked->pid();
}
@ -761,22 +767,10 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_sync()
BAN::ErrorOr<long> Process::sys_sync(bool should_block)
{
BAN::ErrorOr<long> ret = 0;
DevFileSystem::get().for_each_device(
[&](Device* device)
{
if (device->is_storage_device())
{
auto success = ((StorageDevice*)device)->sync_disk_cache();
if (success.is_error())
ret = success.release_error();
}
return BAN::Iteration::Continue;
}
);
return ret;
DevFileSystem::get().initiate_sync(should_block);
return 0;
}
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)

View File

@ -118,30 +118,48 @@ namespace Kernel
BAN::ErrorOr<void> DiskCache::sync()
{
BAN::Vector<uint8_t> sector_buffer;
TRY(sector_buffer.resize(m_sector_size));
PageTable& page_table = PageTable::current();
LockGuard page_table_locker(page_table);
ASSERT(page_table.is_page_free(0));
ASSERT(&PageTable::current() == &PageTable::kernel());
auto& page_table = PageTable::kernel();
for (auto& cache : m_cache)
{
for (int i = 0; cache.dirty_mask; i++)
if (cache.dirty_mask == 0)
continue;
{
if (!(cache.dirty_mask & (1 << i)))
continue;
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
{
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(sector_buffer.data(), (void*)(i * m_sector_size), m_sector_size);
page_table.unmap_page(0);
}
TRY(m_device.write_sectors_impl(cache.first_sector + i, 1, sector_buffer.data()));
cache.dirty_mask &= ~(1 << i);
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(m_sync_cache.data(), (void*)0, PAGE_SIZE);
page_table.unmap_page(0);
}
uint8_t sector_start = 0;
uint8_t sector_count = 0;
while (sector_start + sector_count <= PAGE_SIZE / m_sector_size)
{
if (cache.dirty_mask & (1 << (sector_start + sector_count)))
sector_count++;
else if (sector_count == 0)
sector_start++;
else
{
dprintln("syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
sector_start += sector_count + 1;
sector_count = 0;
}
}
if (sector_count > 0)
{
dprintln("syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
}
cache.dirty_mask = 0;
}
return {};

View File

@ -260,7 +260,7 @@ namespace Kernel
{
LockGuard _(m_lock);
ASSERT(!m_disk_cache.has_value());
m_disk_cache = DiskCache(sector_size(), *this);
m_disk_cache.emplace(sector_size(), *this);
}
BAN::ErrorOr<void> StorageDevice::sync_disk_cache()

View File

@ -185,7 +185,7 @@ namespace Kernel
ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
break;
case SYS_SYNC:
ret = Process::current().sys_sync();
ret = Process::current().sys_sync((bool)arg1);
break;
case SYS_MMAP:
ret = Process::current().sys_mmap((const sys_mmap_t*)arg1);

View File

@ -196,6 +196,7 @@ void swab(const void* __restrict src, void* __restrict dest, ssize_t nbytes);
int symlink(const char* path1, const char* path2);
int symlinkat(const char* path1, int fd, const char* path2);
void sync(void);
void syncsync(int should_block);
long sysconf(int name);
pid_t tcgetpgrp(int fildes);
int tcsetpgrp(int fildes, pid_t pgid_id);

View File

@ -202,7 +202,12 @@ int chdir(const char* path)
void sync(void)
{
syscall(SYS_SYNC);
syscall(SYS_SYNC, false);
}
void syncsync(int should_block)
{
syscall(SYS_SYNC, should_block);
}
pid_t getpid(void)

View File

@ -1,6 +1,29 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
void usage(int ret, char* cmd)
{
sync();
FILE* fout = (ret == 0) ? stdout : stderr;
fprintf(fout, "usage: %s [OPTION]...\n", cmd);
fprintf(fout, "Tells the kernel to start a disk sync as soon as possible\n");
fprintf(fout, " -b, --block return only after sync is complete\n");
fprintf(fout, " -h, --help show this message and exit\n");
exit(ret);
}
int main(int argc, char** argv)
{
bool block = false;
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--block") == 0)
block = true;
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
usage(0, argv[0]);
else
usage(1, argv[0]);
}
syncsync(block);
return 0;
}