Unverified Commit d1bb756f authored by PhoeniX's avatar PhoeniX

Rewrite critical sections / mutexes to C++

parent 68d07bdf
......@@ -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<port + 3>::out<uint8_t>(0x03);
}
void write(const char *str) {
uint64_t t = EnterCritical();
mutex.lock();
Mutex::CriticalLock lock(mutex);
char c;
while ((c = *str++) != 0) Port<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;
}
......
......@@ -3,7 +3,6 @@
#pragma once
#include "kernlib/cpu.hpp"
#include "kernlib/display.hpp"
#include "kernlib/mem.hpp"
#include "kernlib/mutex.hpp"
......
// 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));
}
......@@ -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(); }
};
};
......@@ -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;
......
......@@ -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;
}
......
......@@ -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<HeapPage*>(Pagetable::alloc());
if (!allocs)
allocs = reinterpret_cast<AllocTable*>(Pagetable::alloc());
if (!heap_pages) heap_pages = reinterpret_cast<HeapPage*>(Pagetable::alloc());
if (!allocs) allocs = reinterpret_cast<AllocTable*>(Pagetable::alloc());
uintptr_t ptr = 0, ptr_top;
......@@ -123,7 +121,6 @@ next_page:
table = table->next;
}
done:
heap_mutex.release();
void *a = reinterpret_cast<void*>(ptr);
Memory::zero(a, size);
......@@ -131,51 +128,47 @@ done:
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);
......
......@@ -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<uint64_t*>(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);
}
......@@ -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);
}
......@@ -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);
......
......@@ -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;
}
......@@ -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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment