simplify Qeue, update some comments and include paths

main
Niklas Gollenstede 5 months ago committed by Eggert Jung
parent 68e11c9793
commit d9978ddc37

@ -156,7 +156,7 @@ void set(uint32_t counter, uint8_t divide, uint8_t vector, bool periodic,
* *
* Initializes the \ref LAPIC::Timer * Initializes the \ref LAPIC::Timer
* in such a way that regular interrupts are triggered approx. every `us` * in such a way that regular interrupts are triggered approx. every `us`
* microseconds when \ref LAPIC::Timer:::activate() is called. * microseconds when \ref LAPIC::Timer::activate() is called.
* For this purpose, a suitable timer divisor is determined * For this purpose, a suitable timer divisor is determined
* based on the timer frequency determined with \ref LAPIC::Timer::ticks(). * based on the timer frequency determined with \ref LAPIC::Timer::ticks().
* This timer divisor has to be as small as possible, but large enough to * This timer divisor has to be as small as possible, but large enough to

@ -1,4 +1,4 @@
#include "boot/multiboot/data.h" #include "./data.h"
/*! \brief Multiboot Information Structure according to Specification /*! \brief Multiboot Information Structure according to Specification
* \see [Multiboot Specification]{@ref multiboot} * \see [Multiboot Specification]{@ref multiboot}

@ -28,7 +28,7 @@ namespace Epilogues {
* \todo(15) Store the key to the keyboard buffer for user threads. Wake user * \todo(15) Store the key to the keyboard buffer for user threads. Wake user
* threads waiting for a key using the key semaphore. * threads waiting for a key using the key semaphore.
* *
* @param g * @param v The vault.
*/ */
void keyboard(Vault& g); void keyboard(Vault& g);
@ -37,7 +37,7 @@ void keyboard(Vault& g);
* \todo(15) Preemptively reschedule threads * \todo(15) Preemptively reschedule threads
* \todo(16) Check the bellringer * \todo(16) Check the bellringer
* \todo(17) Refresh screen with fixed FPS rate * \todo(17) Refresh screen with fixed FPS rate
* @param g * @param v The vault.
*/ */
void timer(Vault& g); void timer(Vault& g);
@ -45,6 +45,7 @@ void timer(Vault& g);
* it is set. * it is set.
* *
* \todo(15) Implement the rescheduling (in \MPStuBS only) * \todo(15) Implement the rescheduling (in \MPStuBS only)
* @param v The vault.
*/ */
void assassin(Vault& g); void assassin(Vault& g);
}; // namespace Epilogues }; // namespace Epilogues

