diff --git a/src/kernlib/display.cpp b/src/kernlib/display.cpp index 26304d0..039522a 100644 --- a/src/kernlib/display.cpp +++ b/src/kernlib/display.cpp @@ -42,16 +42,12 @@ class ConsoleDisplay: public Display { clean(); } void write(const char *str) { - uint64_t t = EnterCritical(); - mutex.lock(); + Mutex::CriticalLock lock(mutex); while (*str != 0) putc(*(str++)); - mutex.release(); - LeaveCritical(t); } void clean() { - mutex.lock(); + Mutex::Lock lock(mutex); Memory::fill(base, 0, size); - mutex.release(); } }; @@ -132,16 +128,12 @@ class FramebufferDisplay: public Display { clean(); } void write(const char *str) { - uint64_t t = EnterCritical(); - mutex.lock(); + Mutex::CriticalLock lock(mutex); while (*str != 0) putc(*(str++)); - mutex.release(); - LeaveCritical(t); } void clean() { - mutex.lock(); + Mutex::Lock lock(mutex); Memory::zero(framebuffer, bufferSize()); - mutex.release(); } }; @@ -164,12 +156,9 @@ class SerialDisplay: public Display { Port::out(0x03); } void write(const char *str) { - uint64_t t = EnterCritical(); - mutex.lock(); + Mutex::CriticalLock lock(mutex); char c; while ((c = *str++) != 0) Port::out(uint8_t(c)); - mutex.release(); - LeaveCritical(t); } void clean() {} }; @@ -221,11 +210,8 @@ void Display::setup() { Display *Display::getInstance() { if (instance) return instance; - uint64_t t = EnterCritical(); - instanceMutex.lock(); + Mutex::CriticalLock lock(instanceMutex); if (!instance) setup(); - instanceMutex.release(); - LeaveCritical(t); return instance; } diff --git a/src/kernlib/include/kernlib.hpp b/src/kernlib/include/kernlib.hpp index c76cb43..8bd7618 100644 --- a/src/kernlib/include/kernlib.hpp +++ b/src/kernlib/include/kernlib.hpp @@ -3,7 +3,6 @@ #pragma once -#include "kernlib/cpu.hpp" #include "kernlib/display.hpp" #include "kernlib/mem.hpp" #include "kernlib/mutex.hpp" diff --git a/src/kernlib/include/kernlib/cpu.hpp b/src/kernlib/include/kernlib/cpu.hpp deleted file mode 100644 index d1d7efc..0000000 --- a/src/kernlib/include/kernlib/cpu.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// PhoeniX OS Kernel library cpu functions -// Copyright © 2017 Yury Popov a.k.a. PhoeniX - -#pragma once -#include "std.hpp" - -namespace klib { - inline static uint64_t rdtsc() { - uint32_t eax, edx; - asm volatile("rdtsc":"=a"(eax), "=d"(edx)); - return ((uint64_t(edx) << 32) | eax); - } -} // namespace klib - -inline static uint64_t __attribute__((always_inline)) EnterCritical() { - uint64_t flags; - asm volatile("pushfq; cli; pop %q0":"=r"(flags)); - return flags; -} - -inline static void LeaveCritical(uint64_t flags) { - asm volatile("push %q0; popfq"::"r"(flags)); -} diff --git a/src/kernlib/include/kernlib/mutex.hpp b/src/kernlib/include/kernlib/mutex.hpp index 5d5bb4c..f8e2cd4 100644 --- a/src/kernlib/include/kernlib/mutex.hpp +++ b/src/kernlib/include/kernlib/mutex.hpp @@ -4,9 +4,29 @@ #pragma once #include "std.hpp" +class CriticalSection { + private: + uint64_t flags; + + public: + inline static uint64_t __attribute__((always_inline)) enter() { + uint64_t flags; + asm volatile("pushfq; cli; pop %q0":"=r"(flags)); + return flags; + } + + inline static void leave(uint64_t flags) { + asm volatile("push %q0; popfq"::"r"(flags)); + } + + CriticalSection() : flags(enter()) {} + ~CriticalSection() { leave(flags); } +}; + class Mutex { private: bool state; + public: Mutex(): state(0) {} inline void lock() { @@ -28,4 +48,20 @@ class Mutex { inline void release() { asm volatile("movw $0, %0"::"m"(state)); } + class Lock { + private: + Mutex *mutex; + public: + explicit Lock(Mutex *mutex) : mutex(mutex) { mutex->lock(); } + explicit Lock(Mutex &mutex) : Lock(&mutex) {} + ~Lock() { mutex->release(); } + }; + class CriticalLock: public CriticalSection { + private: + Mutex *mutex; + public: + explicit CriticalLock(Mutex *mutex) : mutex(mutex) { mutex->lock(); } + explicit CriticalLock(Mutex &mutex) : CriticalLock(&mutex) {} + ~CriticalLock() { mutex->release(); } + }; }; diff --git a/src/kernlib/include/kernlib/std.hpp b/src/kernlib/include/kernlib/std.hpp index 43c6bf4..338561b 100644 --- a/src/kernlib/include/kernlib/std.hpp +++ b/src/kernlib/include/kernlib/std.hpp @@ -25,6 +25,12 @@ namespace klib { int strncmp(const char*, const char*, int) PURE; int strcmp(const char*, const char*) PURE; + inline static uint64_t rdtsc() { + uint32_t eax, edx; + asm volatile("rdtsc":"=a"(eax), "=d"(edx)); + return ((uint64_t(edx) << 32) | eax); + } + inline static uintptr_t __align(uintptr_t base, size_t align) { if (base % align == 0) return base; diff --git a/src/platform/acpi.cpp b/src/platform/acpi.cpp index 887a1a5..ea6dbbe 100644 --- a/src/platform/acpi.cpp +++ b/src/platform/acpi.cpp @@ -12,12 +12,8 @@ ACPI* ACPI::controller = nullptr; ACPI* ACPI::getController() { if (controller) return controller; - uint64_t t = EnterCritical(); - controllerMutex.lock(); - if (!controller) - controller = new ACPI(); - controllerMutex.release(); - LeaveCritical(t); + Mutex::CriticalLock lock(controllerMutex); + if (!controller) controller = new ACPI(); return controller; } diff --git a/src/platform/heap.cpp b/src/platform/heap.cpp index 58168ff..297c9fe 100644 --- a/src/platform/heap.cpp +++ b/src/platform/heap.cpp @@ -28,12 +28,10 @@ Mutex Heap::heap_mutex; void* Heap::alloc(size_t size, size_t align) { if (size == 0) return nullptr; - heap_mutex.lock(); + Mutex::Lock lock(heap_mutex); - if (!heap_pages) - heap_pages = reinterpret_cast(Pagetable::alloc()); - if (!allocs) - allocs = reinterpret_cast(Pagetable::alloc()); + if (!heap_pages) heap_pages = reinterpret_cast(Pagetable::alloc()); + if (!allocs) allocs = reinterpret_cast(Pagetable::alloc()); uintptr_t ptr = 0, ptr_top; @@ -123,7 +121,6 @@ void* Heap::alloc(size_t size, size_t align) { table = table->next; } done: - heap_mutex.release(); void *a = reinterpret_cast(ptr); Memory::zero(a, size); @@ -131,51 +128,47 @@ void* Heap::alloc(size_t size, size_t align) { return a; } void Heap::free(void* addr) { - if (addr == nullptr) - return; - heap_mutex.lock(); + if (addr == nullptr) return; + Mutex::Lock lock(heap_mutex); AllocTable *t = allocs; while (1) { for (int i = 0; i < 255; i++) { if (t->allocs[i].addr == addr) { t->allocs[i].addr = nullptr; t->allocs[i].size = 0; - goto end; + return; } } - if (t->next == nullptr) - goto end; + if (t->next == nullptr) return; t = t->next; } - end: heap_mutex.release(); } void *Heap::realloc(void *addr, size_t size, size_t align) { if (size == 0) { free(addr); return nullptr; } - if (addr == nullptr) - return alloc(size, align); - heap_mutex.lock(); - AllocTable *t = allocs; + if (addr == nullptr) return alloc(size, align); size_t oldsize = 0; - while (t != nullptr) { - for (int i = 0; i < 255; i++) { - if (t->allocs[i].addr == addr) { - oldsize = t->allocs[i].size; - if (oldsize >= size) { - t->allocs[i].size = size; - heap_mutex.release(); - return addr; + { + Mutex::Lock lock(heap_mutex); + AllocTable *t = allocs; + while (t != nullptr) { + for (int i = 0; i < 255; i++) { + if (t->allocs[i].addr == addr) { + oldsize = t->allocs[i].size; + if (oldsize >= size) { + t->allocs[i].size = size; + return addr; + } + break; } - break; } + if (oldsize != 0) + break; + t = t->next; } - if (oldsize != 0) - break; - t = t->next; } - heap_mutex.release(); if (oldsize == 0) return nullptr; void *newptr = alloc(size, align); diff --git a/src/platform/interrupts.cpp b/src/platform/interrupts.cpp index 0dc61de..6e04ba3 100644 --- a/src/platform/interrupts.cpp +++ b/src/platform/interrupts.cpp @@ -223,8 +223,9 @@ void Interrupts::print(uint8_t num, CallbackRegs *regs, uint32_t code, const Pro uint64_t __attribute__((sysv_abi)) Interrupts::handle( unsigned char intr, uint64_t stack, uint64_t *pagetable) { - fault.lock(); - fault.release(); + { + Mutex::Lock lock(fault); + } uint64_t *rsp = reinterpret_cast(stack); bool has_code = (intr < 0x20) && FAULTS[intr].has_error_code; uint32_t error_code = 0; @@ -252,10 +253,11 @@ uint64_t __attribute__((sysv_abi)) Interrupts::handle( size_t idx = 0; Callback *cb; for (;;) { - callback_locks[intr].lock(); - cb = (callbacks[intr].getCount() > idx) ? callbacks[intr][idx] : nullptr; - idx++; - callback_locks[intr].release(); + { + Mutex::Lock lock(callback_locks[intr]); + cb = (callbacks[intr].getCount() > idx) ? callbacks[intr][idx] : nullptr; + idx++; + } if (cb == nullptr) break; handled = cb(intr, error_code, &cb_regs); if (handled) break; @@ -402,9 +404,6 @@ uint16_t Interrupts::getIRQmask() { } void Interrupts::addCallback(uint8_t intr, Callback* cb) { - uint64_t t = EnterCritical(); - callback_locks[intr].lock(); + Mutex::CriticalLock lock(callback_locks[intr]); callbacks[intr].add(cb); - callback_locks[intr].release(); - LeaveCritical(t); } diff --git a/src/platform/pagetable.cpp b/src/platform/pagetable.cpp index 3baa6b7..3812f85 100644 --- a/src/platform/pagetable.cpp +++ b/src/platform/pagetable.cpp @@ -412,12 +412,8 @@ void* Pagetable::_map(const void* mem) { } void* Pagetable::map(const void* mem) { - uint64_t t = EnterCritical(); - page_mutex.lock(); - void *addr = _map(mem); - page_mutex.release(); - LeaveCritical(t); - return addr; + Mutex::CriticalLock lock(page_mutex); + return _map(mem); } void* Pagetable::_alloc(uint8_t avl, bool nolow) { @@ -441,18 +437,13 @@ void* Pagetable::_alloc(uint8_t avl, bool nolow) { } void* Pagetable::alloc(uint8_t avl) { - uint64_t t = EnterCritical(); - page_mutex.lock(); - void* ret = _alloc(avl); - page_mutex.release(); - LeaveCritical(t); - return ret; + Mutex::CriticalLock lock(page_mutex); + return _alloc(avl); } void Pagetable::free(void* page) { PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable)); - uint64_t t = EnterCritical(); - page_mutex.lock(); + Mutex::CriticalLock lock(page_mutex); PTE *pdata = PTE::find(page, pagetable); if ((pdata != nullptr) && pdata->present) { pdata->present = 0; @@ -460,6 +451,4 @@ void Pagetable::free(void* page) { if ((uintptr_t(addr) >> 12) < last_page) last_page = uintptr_t(addr) >> 12; } - page_mutex.release(); - LeaveCritical(t); } diff --git a/src/platform/smp.cpp b/src/platform/smp.cpp index b23ec56..006c64e 100644 --- a/src/platform/smp.cpp +++ b/src/platform/smp.cpp @@ -20,8 +20,7 @@ void SMP::setup() { Interrupts::loadVector(); ACPI::getController()->activateCPU(); Syscall::setup(); - startupMutex.lock(); - startupMutex.release(); + Mutex::Lock lock(startupMutex); } void SMP::startup() { @@ -78,24 +77,23 @@ void SMP::init() { if (nullcpus > 0) nullcpus--; - startupMutex.lock(); - - for (uint32_t i = 0; i < cpuCount; i++) { - if (info->cpuids[i] != localId) { - acpi->sendCPUInit(uint32_t(info->cpuids[i])); - } - } - while (cpuCount - nullcpus != acpi->getActiveCPUCount()) { + { + Mutex::Lock lock(startupMutex); for (uint32_t i = 0; i < cpuCount; i++) { if (info->cpuids[i] != localId) { - acpi->sendCPUStartup(uint32_t(info->cpuids[i]), smp_init_vector); + acpi->sendCPUInit(uint32_t(info->cpuids[i])); } } - asm volatile("hlt"); + while (cpuCount - nullcpus != acpi->getActiveCPUCount()) { + for (uint32_t i = 0; i < cpuCount; i++) { + if (info->cpuids[i] != localId) { + acpi->sendCPUStartup(uint32_t(info->cpuids[i]), smp_init_vector); + } + } + asm volatile("hlt"); + } } - startupMutex.release(); - delete info->cpuids; delete info->stacks; Pagetable::free(startupCode); diff --git a/src/process/modules.cpp b/src/process/modules.cpp index 6d47358..16c2109 100644 --- a/src/process/modules.cpp +++ b/src/process/modules.cpp @@ -191,9 +191,7 @@ void ModuleManager::init() { ModuleManager* ModuleManager::getManager() { if (manager) return manager; - managerMutex.lock(); - if (!manager) - manager = new ModuleManager(); - managerMutex.release(); + Mutex::Lock lock(managerMutex); + if (!manager) manager = new ModuleManager(); return manager; } diff --git a/src/process/processmanager.cpp b/src/process/processmanager.cpp index 1601a89..e34c846 100644 --- a/src/process/processmanager.cpp +++ b/src/process/processmanager.cpp @@ -17,12 +17,8 @@ ProcessManager* ProcessManager::manager = nullptr; ProcessManager* ProcessManager::getManager() { if (manager) return manager; - uint64_t t = EnterCritical(); - managerMutex.lock(); - if (!manager) - manager = new ProcessManager(); - managerMutex.release(); - LeaveCritical(t); + Mutex::CriticalLock lock(managerMutex); + if (!manager) manager = new ProcessManager(); return manager; } @@ -44,17 +40,10 @@ bool ProcessManager::FaultHandler(uint8_t intr, uint32_t code, Interrupts::Callb bool ProcessManager::SwitchProcess(Interrupts::CallbackRegs *regs) { uintptr_t loopbase = uintptr_t(&process_loop), looptop; asm volatile("lea process_loop_top(%%rip), %q0":"=r"(looptop)); - processSwitchMutex.lock(); - if (regs->dpl == 0 && - (regs->rip < loopbase || regs->rip >= looptop)) { - processSwitchMutex.release(); - return false; - } + Mutex::Lock lock(processSwitchMutex); + if (regs->dpl == 0 && (regs->rip < loopbase || regs->rip >= looptop)) return false; QueuedThread *thread = nextThread; - if (thread == nullptr) { - processSwitchMutex.release(); - return false; - } + if (thread == nullptr) return false; nextThread = thread->next; if (thread == lastThread) lastThread = nullptr; @@ -88,46 +77,40 @@ bool ProcessManager::SwitchProcess(Interrupts::CallbackRegs *regs) { th->regs.r8, th->regs.r9, th->regs.r10, th->regs.r11, th->regs.r12, th->regs.r13, th->regs.r14, th->regs.r15 }; - processSwitchMutex.release(); return true; } bool ProcessManager::HandleFault(uint8_t intr, uint32_t code, Interrupts::CallbackRegs *regs) { if (regs->dpl == 0) return false; - uint64_t t = EnterCritical(); - processSwitchMutex.lock(); - QueuedThread *thread = cpuThreads[regs->cpuid]; - cpuThreads[regs->cpuid] = nullptr; - processSwitchMutex.release(); - LeaveCritical(t); + QueuedThread *thread; + { + Mutex::CriticalLock lock(processSwitchMutex); + thread = cpuThreads[regs->cpuid]; + cpuThreads[regs->cpuid] = nullptr; + } if (!thread) return false; Interrupts::print(intr, regs, code, thread->process); delete thread->process; delete thread; - if (SwitchProcess(regs)) - return true; - t = EnterCritical(); - processSwitchMutex.lock(); - asm volatile("mov %%cr3, %0":"=r"(regs->cr3)); - regs->rip = uintptr_t(&process_loop); - regs->cs = 0x08; - regs->ss = 0x10; - regs->dpl = 0; - processSwitchMutex.release(); - LeaveCritical(t); + if (SwitchProcess(regs)) return true; + { + Mutex::CriticalLock lock(processSwitchMutex); + asm volatile("mov %%cr3, %0":"=r"(regs->cr3)); + regs->rip = uintptr_t(&process_loop); + regs->cs = 0x08; + regs->ss = 0x10; + regs->dpl = 0; + } return true; } uint64_t ProcessManager::RegisterProcess(Process *process) { - uint64_t t = EnterCritical(); - processSwitchMutex.lock(); + Mutex::CriticalLock lock(processSwitchMutex); uint64_t pid = 1; for (size_t i = 0; i < processes.getCount(); i++) { pid = klib::max(pid, processes[i]->getId()); } processes.add(process); - processSwitchMutex.release(); - LeaveCritical(t); return pid; } @@ -136,20 +119,16 @@ void ProcessManager::queueThread(Process *process, Thread *thread) { q->process = process; q->thread = thread; q->next = nullptr; - uint64_t t = EnterCritical(); - processSwitchMutex.lock(); + Mutex::CriticalLock lock(processSwitchMutex); if (lastThread) { lastThread = (lastThread->next = q); } else { lastThread = nextThread = q; } - processSwitchMutex.release(); - LeaveCritical(t); } void ProcessManager::dequeueThread(Thread *thread) { - uint64_t t = EnterCritical(); - processSwitchMutex.lock(); + Mutex::CriticalLock lock(processSwitchMutex); QueuedThread *next = nextThread, *prev = nullptr; while (next != nullptr) { if (next->thread != thread) { @@ -172,16 +151,11 @@ void ProcessManager::dequeueThread(Thread *thread) { delete cpuThreads[cpu]; cpuThreads[cpu] = nullptr; } - processSwitchMutex.release(); - LeaveCritical(t); } Process *ProcessManager::currentProcess() { uint64_t cpuid = ACPI::getController()->getCPUID(); - uint64_t t = EnterCritical(); - processSwitchMutex.lock(); + Mutex::CriticalLock lock(processSwitchMutex); QueuedThread *curr = cpuThreads[cpuid]; - processSwitchMutex.release(); - LeaveCritical(t); return curr ? curr->process : nullptr; }