Compare commits
6 Commits
1d470fb5ba
...
6e1825d6b4
Author | SHA1 | Date |
---|---|---|
Bananymous | 6e1825d6b4 | |
Bananymous | ec2baeb276 | |
Bananymous | 6cb8bda6e1 | |
Bananymous | 05e57801e7 | |
Bananymous | b924c85669 | |
Bananymous | 09c1aa44d8 |
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/FS/RamFS/FileSystem.h>
|
#include <kernel/FS/RamFS/FileSystem.h>
|
||||||
|
#include <kernel/Semaphore.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -19,6 +20,8 @@ namespace Kernel
|
||||||
|
|
||||||
dev_t get_next_dev();
|
dev_t get_next_dev();
|
||||||
|
|
||||||
|
void initiate_sync(bool should_block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DevFileSystem(size_t size)
|
DevFileSystem(size_t size)
|
||||||
: RamFileSystem(size)
|
: RamFileSystem(size)
|
||||||
|
@ -26,6 +29,10 @@ namespace Kernel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpinLock m_device_lock;
|
SpinLock m_device_lock;
|
||||||
|
|
||||||
|
Semaphore m_sync_done;
|
||||||
|
Semaphore m_sync_semaphore;
|
||||||
|
volatile bool m_should_sync { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -38,11 +38,13 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static Process* create_kernel();
|
||||||
static Process* create_kernel(entry_t, void*);
|
static Process* create_kernel(entry_t, void*);
|
||||||
static BAN::ErrorOr<Process*> create_userspace(const Credentials&, BAN::StringView);
|
static BAN::ErrorOr<Process*> create_userspace(const Credentials&, BAN::StringView);
|
||||||
~Process();
|
~Process();
|
||||||
void cleanup_function();
|
void cleanup_function();
|
||||||
|
|
||||||
|
void register_to_scheduler();
|
||||||
void exit(int status, int signal);
|
void exit(int status, int signal);
|
||||||
|
|
||||||
static void for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback);
|
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_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_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);
|
BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);
|
||||||
|
|
||||||
|
@ -138,7 +140,6 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
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 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
|
// 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);
|
static BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd);
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace Kernel
|
||||||
const size_t m_sector_size;
|
const size_t m_sector_size;
|
||||||
StorageDevice& m_device;
|
StorageDevice& m_device;
|
||||||
BAN::Vector<PageCache> m_cache;
|
BAN::Vector<PageCache> m_cache;
|
||||||
|
BAN::Array<uint8_t, PAGE_SIZE> m_sync_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include <kernel/FS/RamFS/Inode.h>
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -53,6 +54,67 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}, nullptr
|
}, 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)
|
void DevFileSystem::add_device(BAN::StringView path, BAN::RefPtr<RamInode> device)
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> file_data;
|
BAN::Vector<uint8_t> file_data;
|
||||||
TRY(file_data.resize(inode->size()));
|
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)
|
if (file_data.size() < 4)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);
|
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);
|
||||||
|
|
|
@ -78,22 +78,29 @@ namespace Kernel
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::register_process(Process* process)
|
void Process::register_to_scheduler()
|
||||||
{
|
{
|
||||||
s_process_lock.lock();
|
s_process_lock.lock();
|
||||||
MUST(s_processes.push_back(process));
|
MUST(s_processes.push_back(this));
|
||||||
s_process_lock.unlock();
|
s_process_lock.unlock();
|
||||||
for (auto* thread : process->m_threads)
|
for (auto* thread : m_threads)
|
||||||
MUST(Scheduler::get().add_thread(thread));
|
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)
|
Process* Process::create_kernel(entry_t entry, void* data)
|
||||||
{
|
{
|
||||||
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
MUST(process->m_working_directory.push_back('/'));
|
||||||
auto* thread = MUST(Thread::create_kernel(entry, data, process));
|
auto* thread = MUST(Thread::create_kernel(entry, data, process));
|
||||||
process->add_thread(thread);
|
process->add_thread(thread);
|
||||||
register_process(process);
|
process->register_to_scheduler();
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +153,7 @@ namespace Kernel
|
||||||
|
|
||||||
auto* thread = MUST(Thread::create_userspace(process));
|
auto* thread = MUST(Thread::create_userspace(process));
|
||||||
process->add_thread(thread);
|
process->add_thread(thread);
|
||||||
register_process(process);
|
process->register_to_scheduler();
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,8 +360,7 @@ namespace Kernel
|
||||||
// FIXME: this should be able to fail
|
// FIXME: this should be able to fail
|
||||||
Thread* thread = MUST(Thread::current().clone(forked, rsp, rip));
|
Thread* thread = MUST(Thread::current().clone(forked, rsp, rip));
|
||||||
forked->add_thread(thread);
|
forked->add_thread(thread);
|
||||||
|
forked->register_to_scheduler();
|
||||||
register_process(forked);
|
|
||||||
|
|
||||||
return forked->pid();
|
return forked->pid();
|
||||||
}
|
}
|
||||||
|
@ -761,22 +767,10 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_sync()
|
BAN::ErrorOr<long> Process::sys_sync(bool should_block)
|
||||||
{
|
{
|
||||||
BAN::ErrorOr<long> ret = 0;
|
DevFileSystem::get().initiate_sync(should_block);
|
||||||
DevFileSystem::get().for_each_device(
|
return 0;
|
||||||
[&](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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||||
|
|
|
@ -118,30 +118,48 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> DiskCache::sync()
|
BAN::ErrorOr<void> DiskCache::sync()
|
||||||
{
|
{
|
||||||
BAN::Vector<uint8_t> sector_buffer;
|
ASSERT(&PageTable::current() == &PageTable::kernel());
|
||||||
TRY(sector_buffer.resize(m_sector_size));
|
auto& page_table = PageTable::kernel();
|
||||||
|
|
||||||
PageTable& page_table = PageTable::current();
|
|
||||||
LockGuard page_table_locker(page_table);
|
|
||||||
ASSERT(page_table.is_page_free(0));
|
|
||||||
|
|
||||||
for (auto& cache : m_cache)
|
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)))
|
LockGuard _(page_table);
|
||||||
continue;
|
ASSERT(page_table.is_page_free(0));
|
||||||
|
|
||||||
{
|
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
||||||
CriticalScope _;
|
memcpy(m_sync_cache.data(), (void*)0, PAGE_SIZE);
|
||||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
page_table.unmap_page(0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {};
|
return {};
|
||||||
|
|
|
@ -260,7 +260,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
ASSERT(!m_disk_cache.has_value());
|
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()
|
BAN::ErrorOr<void> StorageDevice::sync_disk_cache()
|
||||||
|
|
|
@ -185,7 +185,7 @@ namespace Kernel
|
||||||
ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
|
ret = Process::current().sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
|
||||||
break;
|
break;
|
||||||
case SYS_SYNC:
|
case SYS_SYNC:
|
||||||
ret = Process::current().sys_sync();
|
ret = Process::current().sys_sync((bool)arg1);
|
||||||
break;
|
break;
|
||||||
case SYS_MMAP:
|
case SYS_MMAP:
|
||||||
ret = Process::current().sys_mmap((const sys_mmap_t*)arg1);
|
ret = Process::current().sys_mmap((const sys_mmap_t*)arg1);
|
||||||
|
|
|
@ -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 symlink(const char* path1, const char* path2);
|
||||||
int symlinkat(const char* path1, int fd, const char* path2);
|
int symlinkat(const char* path1, int fd, const char* path2);
|
||||||
void sync(void);
|
void sync(void);
|
||||||
|
void syncsync(int should_block);
|
||||||
long sysconf(int name);
|
long sysconf(int name);
|
||||||
pid_t tcgetpgrp(int fildes);
|
pid_t tcgetpgrp(int fildes);
|
||||||
int tcsetpgrp(int fildes, pid_t pgid_id);
|
int tcsetpgrp(int fildes, pid_t pgid_id);
|
||||||
|
|
|
@ -202,7 +202,12 @@ int chdir(const char* path)
|
||||||
|
|
||||||
void sync(void)
|
void sync(void)
|
||||||
{
|
{
|
||||||
syscall(SYS_SYNC);
|
syscall(SYS_SYNC, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncsync(int should_block)
|
||||||
|
{
|
||||||
|
syscall(SYS_SYNC, should_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t getpid(void)
|
pid_t getpid(void)
|
||||||
|
|
|
@ -1,6 +1,29 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue