Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ws25/v_bsb2/stubsmi
This commit is contained in:
28
.clang-tidy
28
.clang-tidy
@@ -1,6 +1,30 @@
|
|||||||
FormatStyle: google
|
FormatStyle: google
|
||||||
HeaderFilterRegex: '.*'
|
HeaderFilterRegex: '.*'
|
||||||
WarningsAsErrors: 'readability*'
|
#WarningsAsErrors: 'readability*'
|
||||||
Checks: 'readability*,google-readability-casting,google-explicit-constructor,bugprone*,-bugprone-narrowing-conversions,-bugprone-reserved-identifier,-readability-else-after-return,-readability-magic-numbers,-readability-identifier-length,-readability-braces-around-statements,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-pro-*,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-owning-memory'
|
Checks: >
|
||||||
|
google-readability-casting,
|
||||||
|
google-explicit-constructor,
|
||||||
|
readability*,
|
||||||
|
-readability-braces-around-statements,
|
||||||
|
-readability-else-after-return,
|
||||||
|
-readability-function-cognitive-complexity
|
||||||
|
-readability-identifier-length,
|
||||||
|
-readability-implicit-bool-conversion,
|
||||||
|
-readability-magic-numbers,
|
||||||
|
bugprone*,
|
||||||
|
-bugprone-easily-swappable-parameters,
|
||||||
|
-bugprone-narrowing-conversions,
|
||||||
|
-bugprone-reserved-identifier,
|
||||||
|
cppcoreguidelines-*,
|
||||||
|
-cppcoreguidelines-avoid-c-arrays,
|
||||||
|
-cppcoreguidelines-avoid-do-while,
|
||||||
|
-cppcoreguidelines-avoid-magic-numbers,
|
||||||
|
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||||
|
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||||
|
-cppcoreguidelines-owning-memory,
|
||||||
|
-cppcoreguidelines-pro-*,
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
readability-simplify-boolean-expr.IgnoreMacros: 'true'
|
readability-simplify-boolean-expr.IgnoreMacros: 'true'
|
||||||
|
readability-identifier-length.IgnoredVariableNames: '^(g|id|me)$'
|
||||||
|
readability-identifier-length.IgnoredParameterNames: '^(id|ms|p[1-5])$'
|
||||||
|
readability-identifier-length.IgnoredLoopCounterNames: '.*'
|
||||||
|
|||||||
3
LICENSE
3
LICENSE
@@ -8,7 +8,6 @@ Diese Vorlage dient als Grundlage für Lehrveranstaltungen und darf nicht ohne v
|
|||||||
Es ist erlaubt und wünschenswert, diese Vorlage als Inspiration für eigene Projekte zu verwenden, es wird allerdings erbeten, dass die Vorgabe nicht mit deiner Lösung veröffentlicht wird.
|
Es ist erlaubt und wünschenswert, diese Vorlage als Inspiration für eigene Projekte zu verwenden, es wird allerdings erbeten, dass die Vorgabe nicht mit deiner Lösung veröffentlicht wird.
|
||||||
Wir, als Lehrende, möchten alle teilnehmenden Studierenden dazu ermutigen eine eigene Lösung zu erstellen; eine veröffentlichte Lösung ist ein Anreiz zum Abschreiben, den wir gerne vermeiden möchten.
|
Wir, als Lehrende, möchten alle teilnehmenden Studierenden dazu ermutigen eine eigene Lösung zu erstellen; eine veröffentlichte Lösung ist ein Anreiz zum Abschreiben, den wir gerne vermeiden möchten.
|
||||||
|
|
||||||
|
|
||||||
This skeleton is provided as a foundation for educational purposes and therefore MUST NOT BE DISTRIBUTED OR PUBLISHED without prior, written consent of the copyright holders.
|
This skeleton is provided as a foundation for educational purposes and therefore MUST NOT BE DISTRIBUTED OR PUBLISHED without prior, written consent of the copyright holders.
|
||||||
You are free to use this skeleton as inspiration for your projects, but, please, do not publish it along with your solution.
|
You are free to use this skeleton as inspiration for your projects, but, please, do not publish it along with your solution.
|
||||||
We, as lecturers, want to encourage every participating student to write a solution themself; a public solution is an allurement to copying we want to avoid.
|
We, as lecturers, want to encourage every participating student to write a solution on their own; a public solution is an allurement to copying we want to avoid.
|
||||||
|
|||||||
@@ -10,13 +10,9 @@ constinit struct InterruptDescriptor idt[256] = {};
|
|||||||
// Struct used for loading (the address of) the Interrupt Descriptor Table into
|
// Struct used for loading (the address of) the Interrupt Descriptor Table into
|
||||||
// the IDT-Register
|
// the IDT-Register
|
||||||
struct Register {
|
struct Register {
|
||||||
uint16_t limit; // Address of the last valid byte (relative to base)
|
uint16_t limit =
|
||||||
struct InterruptDescriptor* base;
|
sizeof(idt) - 1; // Address of the last valid byte (relative to base)
|
||||||
explicit Register(uint8_t max = 255) {
|
struct InterruptDescriptor* base = idt;
|
||||||
limit =
|
|
||||||
(max + static_cast<uint16_t>(1)) * sizeof(InterruptDescriptor) - 1;
|
|
||||||
base = idt;
|
|
||||||
}
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
static_assert(sizeof(InterruptDescriptor) == 16,
|
static_assert(sizeof(InterruptDescriptor) == 16,
|
||||||
@@ -26,11 +22,11 @@ static_assert(alignof(decltype(idt)) % 8 == 0, "IDT must be 8 byte aligned!");
|
|||||||
|
|
||||||
void load() {
|
void load() {
|
||||||
// Create structure required for writing to idtr and load via lidt
|
// 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));
|
asm volatile("lidt %0\n\t" ::"m"(idtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(Core::Interrupt::Vector vector, InterruptDescriptor descriptor) {
|
void set(Core::Interrupt::Vector vector, InterruptDescriptor descriptor) {
|
||||||
idt[(uint8_t)vector] = descriptor;
|
idt[static_cast<uint8_t>(vector)] = descriptor;
|
||||||
}
|
}
|
||||||
} // namespace IDT
|
} // namespace IDT
|
||||||
|
|||||||
3175
kernel/assets/osg.h
3175
kernel/assets/osg.h
File diff suppressed because it is too large
Load Diff
@@ -96,13 +96,11 @@ Module *getModule(unsigned i) {
|
|||||||
|
|
||||||
unsigned getModuleCount() { return multiboot_addr->mods.size; }
|
unsigned getModuleCount() { return multiboot_addr->mods.size; }
|
||||||
|
|
||||||
void *Memory::getStartAddress() const {
|
void *Memory::getStartAddress() const { return reinterpret_cast<void *>(addr); }
|
||||||
return reinterpret_cast<void *>(static_cast<uintptr_t>(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Memory::getEndAddress() const {
|
void *Memory::getEndAddress() const {
|
||||||
uint64_t end = addr + len;
|
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; }
|
bool Memory::isAvailable() const { return type == AVAILABLE; }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
#include "../arch/core.h"
|
#include "../arch/core.h"
|
||||||
#include "output.h"
|
#include "./output.h"
|
||||||
|
|
||||||
[[noreturn]] void assertion_failed(const char* exp, const char* func,
|
[[noreturn]] void assertion_failed(const char* exp, const char* func,
|
||||||
const char* file, int line) {
|
const char* file, int line) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#ifndef STRINGIFY
|
#ifndef STRINGIFY
|
||||||
/*! \def STRINGIFY(S)
|
/*! \def STRINGIFY(S)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ OutputStream* copyout = ©stream;
|
|||||||
#include "./interrupt/guard.h"
|
#include "./interrupt/guard.h"
|
||||||
#include "./boot/multiboot/data.h"
|
#include "./boot/multiboot/data.h"
|
||||||
#include "./sync/semaphore.h"
|
#include "./sync/semaphore.h"
|
||||||
#include "./thread/thread.h"
|
|
||||||
//Semaphore koutsem(1);
|
//Semaphore koutsem(1);
|
||||||
//TextStream kout(0, 80, 1, 17, true);
|
//TextStream kout(0, 80, 1, 17, true);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ assert_size(ErrorCode, 4);
|
|||||||
uint64_t err) {
|
uint64_t err) {
|
||||||
PageFault::ErrorCode error(err);
|
PageFault::ErrorCode error(err);
|
||||||
// Get the faulting address
|
// Get the faulting address
|
||||||
uintptr_t virt;
|
uintptr_t virt = 0;
|
||||||
asm volatile("mov %%cr2, %0" : "=r"(virt));
|
asm volatile("mov %%cr2, %0" : "=r"(virt));
|
||||||
DBG << "Page fault at " << hex << virt << dec << endl;
|
DBG << "Page fault at " << hex << virt << dec << endl;
|
||||||
|
|
||||||
|
|||||||
@@ -25,18 +25,22 @@ class Queue {
|
|||||||
/// 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
|
||||||
const NextFunc get_link = default_get_link;
|
const NextFunc get_link = default_get_link;
|
||||||
/// head points to the first element (the one returned on first dequeue).
|
/// `head` points to the first element (the one returned on first dequeue).
|
||||||
/// Can be nullptr if the queue is empty.
|
/// Can be `nullptr` if the queue is empty.
|
||||||
T* head = nullptr;
|
T* head = nullptr;
|
||||||
/// tail points to the last element (the one last added).
|
/// `tail` points to the last element (the one last added).
|
||||||
/// Is only valid if head != nullptr
|
/// Is only valid if `head != nullptr`.
|
||||||
T* tail = nullptr;
|
T* tail = nullptr;
|
||||||
|
|
||||||
// Prevent copies and assignments
|
// Prevent copies and assignments
|
||||||
Queue(const Queue&) = delete;
|
Queue(const Queue&) = delete;
|
||||||
|
Queue(Queue&&) = delete;
|
||||||
Queue& operator=(const Queue&) = delete;
|
Queue& operator=(const Queue&) = delete;
|
||||||
|
Queue& operator=(Queue&&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~Queue() = default;
|
||||||
|
|
||||||
/*! \brief Minimal forward iterator
|
/*! \brief Minimal forward iterator
|
||||||
* You can use this iterator to iterate the queue like a normal STL
|
* You can use this iterator to iterate the queue like a normal STL
|
||||||
* container. It only supports forward iteration, since the queue is single
|
* container. It only supports forward iteration, since the queue is single
|
||||||
@@ -44,11 +48,11 @@ class Queue {
|
|||||||
*/
|
*/
|
||||||
class Iterator {
|
class Iterator {
|
||||||
private:
|
private:
|
||||||
Queue<T>& queue;
|
Queue<T>* queue;
|
||||||
T* current;
|
T* current;
|
||||||
friend class Queue<T>;
|
friend class Queue<T>;
|
||||||
Iterator(Queue<T>& queue, T* current)
|
Iterator(Queue<T>& queue, T* current)
|
||||||
: queue(queue), current(current) {}
|
: queue(&queue), current(current) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Iterator operator+(unsigned num) {
|
Iterator operator+(unsigned num) {
|
||||||
@@ -57,21 +61,21 @@ class Queue {
|
|||||||
}
|
}
|
||||||
T* temp = current;
|
T* temp = current;
|
||||||
while (num--) {
|
while (num--) {
|
||||||
temp = queue.next(*temp);
|
temp = queue->next(*temp);
|
||||||
}
|
}
|
||||||
return Iterator(queue, temp);
|
return Iterator(*queue, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pre increment
|
// pre increment
|
||||||
Iterator& operator++() {
|
Iterator& operator++() {
|
||||||
current = queue.next(*current);
|
current = queue->next(*current);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post increment
|
// post increment
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
auto temp = Iterator(queue, current);
|
auto temp = Iterator(queue, current);
|
||||||
current = queue.next(*current);
|
current = queue->next(*current);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +88,6 @@ class Queue {
|
|||||||
bool operator!=(const Iterator& other) { return !(*this == other); }
|
bool operator!=(const Iterator& other) { return !(*this == other); }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Queue(Queue&&) = default;
|
|
||||||
|
|
||||||
/*! \brief Constructor
|
/*! \brief Constructor
|
||||||
* \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 next-pointer of an
|
* which returns a pointer to the next-pointer of an
|
||||||
@@ -97,11 +99,10 @@ class Queue {
|
|||||||
"get_link function pointer must not be nullptr!");
|
"get_link function pointer must not be nullptr!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enqueues the provided item at the end of the queue. If the
|
/*! \brief Enqueues the provided item at the end of the queue.
|
||||||
*element is already contained in the queue, false will be returned
|
* \param[in] item Element to be appended (enqueued).
|
||||||
* \param[in] item element to be appended (enqueued).
|
* \return `false` if the element already was already in this (or a
|
||||||
* \return false if the element already was enqueued (and nothing was done)
|
* different) queue (and nothing was done), `true` otherwise.
|
||||||
* or not (and it is now enqueued, then true)
|
|
||||||
*/
|
*/
|
||||||
bool enqueue(T& item) {
|
bool enqueue(T& item) {
|
||||||
T** nextptr = get_link(item);
|
T** nextptr = get_link(item);
|
||||||
@@ -214,7 +215,7 @@ class Queue {
|
|||||||
T* remove(T* that) {
|
T* remove(T* that) {
|
||||||
if (!that) return nullptr;
|
if (!that) return nullptr;
|
||||||
T* cur = head;
|
T* cur = head;
|
||||||
T** next_link;
|
T** next_link = nullptr;
|
||||||
|
|
||||||
if (head == that) {
|
if (head == that) {
|
||||||
head = *get_link(*head);
|
head = *get_link(*head);
|
||||||
@@ -258,14 +259,14 @@ class Queue {
|
|||||||
* the pointer.
|
* the pointer.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputStream& operator<<(OutputStream& os, Queue<T>& queue) {
|
OutputStream& operator<<(OutputStream& out, Queue<T>& queue) {
|
||||||
os << "{";
|
out << "{";
|
||||||
for (typename Queue<T>::Iterator it = queue.begin(); it != queue.end();
|
for (typename Queue<T>::Iterator it = queue.begin(); it != queue.end();
|
||||||
++it) {
|
++it) {
|
||||||
os << *it;
|
out << *it;
|
||||||
if (it + 1 != queue.end()) {
|
if (it + 1 != queue.end()) {
|
||||||
os << ", ";
|
out << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return os << "}";
|
return out << "}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,42 +3,13 @@
|
|||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
|
|
||||||
struct Message {
|
struct Message {
|
||||||
const size_t pid; ///< Sender Thread ID of message
|
int sender; ///< Sender Thread ID of message
|
||||||
|
|
||||||
const uintptr_t sbuffer; ///< Send buffer
|
uintptr_t sbuffer; ///< Send buffer
|
||||||
const size_t ssize; ///< Send buffer size
|
size_t ssize; ///< Send buffer size
|
||||||
|
|
||||||
const uintptr_t rbuffer; ///< Receive buffer
|
uintptr_t rbuffer; ///< Receive buffer
|
||||||
const size_t rsize; ///< Receive buffer size
|
size_t rsize; ///< Receive buffer size
|
||||||
|
|
||||||
Message *queue_link = nullptr; ///< Next message in the message queue
|
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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ class Thread;
|
|||||||
class Semaphore {
|
class Semaphore {
|
||||||
// Prevent copies and assignments
|
// Prevent copies and assignments
|
||||||
Semaphore(const Semaphore&) = delete;
|
Semaphore(const Semaphore&) = delete;
|
||||||
|
Semaphore(Semaphore&&) = delete;
|
||||||
Semaphore& operator=(const Semaphore&) = delete;
|
Semaphore& operator=(const Semaphore&) = delete;
|
||||||
Queue<Thread> waiting;
|
Queue<Thread> waiting;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*! \brief Constructor; initialized the counter with provided value `c`
|
/*! \param init Initial counter value
|
||||||
* \param c Initial counter value
|
|
||||||
*/
|
*/
|
||||||
explicit Semaphore(unsigned c = 0) : counter(c) {}
|
explicit Semaphore(unsigned c = 0) : counter(c) {}
|
||||||
unsigned counter;
|
unsigned counter;
|
||||||
bool used;
|
bool used;
|
||||||
/*! \brief Wait for access to the critical area.
|
/*! \brief Wait for access to the critical area.
|
||||||
*
|
*
|
||||||
* Enter/decrement/wait operation: If the counter is greater than 0, then
|
* Enter/decrement/wait operation: If the counter is greater than 0, then
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#include "syscall/handler.h"
|
#include "syscall/handler.h"
|
||||||
|
|
||||||
#include "../arch/core.h"
|
#include "arch/core_interrupt.h"
|
||||||
#include "../arch/core_interrupt.h"
|
#include "arch/idt.h"
|
||||||
#include "../arch/gdt.h"
|
#include "debug/kernelpanic.h"
|
||||||
#include "../arch/idt.h"
|
#include "debug/output.h"
|
||||||
#include "../debug/kernelpanic.h"
|
#include "interrupt/guard.h"
|
||||||
#include "../debug/output.h"
|
#include "syscall/skeleton.h"
|
||||||
#include "../interrupt/guard.h"
|
#include "syscall/stub.h"
|
||||||
#include "../syscall/skeleton.h"
|
|
||||||
#include "../syscall/stub.h"
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
/*! \brief Interrupt based system call entry function
|
/*! \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
|
* by the system call number -- allowing up to five parameters for the system
|
||||||
* call.
|
* call.
|
||||||
*
|
*
|
||||||
|
* \param sysnum identifier for the system call
|
||||||
* \param p1 first parameter
|
* \param p1 first parameter
|
||||||
* \param p2 second parameter
|
* \param p2 second parameter
|
||||||
* \param p3 third parameter
|
* \param p3 third parameter
|
||||||
* \param p4 fourth parameter
|
* \param p4 fourth parameter
|
||||||
* \param p5 fifth parameter
|
* \param p5 fifth parameter
|
||||||
* \param sysnum identifier for the system call
|
|
||||||
* \param user pointer to the interrupt \ref context (for example to determine
|
* \param user pointer to the interrupt \ref context (for example to determine
|
||||||
* instruction pointer)
|
* instruction pointer)
|
||||||
* \return system call return value
|
* \return system call return value
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ bool sem_destroy(Vault &vault, size_t id);
|
|||||||
bool sem_signal(Vault &vault, size_t id);
|
bool sem_signal(Vault &vault, size_t id);
|
||||||
bool sem_wait(Vault &vault, size_t id);
|
bool sem_wait(Vault &vault, size_t id);
|
||||||
void exit(Vault &vault);
|
void exit(Vault &vault);
|
||||||
void kill(Vault &vault, size_t pid);
|
void kill(Vault &vault, int pid);
|
||||||
|
|
||||||
} // namespace Skeleton
|
} // namespace Skeleton
|
||||||
} // namespace Syscall
|
} // namespace Syscall
|
||||||
|
|||||||
@@ -32,15 +32,13 @@ void Scheduler::resume(bool ready) {
|
|||||||
Thread *me = dispatcher.active();
|
Thread *me = dispatcher.active();
|
||||||
assert(me != nullptr && "Pointer to active thread should never be nullptr");
|
assert(me != nullptr && "Pointer to active thread should never be nullptr");
|
||||||
|
|
||||||
if (true) {
|
// Be careful, never put the idle thread into the ready list
|
||||||
// Be careful, never put the idle thread into the ready list
|
bool is_idle_thread = static_cast<Thread *>(&idleThread) == me;
|
||||||
bool is_idle_thread = static_cast<Thread *>(&idleThread) == me;
|
|
||||||
|
|
||||||
if (ready && readylist.is_empty()) {
|
if (ready && readylist.is_empty()) {
|
||||||
return;
|
return;
|
||||||
} else if (!is_idle_thread) {
|
} else if (!is_idle_thread) {
|
||||||
if (ready) readylist.enqueue(*me);
|
if (ready) readylist.enqueue(*me);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher.dispatch(getNext());
|
dispatcher.dispatch(getNext());
|
||||||
@@ -56,6 +54,8 @@ void Scheduler::kill(Thread *that) {
|
|||||||
if (dispatcher.active() == that) {
|
if (dispatcher.active() == that) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readylist.remove(that);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scheduler::isEmpty() const { return readylist.is_empty(); }
|
bool Scheduler::isEmpty() const { return readylist.is_empty(); }
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
#include "../interrupt/guard.h"
|
#include "../interrupt/guard.h"
|
||||||
#include "debug/output.h"
|
#include "debug/output.h"
|
||||||
|
|
||||||
// counter for ID
|
static int idCounter = 1; // counter for task IDs
|
||||||
static size_t idCounter = 1;
|
|
||||||
|
|
||||||
void Thread::kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3) {
|
void Thread::kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3) {
|
||||||
Thread *thread = reinterpret_cast<Thread *>(param1);
|
Thread *thread = reinterpret_cast<Thread *>(param1);
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class Thread {
|
|||||||
// alignas(16) char reserved_stack_space_user[STACK_SIZE];
|
// alignas(16) char reserved_stack_space_user[STACK_SIZE];
|
||||||
alignas(16) char reserved_stack_space_isr[STACK_SIZE];
|
alignas(16) char reserved_stack_space_isr[STACK_SIZE];
|
||||||
|
|
||||||
protected:
|
|
||||||
/*! \brief Context of the thread, used for saving and restoring the register
|
/*! \brief Context of the thread, used for saving and restoring the register
|
||||||
* values when context switching.
|
* values when context switching.
|
||||||
*/
|
*/
|
||||||
@@ -59,6 +58,7 @@ class Thread {
|
|||||||
* \param param1 Thread to be started
|
* \param param1 Thread to be started
|
||||||
* \param param2 Second parameter (will be used later)
|
* \param param2 Second parameter (will be used later)
|
||||||
* \param param3 Third 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);
|
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;
|
void* operator new ( size_t count )noexcept;
|
||||||
|
|
||||||
/*! \brief Unique thread id */
|
/*! \brief Unique thread id */
|
||||||
const size_t id;
|
const int id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -81,6 +81,13 @@ class Thread {
|
|||||||
*/
|
*/
|
||||||
volatile bool kill_flag;
|
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
|
/*! \brief Constructor
|
||||||
* Initializes the context using \ref prepareContext with the thread's
|
* Initializes the context using \ref prepareContext with the thread's
|
||||||
* stack space.
|
* stack space.
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
void Application::action() { // NOLINT
|
void Application::action() { // NOLINT
|
||||||
// Thread 1 may be an auxiliary thread
|
// Thread 1 may be an auxiliary thread
|
||||||
|
|
||||||
//sys_test(1,2,3,4,5);
|
//sys_test(1,2,3,4,5);
|
||||||
|
|
||||||
unsigned id = sys_getpid();
|
unsigned id = sys_getpid();
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#include "device/textstream.h"
|
|
||||||
74
libsys/assert.h
Normal file
74
libsys/assert.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// vim: set noet ts=4 sw=4:
|
||||||
|
|
||||||
|
/*! \file
|
||||||
|
* \brief Contains several macros usable for making assertions
|
||||||
|
*
|
||||||
|
* Depending on the type of assertion (either static or at runtime), a failing
|
||||||
|
* assertion will trigger an error. For static assertion, this error will be
|
||||||
|
* shown at compile time and abort compilation. Runtime assertions will trigger
|
||||||
|
* a message containing details about the error occurred and will make the CPU
|
||||||
|
* die.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \defgroup debug Debugging functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#ifndef STRINGIFY
|
||||||
|
/*! \def STRINGIFY(S)
|
||||||
|
* \brief Converts a macro parameter into a string
|
||||||
|
* \ingroup debug
|
||||||
|
* \param S Expression to be converted
|
||||||
|
* \return stringified version of S
|
||||||
|
*/
|
||||||
|
#define STRINGIFY(S) #S
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \def assert_size(TYPE, SIZE)
|
||||||
|
* \brief Statically ensure (at compile time) that a data type (or variable)
|
||||||
|
* has the expected size.
|
||||||
|
*
|
||||||
|
* \ingroup debug
|
||||||
|
* \param TYPE The type to be checked
|
||||||
|
* \param SIZE Expected size in bytes
|
||||||
|
*/
|
||||||
|
#define assert_size(TYPE, SIZE) \
|
||||||
|
static_assert(sizeof(TYPE) == (SIZE), "Wrong size for " STRINGIFY(TYPE))
|
||||||
|
|
||||||
|
/*! \def assert(EXP)
|
||||||
|
* \brief Ensure (at execution time) an expression evaluates to `true`, print
|
||||||
|
* an error message and stop the CPU otherwise.
|
||||||
|
*
|
||||||
|
* \ingroup debug
|
||||||
|
* \param EXP The expression to be checked
|
||||||
|
*/
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define assert(EXP) ((void)0)
|
||||||
|
#else
|
||||||
|
#define assert(EXP) \
|
||||||
|
do { \
|
||||||
|
if (__builtin_expect(!(EXP), 0)) { \
|
||||||
|
assertion_failed(STRINGIFY(EXP), __func__, __FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
/*! \brief Handles a failed assertion
|
||||||
|
*
|
||||||
|
* This function will print a message containing further information about the
|
||||||
|
* failed assertion and stops the current CPU permanently.
|
||||||
|
*
|
||||||
|
* \note This function should never be called directly, but only via the macro
|
||||||
|
* `assert`.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \param exp Expression that did not hold
|
||||||
|
* \param func Name of the function in which the assertion failed
|
||||||
|
* \param file Name of the file in which the assertion failed
|
||||||
|
* \param line Line in which the assertion failed
|
||||||
|
*/
|
||||||
|
[[noreturn]] void assertion_failed(const char* exp, const char* func,
|
||||||
|
const char* file, int line);
|
||||||
|
#endif
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "outputstream.h"
|
|
||||||
#include "stub.h"
|
|
||||||
|
|
||||||
class IOStream : public OutputStream {
|
|
||||||
private:
|
|
||||||
IOStream(IOStream ©); // no copy
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit IOStream(int sysfd = 0) : fd(sysfd) {}
|
|
||||||
|
|
||||||
~IOStream() {
|
|
||||||
if (pos > 0) {
|
|
||||||
sys_write(fd, buffer, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush() override {
|
|
||||||
sys_write(fd, buffer, pos);
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#include "rand.h"
|
|
||||||
|
|
||||||
// Mersenne Twister (32 bit pseudorandom number generator)
|
|
||||||
// https://en.wikipedia.org/wiki/Mersenne_Twister
|
|
||||||
|
|
||||||
static const uint32_t N = 624;
|
|
||||||
static const uint32_t M = 397;
|
|
||||||
static const uint32_t R = 31;
|
|
||||||
static const uint32_t A = 0x9908B0DF;
|
|
||||||
|
|
||||||
// initialization multiplier
|
|
||||||
static const uint32_t F = 1812433253;
|
|
||||||
|
|
||||||
static const uint32_t U = 11;
|
|
||||||
|
|
||||||
static const uint32_t S = 7;
|
|
||||||
static const uint32_t B = 0x9D2C5680;
|
|
||||||
|
|
||||||
static const uint32_t T = 15;
|
|
||||||
static const uint32_t C = 0xEFC60000;
|
|
||||||
|
|
||||||
static const uint32_t L = 18;
|
|
||||||
|
|
||||||
static const uint32_t MASK_LOWER = (1ULL << R) - 1;
|
|
||||||
static const uint32_t MASK_UPPER = (1ULL << R);
|
|
||||||
|
|
||||||
static uint32_t mt[N];
|
|
||||||
static uint16_t index;
|
|
||||||
|
|
||||||
void srand(const uint32_t seed) {
|
|
||||||
mt[0] = seed;
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i < N; i++) {
|
|
||||||
mt[i] = (F * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
index = N;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t rand() {
|
|
||||||
uint16_t v = index;
|
|
||||||
|
|
||||||
if (index >= N) {
|
|
||||||
// Twist
|
|
||||||
for (uint32_t i = 0; i < N; i++) {
|
|
||||||
uint32_t x = (mt[i] & MASK_UPPER) + (mt[(i + 1) % N] & MASK_LOWER);
|
|
||||||
|
|
||||||
uint32_t xA = x >> 1;
|
|
||||||
|
|
||||||
if ((x & 0x1) != 0) {
|
|
||||||
xA ^= A;
|
|
||||||
}
|
|
||||||
|
|
||||||
mt[i] = mt[(i + M) % N] ^ xA;
|
|
||||||
}
|
|
||||||
v = index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t y = mt[v];
|
|
||||||
index = v + 1;
|
|
||||||
|
|
||||||
y ^= (y >> U);
|
|
||||||
y ^= (y << S) & B;
|
|
||||||
y ^= (y << T) & C;
|
|
||||||
y ^= (y >> L);
|
|
||||||
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
const uint32_t RAND_MAX = UINT32_MAX;
|
|
||||||
|
|
||||||
void srand(uint32_t seed);
|
|
||||||
|
|
||||||
uint32_t rand();
|
|
||||||
0
nix-develop.sh
Normal file → Executable file
0
nix-develop.sh
Normal file → Executable file
@@ -99,7 +99,7 @@ $(BUILDDIR)/%.asm.o : %.asm $(MAKEFILE_LIST)
|
|||||||
# The standard target 'clean' removes the whole generated system, the object files, and the dependency files.
|
# The standard target 'clean' removes the whole generated system, the object files, and the dependency files.
|
||||||
clean::
|
clean::
|
||||||
rm -rf "$(BUILDDIR)"
|
rm -rf "$(BUILDDIR)"
|
||||||
|
rm -rf doc
|
||||||
|
|
||||||
# Target issuing a nested call to make generating a fully optimized systems without assertions.
|
# Target issuing a nested call to make generating a fully optimized systems without assertions.
|
||||||
%-$(OPTTAG):
|
%-$(OPTTAG):
|
||||||
@@ -120,6 +120,9 @@ clean::
|
|||||||
%-$(VERBOSETAG):
|
%-$(VERBOSETAG):
|
||||||
$(VERBOSE) $(MAKE) BUILDDIR="$(BUILDDIR)/$(VERBOSETAG)" ISODIR="$(ISODIR)/$(VERBOSETAG)" CXXFLAGS_OPT="-DVERBOSE" $*
|
$(VERBOSE) $(MAKE) BUILDDIR="$(BUILDDIR)/$(VERBOSETAG)" ISODIR="$(ISODIR)/$(VERBOSETAG)" CXXFLAGS_OPT="-DVERBOSE" $*
|
||||||
|
|
||||||
|
# Build the doxygen docs
|
||||||
|
doc:
|
||||||
|
PROJECT_NAME=StuBS doxygen ../doxygen/doxy-sra.cfg
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
help::
|
help::
|
||||||
@@ -134,7 +137,8 @@ help::
|
|||||||
"To get a verbose make output, clear VERBOSE, e.g. \e[3mmake VERBOSE=\e[0m.\n" \
|
"To get a verbose make output, clear VERBOSE, e.g. \e[3mmake VERBOSE=\e[0m.\n" \
|
||||||
"The following targets are available (each target can be suffixed by \e[3m-noopt\e[0m\n" \
|
"The following targets are available (each target can be suffixed by \e[3m-noopt\e[0m\n" \
|
||||||
"and \e[3m-verbose\e[0m):\n\n" \
|
"and \e[3m-verbose\e[0m):\n\n" \
|
||||||
" \e[3mall\e[0m Builds $(PROJECT), generating an ELF binary\n\n"
|
" \e[3mall\e[0m Builds $(PROJECT), generating an ELF binary\n\n" \
|
||||||
|
" \e[3mdoc\e[0m Builds the documention (doc/html/index.html)\n" \
|
||||||
|
|
||||||
|
|
||||||
# Print warnings, if appropriate
|
# Print warnings, if appropriate
|
||||||
@@ -150,4 +154,4 @@ endif
|
|||||||
|
|
||||||
|
|
||||||
# Phony targets
|
# Phony targets
|
||||||
.PHONY: clean help
|
.PHONY: clean doc help
|
||||||
|
|||||||
0
tools/cpplint.py
vendored
Normal file → Executable file
0
tools/cpplint.py
vendored
Normal file → Executable file
@@ -13,8 +13,33 @@ INITRD = $(BUILDDIR)/initrd.img
|
|||||||
|
|
||||||
all: $(INITRD)
|
all: $(INITRD)
|
||||||
|
|
||||||
# recipe for building the final oostubs image
|
# Rezepte fuer Apps (Unterverzeichnisse)
|
||||||
$(INITRD):
|
$(APPS): $(BUILDDIR)/init.o
|
||||||
|
$(VERBOSE) $(MAKE) -C $@ -f ../Makefile.app
|
||||||
|
|
||||||
|
# recipe for compiling imgbuilder
|
||||||
|
$(IMGBUILDER): imgbuilder.cc $(MAKEFILE_LIST)
|
||||||
|
@echo "CXX $@"
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(VERBOSE) $(CXX) -std=c++23 -o $@ $<
|
||||||
|
|
||||||
|
.ONESHELL:
|
||||||
|
# recipe for building the initrd image
|
||||||
|
$(INITRD): $(APPS) $(IMGBUILDER)
|
||||||
@echo "IMGBUILD $@"
|
@echo "IMGBUILD $@"
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
@touch $@
|
if [ -z "$(APPS)" ] ; then touch $@ ; exit 0 ; fi
|
||||||
|
$(VERBOSE) $(IMGBUILDER) $(addsuffix $(BUILDDIR)/app.img, $(APPS)) > $@
|
||||||
|
|
||||||
|
lint::
|
||||||
|
$(VERBOSE) $(foreach APP,$(APPS),$(MAKE) -C $(APP) -f ../Makefile.app lint && ) true
|
||||||
|
|
||||||
|
tidy::
|
||||||
|
$(VERBOSE) $(foreach APP,$(APPS),$(MAKE) -C $(APP) -f ../Makefile.app tidy && ) true
|
||||||
|
|
||||||
|
# clean all apps additionally to default clean recipe from common.mk
|
||||||
|
clean::
|
||||||
|
$(VERBOSE) $(foreach APP,$(APPS),$(MAKE) -C $(APP) -f ../Makefile.app clean && ) true
|
||||||
|
|
||||||
|
.PHONY: all clean $(APPS)
|
||||||
|
|
||||||
|
|||||||
53
user/Makefile.app
Normal file
53
user/Makefile.app
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Linker Script
|
||||||
|
LINKER_SCRIPT = ../sections.ld
|
||||||
|
# Files to be compiled (important: defined prior to importing common.mk!)
|
||||||
|
CC_SOURCES = $(shell find * -name "*.cc" -a ! -name '.*' )
|
||||||
|
ASM_SOURCES = $(shell find * -name "*.asm" -a ! -name '.*' )
|
||||||
|
|
||||||
|
CXXFLAGS_INCLUDE = -I../../libsys -I../../kernel
|
||||||
|
CXXFLAGS_DEFAULT += $(CXXFLAGS_INCLUDE)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Globale Variablen und Standard-Rezepte einbinden
|
||||||
|
include ../../tools/common.mk
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Default target
|
||||||
|
|
||||||
|
.DEFAULT_GOAL = all
|
||||||
|
all: $(BUILDDIR)/app.img
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Parameters & flags:
|
||||||
|
|
||||||
|
CXXFLAGS += $(CXXFLAGS_INCLUDE)
|
||||||
|
# Enable 16-byte compare-and-exchange instruction for debugging purposes (stack alignment)
|
||||||
|
CXXFLAGS += -mcx16
|
||||||
|
|
||||||
|
LDLIBS += -L../../libsys/$(BUILDDIR) -lsys
|
||||||
|
INITOBJ = ../$(BUILDDIR)/init.o
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Linked applications
|
||||||
|
$(BUILDDIR)/app: $(INITOBJ) $(ASM_OBJECTS) $(CC_OBJECTS) $(LINKER_SCRIPT) $(MAKEFILE_LIST)
|
||||||
|
@echo "LD $@"
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(VERBOSE) $(CXX) $(CXXFLAGS) -Wl,-T $(LINKER_SCRIPT) -o $@ $(LDFLAGS) $(INITOBJ) $(ASM_OBJECTS) $(CC_OBJECTS) $(LDLIBS)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# 'app.img' contains all section required for loading an application (flat binary)
|
||||||
|
|
||||||
|
$(BUILDDIR)/app.img: $(BUILDDIR)/app
|
||||||
|
@echo "OBJCOPY $@"
|
||||||
|
@if ! nm $< | grep "4000000 T start" >/dev/null 2>&1 ; then echo "Symbol 'start' is not first address" ; exit 1 ; fi
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(VERBOSE) objcopy -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Include dependency files (generated gcc -MM)
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
-include $(DEP_FILES)
|
||||||
|
endif
|
||||||
|
|
||||||
67
user/imgbuilder.cc
Normal file
67
user/imgbuilder.cc
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <format>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <print>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
constexpr std::streamsize block_size = 4096;
|
||||||
|
const uint8_t zeros[block_size] = {};
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
static void die(std::format_string<Args...> fmt, Args &&...args) {
|
||||||
|
auto msg = std::format(fmt, std::forward<Args>(args)...);
|
||||||
|
perror(msg.c_str());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeBuffer(const void *data, std::streamsize size) {
|
||||||
|
std::cout.write(reinterpret_cast<const char *>(data), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 2) {
|
||||||
|
std::println(stderr, "usage: {} <list of flat binaries>\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else if (argc > 1000) {
|
||||||
|
std::println(stderr, "Only a maximum of 1000 apps are supported\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEADER: Number of apps + size of each app in bytes
|
||||||
|
std::array<uint32_t, block_size / sizeof(uint32_t)> sizes{0};
|
||||||
|
sizes[0] = static_cast<uint32_t>(argc - 1);
|
||||||
|
for (size_t i = 1; i < argc; ++i) {
|
||||||
|
struct stat file;
|
||||||
|
if (stat(argv[i], &file) != 0) die("stat");
|
||||||
|
if (file.st_size >= UINT32_MAX) { // 4 GB Limit
|
||||||
|
errno = EFBIG;
|
||||||
|
die("stat");
|
||||||
|
}
|
||||||
|
sizes[i] = file.st_size;
|
||||||
|
}
|
||||||
|
writeBuffer(sizes.data(), block_size);
|
||||||
|
|
||||||
|
// DATA: Each App
|
||||||
|
for (size_t i = 1; i < argc; ++i) {
|
||||||
|
std::vector<char> buf(sizes[i]);
|
||||||
|
std::ifstream input(argv[i], std::ios::binary);
|
||||||
|
if (!input) die("fopen");
|
||||||
|
|
||||||
|
input.read(buf.data(), sizes[i]);
|
||||||
|
|
||||||
|
writeBuffer(buf.data(), sizes[i]);
|
||||||
|
|
||||||
|
// Fill to block size, if required
|
||||||
|
if (sizes[i] % block_size != 0)
|
||||||
|
writeBuffer(zeros, block_size - (sizes[i] % block_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout.flush();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
73
user/init.cc
Normal file
73
user/init.cc
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include <../libsys/stub.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void _init();
|
||||||
|
extern void _fini();
|
||||||
|
extern void main();
|
||||||
|
|
||||||
|
extern void (*__preinit_array_start[])();
|
||||||
|
extern void (*__preinit_array_end[])();
|
||||||
|
extern void (*__init_array_start[])();
|
||||||
|
extern void (*__init_array_end[])();
|
||||||
|
extern void (*__fini_array_start[])();
|
||||||
|
extern void (*__fini_array_end[])();
|
||||||
|
[[gnu::used]] [[noreturn]] void start() {
|
||||||
|
const unsigned int preinit_size =
|
||||||
|
__preinit_array_end - __preinit_array_start;
|
||||||
|
for (unsigned int i = 0; i != preinit_size; ++i)
|
||||||
|
(*__preinit_array_start[i])();
|
||||||
|
|
||||||
|
const unsigned int init_size = __init_array_end - __init_array_start;
|
||||||
|
for (unsigned int i = 0; i != init_size; ++i) (*__init_array_start[i])();
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
const unsigned int fini_size = __fini_array_end - __fini_array_start;
|
||||||
|
for (unsigned int i = 0; i != fini_size; ++i) (*__fini_array_start[i])();
|
||||||
|
|
||||||
|
sys_exit();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// additional C++ stuff
|
||||||
|
void __cxa_pure_virtual() {
|
||||||
|
// pure virtual error
|
||||||
|
}
|
||||||
|
|
||||||
|
// For libraries
|
||||||
|
int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle) {
|
||||||
|
(void)func;
|
||||||
|
(void)arg;
|
||||||
|
(void)dso_handle;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *operator new([[maybe_unused]] __SIZE_TYPE__ n) {
|
||||||
|
return reinterpret_cast<void *>(0xdeadbeef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new[]([[maybe_unused]] __SIZE_TYPE__ n) {
|
||||||
|
return reinterpret_cast<void *>(0xdeadbeef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void *ptr) { operator delete(ptr); }
|
||||||
|
|
||||||
|
void operator delete[](void *ptr, [[maybe_unused]] __SIZE_TYPE__ size) {
|
||||||
|
operator delete(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete([[maybe_unused]] void *ptr) {}
|
||||||
|
|
||||||
|
void operator delete(void *ptr, [[maybe_unused]] __SIZE_TYPE__ size) {
|
||||||
|
operator delete(ptr);
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
with pkgs;
|
with pkgs;
|
||||||
[
|
[
|
||||||
# for all tasks and maintenance
|
# for all tasks and maintenance
|
||||||
|
gnumake
|
||||||
gdb
|
gdb
|
||||||
qemu_kvm
|
qemu_kvm
|
||||||
nasm
|
nasm
|
||||||
@@ -49,6 +50,8 @@
|
|||||||
python3
|
python3
|
||||||
bear # make compile_commands.json
|
bear # make compile_commands.json
|
||||||
clang-tools # for clangd and clang-format
|
clang-tools # for clangd and clang-format
|
||||||
|
doxygen
|
||||||
|
graphviz # make doc
|
||||||
]
|
]
|
||||||
++ (lib.filter (
|
++ (lib.filter (
|
||||||
pkg: lib.isDerivation pkg && pkg.pname or "" != "glibc"
|
pkg: lib.isDerivation pkg && pkg.pname or "" != "glibc"
|
||||||
|
|||||||
Reference in New Issue
Block a user