Reformat
This commit is contained in:
@ -91,7 +91,7 @@ bool VESA::initGraphicMode(uint16_t mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Kernel::kout << "TotalVideoMemory: " << ((ib->TotalMemory*65536) / (1024*1024)) << " MB" << endl;
|
||||
// Util::System::out << "TotalVideoMemory: " << ((ib->TotalMemory*65536) / (1024*1024)) << " MB" << endl;
|
||||
|
||||
// Gewuenschten Grafikmodus aus Antwort suchen
|
||||
auto *modePtr = reinterpret_cast<uint16_t *>((ib->VideoModePtr[1] << 4) + ib->VideoModePtr[0]);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Bluescreen, falls eine x86 Exception auftritt. Evt. *
|
||||
* ist der Stack und oder Heap kaputt, weswegen hier nicht *
|
||||
* Kernel::kout etc. verwendet wird. *
|
||||
* Util::System::out etc. verwendet wird. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 11.12.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Bluescreen, falls eine x86 Exception auftritt. Evt. *
|
||||
* ist der Stack und oder Heap kaputt, weswegen hier nicht *
|
||||
* Kernel::kout etc. verwendet wird. *
|
||||
* Util::System::out etc. verwendet wird. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 2.2.2017 *
|
||||
*****************************************************************************/
|
||||
|
||||
@ -31,7 +31,7 @@ public:
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// Kernel::kout << "Idle!" << endl;
|
||||
// Util::System::out << "Idle!" << endl;
|
||||
scheduler.yield();
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,14 +29,6 @@ namespace Kernel {
|
||||
|
||||
constexpr const bool INSANE_TRACE = false;
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Dispatcher::dispatch *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Auf den active thread wechseln. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* next Thread der die CPU::erhalten soll. *
|
||||
*****************************************************************************/
|
||||
void Scheduler::start(Container::Vector<Memory::unique_ptr<Thread>>::iterator next) {
|
||||
active = next;
|
||||
if (active >= ready_queue.end()) {
|
||||
@ -139,7 +131,8 @@ void Scheduler::kill(uint32_t tid, Memory::unique_ptr<Thread> *ptr) {
|
||||
uint32_t prev_tid = (*active)->tid;
|
||||
|
||||
// Block queue, can always kill
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = block_queue.begin(); it != block_queue.end(); ++it) {
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = block_queue.begin();
|
||||
it != block_queue.end(); ++it) {
|
||||
if ((*it)->tid == tid) {
|
||||
// Found thread to kill
|
||||
|
||||
@ -165,7 +158,8 @@ void Scheduler::kill(uint32_t tid, Memory::unique_ptr<Thread> *ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = ready_queue.begin(); it != ready_queue.end(); ++it) {
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = ready_queue.begin();
|
||||
it != ready_queue.end(); ++it) {
|
||||
if ((*it)->tid == tid) {
|
||||
// Found thread to kill
|
||||
|
||||
@ -322,7 +316,8 @@ void Scheduler::deblock(uint32_t tid) {
|
||||
|
||||
Device::CPU::disable_int();
|
||||
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = block_queue.begin(); it != block_queue.end(); ++it) {
|
||||
for (Container::Vector<Memory::unique_ptr<Thread>>::iterator it = block_queue.begin();
|
||||
it != block_queue.end(); ++it) {
|
||||
if ((*it)->tid == tid) {
|
||||
// Found thread with correct tid
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
#define Scheduler_include__
|
||||
|
||||
#include "Thread.h"
|
||||
#include "lib/mem/UniquePointer.h"
|
||||
#include "lib/memory/UniquePointer.h"
|
||||
#include "lib/stream/Logger.h"
|
||||
#include "lib/container/Vector.h"
|
||||
|
||||
@ -26,17 +26,20 @@ private:
|
||||
Container::Vector<Memory::unique_ptr<Thread>> ready_queue;
|
||||
Container::Vector<Memory::unique_ptr<Thread>> block_queue;
|
||||
|
||||
// NOTE: It makes sense to keep track of the active thread through this as it makes handling the
|
||||
// It makes sense to keep track of the active thread through this as it makes handling the
|
||||
// unique_ptr easier and reduces the copying in the vector when cycling through the threads
|
||||
// as we don't have to keep the active thread at the front (would only make sense with a queue)
|
||||
Container::Vector<Memory::unique_ptr<Thread>>::iterator active = nullptr;
|
||||
|
||||
// Scheduler wird evt. von einer Unterbrechung vom Zeitgeber gerufen,
|
||||
// bevor er initialisiert wurde
|
||||
uint32_t idle_tid = 0U;
|
||||
uint32_t idle_tid = 0;
|
||||
|
||||
// Roughly the old dispatcher functionality
|
||||
void start(Container::Vector<Memory::unique_ptr<Thread>>::iterator next); // Start next without prev
|
||||
void switch_to(Thread *prev_raw, Container::Vector<Memory::unique_ptr<Thread>>::iterator next); // Switch from prev to next
|
||||
void
|
||||
start(Container::Vector<Memory::unique_ptr<Thread>>::iterator next); // Start next without prev
|
||||
void switch_to(Thread *prev_raw,
|
||||
Container::Vector<Memory::unique_ptr<Thread>>::iterator next); // Switch from prev to next
|
||||
|
||||
// Kann nur vom Idle-Thread aufgerufen werden (erster Thread der vom Scheduler gestartet wird)
|
||||
void enable_preemption(uint32_t tid) { idle_tid = tid; }
|
||||
@ -56,14 +59,14 @@ public:
|
||||
block_queue.reserve();
|
||||
}
|
||||
|
||||
uint32_t get_active() const {
|
||||
[[nodiscard]] uint32_t get_active() const {
|
||||
return (*active)->tid;
|
||||
}
|
||||
|
||||
// Scheduler initialisiert?
|
||||
// Zeitgeber-Unterbrechung kommt evt. bevor der Scheduler fertig
|
||||
// intiialisiert wurde!
|
||||
bool preemption_enabled() const { return idle_tid != 0U; }
|
||||
[[nodiscard]] bool preemption_enabled() const { return idle_tid != 0U; }
|
||||
|
||||
// Scheduler starten
|
||||
void schedule();
|
||||
|
||||
@ -6,6 +6,13 @@
|
||||
|
||||
namespace Container {
|
||||
|
||||
/**
|
||||
* This class implements a stack allocated array with bounds checking
|
||||
* and iterator support.
|
||||
*
|
||||
* @tparam T The type of the objects
|
||||
* @tparam N The number of elements the array can store
|
||||
*/
|
||||
template<typename T, const std::size_t N>
|
||||
class Array {
|
||||
public:
|
||||
@ -15,8 +22,10 @@ namespace Container {
|
||||
T buf[N];
|
||||
|
||||
public:
|
||||
Array() = default; // If i write default something like bse::array<int, 10> arr; is not initialized...
|
||||
Array() = default; // If i write default something like Container::Array<int, 10> arr; is not initialized...
|
||||
|
||||
// TODO: This doesn't account for initializer lists of the wrong length, last value should be repeated
|
||||
// Only increment iterator when it < list.end() - 1?
|
||||
// Construct like this: bse::array<int, 5> {1, 2, 3, 4, 5};
|
||||
Array(std::initializer_list<T> list) {
|
||||
typename std::initializer_list<T>::iterator it = list.begin();
|
||||
@ -26,15 +35,22 @@ namespace Container {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Rest of constructors
|
||||
|
||||
iterator begin() { return iterator(&buf[0]); }
|
||||
|
||||
iterator begin() const { return iterator(&buf[0]); }
|
||||
|
||||
iterator end() { return iterator(&buf[N]); }
|
||||
|
||||
iterator end() const { return iterator(&buf[N]); }
|
||||
|
||||
constexpr T &operator[](std::size_t i) { return buf[i]; }
|
||||
|
||||
constexpr const T &operator[](std::size_t i) const { return buf[i]; }
|
||||
|
||||
T *data() { return &buf[0]; }
|
||||
|
||||
const T *data() const { return &buf[0]; }
|
||||
|
||||
void swap(Array<T, N> &other) {
|
||||
@ -52,11 +68,11 @@ namespace Container {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr std::size_t size() const {
|
||||
[[nodiscard]] constexpr std::size_t size() const {
|
||||
return N;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace bse
|
||||
} // namespace Container
|
||||
|
||||
#endif
|
||||
|
||||
@ -13,8 +13,11 @@ namespace Container {
|
||||
ContinuousIterator() = delete;
|
||||
|
||||
// Use const_cast as the iterator has to increment the pointer
|
||||
// Don't make this explicit: Want to write Container::Vector<int>::iterator = nullptr;
|
||||
ContinuousIterator(const T *ptr) : ptr(const_cast<T *>(ptr)) {}
|
||||
|
||||
// TODO: Rest of constructors
|
||||
|
||||
ContinuousIterator &operator++() {
|
||||
++ptr;
|
||||
return *this;
|
||||
@ -35,15 +38,23 @@ namespace Container {
|
||||
|
||||
// Convenience
|
||||
T *operator->() { return ptr; }
|
||||
|
||||
const T *operator->() const { return ptr; }
|
||||
|
||||
T &operator*() { return *ptr; }
|
||||
|
||||
const T &operator*() const { return *ptr; }
|
||||
|
||||
bool operator<(const ContinuousIterator &other) const { return ptr < other.ptr; }
|
||||
|
||||
bool operator<=(const ContinuousIterator &other) const { return ptr <= other.ptr; }
|
||||
|
||||
bool operator>(const ContinuousIterator &other) const { return ptr > other.ptr; }
|
||||
|
||||
bool operator>=(const ContinuousIterator &other) const { return ptr >= other.ptr; }
|
||||
|
||||
bool operator==(const ContinuousIterator &other) const { return ptr == other.ptr; }
|
||||
|
||||
bool operator!=(const ContinuousIterator &other) const { return ptr != other.ptr; }
|
||||
|
||||
template<typename t>
|
||||
|
||||
@ -107,6 +107,8 @@ namespace Container {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This doesn't account for initializer lists of the wrong length, last value should be repeated
|
||||
// Only increment iterator when it < list.end() - 1?
|
||||
// Initialize like this: bse::vector<int> vec {1, 2, 3, 4, 5};
|
||||
Vector(std::initializer_list<T> list) : buf_cap(list.size()), buf(new T[buf_cap]) {
|
||||
typename std::initializer_list<T>::iterator it = list.begin();
|
||||
@ -116,7 +118,6 @@ namespace Container {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector(const Vector ©) : buf_pos(copy.buf_pos), buf_cap(copy.buf_cap), buf(new T[buf_cap]) {
|
||||
for (unsigned int i = 0; i < buf_pos; ++i) {
|
||||
buf[i] = copy[i]; // Does a copy since copy is marked const reference
|
||||
@ -169,8 +170,11 @@ namespace Container {
|
||||
|
||||
// Iterator
|
||||
iterator begin() { return iterator(&buf[0]); }
|
||||
|
||||
iterator begin() const { return iterator(&buf[0]); }
|
||||
|
||||
iterator end() { return iterator(&buf[size()]); }
|
||||
|
||||
iterator end() const { return iterator(&buf[size()]); }
|
||||
|
||||
// Add elements
|
||||
@ -297,6 +301,6 @@ namespace Container {
|
||||
return erased_els;
|
||||
}
|
||||
|
||||
} // namespace bse
|
||||
} // namespace Container
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
#ifndef UniquePointer_Include_H_
|
||||
#define UniquePointer_Include_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
// https://en.cppreference.com/w/cpp/memory/unique_ptr
|
||||
|
||||
// NOTE: Because of the way the scheduling works our functions are not executed completely.
|
||||
// This means that object destructors are not called if the objects live in a scope
|
||||
// that is left because of thread switching (e.g. a threads run function)...
|
||||
|
||||
namespace Memory {
|
||||
|
||||
// T is the type make_unique is called with, meaning int or int[] for example
|
||||
// T_ is the bare type without extents (int in both cases), so we have a
|
||||
// int* pointer type for both unique_ptr<int> and unique_ptr<int[]>
|
||||
template<typename T>
|
||||
class unique_ptr {
|
||||
private:
|
||||
using T_ = std::remove_extent_t<T>;
|
||||
|
||||
T_* ptr = nullptr;
|
||||
|
||||
// Only use make_unique or reset for construction
|
||||
unique_ptr(T_* ptr) : ptr(ptr) {}
|
||||
|
||||
// I didn't want to introduce custom deleters for my small needs
|
||||
void del() {
|
||||
if constexpr (std::is_array_v<T>) {
|
||||
delete[] ptr;
|
||||
} else {
|
||||
delete ptr;
|
||||
}
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
// Forbid copying
|
||||
unique_ptr(const unique_ptr& copy) = delete;
|
||||
unique_ptr& operator=(const unique_ptr& copy) = delete;
|
||||
|
||||
// Construction
|
||||
unique_ptr() = default; // Allow declaration without explicit definition
|
||||
|
||||
template<typename t, typename... Args>
|
||||
friend typename std::enable_if_t<!std::is_array_v<t>, unique_ptr<t>>
|
||||
make_unique(Args&&... args);
|
||||
|
||||
template<typename t>
|
||||
friend typename std::enable_if_t<std::is_array_v<t>, unique_ptr<t>>
|
||||
make_unique(std::size_t size);
|
||||
|
||||
// Deletion
|
||||
~unique_ptr() {
|
||||
del();
|
||||
}
|
||||
|
||||
// Moving
|
||||
unique_ptr(unique_ptr&& move) noexcept { reset(move.release()); };
|
||||
|
||||
// Implicit upcasting is needed: for sth like
|
||||
// unique_ptr<Thread> ptr = make_unique<IdleThread>();
|
||||
// IdleThread is derived from Thread so the assert passes
|
||||
template<typename t>
|
||||
unique_ptr(unique_ptr<t>&& move) noexcept {
|
||||
static_assert(std::is_base_of_v<T, t>, "Has to be derived type");
|
||||
reset(move.release());
|
||||
}
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& move) noexcept {
|
||||
reset(move.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Resetting: Replaces managed object, deleting the old one
|
||||
void reset() { del(); }
|
||||
void reset(T_* pt) {
|
||||
del();
|
||||
ptr = pt;
|
||||
}
|
||||
|
||||
// Release: Releases ownership without deletion
|
||||
T_* release() {
|
||||
// T* old = ptr;
|
||||
// ptr = nullptr;
|
||||
// return old;
|
||||
return std::exchange(ptr, nullptr);
|
||||
}
|
||||
|
||||
// Get: Access the raw pointer without taking ownership
|
||||
T_* get() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Pointer operators
|
||||
T_* operator->() { return ptr; }
|
||||
const T_* operator->() const { return ptr; }
|
||||
T_& operator*() { return *ptr; }
|
||||
const T_& operator*() const { return *ptr; }
|
||||
|
||||
explicit operator void*() const { return ptr; }
|
||||
explicit operator bool() const { return (ptr != nullptr); }
|
||||
|
||||
bool operator==(const unique_ptr& other) const { return ptr == other.ptr; }
|
||||
|
||||
// These are only for array unique_ptr but I didn't enforce that
|
||||
T_& operator[](std::size_t i) { return ptr[i]; }
|
||||
const T_& operator[](std::size_t i) const { return ptr[i]; }
|
||||
};
|
||||
|
||||
// make_unique implementation =======================================
|
||||
|
||||
// Allow initialization of unique_ptr<int> with optional constructor arguments
|
||||
// and unique_ptr<int[]> without constructor arguments
|
||||
template<typename T, typename... Args>
|
||||
|
||||
// We make the return type dependent on whether T is an array type or not
|
||||
typename std::enable_if_t<!std::is_array_v<T>, unique_ptr<T>>
|
||||
make_unique(Args&&... args) {
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if_t<std::is_array_v<T>, unique_ptr<T>>
|
||||
make_unique(std::size_t size) {
|
||||
using T_ = typename std::remove_extent_t<T>;
|
||||
return unique_ptr<T>(new T_[size]);
|
||||
}
|
||||
|
||||
} // namespace bse
|
||||
|
||||
#endif
|
||||
140
src/lib/memory/UniquePointer.h
Normal file
140
src/lib/memory/UniquePointer.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef UniquePointer_Include_H_
|
||||
#define UniquePointer_Include_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
// https://en.cppreference.com/w/cpp/memory/unique_ptr
|
||||
|
||||
// NOTE: Because of the way the scheduling works our functions are not executed completely.
|
||||
// This means that object destructors are not called if the objects live in a scope
|
||||
// that is left because of thread switching (e.g. a threads run function)...
|
||||
|
||||
namespace Memory {
|
||||
|
||||
// T is the type make_unique is called with, meaning int or int[] for example
|
||||
// T_ is the bare type without extents (int in both cases), so we have a
|
||||
// int* pointer type for both unique_ptr<int> and unique_ptr<int[]>
|
||||
template<typename T>
|
||||
class unique_ptr {
|
||||
private:
|
||||
using T_ = std::remove_extent_t<T>;
|
||||
|
||||
T_ *ptr = nullptr;
|
||||
|
||||
// TODO: Was there a reason I didn't mark this explicit?
|
||||
// Only use make_unique or reset for construction
|
||||
unique_ptr(T_ *ptr) : ptr(ptr) {}
|
||||
|
||||
// I didn't want to introduce custom deleters for my small needs
|
||||
void del() {
|
||||
if constexpr (std::is_array_v<T>) {
|
||||
delete[] ptr;
|
||||
} else {
|
||||
delete ptr;
|
||||
}
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
// Forbid copying
|
||||
unique_ptr(const unique_ptr ©) = delete;
|
||||
|
||||
unique_ptr &operator=(const unique_ptr ©) = delete;
|
||||
|
||||
// Construction
|
||||
unique_ptr() = default; // Allow declaration without explicit definition
|
||||
|
||||
template<typename t, typename... Args>
|
||||
friend typename std::enable_if_t<!std::is_array_v<t>, unique_ptr<t>>
|
||||
make_unique(Args &&... args);
|
||||
|
||||
template<typename t>
|
||||
friend typename std::enable_if_t<std::is_array_v<t>, unique_ptr<t>>
|
||||
make_unique(std::size_t size);
|
||||
|
||||
// Deletion
|
||||
~unique_ptr() {
|
||||
del();
|
||||
}
|
||||
|
||||
// Moving
|
||||
unique_ptr(unique_ptr &&move) noexcept { reset(move.release()); };
|
||||
|
||||
// Implicit upcasting is needed: for sth like
|
||||
// unique_ptr<Thread> ptr = make_unique<IdleThread>();
|
||||
// IdleThread is derived from Thread so the assert passes
|
||||
template<typename t>
|
||||
unique_ptr(unique_ptr<t> &&move) noexcept {
|
||||
static_assert(std::is_base_of_v<T, t>, "Has to be derived type");
|
||||
reset(move.release());
|
||||
}
|
||||
|
||||
unique_ptr &operator=(unique_ptr &&move) noexcept {
|
||||
reset(move.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Resetting: Replaces managed object, deleting the old one
|
||||
void reset() { del(); }
|
||||
|
||||
void reset(T_ *pt) {
|
||||
del();
|
||||
ptr = pt;
|
||||
}
|
||||
|
||||
// Release: Releases ownership without deletion
|
||||
T_ *release() {
|
||||
// T* old = ptr;
|
||||
// ptr = nullptr;
|
||||
// return old;
|
||||
return std::exchange(ptr, nullptr);
|
||||
}
|
||||
|
||||
// Get: Access the raw pointer without taking ownership
|
||||
T_ *get() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Pointer operators
|
||||
T_ *operator->() { return ptr; }
|
||||
|
||||
const T_ *operator->() const { return ptr; }
|
||||
|
||||
T_ &operator*() { return *ptr; }
|
||||
|
||||
const T_ &operator*() const { return *ptr; }
|
||||
|
||||
explicit operator void *() const { return ptr; }
|
||||
|
||||
explicit operator bool() const { return (ptr != nullptr); }
|
||||
|
||||
bool operator==(const unique_ptr &other) const { return ptr == other.ptr; }
|
||||
|
||||
// These are only for array unique_ptr but I didn't enforce that
|
||||
T_ &operator[](std::size_t i) { return ptr[i]; }
|
||||
|
||||
const T_ &operator[](std::size_t i) const { return ptr[i]; }
|
||||
};
|
||||
|
||||
// make_unique implementation =======================================
|
||||
|
||||
// Allow initialization of unique_ptr<int> with optional constructor arguments
|
||||
// and unique_ptr<int[]> without constructor arguments
|
||||
template<typename T, typename... Args>
|
||||
|
||||
// We make the return type dependent on whether T is an array type or not
|
||||
typename std::enable_if_t<!std::is_array_v<T>, unique_ptr<T>>
|
||||
make_unique(Args &&... args) {
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if_t<std::is_array_v<T>, unique_ptr<T>>
|
||||
make_unique(std::size_t size) {
|
||||
using T_ = typename std::remove_extent_t<T>;
|
||||
return unique_ptr<T>(new T_[size]);
|
||||
}
|
||||
|
||||
} // namespace bse
|
||||
|
||||
#endif
|
||||
@ -51,8 +51,6 @@ private:
|
||||
CGA::color color_bg;
|
||||
bool blink;
|
||||
|
||||
friend class Logger; // Give access to the color
|
||||
|
||||
public:
|
||||
CGA_Stream(CGA_Stream ©) = delete; // Verhindere Kopieren
|
||||
|
||||
@ -60,7 +58,7 @@ public:
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// CAn't make singleton because atexit
|
||||
// Can't make singleton because atexit
|
||||
|
||||
// ~CGA_Stream() override = default;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user