Compare commits

..

40 Commits

Author SHA1 Message Date
Eggert Jung 9af6bd4455 Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ss25/v_bsb1/Gruppe_018 5 months ago
Eggert Jung 4ee45e27c2 wip aufg 3 5 months ago
Simon 00c6f9c943 removed interrupt enable/disable from critical app section 5 months ago
Eggert Jung deac8bfb8c fix ) 5 months ago
Eggert Jung 901eb0bbf5 zack fertig 6 months ago
Eggert Jung f1e5f17d1f move reboot call to handlerscc 6 months ago
Eggert Jung a415260776 rename lock 6 months ago
Eggert Jung 2421136335 foo 6 months ago
Eggert Jung b0f129141a fix hw issue 6 months ago
Eggert Jung ae3980cfa2 check cga pos bounds and debug print 6 months ago
Eggert Jung bddcebefae Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ss25/v_bsb1/Gruppe_018 6 months ago
Eggert Jung 7d65db4f45 cleanup code 6 months ago
Simon e4e7cb9d0c added spinlock 6 months ago
Simon 9afe202078 ticketlock foo 6 months ago
Simon 4a731be0ca removed double lines 6 months ago
Simon a053ac561c censored 6 months ago
Eggert Jung 20f7f50fa9 start app on appcpu 6 months ago
Eggert Jung 65514ec040 add app 6 months ago
Eggert Jung b61df61e36 fix endof interrupt 6 months ago
Eggert Jung 220bdd8b77 Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ss25/v_bsb1/Gruppe_018 6 months ago
Eggert Jung 2543dca933 cleanup 6 months ago
Eggert Jung 58f8cf1815 execute fetch in isr 6 months ago
Simon d5dc4935a5 fixed iret 6 months ago
Eggert Jung 2a0f0573db set IDT 6 months ago
Eggert Jung ebd3bd3597 remove unneccessary bullshit 6 months ago
Eggert Jung 7214ce8e53 foo 6 months ago
Eggert Jung 383561a4f6 add ctrl alt del 6 months ago
Simon e9500c1b40 capitalization 6 months ago
Simon 9a311fd38c ich hab das ganz sicher nicht die letzten 5 min gefixed was ich am dienstag vergeigt habe 6 months ago
Eggert Jung 90faf06496 Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ss25/v_bsb1/Gruppe_018 6 months ago
Eggert Jung b2368b2bc5 implement init 6 months ago
Simon f8942434df enable interrupts for each core 6 months ago
Simon 1dc52aa6f2 checkmark to done todo 6 months ago
Eggert Jung 24c6311f38 drain 6 months ago
Eggert Jung ecc3b1011d Merge branch 'main' of gitlab.ibr.cs.tu-bs.de:vss/teaching/ss25/v_bsb1/Gruppe_018 6 months ago
Eggert Jung 5846351aed feedback 6 months ago
Simon 35765897c4 handler asm code for saving the volatile registers created 6 months ago
Simon 6d5f48e154 handle panic now triggers a panic 6 months ago
Simon 55c23fb293 added the user defined interrupt 6 months ago
Simon 6534b4660c mini changes 6 months ago

1
.gitignore vendored

@ -1,3 +1,4 @@
.build*
/build*
/tools/qemu.mk
/tools/remote.mk

