Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ws25/v_bsb2/stubsmi

This commit is contained in:
2026-02-06 23:09:43 +01:00
31 changed files with 402 additions and 3388 deletions

View File

@@ -10,13 +10,9 @@ constinit struct InterruptDescriptor idt[256] = {};
// Struct used for loading (the address of) the Interrupt Descriptor Table into
// the IDT-Register
struct Register {
uint16_t limit; // Address of the last valid byte (relative to base)
struct InterruptDescriptor* base;
explicit Register(uint8_t max = 255) {
limit =
(max + static_cast<uint16_t>(1)) * sizeof(InterruptDescriptor) - 1;
base = idt;
}
uint16_t limit =
sizeof(idt) - 1; // Address of the last valid byte (relative to base)
struct InterruptDescriptor* base = idt;
} __attribute__((packed));
static_assert(sizeof(InterruptDescriptor) == 16,
@@ -26,11 +22,11 @@ static_assert(alignof(decltype(idt)) % 8 == 0, "IDT must be 8 byte aligned!");
void load() {
// Create structure required for writing to idtr and load via lidt
Register idtr(Core::Interrupt::VECTORS - 1);
Register idtr;
asm volatile("lidt %0\n\t" ::"m"(idtr));
}
void set(Core::Interrupt::Vector vector, InterruptDescriptor descriptor) {
idt[(uint8_t)vector] = descriptor;
idt[static_cast<uint8_t>(vector)] = descriptor;
}
} // namespace IDT

File diff suppressed because it is too large Load Diff

View File

