From 70e11f17e78ced81e7c1d384ca23dd462b380005 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 10 Apr 2023 05:29:41 +0300 Subject: [PATCH] Implement std::atomic and remove the old implementation Atomic and rename vector.hpp to vector --- Architecture/amd64/acpi.hpp | 2 +- .../amd64/cpu/SymmetricMultiprocessing.cpp | 10 +- Core/Crash/CrashHandler.cpp | 4 +- Core/InterruptsManager.cpp | 2 +- Core/Lock.cpp | 18 +- ...iversalAsynchronousReceiverTransmitter.cpp | 2 +- KThread.cpp | 2 +- Kernel.cpp | 4 + Tasking/Scheduler.cpp | 30 +- Tasking/Security.cpp | 2 +- Tasking/Task.cpp | 68 +-- Tests/std.cpp | 36 ++ include/atomic | 19 + include/atomic.hpp | 232 -------- include/cstddef | 24 + include/cstring | 6 +- include/disk.hpp | 2 +- include/driver.hpp | 2 +- include/filesystem.hpp | 2 +- include/gui.hpp | 2 +- include/ipc.hpp | 6 +- include/lock.hpp | 20 +- include/net/arp.hpp | 2 +- include/net/nc.hpp | 2 +- include/pci.hpp | 2 +- include/smp.hpp | 8 +- include/std.hpp | 9 +- include/std/atomic.hpp | 521 ++++++++++++++++++ include/std/unordered_map.hpp | 1 + include/task.hpp | 30 +- include/{vector.hpp => vector} | 0 31 files changed, 718 insertions(+), 352 deletions(-) create mode 100644 Tests/std.cpp create mode 100644 include/atomic delete mode 100644 include/atomic.hpp create mode 100644 include/cstddef create mode 100644 include/std/atomic.hpp rename include/{vector.hpp => vector} (100%) diff --git a/Architecture/amd64/acpi.hpp b/Architecture/amd64/acpi.hpp index e6ea0cd..1a71f71 100644 --- a/Architecture/amd64/acpi.hpp +++ b/Architecture/amd64/acpi.hpp @@ -22,8 +22,8 @@ #include #include -#include #include +#include namespace ACPI { diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index 7f3fc51..94dc157 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -18,10 +18,10 @@ #include #include -#include #include #include #include +#include #include "../../../kernel.h" #include "../acpi.hpp" @@ -41,7 +41,7 @@ enum SMPTrampolineAddress TRAMPOLINE_START = 0x2000 }; -Atomic CPUEnabled = false; +std::atomic_bool CPUEnabled = false; #pragma GCC diagnostic ignored "-Wmissing-field-initializers" static __aligned(PAGE_SIZE) CPUData CPUs[MAX_CPU] = {0}; @@ -79,7 +79,7 @@ extern "C" void StartCPU() CPU::Interrupts(CPU::Enable); KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID); - CPUEnabled.Store(true, MemoryOrder::Release); + CPUEnabled.store(true, std::memory_order_release); CPU::Halt(true); } @@ -124,9 +124,9 @@ namespace SMP ((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(((ACPI::MADT *)madt)->lapic[i]->APICId); ((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START); - while (!CPUEnabled.Load(MemoryOrder::Acquire)) + while (!CPUEnabled.load(std::memory_order_acquire)) CPU::Pause(); - CPUEnabled.Store(false, MemoryOrder::Release); + CPUEnabled.store(false, std::memory_order_release); trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId); } else diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index 01233fc..330ce26 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -999,8 +999,8 @@ namespace CrashHandler if (TaskManager && cpudata != nullptr) { - crashdata.Process = cpudata->CurrentProcess.Load(); - crashdata.Thread = cpudata->CurrentThread.Load(); + crashdata.Process = cpudata->CurrentProcess.load(); + crashdata.Thread = cpudata->CurrentThread.load(); error("Current Process: %s(%ld)", cpudata->CurrentProcess->Name, diff --git a/Core/InterruptsManager.cpp b/Core/InterruptsManager.cpp index 37042e6..cf0f653 100644 --- a/Core/InterruptsManager.cpp +++ b/Core/InterruptsManager.cpp @@ -18,8 +18,8 @@ #include #include -#include #include +#include #include #if defined(a64) diff --git a/Core/Lock.cpp b/Core/Lock.cpp index ba1aeb5..f032fec 100644 --- a/Core/Lock.cpp +++ b/Core/Lock.cpp @@ -29,7 +29,7 @@ #endif bool ForceUnlock = false; -Atomic LocksCount = 0; +std::atomic_size_t LocksCount = 0; size_t GetLocksCount() { return LocksCount; } @@ -75,7 +75,7 @@ void LockClass::DeadLock(SpinLockData Lock) this->DeadLocks++; - if (Config.UnlockDeadLock && this->DeadLocks.Load() > 10) + if (Config.UnlockDeadLock && this->DeadLocks.load() > 10) { warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet); this->DeadLocks = 0; @@ -93,7 +93,7 @@ int LockClass::Lock(const char *FunctionName) Retry: int i = 0; - while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) + while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) CPU::Pause(); if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) @@ -120,7 +120,7 @@ int LockClass::Unlock() { __sync; - IsLocked.Store(false, MemoryOrder::Release); + IsLocked.store(false, std::memory_order_release); LockData.Count--; LocksCount--; @@ -178,17 +178,17 @@ int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout) LockData.AttemptingToGet = FunctionName; LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0); - Atomic Target = 0; + std::atomic_uint64_t Target = 0; Retry: int i = 0; - while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) + while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) CPU::Pause(); if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) { - if (Target.Load() == 0) - Target.Store(TimeManager->CalculateTarget(Timeout)); - TimeoutDeadLock(LockData, Target.Load()); + if (Target.load() == 0) + Target.store(TimeManager->CalculateTarget(Timeout)); + TimeoutDeadLock(LockData, Target.load()); goto Retry; } diff --git a/Core/UniversalAsynchronousReceiverTransmitter.cpp b/Core/UniversalAsynchronousReceiverTransmitter.cpp index 737fd0b..7fbac22 100644 --- a/Core/UniversalAsynchronousReceiverTransmitter.cpp +++ b/Core/UniversalAsynchronousReceiverTransmitter.cpp @@ -17,8 +17,8 @@ #include -#include #include +#include volatile bool serialports[8] = {false, false, false, false, false, false, false, false}; std::vector RegisteredEvents; diff --git a/KThread.cpp b/KThread.cpp index be82894..1365149 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -18,12 +18,12 @@ #include "kernel.h" #include -#include #include #include #include #include #include +#include #define STB_IMAGE_IMPLEMENTATION #define STBI_NO_STDIO diff --git a/Kernel.cpp b/Kernel.cpp index a747318..8d1c048 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -155,6 +155,10 @@ LockClass mExtTrkLock; * https://en.wikipedia.org/wiki/Control_register * https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf * https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention + * + * - Atomic operations: + * https://en.cppreference.com/w/cpp/atomic/atomic + * */ #ifdef a64 diff --git a/Tasking/Scheduler.cpp b/Tasking/Scheduler.cpp index cb8803c..f1d8b57 100644 --- a/Tasking/Scheduler.cpp +++ b/Tasking/Scheduler.cpp @@ -124,12 +124,12 @@ namespace Tasking SafeFunction NIF bool Task::FindNewProcess(void *CPUDataPointer) { CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - fnp_schedbg("%d processes", ListProcess.size()); + fnp_schedbg("%d processes", ProcessList.size()); #ifdef DEBUG_FIND_NEW_PROCESS - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) fnp_schedbg("Process %d %s", process->ID, process->Name); #endif - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { if (InvalidPCB(process)) continue; @@ -179,7 +179,7 @@ namespace Tasking for (size_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++) { - if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread.Load()) + if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread.load()) { size_t TempIndex = i; RetryAnotherThread: @@ -213,7 +213,7 @@ namespace Tasking CurrentCPU->CurrentThread = nextThread; gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", thread->ID, thread->Parent->Name, - CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size()); + CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size()); return true; } #ifdef DEBUG @@ -232,9 +232,9 @@ namespace Tasking CPUData *CurrentCPU = (CPUData *)CPUDataPointer; bool Skip = true; - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { - if (process == CurrentCPU->CurrentProcess.Load()) + if (process == CurrentCPU->CurrentProcess.load()) { Skip = false; gnap_schedbg("Found current process %#lx", process); @@ -279,7 +279,7 @@ namespace Tasking CurrentCPU->CurrentProcess = process; CurrentCPU->CurrentThread = thread; gnap_schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", - thread->ID, thread->Name, process->Threads.size(), ListProcess.size()); + thread->ID, thread->Name, process->Threads.size(), ProcessList.size()); return true; } } @@ -291,7 +291,7 @@ namespace Tasking { CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { if (InvalidPCB(process)) { @@ -325,7 +325,7 @@ namespace Tasking CurrentCPU->CurrentProcess = process; CurrentCPU->CurrentThread = thread; sspt_schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", - thread->ID, thread->Parent->Name, process->Threads.size(), ListProcess.size()); + thread->ID, thread->Parent->Name, process->Threads.size(), ProcessList.size()); return true; } } @@ -334,7 +334,7 @@ namespace Tasking SafeFunction NIF void Task::UpdateProcessStatus() { - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { if (InvalidPCB(process)) continue; @@ -363,7 +363,7 @@ namespace Tasking SafeFunction NIF void Task::WakeUpThreads(void *CPUDataPointer) { CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { if (InvalidPCB(process)) continue; @@ -479,7 +479,7 @@ namespace Tasking } CPU::x64::writecr3({.raw = (uint64_t)KernelPageTable}); /* Restore kernel page table for safety reasons. */ uint64_t SchedTmpTicks = CPU::Counter(); - this->LastTaskTicks.Store(SchedTmpTicks - this->SchedulerTicks.Load()); + this->LastTaskTicks.store(SchedTmpTicks - this->SchedulerTicks.load()); CPUData *CurrentCPU = GetCurrentCPU(); schedbg("Scheduler called on CPU %d.", CurrentCPU->ID); schedbg("%d: %ld%%", CurrentCPU->ID, GetUsage(CurrentCPU->ID)); @@ -509,7 +509,7 @@ namespace Tasking } #endif - if (unlikely(InvalidPCB(CurrentCPU->CurrentProcess.Load()) || InvalidTCB(CurrentCPU->CurrentThread.Load()))) + if (unlikely(InvalidPCB(CurrentCPU->CurrentProcess.load()) || InvalidTCB(CurrentCPU->CurrentThread.load()))) { schedbg("Invalid process or thread. Finding a new one."); if (this->FindNewProcess(CurrentCPU)) @@ -669,7 +669,7 @@ namespace Tasking /* RealEnd->[Function Exit] */ RealEnd: - this->SchedulerTicks.Store(CPU::Counter() - SchedTmpTicks); + this->SchedulerTicks.store(CPU::Counter() - SchedTmpTicks); __sync; /* TODO: Is this really needed? */ } diff --git a/Tasking/Security.cpp b/Tasking/Security.cpp index 9f1d1e5..29da4e3 100644 --- a/Tasking/Security.cpp +++ b/Tasking/Security.cpp @@ -17,9 +17,9 @@ #include -#include #include #include +#include namespace Tasking { diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index c3ee5a9..3e528e1 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -130,36 +130,36 @@ namespace Tasking foreach (PCB *process in Process->Children) RemoveProcess(process); - for (size_t i = 0; i < ListProcess.size(); i++) + for (size_t i = 0; i < ProcessList.size(); i++) { - if (ListProcess[i] == Process) + if (ProcessList[i] == Process) { trace("Process \"%s\"(%d) removed from the list", Process->Name, Process->ID); // Free memory - delete ListProcess[i]->IPC, ListProcess[i]->IPC = nullptr; - delete ListProcess[i]->ELFSymbolTable, ListProcess[i]->ELFSymbolTable = nullptr; - SecurityManager.DestroyToken(ListProcess[i]->Security.UniqueToken); - if (ListProcess[i]->Security.TrustLevel == TaskTrustLevel::User) - KernelAllocator.FreePages((void *)ListProcess[i]->PageTable, TO_PAGES(sizeof(Memory::PageTable4) + 1)); + delete ProcessList[i]->IPC, ProcessList[i]->IPC = nullptr; + delete ProcessList[i]->ELFSymbolTable, ProcessList[i]->ELFSymbolTable = nullptr; + SecurityManager.DestroyToken(ProcessList[i]->Security.UniqueToken); + if (ProcessList[i]->Security.TrustLevel == TaskTrustLevel::User) + KernelAllocator.FreePages((void *)ProcessList[i]->PageTable, TO_PAGES(sizeof(Memory::PageTable4) + 1)); // Remove the process from parent's children list - if (ListProcess[i]->Parent) - for (size_t j = 0; j < ListProcess[i]->Parent->Children.size(); j++) + if (ProcessList[i]->Parent) + for (size_t j = 0; j < ProcessList[i]->Parent->Children.size(); j++) { - if (ListProcess[i]->Parent->Children[j] == ListProcess[i]) + if (ProcessList[i]->Parent->Children[j] == ProcessList[i]) { - ListProcess[i]->Parent->Children.remove(j); + ProcessList[i]->Parent->Children.remove(j); break; } } // Delete process directory - vfs->Delete(ListProcess[i]->ProcessDirectory, true); + vfs->Delete(ProcessList[i]->ProcessDirectory, true); // Free memory - delete ListProcess[i], ListProcess[i] = nullptr; + delete ProcessList[i], ProcessList[i] = nullptr; // Remove from the list - ListProcess.remove(i); + ProcessList.remove(i); break; } } @@ -217,23 +217,23 @@ namespace Tasking CPU::Halt(true); } - PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.Load(); } - TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.Load(); } + PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.load(); } + TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.load(); } PCB *Task::GetProcessByID(UPID ID) { - for (size_t i = 0; i < ListProcess.size(); i++) - if (ListProcess[i]->ID == ID) - return ListProcess[i]; + for (size_t i = 0; i < ProcessList.size(); i++) + if (ProcessList[i]->ID == ID) + return ProcessList[i]; return nullptr; } TCB *Task::GetThreadByID(UTID ID) { - for (size_t i = 0; i < ListProcess.size(); i++) - for (size_t j = 0; j < ListProcess[i]->Threads.size(); j++) - if (ListProcess[i]->Threads[j]->ID == ID) - return ListProcess[i]->Threads[j]; + for (size_t i = 0; i < ProcessList.size(); i++) + for (size_t j = 0; j < ProcessList[i]->Threads.size(); j++) + if (ProcessList[i]->Threads[j]->ID == ID) + return ProcessList[i]->Threads[j]; return nullptr; } @@ -312,7 +312,7 @@ namespace Tasking while (true) { this->Sleep(1000); - foreach (auto process in ListProcess) + foreach (auto process in ProcessList) { if (InvalidPCB(process)) continue; @@ -324,9 +324,9 @@ namespace Tasking void Task::RevertProcessCreation(PCB *Process) { - for (size_t i = 0; i < ListProcess.size(); i++) + for (size_t i = 0; i < ProcessList.size(); i++) { - if (ListProcess[i] == Process) + if (ProcessList[i] == Process) { SecurityManager.DestroyToken(Process->Security.UniqueToken); if (Process->Security.TrustLevel == TaskTrustLevel::User) @@ -345,7 +345,7 @@ namespace Tasking delete Process->IPC, Process->IPC = nullptr; delete Process->ELFSymbolTable, Process->ELFSymbolTable = nullptr; delete Process, Process = nullptr; - ListProcess.remove(i); + ProcessList.remove(i); NextPID--; break; } @@ -769,7 +769,7 @@ namespace Tasking if (Parent) Parent->Children.push_back(Process); - ListProcess.push_back(Process); + ProcessList.push_back(Process); return Process; } @@ -859,27 +859,27 @@ namespace Tasking debug("Destructor called"); { SmartLock(TaskingLock); - foreach (PCB *Process in ListProcess) + foreach (PCB *Process in ProcessList) { foreach (TCB *Thread in Process->Threads) { - if (Thread == GetCurrentCPU()->CurrentThread.Load() || + if (Thread == GetCurrentCPU()->CurrentThread.load() || Thread == CleanupThread) continue; this->KillThread(Thread, 0xFFFF); } - if (Process == GetCurrentCPU()->CurrentProcess.Load()) + if (Process == GetCurrentCPU()->CurrentProcess.load()) continue; this->KillProcess(Process, 0xFFFF); } } - while (ListProcess.size() > 0) + while (ProcessList.size() > 0) { - trace("Waiting for %d processes to terminate", ListProcess.size()); + trace("Waiting for %d processes to terminate", ProcessList.size()); int NotTerminated = 0; - foreach (PCB *Process in ListProcess) + foreach (PCB *Process in ProcessList) { debug("Process %s(%d) is still running (or waiting to be removed status %#lx)", Process->Name, Process->ID, Process->Status); if (Process->Status == TaskStatus::Terminated) diff --git a/Tests/std.cpp b/Tests/std.cpp new file mode 100644 index 0000000..6b0c0e9 --- /dev/null +++ b/Tests/std.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifdef DEBUG + +#include +#include + +__constructor void Test_std() +{ + std::atomic_int a = 0; + a++; + assert(a == 1); + + int b = a.exchange(2); + assert(b == 1); + assert(a == 2); + + debug("std: OK"); +} + +#endif // DEBUG diff --git a/include/atomic b/include/atomic new file mode 100644 index 0000000..47ebc29 --- /dev/null +++ b/include/atomic @@ -0,0 +1,19 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once +#include diff --git a/include/atomic.hpp b/include/atomic.hpp deleted file mode 100644 index 6dc77e6..0000000 --- a/include/atomic.hpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_ATOMIC_H__ -#define __FENNIX_KERNEL_ATOMIC_H__ - -#define _Atomic(T) T -#define builtin_atomic_n(name) __atomic_##name##_n -#define builtin_atomic(name) __atomic_##name - -enum MemoryOrder -{ - /** - * @brief Relaxed memory order - * - * This memory ordering specifies that the - * operation on the atomic variable has no - * synchronization with other memory accesses. - * This is the most relaxed ordering and provides - * the least synchronization. - */ - Relaxed = __ATOMIC_RELAXED, - - /** - * @brief Acquire memory order - * - * This memory ordering specifies that subsequent - * memory accesses after the atomic operation - * cannot be reordered before the atomic operation. - * This ordering provides synchronization with - * subsequent loads. - */ - Acquire = __ATOMIC_ACQUIRE, - - /** - * @brief Release memory order - * - * This memory ordering specifies that previous - * memory accesses before the atomic operation - * cannot be reordered after the atomic operation. - * This ordering provides synchronization with - * previous stores. - */ - Release = __ATOMIC_RELEASE, - - /** - * @brief Acquire and release memory order - * - * This memory ordering combines both the acquire - * and release memory orderings. This ordering - * provides synchronization with both previous - * stores and subsequent loads. - */ - AcqRel = __ATOMIC_ACQ_REL, - - /** - * @brief Sequentially consistent memory order - * - * This memory ordering is a combination of - * @see AcqRel and the additional - * guarantee of a single total order of all - * @see SeqCst operations on the same object. - */ - SeqCst = __ATOMIC_SEQ_CST -}; - -template -class Atomic -{ - _Atomic(T) Value; - -public: - Atomic() : Value(0) {} - Atomic(T Init) : Value(Init) {} - - /** - * @brief Load the value of the atomic variable - * - * @param Order The memory order to use - * @return T The value of the atomic variable - */ - T Load(MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic_n(load)(&this->Value, Order); - } - - /** - * @brief Store a value to the atomic variable - * - * @param v The value to store - * @param Order The memory order to use - */ - void Store(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic_n(store)(&this->Value, v, Order); - } - - /** - * @brief Exchange the value of the atomic variable - * - * @param v The value to exchange - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T Exchange(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic_n(exchange)(&this->Value, v, Order); - } - - /** - * @brief Compare and exchange the value of the atomic variable - * - * @param Expected The expected value - * @param Desired The desired value - * @param Order The memory order to use - * @return true If the exchange was successful - * @return false If the exchange was not successful - */ - bool CompareExchange(T &Expected, T Desired, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic_n(compare_exchange)(&this->Value, &Expected, Desired, true, Order, Order); - } - - /** - * @brief Fetch and add the value of the atomic variable - * - * @param v The value to add - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchAdd(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_add)(&this->Value, v, Order); - } - - /** - * @brief Fetch and subtract the value of the atomic variable - * - * @param v The value to subtract - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchSub(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_sub)(&this->Value, v, Order); - } - - /** - * @brief Fetch and and the value of the atomic variable - * - * @param v The value to and - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchAnd(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_and)(&this->Value, v, Order); - } - - /** - * @brief Fetch and or the value of the atomic variable - * - * @param v The value to or - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchOr(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_or)(&this->Value, v, Order); - } - - /** - * @brief Fetch and xor the value of the atomic variable - * - * @param v The value to xor - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchXor(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_xor)(&this->Value, v, Order); - } - - /** - * @brief Fetch and nand the value of the atomic variable - * - * @param v The value to nand - * @param Order The memory order to use - * @return T The old value of the atomic variable - */ - T FetchNand(T v, MemoryOrder Order = MemoryOrder::SeqCst) - { - return builtin_atomic(fetch_nand)(&this->Value, v, Order); - } - - operator bool() { return this->Load() != 0; } - T operator->() { return this->Load(); } - T operator++() { return this->FetchAdd(1) + 1; } - T operator--() { return this->FetchSub(1) - 1; } - T operator++(int) { return this->FetchAdd(1); } - T operator--(int) { return this->FetchSub(1); } - T operator+=(T v) { return this->FetchAdd(v) + v; } - T operator-=(T v) { return this->FetchSub(v) - v; } - T operator&=(T v) { return this->FetchAnd(v) & v; } - T operator|=(T v) { return this->FetchOr(v) | v; } - T operator^=(T v) { return this->FetchXor(v) ^ v; } - T operator~() { return this->FetchNand(-1); } - T operator=(T v) - { - this->Store(v); - return v; - } -}; - -#undef builtin_atomic_n -#undef builtin_atomic - -#endif // !__FENNIX_KERNEL_ATOMIC_H__ diff --git a/include/cstddef b/include/cstddef new file mode 100644 index 0000000..bbfa92b --- /dev/null +++ b/include/cstddef @@ -0,0 +1,24 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +namespace std +{ + typedef unsigned long size_t; + typedef long ptrdiff_t; +} diff --git a/include/cstring b/include/cstring index e63542e..b1a7f20 100644 --- a/include/cstring +++ b/include/cstring @@ -15,9 +15,5 @@ along with Fennix Kernel. If not, see . */ -#ifndef __FENNIX_KERNEL_CSTRING_H__ -#define __FENNIX_KERNEL_CSTRING_H__ - +#pragma once #include - -#endif // !__FENNIX_KERNEL_CSTRING_H__ diff --git a/include/disk.hpp b/include/disk.hpp index b357dc8..7077cbf 100644 --- a/include/disk.hpp +++ b/include/disk.hpp @@ -19,7 +19,7 @@ #define __FENNIX_KERNEL_DISK_H__ #include -#include +#include namespace Disk { diff --git a/include/driver.hpp b/include/driver.hpp index 0919359..f639fb2 100644 --- a/include/driver.hpp +++ b/include/driver.hpp @@ -20,12 +20,12 @@ #include -#include #include #include #include #include #include +#include namespace Driver { diff --git a/include/filesystem.hpp b/include/filesystem.hpp index 4b71d8c..33de81f 100644 --- a/include/filesystem.hpp +++ b/include/filesystem.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace VirtualFileSystem { diff --git a/include/gui.hpp b/include/gui.hpp index 9d8764d..4e6caee 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include namespace GraphicalUserInterface { diff --git a/include/ipc.hpp b/include/ipc.hpp index 18fa06f..1ffc0a3 100644 --- a/include/ipc.hpp +++ b/include/ipc.hpp @@ -20,10 +20,10 @@ #include #include -#include #include -#include #include +#include +#include namespace InterProcessCommunication { @@ -59,7 +59,7 @@ namespace InterProcessCommunication VirtualFileSystem::Node *Node; void *Buffer; long Length; - Atomic Listening; + std::atomic_bool Listening; }; class IPC diff --git a/include/lock.hpp b/include/lock.hpp index 33c7109..31fd7b1 100644 --- a/include/lock.hpp +++ b/include/lock.hpp @@ -20,8 +20,8 @@ #include -#include #include +#include #ifdef __cplusplus @@ -40,19 +40,19 @@ class LockClass { struct SpinLockData { - Atomic LockData = 0x0; - Atomic CurrentHolder = "(nul)"; - Atomic AttemptingToGet = "(nul)"; - Atomic StackPointerHolder = 0; - Atomic StackPointerAttempt = 0; - Atomic Count = 0; - Atomic Core = 0; + std::atomic_uint64_t LockData = 0x0; + std::atomic CurrentHolder = "(nul)"; + std::atomic AttemptingToGet = "(nul)"; + std::atomic_uintptr_t StackPointerHolder = 0; + std::atomic_uintptr_t StackPointerAttempt = 0; + std::atomic_size_t Count = 0; + std::atomic_long Core = 0; }; private: SpinLockData LockData; - Atomic IsLocked = false; - Atomic DeadLocks = 0; + std::atomic_bool IsLocked = false; + std::atomic_ulong DeadLocks = 0; void DeadLock(SpinLockData Lock); void TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout); diff --git a/include/net/arp.hpp b/include/net/arp.hpp index ecc9f30..d4ecce8 100644 --- a/include/net/arp.hpp +++ b/include/net/arp.hpp @@ -20,8 +20,8 @@ #include #include -#include #include +#include namespace NetworkARP { diff --git a/include/net/nc.hpp b/include/net/nc.hpp index a502b6e..3433c56 100644 --- a/include/net/nc.hpp +++ b/include/net/nc.hpp @@ -19,11 +19,11 @@ #define __FENNIX_KERNEL_NETWORK_CONTROLLER_H__ #include -#include #include #include #include #include +#include namespace NetworkInterfaceManager { diff --git a/include/pci.hpp b/include/pci.hpp index 24bfd1d..0925abc 100644 --- a/include/pci.hpp +++ b/include/pci.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace PCI { diff --git a/include/smp.hpp b/include/smp.hpp index 324aa44..473d434 100644 --- a/include/smp.hpp +++ b/include/smp.hpp @@ -18,9 +18,9 @@ #ifndef __FENNIX_KERNEL_SMP_H__ #define __FENNIX_KERNEL_SMP_H__ -#include -#include #include +#include +#include /** @brief Maximum supported number of CPU cores by the kernel */ #define MAX_CPU 256 @@ -54,10 +54,10 @@ struct CPUData long ErrorCode; /** @brief Current running process */ - Atomic CurrentProcess; + std::atomic CurrentProcess; /** @brief Current running thread */ - Atomic CurrentThread; + std::atomic CurrentThread; /** @brief Architecture-specific data. */ CPUArchData Data; diff --git a/include/std.hpp b/include/std.hpp index e4c01d6..1b01608 100644 --- a/include/std.hpp +++ b/include/std.hpp @@ -22,14 +22,15 @@ #define __FENNIX_KERNEL_STD_H__ #include -#include +#include #include -#include +#include #include +#include +#include +#include #include #include -#include -#include /** * @brief // stub namespace for std::align_val_t and new operator diff --git a/include/std/atomic.hpp b/include/std/atomic.hpp new file mode 100644 index 0000000..bee5b49 --- /dev/null +++ b/include/std/atomic.hpp @@ -0,0 +1,521 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_STD_ATOMIC_H__ +#define __FENNIX_KERNEL_STD_ATOMIC_H__ + +#include +#include +#include + +namespace std +{ +#define _atomic(T) T +#define builtin_atomic_n(name) __atomic_##name##_n +#define builtin_atomic(name) __atomic_##name + + /** + * @brief Specifies the memory ordering constraints for atomic operations. + * + * This enum specifies the possible values for the memory order parameter of atomic operations. + * + * Possible values are: + * + * - memory_order_relaxed: There are no synchronization + * or ordering constraints imposed on other reads or writes, + * only this operation's atomicity is guaranteed. + * + * - memory_order_consume: A load operation with this + * memory order performs a consume operation on the + * affected memory location: no reads or writes in the + * current thread dependent on the value currently loaded + * can be reordered before this load. + * + * - memory_order_acquire: A load operation with this + * memory order performs the acquire operation on the + * affected memory location: no reads or writes in the + * current thread can be reordered before this load. + * + * - memory_order_release: A store operation with this + * memory order performs the release operation: no reads + * or writes in the current thread can be reordered after + * this store. + * + * - memory_order_acq_rel: A read-modify-write operation + * with this memory order is both an acquire operation + * and a release operation. + * + * - memory_order_seq_cst: A load operation with this + * memory order performs an acquire operation, a store + * performs a release operation, and read-modify-write + * performs both an acquire operation and a release + * operation, plus a single total order exists in which + * all threads observe all modifications in the same order. + */ + enum class memory_order : int + { + relaxed, + consume, + acquire, + release, + acq_rel, + seq_cst + }; + + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; + + template + class atomic + { + _atomic(T) value; + + public: + atomic() noexcept : value(0) {} + atomic(T desired) noexcept : value(desired) {} + // atomic(const atomic &) = delete; + + /** + * @brief Load the value of the atomic variable + * + * @note Order must be one of memory_order::relaxed, memory_order::consume, memory_order::acquire or memory_order::seq_cst + * + * @param order Memory order constraint to use + * @return The value of the atomic variable + */ + T load(memory_order order = memory_order::seq_cst) const noexcept + { + return builtin_atomic_n(load)(&this->value, static_cast(order)); + } + + /** + * @copydoc load() + */ + T load(memory_order order = memory_order::seq_cst) const volatile noexcept + { + return builtin_atomic_n(load)(&this->value, static_cast(order)); + } + + /** + * @brief Store the value of the atomic variable + * + * @note Order must be one of memory_order::relaxed, memory_order::release or memory_order::seq_cst + * + * @param desired The value to store + * @param order Memory order constraint to use + */ + void store(T desired, memory_order order = memory_order::seq_cst) noexcept + { + builtin_atomic_n(store)(&this->value, desired, static_cast(order)); + } + + /** + * @copydoc store() + */ + void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept + { + builtin_atomic_n(store)(&this->value, desired, static_cast(order)); + } + + /** + * @brief Exchange the value of the atomic variable + * + * @param desired The value to exchange + * @param order Memory order constraint to use + * @return The value of the atomic variable before the exchange + */ + T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept + { + return builtin_atomic_n(exchange)(&this->value, desired, static_cast(order)); + } + + /** + * @copydoc exchange() + */ + T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept + { + return builtin_atomic_n(exchange)(&this->value, desired, static_cast(order)); + } + + /** + * @brief Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param success Memory order constraint to use if the exchange succeeds + * @param failure Memory order constraint to use if the exchange fails + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure); + } + + /** + * @copydoc compare_exchange_weak() + */ + bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure); + } + + /** + * @brief Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param order Memory order constraint to use + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast(order)); + } + + /** + * @copydoc compare_exchange_weak() + */ + bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast(order)); + } + + /** + * @brief Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param success Memory order constraint to use if the exchange succeeds + * @param failure Memory order constraint to use if the exchange fails + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure); + } + + /** + * @copydoc compare_exchange_strong() + */ + bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure); + } + + /** + * @brief Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param order Memory order constraint to use + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast(order)); + } + + /** + * @copydoc compare_exchange_strong() + */ + bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast(order)); + } + + /** + * @brief Fetch and add the value of the atomic variable + * + * @param arg The value to add + * @param order Memory order constraint to use + * @return The value of the atomic variable before the addition + */ + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_add)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_add() + */ + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_add)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Fetch and subtract the value of the atomic variable + * + * @param arg The value to subtract + * @param order Memory order constraint to use + * @return The value of the atomic variable before the subtraction + */ + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_sub)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_sub() + */ + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_sub)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Fetch and bitwise AND the value of the atomic variable + * + * @param arg The value to AND + * @param order Memory order constraint to use + * @return The value of the atomic variable before the AND + */ + T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_and)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_and() + */ + T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_and)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Fetch and bitwise OR the value of the atomic variable + * + * @param arg The value to OR + * @param order Memory order constraint to use + * @return The value of the atomic variable before the OR + */ + T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_or)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_or() + */ + T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_or)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Fetch and bitwise XOR the value of the atomic variable + * + * @param arg The value to XOR + * @param order Memory order constraint to use + * @return The value of the atomic variable before the XOR + */ + T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_xor)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_xor() + */ + T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_xor)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Fetch and bitwise NAND the value of the atomic variable + * + * @param arg The value to NAND + * @param order Memory order constraint to use + * @return The value of the atomic variable before the NAND + */ + T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept + { + return builtin_atomic(fetch_nand)(&this->value, arg, static_cast(order)); + } + + /** + * @copydoc fetch_nand() + */ + T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept + { + return builtin_atomic(fetch_nand)(&this->value, arg, static_cast(order)); + } + + /** + * @brief Notify all threads waiting on this atomic variable + */ + void notify_all() noexcept + { + fixme("not implemented"); + } + + /** + * @copydoc notify_all() + */ + void notify_all() volatile noexcept + { + fixme("not implemented"); + } + + /** + * @brief Notify one thread waiting on this atomic variable + */ + void notify_one() noexcept + { + fixme("not implemented"); + } + + /** + * @copydoc notify_one() + */ + void notify_one() volatile noexcept + { + fixme("not implemented"); + } + + /** + * @brief Wait for the atomic variable to change + * + * @param old The value to wait for + * @param order Memory order constraint to use + */ + void wait(T old, std::memory_order order = std::memory_order::seq_cst) const noexcept + { + fixme("not implemented"); + } + + /** + * @copydoc wait() + */ + void wait(T old, std::memory_order order = std::memory_order::seq_cst) const volatile noexcept + { + fixme("not implemented"); + } + + /** + * @brief Check whether this atomic type is lock-free + * @return True if this atomic type is lock-free + */ + bool is_lock_free() const noexcept + { + fixme("not implemented"); + return true; + } + + /** + * @copydoc is_lock_free() + */ + bool is_lock_free() const volatile noexcept + { + fixme("not implemented"); + return true; + } + + /** + * @brief Equals true if this atomic type is always lock-free + */ + static constexpr bool is_always_lock_free = true; + + T operator++() noexcept { return this->fetch_add(1) + 1; } + T operator--() noexcept { return this->fetch_sub(1) - 1; } + T operator++(int) noexcept { return this->fetch_add(1); } + T operator--(int) noexcept { return this->fetch_sub(1); } + + T operator+=(T desired) noexcept { return this->fetch_add(desired) + desired; } + T operator-=(T desired) noexcept { return this->fetch_sub(desired) - desired; } + // T operator+=(std::ptrdiff_t desired) noexcept { return this->fetch_add(desired) + desired; } + // T operator-=(std::ptrdiff_t desired) noexcept { return this->fetch_sub(desired) - desired; } + + T operator&=(T desired) noexcept { return this->fetch_and(desired) & desired; } + T operator|=(T desired) noexcept { return this->fetch_or(desired) | desired; } + T operator^=(T desired) noexcept { return this->fetch_xor(desired) ^ desired; } + + T operator->() noexcept { return this->load(); } + T operator~() noexcept { return this->fetch_nand(-1); } + + bool operator==(const atomic &other) const noexcept { return this->load() == other.load(); } + bool operator==(T other) const noexcept { return this->load() == other; } + + atomic &operator=(const atomic &) = delete; + T operator=(T desired) noexcept + { + this->store(desired); + return desired; + } + + operator bool() noexcept { return this->load() != 0; } + // operator T() noexcept { return this->load(); } + operator T() const noexcept { return this->load(); } + }; + + typedef atomic atomic_bool; + typedef atomic atomic_char; + typedef atomic atomic_schar; + typedef atomic atomic_uchar; + typedef atomic atomic_short; + typedef atomic atomic_ushort; + typedef atomic atomic_int; + typedef atomic atomic_uint; + typedef atomic atomic_long; + typedef atomic atomic_ulong; + typedef atomic atomic_llong; + typedef atomic atomic_ullong; + typedef atomic atomic_char16_t; + typedef atomic atomic_char32_t; + typedef atomic atomic_wchar_t; + typedef atomic atomic_int8_t; + typedef atomic atomic_uint8_t; + typedef atomic atomic_int16_t; + typedef atomic atomic_uint16_t; + typedef atomic atomic_int32_t; + typedef atomic atomic_uint32_t; + typedef atomic atomic_int64_t; + typedef atomic atomic_uint64_t; + typedef atomic atomic_int_least8_t; + typedef atomic atomic_uint_least8_t; + typedef atomic atomic_int_least16_t; + typedef atomic atomic_uint_least16_t; + typedef atomic atomic_int_least32_t; + typedef atomic atomic_uint_least32_t; + typedef atomic atomic_int_least64_t; + typedef atomic atomic_uint_least64_t; + typedef atomic atomic_int_fast8_t; + typedef atomic atomic_uint_fast8_t; + typedef atomic atomic_int_fast16_t; + typedef atomic atomic_uint_fast16_t; + typedef atomic atomic_int_fast32_t; + typedef atomic atomic_uint_fast32_t; + typedef atomic atomic_int_fast64_t; + typedef atomic atomic_uint_fast64_t; + typedef atomic atomic_intptr_t; + typedef atomic atomic_uintptr_t; + typedef atomic atomic_size_t; + typedef atomic atomic_ptrdiff_t; + typedef atomic atomic_intmax_t; + typedef atomic atomic_uintmax_t; +} + +#undef builtin_atomic_n +#undef builtin_atomic + +#endif // !__FENNIX_KERNEL_STD_ATOMIC_H__ diff --git a/include/std/unordered_map.hpp b/include/std/unordered_map.hpp index 980a7d6..9e956f3 100644 --- a/include/std/unordered_map.hpp +++ b/include/std/unordered_map.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace std diff --git a/include/task.hpp b/include/task.hpp index 96df5e6..39a6500 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -21,13 +21,13 @@ #include #include -#include #include -#include #include -#include +#include #include #include +#include +#include #include namespace Tasking @@ -136,18 +136,14 @@ namespace Tasking void Rename(const char *name) { CriticalSection cs; - if (!Name[0]) + if (strlen(name) > 256 || strlen(name) == 0) { - warn("Tried to rename thread %d to NULL", ID); + debug("Invalid thread name"); return; } + trace("Renaming thread %s to %s", Name, name); - for (int i = 0; i < 256; i++) - { - Name[i] = name[i]; - if (name[i] == '\0') - break; - } + strncpy(Name, name, 256); } void SetPriority(TaskPriority priority) @@ -243,12 +239,12 @@ namespace Tasking UPID NextPID = 0; UTID NextTID = 0; - std::vector ListProcess; + std::vector ProcessList; PCB *IdleProcess = nullptr; TCB *IdleThread = nullptr; TCB *CleanupThread = nullptr; - Atomic SchedulerTicks = 0; - Atomic LastTaskTicks = 0; + std::atomic_uint64_t SchedulerTicks = 0; + std::atomic_uint64_t LastTaskTicks = 0; bool StopScheduler = false; bool InvalidPCB(PCB *pcb); bool InvalidTCB(TCB *tcb); @@ -280,9 +276,9 @@ namespace Tasking public: void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; } - uint64_t GetSchedulerTicks() { return SchedulerTicks.Load(); } - uint64_t GetLastTaskTicks() { return LastTaskTicks.Load(); } - std::vector GetProcessList() { return ListProcess; } + uint64_t GetSchedulerTicks() { return SchedulerTicks.load(); } + uint64_t GetLastTaskTicks() { return LastTaskTicks.load(); } + std::vector GetProcessList() { return ProcessList; } Security *GetSecurityManager() { return &SecurityManager; } void CleanupProcessesThread(); void Panic() { StopScheduler = true; } diff --git a/include/vector.hpp b/include/vector similarity index 100% rename from include/vector.hpp rename to include/vector