...
 
Commits (2)
......@@ -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() {}
};
......@@ -181,7 +170,7 @@ const size_t ConsoleDisplay::size = ConsoleDisplay::top - ConsoleDisplay::base;
static Display *getSerialDisplay();
static SerialDisplay serialConsole;
Display *Display::instance = getSerialDisplay();
volatile Display *Display::instance = getSerialDisplay();
Mutex Display::instanceMutex;
static Display *getSerialDisplay() { return &serialConsole; }
......@@ -220,13 +209,10 @@ void Display::setup() {
}
Display *Display::getInstance() {
if (instance) return instance;
uint64_t t = EnterCritical();
instanceMutex.lock();
if (instance) return const_cast<Display*>(instance);
Mutex::CriticalLock lock(instanceMutex);
if (!instance) setup();
instanceMutex.release();
LeaveCritical(t);
return instance;
return const_cast<Display*>(instance);
}
Display::~Display() {}
......@@ -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));
}
......@@ -8,7 +8,7 @@
class Display {
private:
static Mutex instanceMutex;
static Display *instance;
static volatile Display *instance;
static void setup();
protected:
Mutex mutex;
......
......@@ -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;
......
......@@ -8,17 +8,13 @@
#include "pagetable.hpp"
Mutex ACPI::controllerMutex;
ACPI* ACPI::controller = nullptr;
volatile 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);
return controller;
if (controller) return const_cast<ACPI*>(controller);
Mutex::CriticalLock lock(controllerMutex);
if (!controller) controller = new ACPI();
return const_cast<ACPI*>(controller);
}
ACPI::ACPI() {
......@@ -33,7 +29,7 @@ ACPI::ACPI() {
ioApicAddr = nullptr;
const uint64_t *ptr = nullptr;
if (!ptr && (ptr = static_cast<const uint64_t*>(EFI::getACPI2Addr()))) {
if (nullptr != (ptr = static_cast<const uint64_t*>(EFI::getACPI2Addr()))) {
Pagetable::map(ptr);
Pagetable::map(ptr + 1);
if ((*ptr != ACPI_SIG_RTP_DSR) || !ParseRsdp(ptr)) ptr = nullptr;
......
......@@ -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);
......
......@@ -105,7 +105,7 @@ class ACPI {
private:
static Mutex controllerMutex;
static ACPI *controller;
static volatile ACPI *controller;
char *localApicAddr, *ioApicAddr;
uint8_t ioApicMaxCount;
......
......@@ -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);
......
......@@ -12,7 +12,7 @@ class ModuleManager {
char *name, *version, *description, *requirements, *developer;
};
static Mutex managerMutex;
static ModuleManager* manager;
static volatile ModuleManager* manager;
void parseInternal();
void parseInitRD();
void loadStream(Stream *stream);
......
......@@ -16,7 +16,7 @@ class ProcessManager {
};
static Mutex managerMutex;
static ProcessManager* manager;
static volatile ProcessManager* manager;
ProcessManager();
QueuedThread *nextThread, *lastThread;
......
......@@ -6,6 +6,7 @@
#include "readelf.hpp"
#include "multiboot_info.hpp"
volatile ModuleManager* ModuleManager::manager = nullptr;
Mutex ModuleManager::managerMutex;
bool ModuleManager::parseModuleInfo(ModuleInfo *info, Process *process) {
......@@ -122,7 +123,6 @@ bool ModuleManager::bindRequirements(const char *reqs, Process *process) {
return 1;
}
ModuleManager* ModuleManager::manager = nullptr;
void ModuleManager::loadStream(Stream *stream) {
Stream *sub = stream;
Process *process;
......@@ -190,10 +190,8 @@ void ModuleManager::init() {
}
ModuleManager* ModuleManager::getManager() {
if (manager) return manager;
managerMutex.lock();
if (!manager)
manager = new ModuleManager();
managerMutex.release();
return manager;
if (manager) return const_cast<ModuleManager*>(manager);
Mutex::Lock lock(managerMutex);
if (!manager) manager = new ModuleManager();
return const_cast<ModuleManager*>(manager);
}
......@@ -13,17 +13,13 @@ void __attribute((naked)) ProcessManager::process_loop() {
}
Mutex ProcessManager::managerMutex;
ProcessManager* ProcessManager::manager = nullptr;
volatile 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);
return manager;
if (manager) return const_cast<ProcessManager*>(manager);
Mutex::CriticalLock lock(managerMutex);
if (!manager) manager = new ProcessManager();
return const_cast<ProcessManager*>(manager);
}
ProcessManager::ProcessManager() {
......@@ -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;
}