merged cleanup
This commit is contained in:
@ -34,9 +34,9 @@
|
||||
#include "kernel/Allocator.h"
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
#define MEM_SIZE_DEF 8 * 1024 * 1024 // Groesse des Speichers = 8 MB
|
||||
#define HEAP_START 0x300000 // Startadresse des Heaps
|
||||
#define HEAP_SIZE 1024 * 1024 // Default-Groesse des Heaps, falls \
|
||||
constexpr const unsigned int MEM_SIZE_DEF = 8 * 1024 * 1024; // Groesse des Speichers = 8 MB
|
||||
constexpr const unsigned int HEAP_START = 0x300000; // Startadresse des Heaps
|
||||
constexpr const unsigned int HEAP_SIZE = 1024 * 1024; // Default-Groesse des Heaps, falls \
|
||||
// nicht über das BIOS ermittelbar
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
@ -30,11 +30,11 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 13.6.2020 *
|
||||
*****************************************************************************/
|
||||
#ifndef __Allocator_include__
|
||||
#define __Allocator_include__
|
||||
#ifndef Allocator_include__
|
||||
#define Allocator_include__
|
||||
|
||||
constexpr unsigned int BASIC_ALIGN = 4; // 32 Bit so 4 Bytes?
|
||||
constexpr unsigned int HEAP_MIN_FREE_BLOCK_SIZE = 64; // min. Groesse eines freien Blocks
|
||||
constexpr const unsigned int BASIC_ALIGN = 4; // 32 Bit so 4 Bytes?
|
||||
constexpr const unsigned int HEAP_MIN_FREE_BLOCK_SIZE = 64; // min. Groesse eines freien Blocks
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
@ -42,6 +42,8 @@ public:
|
||||
|
||||
Allocator();
|
||||
|
||||
// virtual ~Allocator() = default;
|
||||
|
||||
unsigned int heap_start;
|
||||
unsigned int heap_end;
|
||||
unsigned int heap_size;
|
||||
|
||||
@ -17,13 +17,13 @@ extern "C" {
|
||||
}
|
||||
|
||||
// in startup.asm im GDT-Eintrag so festgeschrieben!
|
||||
#define BIOS16_CODE_MEMORY_START 0x24000
|
||||
constexpr const unsigned int BIOS16_CODE_MEMORY_START = 0x24000;
|
||||
|
||||
// Parameter fuer BIOS-Aufrufe (Register)
|
||||
#define BIOS16_PARAM_BASE 0x26000
|
||||
constexpr const unsigned int BIOS16_PARAM_BASE = 0x26000;
|
||||
|
||||
// Zeiger auf Speichbereich fuer Parameter fuer BIOS-Aufruf (siehe BIOS.h)
|
||||
struct BIOScall_params* BC_params = (struct BIOScall_params*)BIOS16_PARAM_BASE;
|
||||
BIOScall_params* BC_params = reinterpret_cast<BIOScall_params*>(BIOS16_PARAM_BASE);
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BIOS::BIOS *
|
||||
@ -33,7 +33,7 @@ struct BIOScall_params* BC_params = (struct BIOScall_params*)BIOS16_PARAM_BASE;
|
||||
* im 4. GDT-Eintrag (siehe startup.asm). *
|
||||
*****************************************************************************/
|
||||
BIOS::BIOS() {
|
||||
unsigned char* codeAddr = (unsigned char*)BIOS16_CODE_MEMORY_START;
|
||||
unsigned char* codeAddr = reinterpret_cast<unsigned char*>(BIOS16_CODE_MEMORY_START);
|
||||
|
||||
// mov eax, 25000 (Adresse wohin aktuelles esp gesichert wird)
|
||||
*codeAddr = 0x66;
|
||||
@ -305,7 +305,6 @@ BIOS::BIOS() {
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xCB;
|
||||
codeAddr++;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -314,10 +313,10 @@ BIOS::BIOS() {
|
||||
* Beschreibung: Fuehrt einen BIOS-Aufruf per Software-Interrupt durch. *
|
||||
*****************************************************************************/
|
||||
void BIOS::Int(int inter) {
|
||||
unsigned char* ptr = (unsigned char*)BIOS16_CODE_MEMORY_START;
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(BIOS16_CODE_MEMORY_START);
|
||||
|
||||
// Interrupt-Nummer in 16-Bit Code-Segment schreiben (unschoen, aber ...)
|
||||
*(ptr + 48) = (unsigned char)inter;
|
||||
*(ptr + 48) = static_cast<unsigned char>(inter);
|
||||
|
||||
CPU::disable_int(); // Interrupts abschalten
|
||||
bios_call();
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 13.9.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef __BIOS_include__
|
||||
#define __BIOS_include__
|
||||
#ifndef BIOS_include__
|
||||
#define BIOS_include__
|
||||
|
||||
// Speicherseite fuer Rueckgabewerte von BIOS-Aufrufen
|
||||
#define RETURN_MEM 0x9F000
|
||||
constexpr const unsigned int RETURN_MEM = 0x9F000;
|
||||
|
||||
// Struktur fuer Parameteruebergabe fuer einen BIOS-Aufruf
|
||||
struct BIOScall_params {
|
||||
@ -31,7 +31,7 @@ struct BIOScall_params {
|
||||
// kein Auffuellen von bytes auf Wortgrenzen
|
||||
|
||||
// Zeiger auf Speichbereich fuer Parameter fuer BIOS-Aufruf
|
||||
extern struct BIOScall_params* BC_params;
|
||||
extern BIOScall_params* BC_params;
|
||||
|
||||
class BIOS {
|
||||
public:
|
||||
@ -41,7 +41,7 @@ public:
|
||||
BIOS();
|
||||
|
||||
// BIOS-Aufruf, per Software-Interrupt
|
||||
void Int(int inter);
|
||||
static void Int(int inter);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 30.7.16 *
|
||||
*****************************************************************************/
|
||||
#ifndef __CPU_include__
|
||||
#define __CPU_include__
|
||||
#ifndef CPU_include__
|
||||
#define CPU_include__
|
||||
|
||||
class CPU {
|
||||
public:
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 30.7.16 *
|
||||
*****************************************************************************/
|
||||
#ifndef __Globals_include__
|
||||
#define __Globals_include__
|
||||
#ifndef Globals_include__
|
||||
#define Globals_include__
|
||||
|
||||
#include "devices/CGA_Stream.h"
|
||||
#include "devices/Keyboard.h"
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 28.8.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef __IOport_include__
|
||||
#define __IOport_include__
|
||||
#ifndef IOport_include__
|
||||
#define IOport_include__
|
||||
|
||||
class IOport {
|
||||
private:
|
||||
@ -36,7 +36,7 @@ public:
|
||||
void outb(unsigned char offset, unsigned char val) const {
|
||||
asm volatile("outb %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"((unsigned short)(address + offset)));
|
||||
: "a"(val), "Nd"(static_cast<unsigned short>(address + offset)));
|
||||
}
|
||||
|
||||
// Wortweise Ausgabe eines Wertes ueber einen I/O-Port.
|
||||
@ -69,7 +69,7 @@ public:
|
||||
|
||||
asm volatile("inb %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"((unsigned short)(address + offset)));
|
||||
: "Nd"(static_cast<unsigned short>(address + offset)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -53,20 +53,20 @@
|
||||
#include "user/lib/Logger.h"
|
||||
|
||||
// Bits fuer Eintraege in der Page-Table
|
||||
#define PAGE_PRESENT 0x001
|
||||
#define PAGE_WRITEABLE 0x002
|
||||
#define PAGE_BIGSIZE 0x080
|
||||
#define PAGE_RESERVED 0x800 // Bit 11 ist frei fuer das OS
|
||||
constexpr const unsigned int PAGE_PRESENT = 0x001;
|
||||
constexpr const unsigned int PAGE_WRITEABLE = 0x002;
|
||||
constexpr const unsigned int PAGE_BIGSIZE = 0x080;
|
||||
constexpr const unsigned int PAGE_RESERVED = 0x800; // Bit 11 ist frei fuer das OS
|
||||
|
||||
// Adresse des Page-Directory (benoetigt 4 KB)
|
||||
#define PAGE_DIRECTORY 0x200000
|
||||
constexpr const unsigned int PAGE_DIRECTORY = 0x200000;
|
||||
|
||||
// Adresse der Page-Table (benoetigt 4 KB)
|
||||
#define PAGE_TABLE 0x201000
|
||||
constexpr const unsigned int PAGE_TABLE = 0x201000;
|
||||
|
||||
// Start- und End-Adresse der 4 KB Seiten die durch die Page-Table adressiert werden
|
||||
#define FST_ALLOCABLE_PAGE 0x202000
|
||||
#define LST_ALLOCABLE_PAGE 0x2FF000
|
||||
constexpr const unsigned int FST_ALLOCABLE_PAGE = 0x202000;
|
||||
constexpr const unsigned int LST_ALLOCABLE_PAGE = 0x2FF000;
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: pg_alloc_page *
|
||||
@ -77,7 +77,7 @@
|
||||
unsigned int* pg_alloc_page() {
|
||||
unsigned int* p_page;
|
||||
|
||||
p_page = (unsigned int*)PAGE_TABLE;
|
||||
p_page = reinterpret_cast<unsigned int*>(PAGE_TABLE);
|
||||
|
||||
// 1. Eintrag ist fuer Null-Pointer-Exception reserviert
|
||||
// ausserdem liegt an die Page-Table an Adresse PAGE_TABLE
|
||||
@ -87,10 +87,10 @@ unsigned int* pg_alloc_page() {
|
||||
// pruefe ob Page frei
|
||||
if (((*p_page) & PAGE_RESERVED) == 0) {
|
||||
*p_page = (*p_page | PAGE_RESERVED);
|
||||
return (unsigned int*)(i << 12); // Address without flags (Offset 0)
|
||||
return reinterpret_cast<unsigned int*>(i << 12); // Address without flags (Offset 0)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -103,7 +103,7 @@ void pg_write_protect_page(const unsigned int* p_page) {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
|
||||
unsigned int* page = (unsigned int*)PAGE_TABLE + ((unsigned int)p_page >> 12); // Pagetable entry
|
||||
unsigned int* page = reinterpret_cast<unsigned int*>(PAGE_TABLE) + (reinterpret_cast<unsigned int>(p_page) >> 12); // Pagetable entry
|
||||
|
||||
unsigned int mask = PAGE_WRITEABLE; // fill to 32bit
|
||||
*page = *page & ~mask; // set writable to 0
|
||||
@ -118,7 +118,7 @@ void pg_notpresent_page(const unsigned int* p_page) {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
|
||||
unsigned int* page = (unsigned int*)PAGE_TABLE + ((unsigned int)p_page >> 12); // Pagetable entry
|
||||
unsigned int* page = reinterpret_cast<unsigned int*>(PAGE_TABLE) + (reinterpret_cast<unsigned int>(p_page) >> 12); // Pagetable entry
|
||||
|
||||
unsigned int mask = PAGE_PRESENT;
|
||||
*page = *page & ~mask; // set present to 0
|
||||
@ -131,7 +131,7 @@ void pg_notpresent_page(const unsigned int* p_page) {
|
||||
* Bit geloescht. *
|
||||
*****************************************************************************/
|
||||
void pg_free_page(unsigned int* p_page) {
|
||||
int idx = (unsigned int)p_page >> 12;
|
||||
unsigned int idx = reinterpret_cast<unsigned int>(p_page) >> 12;
|
||||
|
||||
// ausserhalb Page ?
|
||||
if (idx < 1 || idx > 1023) {
|
||||
@ -139,7 +139,7 @@ void pg_free_page(unsigned int* p_page) {
|
||||
}
|
||||
|
||||
// Eintrag einlesen und aendern (PAGE_WRITEABLE loeschen)
|
||||
p_page = (unsigned int*)PAGE_TABLE;
|
||||
p_page = reinterpret_cast<unsigned int*>(PAGE_TABLE);
|
||||
p_page += idx;
|
||||
|
||||
*p_page = ((idx << 12) | PAGE_WRITEABLE | PAGE_PRESENT);
|
||||
@ -170,7 +170,7 @@ void pg_init() {
|
||||
//
|
||||
|
||||
// Eintrag 0: Zeiger auf 4 KB Page-Table
|
||||
p_pdir = (unsigned int*)PAGE_DIRECTORY;
|
||||
p_pdir = reinterpret_cast<unsigned int*>(PAGE_DIRECTORY);
|
||||
*p_pdir = PAGE_TABLE | PAGE_WRITEABLE | PAGE_PRESENT;
|
||||
|
||||
// Eintraege 1-1023: Direktes Mapping (1:1) auf 4 MB Pages (ohne Page-Table)
|
||||
@ -186,7 +186,7 @@ void pg_init() {
|
||||
//
|
||||
// 1. Page-Table
|
||||
//
|
||||
p_page = (unsigned int*)PAGE_TABLE;
|
||||
p_page = reinterpret_cast<unsigned int*>(PAGE_TABLE);
|
||||
|
||||
// ersten Eintrag loeschen -> not present, write protected -> Null-Pointer abfangen
|
||||
*p_page = 0;
|
||||
@ -205,5 +205,5 @@ void pg_init() {
|
||||
}
|
||||
|
||||
// Paging aktivieren (in startup.asm)
|
||||
paging_on((unsigned int*)PAGE_DIRECTORY);
|
||||
paging_on(reinterpret_cast<unsigned int*>(PAGE_DIRECTORY));
|
||||
}
|
||||
|
||||
@ -49,8 +49,8 @@
|
||||
* Autor: Michael Schoettner, 2.2.2017 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Paging_include__
|
||||
#define __Paging_include__
|
||||
#ifndef Paging_include__
|
||||
#define Paging_include__
|
||||
|
||||
// Externe Funktionen in startup.asm
|
||||
extern "C" {
|
||||
|
||||
@ -20,8 +20,8 @@ void BumpAllocator::init() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
this->allocations = 0;
|
||||
this->next = (unsigned char*)heap_start;
|
||||
allocations = 0;
|
||||
next = reinterpret_cast<unsigned char*>(heap_start);
|
||||
|
||||
log.info() << "Initialized Bump Allocator" << endl;
|
||||
}
|
||||
@ -36,8 +36,8 @@ void BumpAllocator::dump_free_memory() {
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
kout << "Freier Speicher:" << endl
|
||||
<< " - Next: " << hex << (unsigned int)this->next
|
||||
<< ", Allocations: " << dec << this->allocations << endl;
|
||||
<< " - Next: " << hex << reinterpret_cast<unsigned int>(next)
|
||||
<< ", Allocations: " << dec << allocations << endl;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -51,14 +51,14 @@ void* BumpAllocator::alloc(unsigned int req_size) {
|
||||
|
||||
log.debug() << "Requested " << hex << req_size << " Bytes" << endl;
|
||||
|
||||
if (req_size + (unsigned int)this->next > this->heap_end) {
|
||||
if (req_size + reinterpret_cast<unsigned int>(next) > heap_end) {
|
||||
log.error() << " - More memory requested than available :(" << endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* allocated = this->next;
|
||||
this->next = (unsigned char*)((unsigned int)this->next + req_size);
|
||||
this->allocations = this->allocations + 1;
|
||||
void* allocated = next;
|
||||
next = reinterpret_cast<unsigned char*>(reinterpret_cast<unsigned int>(next) + req_size);
|
||||
allocations = allocations + 1;
|
||||
|
||||
log.trace() << " - Allocated " << hex << req_size << " Bytes." << endl;
|
||||
|
||||
@ -71,5 +71,5 @@ void* BumpAllocator::alloc(unsigned int req_size) {
|
||||
* Beschreibung: Nicht implementiert. *
|
||||
*****************************************************************************/
|
||||
void BumpAllocator::free(void* ptr) {
|
||||
log.error() << " mm_free: ptr= " << hex << (unsigned int)ptr << ", not supported" << endl;
|
||||
log.error() << " mm_free: ptr= " << hex << reinterpret_cast<unsigned int>(ptr) << ", not supported" << endl;
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
* Autor: Michael Schoettner, HHU, 3.3.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __BumpAllocator_include__
|
||||
#define __BumpAllocator_include__
|
||||
#ifndef BumpAllocator_include__
|
||||
#define BumpAllocator_include__
|
||||
|
||||
#include "kernel/Allocator.h"
|
||||
#include "user/lib/Logger.h"
|
||||
@ -27,6 +27,8 @@ public:
|
||||
|
||||
BumpAllocator() : log("BMP-Alloc") {}; // Allocator() called implicitely in C++
|
||||
|
||||
// ~BumpAllocator() override = default;
|
||||
|
||||
void init() override;
|
||||
void dump_free_memory() override;
|
||||
void* alloc(unsigned int req_size) override;
|
||||
|
||||
@ -32,10 +32,10 @@ void LinkedListAllocator::init() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
this->free_start = (free_block_t*)this->heap_start;
|
||||
this->free_start->allocated = false;
|
||||
this->free_start->size = this->heap_size - sizeof(free_block_t);
|
||||
this->free_start->next = this->free_start; // Only one block, points to itself
|
||||
free_start = reinterpret_cast<free_block_t*>(heap_start);
|
||||
free_start->allocated = false;
|
||||
free_start->size = heap_size - sizeof(free_block_t);
|
||||
free_start->next = free_start; // Only one block, points to itself
|
||||
|
||||
log.info() << "Initialized LinkedList Allocator" << endl;
|
||||
}
|
||||
@ -51,14 +51,14 @@ void LinkedListAllocator::dump_free_memory() {
|
||||
|
||||
kout << "Freier Speicher:" << endl;
|
||||
|
||||
if (this->free_start == nullptr) {
|
||||
if (free_start == nullptr) {
|
||||
kout << " - No free Blocks" << endl;
|
||||
} else {
|
||||
kout << " - Freelist start: " << hex << (unsigned int)this->free_start << endl;
|
||||
kout << " - Freelist start: " << hex << reinterpret_cast<unsigned int>(free_start) << endl;
|
||||
|
||||
free_block_t* current = this->free_start;
|
||||
free_block_t* current = free_start;
|
||||
do {
|
||||
kout << " - Free Block (Start: " << hex << (unsigned int)current
|
||||
kout << " - Free Block (Start: " << hex << reinterpret_cast<unsigned int>(current)
|
||||
<< " Size: " << hex << current->size << ")" << endl;
|
||||
current = current->next;
|
||||
} while (current != free_start);
|
||||
@ -71,16 +71,16 @@ void LinkedListAllocator::dump_free_memory() {
|
||||
* Beschreibung: Einen neuen Speicherblock allozieren. *
|
||||
*****************************************************************************/
|
||||
void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
this->lock.acquire();
|
||||
lock.acquire();
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
// NOTE: next pointer zeigt auf headeranfang, returned wird zeiger auf anfang des nutzbaren freispeichers
|
||||
|
||||
log.debug() << "Requested " << hex << req_size << " Bytes" << endl;
|
||||
|
||||
if (this->free_start == nullptr) {
|
||||
if (free_start == nullptr) {
|
||||
log.error() << " - No free memory remaining :(" << endl;
|
||||
this->lock.release();
|
||||
lock.release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
log.trace() << " - Rounded to word border (+" << dec << req_size_diff << " bytes)" << endl;
|
||||
}
|
||||
|
||||
free_block_t* current = this->free_start;
|
||||
free_block_t* current = free_start;
|
||||
do {
|
||||
if (current->size >= rreq_size) { // Size doesn't contain header, only usable
|
||||
// Current block large enough
|
||||
@ -106,7 +106,7 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
// In case of only one freeblock:
|
||||
// [current | new_next]
|
||||
free_block_t* new_next =
|
||||
(free_block_t*)((unsigned int)current + sizeof(free_block_t) + rreq_size);
|
||||
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(current) + sizeof(free_block_t) + rreq_size);
|
||||
|
||||
// If only one block exists, current->next is current
|
||||
// This shouldn't be a problem since the block gets removed from the list later
|
||||
@ -118,18 +118,18 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
current->size = rreq_size;
|
||||
|
||||
// Next-fit
|
||||
this->free_start = new_next;
|
||||
free_start = new_next;
|
||||
|
||||
log.trace() << " - Allocated " << hex << rreq_size << " Bytes with cutting" << endl;
|
||||
} else {
|
||||
// Block too small to be cut, allocate whole block
|
||||
|
||||
// Next-fit
|
||||
this->free_start = current->next; // Pointer keeps pointing to current if last block
|
||||
if (this->free_start == current) {
|
||||
free_start = current->next; // Pointer keeps pointing to current if last block
|
||||
if (free_start == current) {
|
||||
// No free block remaining
|
||||
log.trace() << " - Disabled freelist" << endl;
|
||||
this->free_start = nullptr;
|
||||
free_start = nullptr;
|
||||
}
|
||||
|
||||
log.trace() << " - Allocated " << hex << current->size << " Bytes without cutting" << endl;
|
||||
@ -155,16 +155,16 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
// }
|
||||
// log.debug() << "Finished check" << endl;
|
||||
|
||||
log.debug() << "Returning memory address " << hex << ((unsigned int)current + sizeof(free_block_t)) << endl;
|
||||
this->lock.release();
|
||||
return (void*)((unsigned int)current + sizeof(free_block_t)); // Speicheranfang, nicht header
|
||||
log.debug() << "returning memory address " << hex << reinterpret_cast<unsigned int>(current) + sizeof(free_block_t) << endl;
|
||||
lock.release();
|
||||
return reinterpret_cast<void*>(reinterpret_cast<unsigned int>(current) + sizeof(free_block_t)); // Speicheranfang, nicht header
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
} while (current != this->free_start); // Stop when arriving at the first block again
|
||||
} while (current != free_start); // Stop when arriving at the first block again
|
||||
|
||||
log.error() << " - More memory requested than available :(" << endl;
|
||||
this->lock.release();
|
||||
lock.release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -174,35 +174,35 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
|
||||
* Beschreibung: Einen Speicherblock freigeben. *
|
||||
*****************************************************************************/
|
||||
void LinkedListAllocator::free(void* ptr) {
|
||||
this->lock.acquire();
|
||||
lock.acquire();
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
// Account for header
|
||||
free_block_t* block_start = (free_block_t*)((unsigned int)ptr - sizeof(free_block_t));
|
||||
free_block_t* block_start = reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(ptr) - sizeof(free_block_t));
|
||||
|
||||
log.debug() << "Freeing " << hex << (unsigned int)ptr << ", Size: " << block_start->size << endl;
|
||||
log.debug() << "Freeing " << hex << reinterpret_cast<unsigned int>(ptr) << ", Size: " << block_start->size << endl;
|
||||
|
||||
if (!block_start->allocated) {
|
||||
log.error() << "Block already free" << endl;
|
||||
this->lock.release();
|
||||
lock.release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reenable the freelist if no block was available
|
||||
// This also means that no merging can be done
|
||||
if (this->free_start == nullptr) {
|
||||
this->free_start = block_start;
|
||||
if (free_start == nullptr) {
|
||||
free_start = block_start;
|
||||
block_start->allocated = false;
|
||||
block_start->next = block_start;
|
||||
|
||||
log.trace() << " - Enabling freelist with one block" << endl;
|
||||
this->lock.release();
|
||||
lock.release();
|
||||
return;
|
||||
}
|
||||
|
||||
free_block_t* next_block =
|
||||
(free_block_t*)((unsigned int)block_start + sizeof(free_block_t) + block_start->size);
|
||||
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(block_start) + sizeof(free_block_t) + block_start->size);
|
||||
|
||||
// Find the next free block, multiple next blocks can be allocated so walk through them
|
||||
free_block_t* next_free = block_start->next;
|
||||
@ -212,7 +212,7 @@ void LinkedListAllocator::free(void* ptr) {
|
||||
|
||||
free_block_t* previous_free = LinkedListAllocator::find_previous_block(next_free);
|
||||
free_block_t* previous_free_next =
|
||||
(free_block_t*)((unsigned int)previous_free + sizeof(free_block_t) + previous_free->size);
|
||||
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(previous_free) + sizeof(free_block_t) + previous_free->size);
|
||||
|
||||
// We have: [previous_free | previous_free_next | <> | block_start | next_block | <> | next_free]
|
||||
// The <> spaces don't have to exist and next_block could be the same as next_free
|
||||
@ -254,10 +254,10 @@ void LinkedListAllocator::free(void* ptr) {
|
||||
// If thats the case I should set the next pointer to the next adjacent block
|
||||
// when allocating a new block
|
||||
|
||||
if (this->free_start == next_free) {
|
||||
if (free_start == next_free) {
|
||||
// next_free is now invalid after merge
|
||||
log.trace() << " - Moving freelist start to " << hex << (unsigned int)block_start << endl;
|
||||
this->free_start = block_start;
|
||||
log.trace() << " - Moving freelist start to " << hex << reinterpret_cast<unsigned int>(block_start) << endl;
|
||||
free_start = block_start;
|
||||
}
|
||||
} else {
|
||||
// Can't merge forward so size stays the same
|
||||
@ -283,16 +283,16 @@ void LinkedListAllocator::free(void* ptr) {
|
||||
// For pointers to block_start the same as above applies
|
||||
// so I don't think I have to manage anything else here
|
||||
|
||||
if (this->free_start == block_start) {
|
||||
if (free_start == block_start) {
|
||||
// block_start is now invalid after merge
|
||||
log.trace() << " - Moving freelist start to " << hex << (unsigned int)previous_free << endl;
|
||||
this->free_start = previous_free;
|
||||
log.trace() << " - Moving freelist start to " << hex << reinterpret_cast<unsigned int>(previous_free) << endl;
|
||||
free_start = previous_free;
|
||||
}
|
||||
}
|
||||
|
||||
// Depending on the merging this might write into the block, but doesn't matter
|
||||
block_start->allocated = false;
|
||||
this->lock.release();
|
||||
lock.release();
|
||||
}
|
||||
|
||||
free_block_t* LinkedListAllocator::find_previous_block(free_block_t* next_block) {
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
* Autor: Michael Schoettner, HHU, 13.6.2020 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __LinkedListAllocator_include__
|
||||
#define __LinkedListAllocator_include__
|
||||
#ifndef LinkedListAllocator_include__
|
||||
#define LinkedListAllocator_include__
|
||||
|
||||
#include "kernel/Allocator.h"
|
||||
#include "lib/SpinLock.h"
|
||||
@ -47,6 +47,8 @@ public:
|
||||
|
||||
LinkedListAllocator() : log("LL-Alloc") {}
|
||||
|
||||
// ~LinkedListAllocator() override = default;
|
||||
|
||||
void init() override;
|
||||
void dump_free_memory() override;
|
||||
void* alloc(unsigned int req_size) override;
|
||||
|
||||
@ -2,27 +2,29 @@
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
void TreeAllocator::init() {
|
||||
this->free_start = (tree_block_t*)this->heap_start;
|
||||
this->free_start->allocated = false;
|
||||
this->free_start->left = nullptr;
|
||||
this->free_start->right = nullptr;
|
||||
this->free_start->parent = nullptr;
|
||||
this->free_start->red = false; // The root is always black
|
||||
this->free_start->next = (list_block_t*)this->free_start;
|
||||
this->free_start->previous = (list_block_t*)this->free_start;
|
||||
free_start = reinterpret_cast<tree_block_t*>(heap_start);
|
||||
free_start->allocated = false;
|
||||
free_start->left = nullptr;
|
||||
free_start->right = nullptr;
|
||||
free_start->parent = nullptr;
|
||||
free_start->red = false; // The root is always black
|
||||
free_start->next = reinterpret_cast<list_block_t*>(free_start);
|
||||
free_start->previous = reinterpret_cast<list_block_t*>(free_start);
|
||||
|
||||
log.info() << "Initialized Tree Allocator" << endl;
|
||||
}
|
||||
|
||||
void TreeAllocator::dump_free_memory() {
|
||||
kout << "Free Memory:" << endl;
|
||||
list_block_t* current = (list_block_t*)this->heap_start;
|
||||
list_block_t* current = reinterpret_cast<list_block_t*>(heap_start);
|
||||
do {
|
||||
if (!current->allocated) {
|
||||
kout << " - Free Block at " << (unsigned int)current << ", Size: " << (unsigned int)current->next - (unsigned int)current << endl;
|
||||
kout << " - Free Block at " << reinterpret_cast<unsigned int>(current) << ", Size: "
|
||||
<< reinterpret_cast<unsigned int>(current->next) - reinterpret_cast<unsigned int>(current)
|
||||
<< endl;
|
||||
}
|
||||
current = current->next;
|
||||
} while ((unsigned int)current != this->heap_start);
|
||||
} while (reinterpret_cast<unsigned int>(current) != heap_start);
|
||||
}
|
||||
|
||||
void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
@ -43,7 +45,7 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
}
|
||||
|
||||
// Finds smallest block that is large enough
|
||||
tree_block_t* best_fit = this->rbt_search_bestfit(rreq_size);
|
||||
tree_block_t* best_fit = rbt_search_bestfit(rreq_size);
|
||||
if (best_fit == nullptr) {
|
||||
log.error() << " - No block found" << endl;
|
||||
return nullptr;
|
||||
@ -54,8 +56,8 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
return nullptr;
|
||||
}
|
||||
best_fit->allocated = true;
|
||||
unsigned int size = this->get_size(best_fit);
|
||||
log.trace() << " - Found best-fit: " << hex << (unsigned int)best_fit << endl;
|
||||
unsigned int size = get_size(best_fit);
|
||||
log.trace() << " - Found best-fit: " << hex << reinterpret_cast<unsigned int>(best_fit) << endl;
|
||||
|
||||
// HACK: I didn't want to handle situations with only one block (where the tree root would
|
||||
// get removed), so I make sure there are always at least 2 blocks by inserting a dummy
|
||||
@ -63,19 +65,20 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
// I should change this so it only happens when only one block exists in the freelist
|
||||
tree_block_t dummy;
|
||||
dummy.allocated = false;
|
||||
this->rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
// removed before exiting the function
|
||||
|
||||
this->rbt_remove(best_fit); // BUG: Can trigger bluescreen
|
||||
rbt_remove(best_fit); // BUG: Can trigger bluescreen
|
||||
if (size > HEAP_MIN_FREE_BLOCK_SIZE + rreq_size + sizeof(list_block_t)) {
|
||||
// Block can be cut
|
||||
log.trace() << " - Allocating " << dec << rreq_size << " Bytes with cutting" << endl;
|
||||
|
||||
// [best_fit_start | sizeof(list_block_t) | rreq_size | new_block_start]
|
||||
tree_block_t* new_block = (tree_block_t*)((char*)best_fit + sizeof(list_block_t) + rreq_size);
|
||||
tree_block_t* new_block
|
||||
= reinterpret_cast<tree_block_t*>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t) + rreq_size);
|
||||
new_block->allocated = false;
|
||||
this->dll_insert(best_fit, new_block);
|
||||
this->rbt_insert(new_block);
|
||||
dll_insert(best_fit, new_block);
|
||||
rbt_insert(new_block);
|
||||
} else {
|
||||
// Don't cut block
|
||||
// The block is already correctly positioned in the linked list so we only
|
||||
@ -84,16 +87,18 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
}
|
||||
|
||||
// HACK: Remove the dummy element
|
||||
this->rbt_remove(&dummy);
|
||||
rbt_remove(&dummy);
|
||||
|
||||
log.trace() << " - Returned address " << hex << (unsigned int)((char*)best_fit + sizeof(list_block_t)) << endl;
|
||||
return (void*)((char*)best_fit + sizeof(list_block_t));
|
||||
log.trace() << " - Returned address " << hex
|
||||
<< reinterpret_cast<unsigned int>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t))
|
||||
<< endl;
|
||||
return reinterpret_cast<void*>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
void TreeAllocator::free(void* ptr) {
|
||||
log.info() << "Freeing " << hex << (unsigned int)ptr << endl;
|
||||
log.info() << "Freeing " << hex << reinterpret_cast<unsigned int>(ptr) << endl;
|
||||
|
||||
list_block_t* block = (list_block_t*)((char*)ptr - sizeof(list_block_t));
|
||||
list_block_t* block = reinterpret_cast<list_block_t*>(reinterpret_cast<char*>(ptr) - sizeof(list_block_t));
|
||||
if (!block->allocated) {
|
||||
// Block already free
|
||||
return;
|
||||
@ -105,25 +110,25 @@ void TreeAllocator::free(void* ptr) {
|
||||
|
||||
if (next->allocated && previous->allocated) {
|
||||
// No merge
|
||||
this->rbt_insert((tree_block_t*)block);
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(block));
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK: Same as when allocating
|
||||
tree_block_t dummy;
|
||||
dummy.allocated = false;
|
||||
this->rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
|
||||
if (!next->allocated) {
|
||||
// Merge forward
|
||||
log.trace() << " - Merging forward" << endl;
|
||||
|
||||
// Remove the next block from all lists as it is now part of our freed block
|
||||
this->dll_remove(next);
|
||||
this->rbt_remove((tree_block_t*)next); // BUG: Bluescreen if next is the only block in the freelist
|
||||
dll_remove(next);
|
||||
rbt_remove(reinterpret_cast<tree_block_t*>(next)); // BUG: Bluescreen if next is the only block in the freelist
|
||||
if (previous->allocated) {
|
||||
// Don't insert if removed later because of backward merge
|
||||
this->rbt_insert((tree_block_t*)block);
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(block));
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,26 +138,26 @@ void TreeAllocator::free(void* ptr) {
|
||||
|
||||
// Remove the current block from all lists as it is now part of the previous block
|
||||
// It doesn't have to be removed from rbt as it wasn't in there as it was allocated before
|
||||
this->dll_remove(block);
|
||||
this->rbt_remove((tree_block_t*)previous);
|
||||
this->rbt_insert((tree_block_t*)previous); // Reinsert with new size
|
||||
dll_remove(block);
|
||||
rbt_remove(reinterpret_cast<tree_block_t*>(previous));
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(previous)); // Reinsert with new size
|
||||
}
|
||||
|
||||
// HACK: Same as when allocating
|
||||
this->rbt_remove(&dummy);
|
||||
rbt_remove(&dummy);
|
||||
}
|
||||
|
||||
unsigned int TreeAllocator::get_size(list_block_t* block) const {
|
||||
if (block->next == block) {
|
||||
// Only one block exists
|
||||
return this->heap_end - ((unsigned int)block + sizeof(list_block_t));
|
||||
return heap_end - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
if ((unsigned int)block->next > (unsigned int)block) {
|
||||
if (reinterpret_cast<unsigned int>(block->next) > reinterpret_cast<unsigned int>(block)) {
|
||||
// Next block is placed later in memory
|
||||
return (unsigned int)block->next - ((unsigned int)block + sizeof(list_block_t));
|
||||
return reinterpret_cast<unsigned int>(block->next) - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
// Next block is placed earlier in memory which means block is at memory end
|
||||
return (unsigned int)this->heap_end - ((unsigned int)block + sizeof(list_block_t));
|
||||
return reinterpret_cast<unsigned int>(heap_end) - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef __TreeAllocator_include__
|
||||
#define __TreeAllocator_include__
|
||||
#ifndef TreeAllocator_include__
|
||||
#define TreeAllocator_include__
|
||||
|
||||
#include "kernel/Allocator.h"
|
||||
#include "user/lib/Logger.h"
|
||||
@ -40,7 +40,7 @@ private:
|
||||
|
||||
// Returns the size of the usable memory of a block
|
||||
unsigned int get_size(list_block_t* block) const;
|
||||
unsigned int get_size(tree_block_t* block) const { return this->get_size((list_block_t*)block); }
|
||||
unsigned int get_size(tree_block_t* block) const { return get_size(reinterpret_cast<list_block_t*>(block)); }
|
||||
|
||||
void dump_free_memory(tree_block_t* node);
|
||||
|
||||
@ -57,10 +57,12 @@ private:
|
||||
void rbt_fix_remove(tree_block_t* x);
|
||||
|
||||
tree_block_t* rbt_search_bestfit(tree_block_t* node, unsigned int req_size);
|
||||
tree_block_t* rbt_search_bestfit(unsigned int req_size) { return this->rbt_search_bestfit(this->free_start, req_size); }
|
||||
tree_block_t* rbt_search_bestfit(unsigned int req_size) { return rbt_search_bestfit(free_start, req_size); }
|
||||
|
||||
void dll_insert(list_block_t* previous, list_block_t* node);
|
||||
void dll_insert(tree_block_t* previous, tree_block_t* node) { this->dll_insert((list_block_t*)previous, (list_block_t*)node); }
|
||||
void dll_insert(tree_block_t* previous, tree_block_t* node) {
|
||||
dll_insert(reinterpret_cast<list_block_t*>(previous), reinterpret_cast<list_block_t*>(node));
|
||||
}
|
||||
void dll_remove(list_block_t* node);
|
||||
|
||||
public:
|
||||
@ -68,6 +70,8 @@ public:
|
||||
|
||||
TreeAllocator() : log("RBT-Alloc") {};
|
||||
|
||||
// ~TreeAllocator() override = default;
|
||||
|
||||
void init() override;
|
||||
void dump_free_memory() override;
|
||||
void* alloc(unsigned int req_size) override;
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
#include "kernel/allocator/TreeAllocator.h"
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
// RBT code taken from https://github.com/Bibeknam/algorithmtutorprograms
|
||||
|
||||
// START copy from algorithmtutorprograms
|
||||
void TreeAllocator::rbt_transplant(tree_block_t* a, tree_block_t* b) {
|
||||
if (a->parent == nullptr) {
|
||||
this->free_start = b;
|
||||
free_start = b;
|
||||
} else if (a == a->parent->left) {
|
||||
a->parent->left = b;
|
||||
} else {
|
||||
@ -25,11 +24,11 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
|
||||
node->red = true; // new node must be red
|
||||
|
||||
tree_block_t* y = nullptr;
|
||||
tree_block_t* x = this->free_start;
|
||||
tree_block_t* x = free_start;
|
||||
|
||||
while (x != nullptr) {
|
||||
y = x;
|
||||
if (this->get_size(node) < this->get_size(x)) {
|
||||
if (get_size(node) < get_size(x)) {
|
||||
x = x->left;
|
||||
} else {
|
||||
x = x->right;
|
||||
@ -39,8 +38,8 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
|
||||
// y is parent of x
|
||||
node->parent = y;
|
||||
if (y == nullptr) {
|
||||
this->free_start = node;
|
||||
} else if (this->get_size(node) < this->get_size(y)) {
|
||||
free_start = node;
|
||||
} else if (get_size(node) < get_size(y)) {
|
||||
y->left = node;
|
||||
} else {
|
||||
y->right = node;
|
||||
@ -58,7 +57,7 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
|
||||
}
|
||||
|
||||
// Fix the tree
|
||||
this->rbt_fix_insert(node);
|
||||
rbt_fix_insert(node);
|
||||
}
|
||||
|
||||
// fix the red-black tree
|
||||
@ -77,12 +76,12 @@ void TreeAllocator::rbt_fix_insert(tree_block_t* k) {
|
||||
if (k == k->parent->left) {
|
||||
// case 3.2.2
|
||||
k = k->parent;
|
||||
this->rbt_rot_r(k);
|
||||
rbt_rot_r(k);
|
||||
}
|
||||
// case 3.2.1
|
||||
k->parent->red = false;
|
||||
k->parent->parent->red = true;
|
||||
this->rbt_rot_l(k->parent->parent);
|
||||
rbt_rot_l(k->parent->parent);
|
||||
}
|
||||
} else {
|
||||
u = k->parent->parent->right; // uncle
|
||||
@ -97,19 +96,19 @@ void TreeAllocator::rbt_fix_insert(tree_block_t* k) {
|
||||
if (k == k->parent->right) {
|
||||
// mirror case 3.2.2
|
||||
k = k->parent;
|
||||
this->rbt_rot_l(k);
|
||||
rbt_rot_l(k);
|
||||
}
|
||||
// mirror case 3.2.1
|
||||
k->parent->red = false;
|
||||
k->parent->parent->red = true;
|
||||
this->rbt_rot_r(k->parent->parent);
|
||||
rbt_rot_r(k->parent->parent);
|
||||
}
|
||||
}
|
||||
if (k == this->free_start) {
|
||||
if (k == free_start) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->free_start->red = false;
|
||||
free_start->red = false;
|
||||
}
|
||||
|
||||
// rotate left at node x
|
||||
@ -121,7 +120,7 @@ void TreeAllocator::rbt_rot_l(tree_block_t* x) {
|
||||
}
|
||||
y->parent = x->parent;
|
||||
if (x->parent == nullptr) {
|
||||
this->free_start = y;
|
||||
free_start = y;
|
||||
} else if (x == x->parent->left) {
|
||||
x->parent->left = y;
|
||||
} else {
|
||||
@ -140,7 +139,7 @@ void TreeAllocator::rbt_rot_r(tree_block_t* x) {
|
||||
}
|
||||
y->parent = x->parent;
|
||||
if (x->parent == nullptr) {
|
||||
this->free_start = y;
|
||||
free_start = y;
|
||||
} else if (x == x->parent->right) {
|
||||
x->parent->right = y;
|
||||
} else {
|
||||
@ -166,43 +165,43 @@ void TreeAllocator::rbt_remove(tree_block_t* z) {
|
||||
bool y_original_red = y->red;
|
||||
if (z->left == nullptr) {
|
||||
x = z->right;
|
||||
this->rbt_transplant(z, z->right);
|
||||
rbt_transplant(z, z->right);
|
||||
} else if (z->right == nullptr) {
|
||||
x = z->left;
|
||||
this->rbt_transplant(z, z->left);
|
||||
rbt_transplant(z, z->left);
|
||||
} else {
|
||||
y = this->rbt_minimum(z->right);
|
||||
y = rbt_minimum(z->right);
|
||||
y_original_red = y->red;
|
||||
x = y->right;
|
||||
if (y->parent == z) {
|
||||
x->parent = y;
|
||||
} else {
|
||||
this->rbt_transplant(y, y->right);
|
||||
rbt_transplant(y, y->right);
|
||||
y->right = z->right;
|
||||
y->right->parent = y;
|
||||
}
|
||||
|
||||
this->rbt_transplant(z, y);
|
||||
rbt_transplant(z, y);
|
||||
y->left = z->left;
|
||||
y->left->parent = y;
|
||||
y->red = z->red;
|
||||
}
|
||||
if (!y_original_red) {
|
||||
this->rbt_fix_remove(x);
|
||||
rbt_fix_remove(x);
|
||||
}
|
||||
}
|
||||
|
||||
// fix the rb tree modified by the delete operation
|
||||
void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
tree_block_t* s;
|
||||
while (x != this->free_start && !x->red) {
|
||||
while (x != free_start && !x->red) {
|
||||
if (x == x->parent->left) {
|
||||
s = x->parent->right;
|
||||
if (s->red) {
|
||||
// case 3.1
|
||||
s->red = false;
|
||||
x->parent->red = true;
|
||||
this->rbt_rot_l(x->parent);
|
||||
rbt_rot_l(x->parent);
|
||||
s = x->parent->right;
|
||||
}
|
||||
|
||||
@ -215,7 +214,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
// case 3.3
|
||||
s->left->red = false;
|
||||
s->red = true;
|
||||
this->rbt_rot_r(s);
|
||||
rbt_rot_r(s);
|
||||
s = x->parent->right;
|
||||
}
|
||||
|
||||
@ -223,8 +222,8 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
s->red = x->parent->red;
|
||||
x->parent->red = false;
|
||||
s->right->red = false;
|
||||
this->rbt_rot_l(x->parent);
|
||||
x = this->free_start;
|
||||
rbt_rot_l(x->parent);
|
||||
x = free_start;
|
||||
}
|
||||
} else {
|
||||
s = x->parent->left;
|
||||
@ -232,7 +231,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
// case 3.1
|
||||
s->red = false;
|
||||
x->parent->red = true;
|
||||
this->rbt_rot_r(x->parent);
|
||||
rbt_rot_r(x->parent);
|
||||
s = x->parent->left;
|
||||
}
|
||||
|
||||
@ -245,7 +244,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
// case 3.3
|
||||
s->right->red = false;
|
||||
s->red = true;
|
||||
this->rbt_rot_l(s);
|
||||
rbt_rot_l(s);
|
||||
s = x->parent->left;
|
||||
}
|
||||
|
||||
@ -253,8 +252,8 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
|
||||
s->red = x->parent->red;
|
||||
x->parent->red = false;
|
||||
s->left->red = false;
|
||||
this->rbt_rot_r(x->parent);
|
||||
x = this->free_start;
|
||||
rbt_rot_r(x->parent);
|
||||
x = free_start;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,17 +267,17 @@ tree_block_t* TreeAllocator::rbt_search_bestfit(tree_block_t* node, unsigned int
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (req_size < this->get_size(node)) {
|
||||
if (node->left != nullptr && this->get_size(node->left) >= req_size) {
|
||||
return this->rbt_search_bestfit(node->left, req_size);
|
||||
if (req_size < get_size(node)) {
|
||||
if (node->left != nullptr && get_size(node->left) >= req_size) {
|
||||
return rbt_search_bestfit(node->left, req_size);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
if (req_size > this->get_size(node)) {
|
||||
if (node->right != nullptr && this->get_size(node->right) >= req_size) {
|
||||
return this->rbt_search_bestfit(node->right, req_size);
|
||||
if (req_size > get_size(node)) {
|
||||
if (node->right != nullptr && get_size(node->right) >= req_size) {
|
||||
return rbt_search_bestfit(node->right, req_size);
|
||||
}
|
||||
|
||||
// Block doesn't fit
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 11.12.2018 *
|
||||
*****************************************************************************/
|
||||
#include "devices/CGA.h"
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
// in startup.asm
|
||||
@ -68,11 +67,11 @@ int bs_ypos = 0;
|
||||
void bs_clear() {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned short* ptr = (unsigned short*)0xb8000;
|
||||
unsigned short* ptr = reinterpret_cast<unsigned short*>(0xb8000);
|
||||
|
||||
for (x = 0; x < 80; x++) {
|
||||
for (y = 0; y < 25; y++) {
|
||||
*(ptr + y * 80 + x) = (short)0x1F00;
|
||||
*(ptr + y * 80 + x) = static_cast<short>(0x1F00);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +95,7 @@ void bs_lf() {
|
||||
* Beschreibung: Ein Zeichen ausgeben. *
|
||||
*****************************************************************************/
|
||||
void bs_print_char(char c) {
|
||||
unsigned char* ptr = (unsigned char*)0xb8000;
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(0xb8000);
|
||||
|
||||
*(ptr + bs_ypos * 80 * 2 + bs_xpos * 2) = c;
|
||||
bs_xpos++;
|
||||
@ -122,9 +121,9 @@ void bs_print_string(char* str) {
|
||||
*****************************************************************************/
|
||||
void bs_printHexDigit(int c) {
|
||||
if (c < 10) {
|
||||
bs_print_char('0' + (unsigned char)c);
|
||||
bs_print_char('0' + static_cast<unsigned char>(c));
|
||||
} else {
|
||||
bs_print_char('A' + (unsigned char)(c - 10));
|
||||
bs_print_char('A' + static_cast<unsigned char>(c - 10));
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +144,7 @@ void bs_print_uintHex(unsigned int c) {
|
||||
* Beschreibung: String mit Integer ausgeben. Wird verwendet um ein *
|
||||
* Register auszugeben. *
|
||||
*****************************************************************************/
|
||||
void bs_printReg(char* str, int value) {
|
||||
void bs_printReg(char* str, unsigned int value) {
|
||||
bs_print_string(str);
|
||||
bs_print_uintHex(value);
|
||||
bs_print_string(" \0");
|
||||
@ -211,7 +210,7 @@ void bs_dump(unsigned int exceptionNr) {
|
||||
get_int_esp(&int_esp);
|
||||
|
||||
// wir müssen den Inhalt auslesen und das als Zeiger verwenden, um den Stack auszulesen
|
||||
sptr = (unsigned int*)*int_esp;
|
||||
sptr = reinterpret_cast<unsigned int*>(*int_esp);
|
||||
|
||||
bs_lf();
|
||||
|
||||
@ -252,7 +251,7 @@ void bs_dump(unsigned int exceptionNr) {
|
||||
|
||||
// Exception mit Error-Code?
|
||||
if (has_error_code == 1) {
|
||||
int error_nr = *(sptr + 8);
|
||||
unsigned int error_nr = *(sptr + 8);
|
||||
|
||||
if (exceptionNr == 14) {
|
||||
if (error_nr == 3) {
|
||||
@ -278,7 +277,7 @@ void bs_dump(unsigned int exceptionNr) {
|
||||
bs_print_string("Calling Stack:\0");
|
||||
bs_lf();
|
||||
int x = 0;
|
||||
unsigned int* ebp = (unsigned int*)*(sptr + 2);
|
||||
unsigned int* ebp = reinterpret_cast<unsigned int*>(*(sptr + 2));
|
||||
unsigned int raddr;
|
||||
|
||||
// solange eip > 1 MB && ebp < 128 MB, max. Aufruftiefe 10
|
||||
@ -289,7 +288,7 @@ void bs_dump(unsigned int exceptionNr) {
|
||||
bs_lf();
|
||||
|
||||
// dynamische Kette -> zum Aufrufer
|
||||
ebp = (unsigned int*)*ebp;
|
||||
ebp = reinterpret_cast<unsigned int*>(*ebp);
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
* Autor: Michael Schoettner, 2.2.2017 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Bluescreen_include__
|
||||
#define __Bluescreen_include__
|
||||
#ifndef Bluescreen_include__
|
||||
#define Bluescreen_include__
|
||||
|
||||
// dump blue screen (will not return)
|
||||
void bs_dump(unsigned int exceptionNr);
|
||||
|
||||
@ -9,16 +9,16 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 06.04.20 *
|
||||
*****************************************************************************/
|
||||
#ifndef __ISR_include__
|
||||
#define __ISR_include__
|
||||
#ifndef ISR_include__
|
||||
#define ISR_include__
|
||||
|
||||
class ISR {
|
||||
|
||||
private:
|
||||
public:
|
||||
ISR(const ISR& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
public:
|
||||
ISR() {}
|
||||
// virtual ~ISR() = default;
|
||||
|
||||
ISR() = default;
|
||||
|
||||
// Unterbrechungsbehandlungsroutine
|
||||
virtual void trigger() = 0;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include "kernel/Globals.h"
|
||||
#include "kernel/interrupts/Bluescreen.h"
|
||||
|
||||
extern "C" void int_disp(unsigned int slot);
|
||||
extern "C" void int_disp(unsigned int vector);
|
||||
|
||||
/*****************************************************************************
|
||||
* Prozedur: int_disp *
|
||||
@ -60,12 +60,12 @@ int IntDispatcher::assign(unsigned int vector, ISR& isr) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
if (vector >= this->size) {
|
||||
if (vector >= size) {
|
||||
log.error() << "Invalid vector number when assigning" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->map[vector] = &isr;
|
||||
map[vector] = &isr;
|
||||
log.info() << "Registered ISR for vector " << dec << vector << endl;
|
||||
|
||||
return 0;
|
||||
@ -85,11 +85,11 @@ int IntDispatcher::report(unsigned int vector) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
if (vector >= this->size) {
|
||||
if (vector >= size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ISR* isr = this->map[vector];
|
||||
ISR* isr = map[vector];
|
||||
|
||||
if (isr == nullptr) {
|
||||
log.error() << "No ISR registered for vector " << vector << endl;
|
||||
|
||||
@ -10,18 +10,19 @@
|
||||
* *
|
||||
* Autor: Michael Schoettner, 30.7.16 *
|
||||
*****************************************************************************/
|
||||
#ifndef __IntDispatcher_include__
|
||||
#define __IntDispatcher_include__
|
||||
#ifndef IntDispatcher_include__
|
||||
#define IntDispatcher_include__
|
||||
|
||||
#include "kernel/interrupts/ISR.h"
|
||||
#include "user/lib/Logger.h"
|
||||
#include "user/lib/Array.h"
|
||||
|
||||
class IntDispatcher {
|
||||
private:
|
||||
NamedLogger log;
|
||||
|
||||
enum { size = 256 };
|
||||
ISR* map[size];
|
||||
bse::array<ISR*, size> map;
|
||||
|
||||
public:
|
||||
IntDispatcher(const IntDispatcher& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
#ifndef __PIC_include__
|
||||
#define __PIC_include__
|
||||
#ifndef PIC_include__
|
||||
#define PIC_include__
|
||||
|
||||
#include "kernel/IOport.h"
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
* Autor: Michael, Schoettner, HHU, 13.8.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __IdleThread_include__
|
||||
#define __IdleThread_include__
|
||||
#ifndef IdleThread_include__
|
||||
#define IdleThread_include__
|
||||
|
||||
#include "kernel/Globals.h"
|
||||
#include "kernel/threads/Thread.h"
|
||||
@ -20,10 +20,10 @@ public:
|
||||
|
||||
IdleThread() : Thread("IdleThread") {}
|
||||
|
||||
/*[[noreturn]]*/ void run() override {
|
||||
[[noreturn]] void run() override {
|
||||
// Idle-Thread läuft, ab jetzt ist der Scheduler fertig initialisiert
|
||||
log.info() << "IdleThread enabled preemption" << endl;
|
||||
scheduler.enable_preemption(this->tid);
|
||||
scheduler.enable_preemption(tid);
|
||||
if (!scheduler.preemption_enabled()) {
|
||||
log.error() << "Preemption disabled" << endl;
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
* Autor: Michael, Schoettner, HHU, 22.8.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Scheduler_include__
|
||||
#define __Scheduler_include__
|
||||
#ifndef Scheduler_include__
|
||||
#define Scheduler_include__
|
||||
|
||||
#include "kernel/threads/Thread.h"
|
||||
#include "user/lib/Logger.h"
|
||||
@ -33,8 +33,8 @@ private:
|
||||
unsigned int idle_tid = 0U;
|
||||
|
||||
// Roughly the old dispatcher functionality
|
||||
/*[[noreturn]]*/ void start(bse::vector<bse::unique_ptr<Thread>>::iterator next); // Start next without prev
|
||||
/*[[noreturn]]*/ void switch_to(Thread* prev_raw, bse::vector<bse::unique_ptr<Thread>>::iterator next); // Switch from prev to next
|
||||
void start(bse::vector<bse::unique_ptr<Thread>>::iterator next); // Start next without prev
|
||||
void switch_to(Thread* prev_raw, bse::vector<bse::unique_ptr<Thread>>::iterator next); // Switch from prev to next
|
||||
|
||||
// Kann nur vom Idle-Thread aufgerufen werden (erster Thread der vom Scheduler gestartet wird)
|
||||
void enable_preemption(unsigned int tid) { idle_tid = tid; }
|
||||
@ -63,7 +63,7 @@ public:
|
||||
bool preemption_enabled() const { return idle_tid != 0U; }
|
||||
|
||||
// Scheduler starten
|
||||
/*[[noreturn]]*/ void schedule();
|
||||
void schedule();
|
||||
|
||||
// Helper that directly constructs the thread, then readys it
|
||||
template<typename T, typename... Args>
|
||||
@ -80,7 +80,7 @@ public:
|
||||
// NOTE: When a thread exits itself it will disappear...
|
||||
// Maybe put exited threads in an exited queue?
|
||||
// Then they would have to be acquired from there to exit...
|
||||
/* [[noreturn]] */ void exit(); // Returns on error because we don't have exceptions
|
||||
void exit(); // Returns on error because we don't have exceptions
|
||||
|
||||
// Thread mit 'Gewalt' terminieren
|
||||
void kill(unsigned int tid, bse::unique_ptr<Thread>* ptr);
|
||||
@ -94,13 +94,13 @@ public:
|
||||
void nice_kill(unsigned int tid) { nice_kill(tid, nullptr); }
|
||||
|
||||
// CPU freiwillig abgeben und Auswahl des naechsten Threads
|
||||
/* [[noreturn]] */ void yield(); // Returns when only the idle thread runs
|
||||
void yield(); // Returns when only the idle thread runs
|
||||
|
||||
// Thread umschalten; wird aus der ISR des PITs gerufen
|
||||
/* [[noreturn]] */ void preempt(); // Returns when only the idle thread runs
|
||||
void preempt(); // Returns when only the idle thread runs
|
||||
|
||||
// Blocks current thread (move to block_queue)
|
||||
/* [[noreturn]] */ void block(); // Returns on error because we don't have exceptions
|
||||
void block(); // Returns on error because we don't have exceptions
|
||||
|
||||
// Deblock by tid (move to ready_queue)
|
||||
void deblock(unsigned int tid);
|
||||
|
||||
@ -56,20 +56,20 @@ void Thread_init(unsigned int* esp, unsigned int* stack, void (*kickoff)(Thread*
|
||||
// wird, sie darf also nicht terminieren, sonst kracht's.
|
||||
|
||||
// I thought this syntax was a bit clearer than decrementing a pointer
|
||||
stack[-1] = (unsigned int)object;
|
||||
stack[-1] = reinterpret_cast<unsigned int>(object);
|
||||
stack[-2] = 0x131155U;
|
||||
stack[-3] = (unsigned int)kickoff;
|
||||
stack[-3] = reinterpret_cast<unsigned int>(kickoff);
|
||||
stack[-4] = 0; // EAX
|
||||
stack[-5] = 0; // ECX
|
||||
stack[-6] = 0; // EDX
|
||||
stack[-7] = 0; // EBX
|
||||
stack[-8] = (unsigned int)&stack[-3]; // ESP
|
||||
stack[-8] = reinterpret_cast<unsigned int>(&stack[-3]); // ESP
|
||||
stack[-9] = 0; // EBP
|
||||
stack[-10] = 0; // ESI
|
||||
stack[-11] = 0; // EDI
|
||||
stack[-12] = 0x200U;
|
||||
|
||||
*esp = (unsigned int)&stack[-12];
|
||||
*esp = reinterpret_cast<unsigned int>(&stack[-12]);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -98,7 +98,7 @@ void Thread_init(unsigned int* esp, unsigned int* stack, void (*kickoff)(Thread*
|
||||
* stack Stack für die neue Koroutine *
|
||||
*****************************************************************************/
|
||||
Thread::Thread(char* name) : stack(new unsigned int[1024]), esp(0), log(name), name(name), tid(ThreadCnt++) {
|
||||
log.info() << "Initialized thread with ID: " << this->tid << " (" << name << ")" << endl;
|
||||
log.info() << "Initialized thread with ID: " << tid << " (" << name << ")" << endl;
|
||||
Thread_init(&esp, &stack[1024], kickoff, this); // Stack grows from top to bottom
|
||||
}
|
||||
|
||||
@ -124,5 +124,5 @@ void Thread::start() const {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
|
||||
Thread_start(this->esp);
|
||||
Thread_start(esp);
|
||||
}
|
||||
|
||||
@ -7,9 +7,9 @@
|
||||
* Thread-Objekte werden vom Scheduler in einer verketteten *
|
||||
* Liste 'readylist' verwaltet. *
|
||||
* *
|
||||
* Im Konstruktor wird der initialie Kontext des Threads *
|
||||
* Im Konstruktor wird der initialie Kontext des Threads *
|
||||
* eingerichtet. Mit 'start' wird ein Thread aktiviert. *
|
||||
* Die CPU sollte mit 'yield' freiwillig abgegeben werden. *
|
||||
* Die CPU sollte mit 'yield' freiwillig abgegeben werden. *
|
||||
* Um bei einem Threadwechsel den Kontext sichern zu *
|
||||
* koennen, enthaelt jedes Threadobjekt eine Struktur *
|
||||
* ThreadState, in dem die Werte der nicht-fluechtigen *
|
||||
@ -25,8 +25,8 @@
|
||||
* Autor: Michael, Schoettner, HHU, 16.12.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Thread_include__
|
||||
#define __Thread_include__
|
||||
#ifndef Thread_include__
|
||||
#define Thread_include__
|
||||
|
||||
#include "user/lib/Logger.h"
|
||||
|
||||
@ -49,21 +49,21 @@ public:
|
||||
Thread(const Thread& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
virtual ~Thread() {
|
||||
log.info() << "Uninitialized thread, ID: " << dec << this->tid << " (" << name << ")" << endl;
|
||||
delete[] this->stack;
|
||||
log.info() << "Uninitialized thread, ID: " << dec << tid << " (" << name << ")" << endl;
|
||||
delete[] stack;
|
||||
}
|
||||
|
||||
// Thread aktivieren
|
||||
/*[[noreturn]]*/ void start() const;
|
||||
void start() const;
|
||||
|
||||
// Umschalten auf Thread 'next'
|
||||
/*[[noreturn]]*/ void switchTo(Thread& next);
|
||||
void switchTo(Thread& next);
|
||||
|
||||
// Ask thread to terminate itself
|
||||
void suicide() { running = false; }
|
||||
|
||||
// Methode des Threads, muss in Sub-Klasse implementiert werden
|
||||
[[noreturn]] virtual void run() = 0;
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user