@ -1,5 +1,6 @@
#include "cga.h"
#include "arch/ioport.h"
#include "../debug/output.h"
#include "../arch/ioport.h"
namespace CGA {
@ -8,7 +9,7 @@ namespace CGA {
void writeCGAReg(int reg, int data){
index_port.outb(reg);
data_port.outw(data);
data_port.outb(data);
}
uint16_t readCGAReg(int reg){
@ -17,7 +18,7 @@ namespace CGA {
}
void setCursor(unsigned abs_x, unsigned abs_y) {
uint16_t pos = abs_y * COLUMNS + abs_x;
uint16_t pos = abs_y * COLUMNS + abs_x;
writeCGAReg(RegisterIndex::CURSOR_LOW, pos & 0xFF);
writeCGAReg(RegisterIndex::CURSOR_HIGH, ((pos >> 8) & 0xFF));

@ -28,7 +28,7 @@ constexpr uintptr_t FLAG_ENABLE = 1 << 9;
*
* \see [ISDMv3, 6.15 Exception and Interrupt
* Reference](intel_manual_vol3.pdf#page=203)
* \todo(12) Add Keyboard and Panic vector numbers
* \todo
*/
enum Vector {
// Predefined Exceptions
@ -67,6 +67,8 @@ enum Vector {
SECURITY_EXCEPTION = 31,
// Interrupts
KEYBOARD=32,
PANIC=33
};
constexpr size_t VECTORS = 256;

@ -1,4 +1,7 @@
#include "ioapic.h"
#include "apic.h"
#include "core.h"
#include "../debug/assert.h"
namespace IOAPIC {
/*! \brief IOAPIC registers memory mapped into the CPU's address space.
@ -20,22 +23,66 @@ volatile Register *IOWIN_REG =
// IOAPIC manual, p. 8
const Index IOAPICID_IDX = 0x00;
const Index IOREDTBL_IDX = 0x10;
const Index IOREDTBL_ENTRY_SIZE = 0x02;
const uint8_t slot_max = 24;
void init() {}
RedirectionTableEntry readEntry(Index slot) {
*IOREGSEL_REG = IOREDTBL_IDX + slot * IOREDTBL_ENTRY_SIZE;
Register low = *IOWIN_REG;
*IOREGSEL_REG += IOREDTBL_ENTRY_SIZE / 2;
Register high = *IOWIN_REG;
return RedirectionTableEntry{low, high};
}
void writeEntry(Index slot, RedirectionTableEntry entry) {
*IOREGSEL_REG = IOREDTBL_IDX + slot * IOREDTBL_ENTRY_SIZE;
*IOWIN_REG = entry.value_low;
*IOREGSEL_REG += IOREDTBL_ENTRY_SIZE / 2;
*IOWIN_REG = entry.value_high;
}
void init() {
for (uint8_t slot = 0; slot < slot_max; slot++) {
RedirectionTableEntry entry = readEntry(slot);
entry.destination = (1 << Core::count()) - 1;
entry.interrupt_mask = MASKED;
entry.trigger_mode = EDGE;
entry.polarity = HIGH;
entry.destination_mode = LOGICAL;
entry.delivery_mode = LOWEST_PRIORITY;
entry.vector = Core::Interrupt::PANIC;
writeEntry(slot, entry);
}
*IOREGSEL_REG = IOAPICID_IDX;
Identification IOAPICID{*IOWIN_REG};
IOAPICID.id = APIC::getIOAPICID();
*IOWIN_REG = IOAPICID.value;
}
void config(uint8_t slot, Core::Interrupt::Vector vector,
TriggerMode trigger_mode, Polarity polarity) {
(void)slot;
(void)vector;
(void)trigger_mode;
(void)polarity;
TriggerMode trigger_mode, Polarity polarity) {
assert(slot < slot_max);
RedirectionTableEntry entry = readEntry(slot);
entry.vector = vector;
entry.trigger_mode = trigger_mode;
entry.polarity = polarity;
writeEntry(slot, entry);
}
void allow(uint8_t slot) { (void)slot; }
void allow(uint8_t slot) {
assert(slot < slot_max);
RedirectionTableEntry entry = readEntry(slot);
entry.interrupt_mask = UNMASKED;
writeEntry(slot, entry);
}
void forbid(uint8_t slot) { (void)slot; }
void forbid(uint8_t slot) {
assert(slot < slot_max);
RedirectionTableEntry entry = readEntry(slot);
entry.interrupt_mask = MASKED;
writeEntry(slot, entry);
}
bool status(uint8_t slot) {
(void)slot;

@ -45,7 +45,7 @@ void init();
* \param polarity Polarity of the interrupt signaling (active high or
active low)
*
* \todo(12) Implement Function
* \todo Implement Function
*/
void config(uint8_t slot, Core::Interrupt::Vector vector,
TriggerMode trigger_mode = TriggerMode::EDGE,
@ -57,7 +57,7 @@ void config(uint8_t slot, Core::Interrupt::Vector vector,
* To fully enable interrupt handling, the interrupts must be enabled for every
* CPU (e.g., by calling
* \ref Core::Interrupt::enable() in main).
* \todo(12) Do that somewhere appropriate.
* \todo Do that somewhere appropriate.
*
* \param slot Number of the external interrupt that should be enabled.
*

@ -43,9 +43,8 @@ int Serial::write(char out) {
if(out == '\n')
write('\r');
if(readReg(LINE_STATUS_REGISTER) & TRANSMITTER_EMPTY){
writeReg(TRANSMIT_BUFFER_REGISTER, out);
return out;
}
return -1;
while(!(readReg(LINE_STATUS_REGISTER) & TRANSMITTER_EMPTY));
writeReg(TRANSMIT_BUFFER_REGISTER, out);
return out;
}

@ -1,6 +1,7 @@
#include "textwindow.h"
#include "cga.h"
#include "../utils/string.h"
#include "../debug/output.h"
TextWindow::TextWindow(unsigned from_col, unsigned to_col, unsigned from_row,
unsigned to_row, bool use_cursor) {
@ -13,12 +14,23 @@ TextWindow::TextWindow(unsigned from_col, unsigned to_col, unsigned from_row,
setPos(0,0);
}
extern unsigned int testx, testy;
void TextWindow::setPos(unsigned rel_x, unsigned rel_y) {
unsigned abs_x = from_col + rel_x;
unsigned abs_y = from_row + rel_y;
if(abs_x >= CGA::COLUMNS)
return;
if(abs_y >= CGA::ROWS)
return;
if(use_cursor){
CGA::setCursor(from_col + rel_x, from_row + rel_y);
testx = abs_x;
testy = abs_y;
CGA::setCursor(abs_x, abs_y);
}else{
pos_x = from_col + rel_x;
pos_y = from_row + rel_y;
pos_x = abs_x;
pos_y = abs_y;
}
}

@ -0,0 +1,2 @@
-Iarch
-xc++

@ -1,4 +1,5 @@
#include "assert.h"
#include "output.h"
[[noreturn]] void assertion_failed(const char* exp, const char* func,
const char* file, int line) {
@ -6,6 +7,7 @@
(void)func;
(void)file;
(void)line;
DBG << "Assertion failed: " << exp << "\nin function: " << func << "\nfrom file: \"" << file << "\" in line " << dec << line << flush;
// TODO: Print error message (in debug window)
// TODO: Then stop the current core permanently
// Use appropriate method from class Core to do so.

@ -17,7 +17,7 @@
#define kernelpanic(MSG) \
do { \
DBG << "PANIC: '" << (MSG) << "' in " << __func__ << " @ " << __FILE__ \
<< ":" << __LINE__ << ") - CPU stopped." << endl; \
<< ":" << dec << __LINE__ << ") - CPU stopped." << endl; \
Core::die(); \
} while (0)

@ -1,5 +1,6 @@
#include "ps2controller.h"
#include "../arch/system.h"
#include "../arch/core_interrupt.h"
#include "../arch/ioport.h"
#include "../compiler/fix.h"
@ -108,18 +109,20 @@ void init() {
}
bool fetch(Key &pressed) {
// TODO: You have to implement this method
uint8_t status_reg = ctrl_port.inb();
if(status_reg & IS_MOUSE || !(status_reg & HAS_OUTPUT) )
return false; // TODO Remove mouse events from buffer
if(!(status_reg & HAS_OUTPUT) )
return false;
DBG_VERBOSE << "status: " << hex << static_cast<int>(status_reg) << "\n" << flush;
uint8_t out_buffer = data_port.inb();
DBG_VERBOSE << "scancode: " << hex << static_cast<int>(out_buffer) << "\n" << flush;
if (status_reg & IS_MOUSE)
return false;
pressed = key_decoder.decode(out_buffer);
if (pressed.alt() || pressed.ctrl() || pressed.shift || !pressed.valid())
if (pressed.alt() || pressed.ctrl() || !pressed.valid())
return false;
else
return true;
@ -140,6 +143,8 @@ void setLed(enum LED led, bool on) {
sendData(leds); // Parameter
}
void drainBuffer() {}
void drainBuffer() {
while(ctrl_port.inb() & HAS_OUTPUT)
data_port.inb();
}
} // namespace PS2Controller

@ -146,7 +146,6 @@ void setLed(enum LED led, bool on);
* should be emptied once right before allowing keyboard interrupts
* (even if keystrokes might be lost).
*
* \todo(12) Implement method
*/
void drainBuffer();

@ -41,8 +41,6 @@ void SerialStream::reset() {
}
void SerialStream::setPos(int x, int y) {
//char out[] = {0x1b, '[', 0, 0, ';', 0, 0, 'H', 0};
//*this << 0x1b;
write(0x1b);
sout << '[';
sout << dec << x;
@ -50,9 +48,6 @@ void SerialStream::setPos(int x, int y) {
sout << dec << y;
sout << 'H';
flush();
//itoa(x, &out[2], 10);
//itoa(y, &out[5], 10);
//print( out , strlen(out));
}
void SerialStream::print(char* str, int length) {

@ -1,5 +1,5 @@
#include "textstream.h"
#include "../arch/lapic.h"
#include "../arch/core.h"
TextStream::TextStream(unsigned from_col,
unsigned to_col,
@ -17,7 +17,7 @@ TextStream::TextStream(unsigned from_col,
void TextStream::flush() {
CGA::Color fg = static_cast<CGA::Color>((LAPIC::getID() + 1 ));
CGA::Color fg = static_cast<CGA::Color>((Core::getID() + 1 ));
print(buffer,pos,CGA::Attribute(CGA::LIGHT_GREEN, fg, false));
pos = 0;
}

@ -4,7 +4,9 @@
namespace Epilogues {
void keyboard(Vault& g) { (void)g; }
void keyboard(Vault& g) {
}
void timer(Vault& g) { (void)g; }

@ -4,6 +4,7 @@
#include "../debug/output.h"
#include "../object/bbuffer.h"
#include "../sync/ticketlock.h"
#include "../arch/core_interrupt.h"
#include "epilogues.h"
#define FOR_CURRENT_CORE [Core::getID()]
@ -21,10 +22,45 @@ Vault::Vault() {}
Guarded::~Guarded() { Guard::leave(); }
Guarded Guard::enter() { while (true); }
Guarded Guard::enter() {
epi_flag FOR_CURRENT_CORE = true;
Core::Interrupt::enable();
global_lock.lock();
}
void Guard::leave() {}
void Guard::leave() {
bool istate = Core::Interrupt::disable();
void Guard::relay(Epilogue handler) { (void)handler; }
Epilogue next;
while(epilogue_queue FOR_CURRENT_CORE.consume(next)){
Core::Interrupt::enable();
next(global_vault);
Core::Interrupt::disable();
}
epi_flag FOR_CURRENT_CORE = false;
global_lock.unlock();
Core::Interrupt::restore(istate);
}
void Guard::relay(Epilogue handler) {
if(!epilogue_queue FOR_CURRENT_CORE.consume(handler))
return; // enqueue, but dont execute
if(epi_flag FOR_CURRENT_CORE){
enter();
Core::Interrupt::disable();
leave();
}
//Core::Interrupt::enable(); // goto level 0.5
//if(epi_flag FOR_CURRENT_CORE){
// epilogue_queue->produce(handler);
//}
//else{
// epi_flag FOR_CURRENT_CORE = true;
// handler(global_vault);
// leave(); // maybe not needed since destructor also calls leave
//}
}
const Vault &Guard::unsafeConstAccess() { return global_vault; }

@ -11,4 +11,26 @@ handle_keyboard_asm:
; continue. The C++ compiler will only generates code to preserve
; non-scratch registers in the high-level interrupt handler -- the scratch
; registers have to be saved (and restored later) manually!
; TODO(12): Implement the context save and restore for the keyboard interrupt
; TODO: Implement the context save and restore for the keyboard interrupt
;
;
push rax;
push rdi;
push rsi;
push rdx;
push rcx;
push r8;
push r9;
push r10;
push r11;
call handle_keyboard;
pop r11;
pop r10;
pop r9;
pop r8;
pop rcx;
pop rdx;
pop rsi;
pop rdi;
pop rax;
iretq ;

@ -7,6 +7,12 @@
#include "../debug/kernelpanic.h"
#include "../debug/output.h"
#include "../device/ps2controller.h"
#include "../sync/ticketlock.h"
#include "epilogues.h"
#include "guard.h"
void printContext(const InterruptContext *context) {
DBG << "ip: " << hex << context->cs << ':' << context->ip
<< " sp: " << context->ss << ':' << context->sp << " flags" << bin
@ -65,10 +71,27 @@ enum PAGE_FAULT_ERROR {
kernelpanic("Page fault!");
}
void handle_keyboard() {}
extern TextStream kout;
extern Ticketlock koutlock;
extern Vault keyboard_vault;
void handle_keyboard() {
Key key = Key();
if (PS2Controller::fetch(key)) {
Guard::relay(Epilogues::keyboard);
//koutlock.lock();
//kout << key.ascii() << endl << flush ;
//koutlock.unlock();
}
else if (key.ctrl() && key.alt() && key.scancode == Key::KEY_DEL)
System::reboot();
LAPIC::endOfInterrupt();
}
[[gnu::interrupt]] void handle_panic(InterruptContext *context) {
(void)context;
DBG << "Generic KernelPanic triggered"<< endl;
printContext(context);
kernelpanic("Generic Panic Triggerd");
}
[[gnu::interrupt]] void handle_timer(InterruptContext *context) {
@ -97,6 +120,9 @@ void initInterruptHandlers() {
IDT::InterruptDescriptor::ReturningWithError(handle_page_fault));
// TODO: Add more handlers here
IDT::set(Core::Interrupt::Vector::KEYBOARD,
IDT::InterruptDescriptor::Returning(handle_keyboard_asm));
// Load the idt pointer
IDT::load();
}

@ -65,7 +65,7 @@ extern "C" { // disable C++ name mangling for asm function
* On keyboard interrupt, the register state is saved to and restored from the
* stack. This function wraps the handle_keyboard C-function.
*
* \todo(12) Implement in assembly
* \todo Implement in assembly
*/
[[gnu::interrupt]] void handle_keyboard_asm(InterruptContext *context);
@ -77,12 +77,12 @@ extern "C" { // disable C++ name mangling for asm function
* \todo(12) Fetch a single key
* \todo(13) Extend to use the Prologue-Epilogue pattern
*/
void handle_keyboard();
void handle_keyboard();
}
/*! \brief handle_panic
*
* \todo(12) Trigger a kernel panic
* \todo Trigger a kernel panic
*/
[[gnu::interrupt]] void handle_panic(InterruptContext *context);

@ -1,7 +1,9 @@
#include "arch/lapic.h"
#include "boot/startup_ap.h"
#include "arch/core_interrupt.h"
#include "debug/copystream.h"
#include "debug/output.h"
#include "debug/assert.h"
#include "arch/cga.h"
#include "arch/textwindow.h"
@ -9,7 +11,13 @@
#include "device/serialstream.h"
#include "device/textstream.h"
#include "device/ps2controller.h"
#include "arch/ioapic.h"
#include "user/app1/appl.h"
#include "sync/ticketlock.h"
#include "interrupt/guard.h"
TextStream kout = TextStream(0, 80, 0, 10, true);
Ticketlock koutlock;
//TextStream dout[8] = {
// TextStream(0 ,20,12,25,false),
@ -21,6 +29,7 @@ TextStream kout = TextStream(0, 80, 0, 10, true);
// TextStream(0 ,0 ,0, 0,false),
// TextStream(0 ,0 ,0, 0,false),
//};
TextStream dout[Core::MAX] = {
{0, 40, 10, 14},
{40, 80, 10, 14},
@ -54,39 +63,16 @@ OutputStream* copyout[Core::MAX]{
&dout[7]
};
unsigned int testx, testy;
// Main function
// (the bootstrap processor starts here)}
extern "C" int main() {
CGA::setCursor(0, 0);
unsigned int numCPUs = Core::count();
DBG_VERBOSE << "Number of CPUs: " << numCPUs << endl;
////test cga implemantation
// CGA::setCursor(1, 2);
// unsigned x,y;
// CGA::getCursor(x, y);
// CGA::setCursor(x+1, y+1);
// for(uint8_t i = 0; i < 10; i++)
// CGA::show(i, i, i+0x30, CGA::Attribute());
////test textwindow implemantation
//TextWindow tw_global = TextWindow(0, 80, 0, 25, true);
//tw_global.reset(' ', CGA::Attribute(CGA::LIGHT_GREEN, CGA::BLUE, false));
//// test SerialStream
//SerialStream ss = SerialStream();
//ss.print("test", 4);
//ss.setAttribute(SerialStream::UNDERSCORE);
//ss.print("test", 4);
//ss.setAttribute(SerialStream::RESET);
//ss.setForeground(SerialStream::MAGENTA);
//ss.print("test", 4);
//ss.setBackground(SerialStream::CYAN);
//ss.print("test", 4);
//ss.setPos(10, 10);
//ss.print("test\n", 5);
//ss.setBackground(SerialStream::BLACK);
kout << "Test <stream result> -> <expected>" << endl;
kout << "bool: " << true << " -> true" << endl;
kout << "zero: " << 0 << " -> 0" << endl;
@ -111,12 +97,23 @@ extern "C" int main() {
ApplicationProcessor::boot();
PS2Controller::init();
Key key = Key();
IOAPIC::init();
IOAPIC::config(1, Core::Interrupt::KEYBOARD);
IOAPIC::allow(1);
Core::Interrupt::enable();
PS2Controller::drainBuffer();
DBG << "Main CPU " << static_cast<int>(LAPIC::getID()) << endl << flush;
Application{}.action();
while (true){
if (PS2Controller::fetch(key)) {
kout << key.ascii() << flush ;
}
DBG << "pos: " << testx << ", " << testy << endl << flush;
Core::pause();
}
return 0;
}
@ -124,24 +121,12 @@ extern "C" int main() {
extern "C" int main_ap() {
DBG_VERBOSE << "CPU core " << static_cast<int>(Core::getID()) << " / LAPIC "
<< static_cast<int>(LAPIC::getID()) << " in main_ap()" << endl;
Core::Interrupt::enable();
DBG << "App CPU " << static_cast<int>(Core::getID()) << endl << flush;
//TextWindow dout0 = TextWindow(0,20,13,19, false);
//dout0.reset();
//dout0.reset(' ', CGA::Attribute(CGA::LIGHT_GREEN, CGA::RED, false));
////test Serial
//Serial s = Serial();
//s.write('a');
//uint8_t from = static_cast<int>(LAPIC::getID()) * 20;
//uint8_t to = from+20;
//dout[LAPIC::getID()] = TextStream(from, to, 0, 6, false);
DBG << "test\n" << flush;
DBG << static_cast<int>(LAPIC::getID()) << flush;
//assert(Core::getID() != 1);
Application{}.action();
return 0;
}

@ -35,14 +35,15 @@ class Spinlock {
// Prevent copies and assignments
Spinlock(const Spinlock& copy) = delete;
Spinlock& operator=(const Spinlock&) = delete;
private:
volatile uint64_t locked;
public:
/*! \brief Constructor; Initializes as unlocked.
*
* \todo(12) Complete Constructor (for \MPStuBS, or use \ref Ticketlock)
*
*/
consteval Spinlock() {}
consteval Spinlock() : locked(0) {}
/*! \brief Enters the critical area. In case the area is already locked,
* \ref lock() will actively wait until the area can be entered.
@ -50,11 +51,11 @@ class Spinlock {
* \see \ref Core::pause()
* \todo(12) Implement Method (for \MPStuBS, or use \ref Ticketlock)
*/
void lock() {}
void lock();
/*! \brief Unblocks the critical area.
*
* \todo(12) Implement Method (for \MPStuBS, or use \ref Ticketlock)
*/
void unlock() {}
void unlock();
};

@ -0,0 +1,12 @@
#include "sync/ticketlock.h"
void Ticketlock::lock() {
uint64_t ticket = __atomic_fetch_add(&ticket_count, 1, __ATOMIC_RELAXED);
while (ticket != __atomic_fetch_add(&ticket_current, 0, __ATOMIC_ACQUIRE)) {
Core::pause();
}
}
void Ticketlock::unlock() {
__atomic_fetch_add(&ticket_current, 1, __ATOMIC_RELEASE);
}

@ -4,6 +4,8 @@
#pragma once
#include "../arch/core.h"
#include "../arch/cache.h"
/*! \brief Using Ticketlocks, it is possible to serialize blocks of code
* that might otherwise run in parallel on multiple CPU cores,
* or be interleaved due to interrupts or scheduling.
@ -29,12 +31,17 @@ class Ticketlock {
Ticketlock(const Ticketlock& copy) = delete;
Ticketlock& operator=(const Ticketlock&) = delete;
private:
volatile uint64_t ticket_current;
volatile uint64_t ticket_count;
public:
/*! \brief Constructor
*
* \todo(12) Complete Constructor (for \MPStuBS)
*/
consteval Ticketlock() {}
consteval Ticketlock() : ticket_current(0), ticket_count(0) {}
/*! \brief Enters the critical area. In case the area is already locked,
* \ref lock() will actively wait until the area can be entered.
@ -42,11 +49,11 @@ class Ticketlock {
* \see \ref Core::pause()
* \todo(12) Implement Method (for \MPStuBS)
*/
void lock() {}
void lock();
/*! \brief Unblocks the critical area.
*
* \todo(12) Implement Method (for \MPStuBS)
*/
void unlock() {}
void unlock();
};

@ -1,7 +1,7 @@
# Test your system on real hardware
NETBOOT_LOCAL="/ibr/adm/user-boot/"
NETBOOT_HOST="x1.ibr.cs.tu-bs.de"
NETBOOT_HOST="y0085044@x1.ibr.cs.tu-bs.de"
# The boot menu shows pairs of `vmlinuz-*` + `initrd-*.img` with owning user and timestamp.
# We just need to choose a name that doesn't overlap with another user's.

@ -1,6 +1,49 @@
// vim: set noet ts=4 sw=4:
#include "appl.h"
#include "../../device/ps2controller.h"
#include "../../object/outputstream.h"
#include "../../device/textstream.h"
#include "../../sync/ticketlock.h"
#include "../../arch/core.h"
char text[] = "Ich mag\n\
Saftige Pflaumen voller Aroma\n\
Ich knuddel jede Oma ins Koma\n\
Ich bin Großmutterknuddler, Großmutterknuddler\n\
Ich bin Großmutterknuddler, ich bin Großmutterknuddler\n\
\n\
Saftige Pflaumen voller Aroma\n\
Ich knuddel jede Oma ins Koma\n\
Ich bin Großmutterknuddler, Großmutterknuddler\n\
Ich bin Großmuttersniffer\n\
Und wacht sie aus'm Koma auf, kriegt sie von mir 'n Sticker\n\
\n";
extern TextStream kout;
extern Ticketlock koutlock;
void activeWaitDelay(uint64_t cycles) {
uint64_t counter = 0; // Use volatile to prevent optimization
for (uint64_t i = 0; i < cycles; ++i) {
counter++; // Simple operation to consume cycles
asm("nop");
//Core::pause();
}
}
void Application::action() { // NOLINT
uint16_t cnt = 0;
while (1) {
koutlock.lock();
while(text[cnt++] != '\n'){
kout << text[cnt-1];
}
kout << endl << flush;
koutlock.unlock();
activeWaitDelay(1000000000);
if(cnt >= sizeof(text)-1)
cnt=0;
}
}

@ -18,7 +18,7 @@ class Application {
Application& operator=(const Application&) = delete;
public:
Application(Application&&) = default; // XXX: is this used anywhere?
Application() = default; // XXX: is this used anywhere?
/*! \brief Constructor
*

Loading…
Cancel
Save