fixes for A2

mostly include some things that should and remove some things that shouldn't have been included in the handout (yes this does hint at some places that need to be touched for A2)
This commit is contained in:
Niklas Gollenstede
2025-11-24 15:04:26 +01:00
parent 174fe17e89
commit 4245798955
18 changed files with 186 additions and 3300 deletions

View File

@@ -1,6 +1,26 @@
FormatStyle: google
HeaderFilterRegex: '.*'
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-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-owning-memory,
-cppcoreguidelines-pro-*,
CheckOptions:
readability-simplify-boolean-expr.IgnoreMacros: 'true'
readability-identifier-length.IgnoreNames: 'me'

View File

@@ -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.
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.
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.

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

@@ -21,7 +21,6 @@ OutputStream* copyout = &copystream;
#include "./device/ps2controller.h"
#include "./interrupt/guard.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

@@ -1,8 +1,6 @@
#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"
@@ -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

@@ -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

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

View File

@@ -1,24 +0,0 @@
#pragma once
#include "outputstream.h"
#include "stub.h"
class IOStream : public OutputStream {
private:
IOStream(IOStream &copy); // 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;
}
};

View File

@@ -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;
}

View File

@@ -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
View File

View 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.
clean::
rm -rf "$(BUILDDIR)"
rm -rf doc
# Target issuing a nested call to make generating a fully optimized systems without assertions.
%-$(OPTTAG):
@@ -120,6 +120,9 @@ clean::
%-$(VERBOSETAG):
$(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
help::
@@ -134,7 +137,8 @@ help::
"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" \
"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
@@ -150,4 +154,4 @@ endif
# Phony targets
.PHONY: clean help
.PHONY: clean doc help

0
tools/cpplint.py vendored Normal file → Executable file
View File

69
user/imgbuilder.cc Normal file
View File

@@ -0,0 +1,69 @@
#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 size_t 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, size_t 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
std::array<uint32_t, block_size / sizeof(uint32_t)> size{0};
size[0] = static_cast<uint32_t>(argc - 1);
for (size_t i = 1; i < argc; ++i) {
struct stat sb;
if (stat(argv[i], &sb) != 0) die("stat");
// 4 GB Limit
if (sb.st_size >= UINT32_MAX) {
errno = EFBIG;
die("stat");
}
size[i] = sb.st_size;
}
writeBuffer(size.data(), block_size);
// DATA: Each App
for (size_t i = 1; i < argc; ++i) {
std::vector<char> buf(size[i]);
std::ifstream input(argv[i], std::ios::binary);
if (!input) die("fopen");
input.read(buf.data(), size[i]);
writeBuffer(buf.data(), size[i]);
// Fill to block size, if required
if (size[i] % block_size != 0)
writeBuffer(zeros, block_size - (size[i] % block_size));
}
std::cout.flush();
return EXIT_SUCCESS;
}

73
user/init.cc Normal file
View 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);
}

View File

@@ -38,6 +38,7 @@
with pkgs;
[
# for all tasks and maintenance
gnumake
gdb
qemu_kvm
nasm
@@ -49,6 +50,8 @@
python3
bear # make compile_commands.json
clang-tools # for clangd and clang-format
doxygen
graphviz # make doc
]
++ (lib.filter (
pkg: lib.isDerivation pkg && pkg.pname or "" != "glibc"