@ -1,4 +1,4 @@
#include "handlers.h" #include "./handlers.h"
#include "../arch/core_cr.h" #include "../arch/core_cr.h"
#include "../arch/idt.h" #include "../arch/idt.h"
@ -29,8 +29,7 @@ void printContext(const InterruptContext *context) {
[[gnu::interrupt]] void handle_double_fault(InterruptContext *context, [[gnu::interrupt]] void handle_double_fault(InterruptContext *context,
uint64_t error) { uint64_t error) {
(void)error; DBG << "Double fault encountered. Error code: " << dec << error << endl;
DBG << "Double fault encoutered" << endl;
printContext(context); printContext(context);
kernelpanic("Double fault!"); kernelpanic("Double fault!");
} }
@ -61,8 +60,12 @@ enum PAGE_FAULT_ERROR {
[[gnu::interrupt]] void handle_page_fault(InterruptContext *context, [[gnu::interrupt]] void handle_page_fault(InterruptContext *context,
uint64_t error) { uint64_t error) {
<<<<<<< HEAD
(void)error; (void)error;
DBG << "Page fault encoutered at linear address " << hex DBG << "Page fault encoutered at linear address " << hex
=======
DBG << "Page fault encountered at linear address " << hex
>>>>>>> c0b78ee (simplify Qeue, update some comments and include paths)
<< Core::CR<2>::read() << endl << Core::CR<2>::read() << endl
<< (error & PF_ERR_PRESENT ? "present" : "non-present") << " page|" << (error & PF_ERR_PRESENT ? "present" : "non-present") << " page|"
<< (error & PF_ERR_WRITE ? "write" : "read") << " access|" << (error & PF_ERR_WRITE ? "write" : "read") << " access|"

@ -1,3 +1,4 @@
<<<<<<< HEAD
#include "arch/lapic.h" #include "arch/lapic.h"
#include "boot/startup_ap.h" #include "boot/startup_ap.h"
#include "arch/core_interrupt.h" #include "arch/core_interrupt.h"
@ -100,7 +101,6 @@ Application application = Application(test1_stack);
//} //}
// Main function // Main function
// (the bootstrap processor starts here)} // (the bootstrap processor starts here)}
extern "C" int main() { extern "C" int main() {

@ -11,39 +11,16 @@
/*! \brief Templated Queue for arbitrary objects. /*! \brief Templated Queue for arbitrary objects.
* *
* Queue is implemented by a head-object (Queue<T>) and next-pointers embedded * Queue is implemented by a head-object (Queue<T>) and next-pointers embedded
* in the queued objects. This Queue supports arrays of next-pointers by passing * in the queued objects. By passing a different get_link function into the
* an index into the constructor identifying the index into the next-pointer * constructor, the member name of the next-pointer can be changed and objects
* array. By passing a different get_link function into the constructor, the * can be contained in different independent queues.
* member name of the next-pointer array can be changed and objects can be
* contained in different independent queues.
*/ */
template <class T> template <class T>
class Queue { class Queue {
/*! \brief Default get_link implementation returns a pointer to the /// Default get_link implementation returns a pointer to the next-pointer.
* link_index'th element of the next-pointer array. static T** default_get_link(T& obj) { return &obj.queue_link; }
* The function assumes a member named "queue_link" that stores the
* next-pointer.
*
* If your object contains a queue_link member you can just ignore this
* function and the get_link keyword argument of the constructor.
*
* \param[in] obj the object whose link should be accessed.
* \param[in] link_index the index within the array.
*
* \return A pointer to the next-object pointer.
*/
static T** default_get_link(T& obj, unsigned link_index) {
assert(link_index < sizeof(T::queue_link) / sizeof(void*));
return &obj.queue_link[link_index];
}
/// Type definition for the get_link function /// Type definition for the get_link function
typedef T** (*NextFunc)(T&, unsigned); typedef T** (*NextFunc)(T&);
/// Queue-local index into the next-pointer array
unsigned link_index;
/// Provides the same signature for single- and multi-core Queue
T** get_link_wrapped(T& obj) { return get_link(obj, link_index); }
/// Function pointer to the get_link function, called whenever the /// Function pointer to the get_link function, called whenever the
/// next pointer array is referenced /// next pointer array is referenced
@ -106,18 +83,15 @@ class Queue {
constexpr Queue(Queue&&) = default; constexpr Queue(Queue&&) = default;
/*! \brief Constructor /*! \brief Constructor
* \param[in] link_index denotes the index into the next-pointer array
* to be used by this
*queue-object
* \param[in] get_link A function pointer to the get_link, i.e. a function * \param[in] get_link A function pointer to the get_link, i.e. a function
* which returns a pointer to the * which returns a pointer to the
*next-pointer of an element in the Queue. *next-pointer of an element in the Queue.
*/ */
explicit Queue(unsigned link_index, NextFunc get_link = default_get_link) explicit Queue(NextFunc get_link = default_get_link)
: link_index(link_index), : get_link(get_link), head(nullptr), tail(nullptr) {
get_link(get_link), assert(get_link != nullptr &&
head(nullptr), "get_link function pointer must not be nullptr!");
tail(nullptr) {} };
/*! \brief Enqueues the provided item at the end of the queue. If the element /*! \brief Enqueues the provided item at the end of the queue. If the element
* is already contained in the queue, false will be returned * is already contained in the queue, false will be returned
@ -126,7 +100,7 @@ class Queue {
* or not (and it is now enqueued, then true) * or not (and it is now enqueued, then true)
*/ */
bool enqueue(T& item) { bool enqueue(T& item) {
T** nextptr = get_link_wrapped(item); T** nextptr = get_link(item);
if (*nextptr != nullptr || (head != nullptr && tail == &item)) { if (*nextptr != nullptr || (head != nullptr && tail == &item)) {
return false; return false;
} }
@ -136,7 +110,7 @@ class Queue {
head = tail = &item; head = tail = &item;
} else { } else {
assert(tail != nullptr); assert(tail != nullptr);
*get_link_wrapped(*tail) = &item; *get_link(*tail) = &item;
tail = &item; tail = &item;
} }
return true; return true;
@ -147,7 +121,7 @@ class Queue {
* \return true if successful, false if item was already in the queue * \return true if successful, false if item was already in the queue
**/ **/
bool insertFirst(T& item) { bool insertFirst(T& item) {
T** nextptr = get_link_wrapped(item); T** nextptr = get_link(item);
if (*nextptr != nullptr || (head != nullptr && tail == &item)) { if (*nextptr != nullptr || (head != nullptr && tail == &item)) {
return false; return false;
} }
@ -177,13 +151,13 @@ class Queue {
if (&after == tail) { if (&after == tail) {
return enqueue(item); return enqueue(item);
} }
T** nextptr = get_link_wrapped(item); T** nextptr = get_link(item);
// if item is already in the list return false // if item is already in the list return false
if (*nextptr != nullptr || tail == &item) { if (*nextptr != nullptr || tail == &item) {
return false; return false;
} }
T** pnextptr = get_link_wrapped(after); T** pnextptr = get_link(after);
// if after is NOT in the list, return false // if after is NOT in the list, return false
if (!(pnextptr != nullptr || tail == &after)) { if (!(pnextptr != nullptr || tail == &after)) {
return false; return false;
@ -201,8 +175,7 @@ class Queue {
*not in this list *not in this list
**/ **/
T* next(T& item) { T* next(T& item) {
T** nextptr = get_link_wrapped(item); T** nextptr = get_link(item);
// if item is already in the list return nullptr
if (head == nullptr || (*nextptr == nullptr && tail != &item)) { if (head == nullptr || (*nextptr == nullptr && tail != &item)) {
return nullptr; return nullptr;
} }
@ -222,7 +195,7 @@ class Queue {
T* dequeue() { T* dequeue() {
T* out = head; T* out = head;
if (head != nullptr) { if (head != nullptr) {
T** nextptr = get_link_wrapped(*head); T** nextptr = get_link(*head);
head = *nextptr; head = *nextptr;
*nextptr = nullptr; *nextptr = nullptr;
} }
@ -239,21 +212,21 @@ class Queue {
T** next_link; T** next_link;
if (head == that) { if (head == that) {
head = *get_link_wrapped(*head); head = *get_link(*head);
*get_link_wrapped(*that) = nullptr; *get_link(*that) = nullptr;
return that; return that;
} }
while (cur) { while (cur) {
next_link = get_link_wrapped(*cur); next_link = get_link(*cur);
if (*next_link == that) { if (*next_link == that) {
*next_link = *get_link_wrapped(**next_link); *next_link = *get_link(**next_link);
if (that == tail) { if (that == tail) {
tail = cur; tail = cur;
} }
*get_link_wrapped(*that) = nullptr; *get_link(*that) = nullptr;
return that; return that;
} }
cur = *next_link; cur = *next_link;

@ -1,19 +1,6 @@
#include "bellringer.h" #include "./bellringer.h"
#include "../interrupt/guard.h" #include "../interrupt/guard.h"
#include "../thread/thread.h"
struct Bell {
// link pointer to the next bell in the bellringers bell list
Bell *queue_link[1] = {nullptr};
Thread *thread;
size_t counter;
};
Bell **Bellringer::bell_link(Bell &obj, unsigned link_index) {
return &obj.queue_link[link_index];
}
// check: Checks whether bells are running out of time and rings them if // check: Checks whether bells are running out of time and rings them if
// necessary // necessary

@ -4,10 +4,10 @@
#pragma once #pragma once
#include "../object/queue.h" #include "../object/queue.h"
#include "../thread/thread.h"
#include "../types.h" #include "../types.h"
struct Vault; struct Vault;
struct Bell;
/*! \brief Manages and activates time-triggered activities. /*! \brief Manages and activates time-triggered activities.
* \ingroup ipc * \ingroup ipc
@ -24,6 +24,14 @@ class Bellringer {
Bellringer(const Bellringer&) = delete; Bellringer(const Bellringer&) = delete;
Bellringer& operator=(const Bellringer&) = delete; Bellringer& operator=(const Bellringer&) = delete;
struct Bell {
// link pointer to the next bell in the bellringers bell list
Bell* queue_link = nullptr;
Thread* thread;
size_t counter;
};
/*! \brief List of bells currently managed. /*! \brief List of bells currently managed.
* *
* This list contains non-expired bells enqueued by job(). * This list contains non-expired bells enqueued by job().
@ -34,26 +42,26 @@ class Bellringer {
*/ */
Queue<Bell> bells; Queue<Bell> bells;
//! Link pointer for bells
static Bell** bell_link(Bell& obj, unsigned link_index);
public: public:
// constructor // constructor
Bellringer() : bells(0, bell_link) {} Bellringer() : bells() {}
/*! \brief Checks whether there are bells to be rung. /*! \brief Checks whether there are bells to be rung.
* *
* Every call to check elapses a tick. Once such a tick reduces a bells * Every call to check elapses a tick. Once such a tick reduces a bells
* remaining time to zero, the bell will be rung. * remaining time to zero, the bell will be rung.
* *
* \param vault The vault containing the bellringer instance
*
* \todo(16) Implement Method * \todo(16) Implement Method
*/ */
void check(Vault& vault); void check(Vault& vault);
/*! \brief Passes a `bell` to the bellringer to be rung after `ms` /*! \brief Passes a `bell` to the bellringer to be rung after `ms`
* milliseconds. * milliseconds.
* \param bell Bell that should be rung after `ms` milliseconds *
* \param ms number of milliseconds that should be waited before * \param vault The vault containing the bellringer instance
* \param ms Number of milliseconds that should be waited before
* ringing the bell * ringing the bell
* *
* \todo(16) Implement Method * \todo(16) Implement Method

@ -1,16 +1,7 @@
#include "./semaphore.h" #include "./semaphore.h"
#include "../interrupt/guard.h"
#include "../thread/thread.h"
Semaphore::Semaphore(unsigned c) { (void)c; } Semaphore::Semaphore(unsigned c) { (void)c; }
Thread **Semaphore::thread_link(Thread &obj, unsigned link_index) {
(void)obj;
(void)link_index;
return nullptr;
}
void Semaphore::p(Vault &vault) { (void)vault; } void Semaphore::p(Vault &vault) { (void)vault; }
void Semaphore::v(Vault &vault) { (void)vault; } void Semaphore::v(Vault &vault) { (void)vault; }

@ -26,8 +26,6 @@ class Semaphore {
Semaphore(const Semaphore&) = delete; Semaphore(const Semaphore&) = delete;
Semaphore& operator=(const Semaphore&) = delete; Semaphore& operator=(const Semaphore&) = delete;
static Thread** thread_link(Thread& obj, unsigned link_index);
public: public:
/*! \brief Constructor; initialized the counter with provided value `c` /*! \brief Constructor; initialized the counter with provided value `c`
* \param c Initial counter value * \param c Initial counter value

@ -3,6 +3,7 @@
*/ */
#pragma once #pragma once
#include "../types.h"
#include "../arch/core.h" #include "../arch/core.h"
#include "../arch/cache.h" #include "../arch/cache.h"

@ -41,8 +41,8 @@ void Scheduler::kill(Thread* that) {
that->kill_flag = true; that->kill_flag = true;
} }
bool Scheduler::isActive(const Thread* that, unsigned int* cpu) { bool Scheduler::isActive(const Thread* thread, unsigned int* cpu) {
(void)that; (void)thread;
(void)cpu; (void)cpu;
return false; return false;
} }

@ -104,7 +104,7 @@ class Scheduler {
Thread* active() { return dispatcher.active(); } Thread* active() { return dispatcher.active(); }
/// \copydoc Dispatcher::isActive /// \copydoc Dispatcher::isActive
bool isActive(const Thread* that, unsigned int* cpu = nullptr); bool isActive(const Thread* thread, unsigned int* cpu = nullptr);
/*! \brief Checks whether the ready queue is empty. /*! \brief Checks whether the ready queue is empty.
* *

Loading…
Cancel
Save