@@ -96,13 +96,11 @@ Module *getModule(unsigned i) {
unsigned getModuleCount() { return multiboot_addr->mods.size; }
void *Memory::getStartAddress() const {
return reinterpret_cast<void *>(static_cast<uintptr_t>(addr));
}
void *Memory::getStartAddress() const { return reinterpret_cast<void *>(addr); }
void *Memory::getEndAddress() const {
uint64_t end = addr + len;
return reinterpret_cast<void *>(static_cast<uintptr_t>(end));
return reinterpret_cast<void *>(end);
}
bool Memory::isAvailable() const { return type == AVAILABLE; }

View File

@@ -1,7 +1,7 @@
#include "assert.h"
#include "../arch/core.h"
#include "output.h"
#include "./output.h"
[[noreturn]] void assertion_failed(const char* exp, const char* func,
const char* file, int line) {

View File

@@ -15,7 +15,7 @@
*/
#pragma once
#include "../types.h"
#include "types.h"
#ifndef STRINGIFY
/*! \def STRINGIFY(S)

View File

@@ -33,7 +33,7 @@ OutputStream* copyout = &copystream;
#include "./interrupt/guard.h"
#include "./boot/multiboot/data.h"
#include "./sync/semaphore.h"
#include "./thread/thread.h"
//Semaphore koutsem(1);
//TextStream kout(0, 80, 1, 17, true);

View File

@@ -29,7 +29,7 @@ assert_size(ErrorCode, 4);
uint64_t err) {
PageFault::ErrorCode error(err);
// Get the faulting address
uintptr_t virt;
uintptr_t virt = 0;
asm volatile("mov %%cr2, %0" : "=r"(virt));
DBG << "Page fault at " << hex << virt << dec << endl;

View File

@@ -25,18 +25,22 @@ class Queue {
/// Function pointer to the get_link function, called whenever the
/// next pointer array is referenced
const NextFunc get_link = default_get_link;
/// head points to the first element (the one returned on first dequeue).
/// Can be nullptr if the queue is empty.
/// `head` points to the first element (the one returned on first dequeue).
/// Can be `nullptr` if the queue is empty.
T* head = nullptr;
/// tail points to the last element (the one last added).
/// Is only valid if head != nullptr
/// `tail` points to the last element (the one last added).
/// Is only valid if `head != nullptr`.
T* tail = nullptr;
// Prevent copies and assignments
Queue(const Queue&) = delete;
Queue(Queue&&) = delete;
Queue& operator=(const Queue&) = delete;
Queue& operator=(Queue&&) = delete;
public:
~Queue() = default;
/*! \brief Minimal forward iterator
* You can use this iterator to iterate the queue like a normal STL
* container. It only supports forward iteration, since the queue is single
@@ -44,11 +48,11 @@ class Queue {
*/
class Iterator {
private:
Queue<T>& queue;
Queue<T>* queue;
T* current;
friend class Queue<T>;
Iterator(Queue<T>& queue, T* current)
: queue(queue), current(current) {}
: queue(&queue), current(current) {}
public:
Iterator operator+(unsigned num) {
@@ -57,21 +61,21 @@ class Queue {
}
T* temp = current;
while (num--) {
temp = queue.next(*temp);
temp = queue->next(*temp);
}
return Iterator(queue, temp);
return Iterator(*queue, temp);
}
// pre increment
Iterator& operator++() {
current = queue.next(*current);
current = queue->next(*current);
return *this;
}
// post increment
Iterator operator++(int) {
auto temp = Iterator(queue, current);
current = queue.next(*current);
current = queue->next(*current);
return temp;
}
@@ -84,8 +88,6 @@ class Queue {
bool operator!=(const Iterator& other) { return !(*this == other); }
};
constexpr Queue(Queue&&) = default;
/*! \brief Constructor
* \param[in] get_link A function pointer to the get_link, i.e. a function
* which returns a pointer to the next-pointer of an
@@ -97,11 +99,10 @@ class Queue {
"get_link function pointer must not be nullptr!");
}
/*! \brief Enqueues the provided item at the end of the queue. If the
*element is already contained in the queue, false will be returned
* \param[in] item element to be appended (enqueued).
* \return false if the element already was enqueued (and nothing was done)
* or not (and it is now enqueued, then true)
/*! \brief Enqueues the provided item at the end of the queue.
* \param[in] item Element to be appended (enqueued).
* \return `false` if the element already was already in this (or a
* different) queue (and nothing was done), `true` otherwise.
*/
bool enqueue(T& item) {
T** nextptr = get_link(item);
@@ -214,7 +215,7 @@ class Queue {
T* remove(T* that) {
if (!that) return nullptr;
T* cur = head;
T** next_link;
T** next_link = nullptr;
if (head == that) {
head = *get_link(*head);
@@ -258,14 +259,14 @@ class Queue {
* the pointer.
*/
template <class T>
OutputStream& operator<<(OutputStream& os, Queue<T>& queue) {
os << "{";
OutputStream& operator<<(OutputStream& out, Queue<T>& queue) {
out << "{";
for (typename Queue<T>::Iterator it = queue.begin(); it != queue.end();
++it) {
os << *it;
out << *it;
if (it + 1 != queue.end()) {
os << ", ";
out << ", ";
}
}
return os << "}";
return out << "}";
}

View File

@@ -3,42 +3,13 @@
#include "../types.h"
struct Message {
const size_t pid; ///< Sender Thread ID of message
int sender; ///< Sender Thread ID of message
const uintptr_t sbuffer; ///< Send buffer
const size_t ssize; ///< Send buffer size
uintptr_t sbuffer; ///< Send buffer
size_t ssize; ///< Send buffer size
const uintptr_t rbuffer; ///< Receive buffer
const size_t rsize; ///< Receive buffer size
uintptr_t rbuffer; ///< Receive buffer
size_t rsize; ///< Receive buffer size
Message *queue_link = nullptr; ///< Next message in the message queue
/*! \brief Constructor
* \param pid Sender Thread ID of message
* \param sbuffer Send buffer
* \param ssize Send buffer size
* \param rbuffer Receive buffer
* \param rsize Receive buffer size
*/
explicit Message(int pid, uintptr_t sbuffer = 0, size_t ssize = 0,
uintptr_t rbuffer = 0, size_t rsize = 0)
: pid(pid),
sbuffer(sbuffer),
ssize(ssize),
rbuffer(rbuffer),
rsize(rsize) {}
/*! \brief Helper to retrieve (and remove) a message from the queue
* \param pid Thread id of message
* \param queue Queue with message
* \return Pointer to message or nullptr
*/
static Message *dequeueByPID(size_t pid, Queue<Message> &queue) {
for (Message *m : queue) {
if (m->pid == pid) {
return queue.remove(m);
}
}
return nullptr;
}
};

View File

@@ -24,16 +24,16 @@ class Thread;
class Semaphore {
// Prevent copies and assignments
Semaphore(const Semaphore&) = delete;
Semaphore(Semaphore&&) = delete;
Semaphore& operator=(const Semaphore&) = delete;
Queue<Thread> waiting;
public:
/*! \brief Constructor; initialized the counter with provided value `c`
* \param c Initial counter value
/*! \param init Initial counter value
*/
explicit Semaphore(unsigned c = 0) : counter(c) {}
unsigned counter;
bool used;
bool used;
/*! \brief Wait for access to the critical area.
*
* Enter/decrement/wait operation: If the counter is greater than 0, then

View File

@@ -1,14 +1,12 @@
#include "syscall/handler.h"
#include "../arch/core.h"
#include "../arch/core_interrupt.h"
#include "../arch/gdt.h"
#include "../arch/idt.h"
#include "../debug/kernelpanic.h"
#include "../debug/output.h"
#include "../interrupt/guard.h"
#include "../syscall/skeleton.h"
#include "../syscall/stub.h"
#include "arch/core_interrupt.h"
#include "arch/idt.h"
#include "debug/kernelpanic.h"
#include "debug/output.h"
#include "interrupt/guard.h"
#include "syscall/skeleton.h"
#include "syscall/stub.h"
#include "types.h"
/*! \brief Interrupt based system call entry function
@@ -26,12 +24,12 @@ namespace Syscall {
* by the system call number -- allowing up to five parameters for the system
* call.
*
* \param sysnum identifier for the system call
* \param p1 first parameter
* \param p2 second parameter
* \param p3 third parameter
* \param p4 fourth parameter
* \param p5 fifth parameter
* \param sysnum identifier for the system call
* \param user pointer to the interrupt \ref context (for example to determine
* instruction pointer)
* \return system call return value

View File

@@ -22,7 +22,7 @@ bool sem_destroy(Vault &vault, size_t id);
bool sem_signal(Vault &vault, size_t id);
bool sem_wait(Vault &vault, size_t id);
void exit(Vault &vault);
void kill(Vault &vault, size_t pid);
void kill(Vault &vault, int pid);
} // namespace Skeleton
} // namespace Syscall

View File

@@ -32,15 +32,13 @@ void Scheduler::resume(bool ready) {
Thread *me = dispatcher.active();
assert(me != nullptr && "Pointer to active thread should never be nullptr");
if (true) {
// Be careful, never put the idle thread into the ready list
bool is_idle_thread = static_cast<Thread *>(&idleThread) == me;
// Be careful, never put the idle thread into the ready list
bool is_idle_thread = static_cast<Thread *>(&idleThread) == me;
if (ready && readylist.is_empty()) {
return;
} else if (!is_idle_thread) {
if (ready) readylist.enqueue(*me);
}
if (ready && readylist.is_empty()) {
return;
} else if (!is_idle_thread) {
if (ready) readylist.enqueue(*me);
}
dispatcher.dispatch(getNext());
@@ -56,6 +54,8 @@ void Scheduler::kill(Thread *that) {
if (dispatcher.active() == that) {
exit();
}
readylist.remove(that);
}
bool Scheduler::isEmpty() const { return readylist.is_empty(); }

View File

@@ -7,8 +7,7 @@
#include "../interrupt/guard.h"
#include "debug/output.h"
// counter for ID
static size_t idCounter = 1;
static int idCounter = 1; // counter for task IDs
void Thread::kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3) {
Thread *thread = reinterpret_cast<Thread *>(param1);

View File

@@ -38,7 +38,6 @@ class Thread {
// alignas(16) char reserved_stack_space_user[STACK_SIZE];
alignas(16) char reserved_stack_space_isr[STACK_SIZE];
protected:
/*! \brief Context of the thread, used for saving and restoring the register
* values when context switching.
*/
@@ -59,6 +58,7 @@ class Thread {
* \param param1 Thread to be started
* \param param2 Second parameter (will be used later)
* \param param3 Third parameter (will be used later)
*
*/
static void kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3);
@@ -72,7 +72,7 @@ class Thread {
void* operator new ( size_t count )noexcept;
/*! \brief Unique thread id */
const size_t id;
const int id;
@@ -81,6 +81,13 @@ class Thread {
*/
volatile bool kill_flag;
// Naively moving or copying esp. the (user) stack of a thread would be a
// bad idea:
Thread(const Thread&) = delete;
Thread(Thread&&) = delete;
Thread& operator=(const Thread&) = delete;
Thread& operator=(Thread&&) = delete;
/*! \brief Constructor
* Initializes the context using \ref prepareContext with the thread's
* stack space.

View File

@@ -4,7 +4,6 @@
void Application::action() { // NOLINT
// Thread 1 may be an auxiliary thread
//sys_test(1,2,3,4,5);
unsigned id = sys_getpid();

View File

@@ -1 +0,0 @@
#include "device/textstream.h"