Compare commits

..

No commits in common. '9af6bd4455418cd2fcc8ec6d12cad8df4c03bc8b' and '35c2667fbfb57ccde005f826800993d3db2890e3' have entirely different histories.

1
.gitignore vendored

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

@ -1,6 +1,5 @@
#include "cga.h" #include "cga.h"
#include "../debug/output.h" #include "arch/ioport.h"
#include "../arch/ioport.h"
namespace CGA { namespace CGA {
@ -9,7 +8,7 @@ namespace CGA {
void writeCGAReg(int reg, int data){ void writeCGAReg(int reg, int data){
index_port.outb(reg); index_port.outb(reg);
data_port.outb(data); data_port.outw(data);
} }
uint16_t readCGAReg(int reg){ uint16_t readCGAReg(int reg){

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

@ -1,7 +1,4 @@
#include "ioapic.h" #include "ioapic.h"
#include "apic.h"
#include "core.h"
#include "../debug/assert.h"
namespace IOAPIC { namespace IOAPIC {
/*! \brief IOAPIC registers memory mapped into the CPU's address space. /*! \brief IOAPIC registers memory mapped into the CPU's address space.
@ -23,66 +20,22 @@ volatile Register *IOWIN_REG =
// IOAPIC manual, p. 8 // IOAPIC manual, p. 8
const Index IOAPICID_IDX = 0x00; const Index IOAPICID_IDX = 0x00;
const Index IOREDTBL_IDX = 0x10; const Index IOREDTBL_IDX = 0x10;
const Index IOREDTBL_ENTRY_SIZE = 0x02;
const uint8_t slot_max = 24; const uint8_t slot_max = 24;
RedirectionTableEntry readEntry(Index slot) { void init() {}
*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, void config(uint8_t slot, Core::Interrupt::Vector vector,
TriggerMode trigger_mode, Polarity polarity) { TriggerMode trigger_mode, Polarity polarity) {
assert(slot < slot_max); (void)slot;
RedirectionTableEntry entry = readEntry(slot); (void)vector;
entry.vector = vector; (void)trigger_mode;
entry.trigger_mode = trigger_mode; (void)polarity;
entry.polarity = polarity;
writeEntry(slot, entry);
} }
void allow(uint8_t slot) { void allow(uint8_t slot) { (void)slot; }
assert(slot < slot_max);
RedirectionTableEntry entry = readEntry(slot);
entry.interrupt_mask = UNMASKED;
writeEntry(slot, entry);
}
void forbid(uint8_t slot) { void forbid(uint8_t slot) { (void)slot; }
assert(slot < slot_max);
RedirectionTableEntry entry = readEntry(slot);
entry.interrupt_mask = MASKED;
writeEntry(slot, entry);
}
bool status(uint8_t slot) { bool status(uint8_t slot) {
(void)slot; (void)slot;

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

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

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

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

@ -1,5 +1,4 @@
#include "assert.h" #include "assert.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) {
@ -7,7 +6,6 @@
(void)func; (void)func;
(void)file; (void)file;
(void)line; (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: Print error message (in debug window)
// TODO: Then stop the current core permanently // TODO: Then stop the current core permanently
// Use appropriate method from class Core to do so. // Use appropriate method from class Core to do so.

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

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

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

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

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

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

@ -4,7 +4,6 @@
#include "../debug/output.h" #include "../debug/output.h"
#include "../object/bbuffer.h" #include "../object/bbuffer.h"
#include "../sync/ticketlock.h" #include "../sync/ticketlock.h"
#include "../arch/core_interrupt.h"
#include "epilogues.h" #include "epilogues.h"
#define FOR_CURRENT_CORE [Core::getID()] #define FOR_CURRENT_CORE [Core::getID()]
@ -22,45 +21,10 @@ Vault::Vault() {}
Guarded::~Guarded() { Guard::leave(); } Guarded::~Guarded() { Guard::leave(); }
Guarded Guard::enter() { Guarded Guard::enter() { while (true); }
epi_flag FOR_CURRENT_CORE = true;
Core::Interrupt::enable();
global_lock.lock();
}
void Guard::leave() { void Guard::leave() {}
bool istate = Core::Interrupt::disable();
Epilogue next; void Guard::relay(Epilogue handler) { (void)handler; }
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; } const Vault &Guard::unsafeConstAccess() { return global_vault; }

@ -11,26 +11,4 @@ handle_keyboard_asm:
; continue. The C++ compiler will only generates code to preserve ; continue. The C++ compiler will only generates code to preserve
; non-scratch registers in the high-level interrupt handler -- the scratch ; non-scratch registers in the high-level interrupt handler -- the scratch
; registers have to be saved (and restored later) manually! ; registers have to be saved (and restored later) manually!
; TODO: Implement the context save and restore for the keyboard interrupt ; TODO(12): 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,12 +7,6 @@
#include "../debug/kernelpanic.h" #include "../debug/kernelpanic.h"
#include "../debug/output.h" #include "../debug/output.h"
#include "../device/ps2controller.h"
#include "../sync/ticketlock.h"
#include "epilogues.h"
#include "guard.h"
void printContext(const InterruptContext *context) { void printContext(const InterruptContext *context) {
DBG << "ip: " << hex << context->cs << ':' << context->ip DBG << "ip: " << hex << context->cs << ':' << context->ip
<< " sp: " << context->ss << ':' << context->sp << " flags" << bin << " sp: " << context->ss << ':' << context->sp << " flags" << bin
@ -71,27 +65,10 @@ enum PAGE_FAULT_ERROR {
kernelpanic("Page fault!"); kernelpanic("Page fault!");
} }
extern TextStream kout; void handle_keyboard() {}
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) { [[gnu::interrupt]] void handle_panic(InterruptContext *context) {
DBG << "Generic KernelPanic triggered"<< endl; (void)context;
printContext(context);
kernelpanic("Generic Panic Triggerd");
} }
[[gnu::interrupt]] void handle_timer(InterruptContext *context) { [[gnu::interrupt]] void handle_timer(InterruptContext *context) {
@ -120,9 +97,6 @@ void initInterruptHandlers() {
IDT::InterruptDescriptor::ReturningWithError(handle_page_fault)); IDT::InterruptDescriptor::ReturningWithError(handle_page_fault));
// TODO: Add more handlers here // TODO: Add more handlers here
IDT::set(Core::Interrupt::Vector::KEYBOARD,
IDT::InterruptDescriptor::Returning(handle_keyboard_asm));
// Load the idt pointer // Load the idt pointer
IDT::load(); 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 * On keyboard interrupt, the register state is saved to and restored from the
* stack. This function wraps the handle_keyboard C-function. * stack. This function wraps the handle_keyboard C-function.
* *
* \todo Implement in assembly * \todo(12) Implement in assembly
*/ */
[[gnu::interrupt]] void handle_keyboard_asm(InterruptContext *context); [[gnu::interrupt]] void handle_keyboard_asm(InterruptContext *context);
@ -82,7 +82,7 @@ extern "C" { // disable C++ name mangling for asm function
/*! \brief handle_panic /*! \brief handle_panic
* *
* \todo Trigger a kernel panic * \todo(12) Trigger a kernel panic
*/ */
[[gnu::interrupt]] void handle_panic(InterruptContext *context); [[gnu::interrupt]] void handle_panic(InterruptContext *context);

@ -1,9 +1,7 @@
#include "arch/lapic.h" #include "arch/lapic.h"
#include "boot/startup_ap.h" #include "boot/startup_ap.h"
#include "arch/core_interrupt.h"
#include "debug/copystream.h" #include "debug/copystream.h"
#include "debug/output.h" #include "debug/output.h"
#include "debug/assert.h"
#include "arch/cga.h" #include "arch/cga.h"
#include "arch/textwindow.h" #include "arch/textwindow.h"
@ -11,13 +9,7 @@
#include "device/serialstream.h" #include "device/serialstream.h"
#include "device/textstream.h" #include "device/textstream.h"
#include "device/ps2controller.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); TextStream kout = TextStream(0, 80, 0, 10, true);
Ticketlock koutlock;
//TextStream dout[8] = { //TextStream dout[8] = {
// TextStream(0 ,20,12,25,false), // TextStream(0 ,20,12,25,false),
@ -29,7 +21,6 @@ Ticketlock koutlock;
// TextStream(0 ,0 ,0, 0,false), // TextStream(0 ,0 ,0, 0,false),
// TextStream(0 ,0 ,0, 0,false), // TextStream(0 ,0 ,0, 0,false),
//}; //};
TextStream dout[Core::MAX] = { TextStream dout[Core::MAX] = {
{0, 40, 10, 14}, {0, 40, 10, 14},
{40, 80, 10, 14}, {40, 80, 10, 14},
@ -63,16 +54,39 @@ OutputStream* copyout[Core::MAX]{
&dout[7] &dout[7]
}; };
unsigned int testx, testy;
// Main function // Main function
// (the bootstrap processor starts here)} // (the bootstrap processor starts here)}
extern "C" int main() { extern "C" int main() {
CGA::setCursor(0, 0);
unsigned int numCPUs = Core::count(); unsigned int numCPUs = Core::count();
DBG_VERBOSE << "Number of CPUs: " << numCPUs << endl; 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 << "Test <stream result> -> <expected>" << endl;
kout << "bool: " << true << " -> true" << endl; kout << "bool: " << true << " -> true" << endl;
kout << "zero: " << 0 << " -> 0" << endl; kout << "zero: " << 0 << " -> 0" << endl;
@ -97,23 +111,12 @@ extern "C" int main() {
ApplicationProcessor::boot(); ApplicationProcessor::boot();
PS2Controller::init(); 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){ while (true){
DBG << "pos: " << testx << ", " << testy << endl << flush; if (PS2Controller::fetch(key)) {
Core::pause(); kout << key.ascii() << flush ;
}
} }
return 0; return 0;
} }
@ -121,12 +124,24 @@ extern "C" int main() {
extern "C" int main_ap() { extern "C" int main_ap() {
DBG_VERBOSE << "CPU core " << static_cast<int>(Core::getID()) << " / LAPIC " DBG_VERBOSE << "CPU core " << static_cast<int>(Core::getID()) << " / LAPIC "
<< static_cast<int>(LAPIC::getID()) << " in main_ap()" << endl; << static_cast<int>(LAPIC::getID()) << " in main_ap()" << endl;
Core::Interrupt::enable();
DBG << "App CPU " << static_cast<int>(Core::getID()) << endl << flush;
//assert(Core::getID() != 1);
Application{}.action(); //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;
return 0; return 0;
} }

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

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

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

@ -1,49 +1,6 @@
// vim: set noet ts=4 sw=4: // vim: set noet ts=4 sw=4:
#include "appl.h" #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 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; Application& operator=(const Application&) = delete;
public: public:
Application() = default; // XXX: is this used anywhere? Application(Application&&) = default; // XXX: is this used anywhere?
/*! \brief Constructor /*! \brief Constructor
* *

Loading…
Cancel
Save