Commit 127fec64 authored by Antônio Augusto Fröhlich's avatar Antônio Augusto Fröhlich
Browse files

Solving exercise about memory management

parent c936f598
// EPOS Address_Space Abstraction Declarations
#ifndef __address_space_h
#define __address_space_h
#include <mmu.h>
#include <segment.h>
__BEGIN_SYS
class Address_Space: private MMU::Directory
{
private:
typedef CPU::Phy_Addr Phy_Addr;
typedef CPU::Log_Addr Log_Addr;
typedef MMU::Directory Directory;
public:
Address_Space();
Address_Space(const Self & s);
~Address_Space();
Log_Addr attach(const Segment & seg);
Log_Addr attach(const Segment & seg, Log_Addr addr);
void detach(const Segment & seg);
using MMU::Directory::activate;
using MMU::Directory::pd;
Phy_Addr physical(Log_Addr address);
};
__END_SYS
#endif
......@@ -4,17 +4,27 @@
#define __application_h
#include <utility/heap.h>
#include <segment.h>
extern "C"
{
void * malloc(size_t);
void free(void *);
}
__BEGIN_SYS
class Application
{
public:
static Heap * const heap() { return &_heap; }
friend class Init_Application;
friend void * ::malloc(size_t);
friend void ::free(void *);
public:
static void init();
private:
static Segment _heap_segment;
static Heap _heap;
};
......
......@@ -99,24 +99,19 @@ public:
SEG_4K = 0x80,
SEG_FLT_CODE = (SEG_PRE | SEG_NOSYS | SEG_CODE | SEG_ACC),
SEG_FLT_DATA = (SEG_PRE | SEG_NOSYS | SEG_RW | SEG_ACC),
SEG_SYS_CODE = (SEG_PRE | SEG_NOSYS | SEG_RW | SEG_CODE | SEG_ACC),
SEG_SYS_DATA = (SEG_PRE | SEG_NOSYS | SEG_RW | SEG_ACC),
SEG_APP_CODE = (SEG_PRE | SEG_NOSYS | SEG_DPL2 | SEG_DPL1 |
SEG_CODE | SEG_ACC), // P, DPL=3, S, C, W, A
SEG_APP_DATA = (SEG_PRE | SEG_NOSYS | SEG_DPL2 | SEG_DPL1 |
SEG_RW | SEG_ACC), // P, DPL=3, S, W, A
// SEG_SYS_CODE = (SEG_PRE | SEG_NOSYS | SEG_DPL2 | SEG_DPL1 |
// SEG_CODE | SEG_ACC), // P, DPL=3, S, C, W, A
// SEG_SYS_DATA = (SEG_PRE | SEG_NOSYS | SEG_DPL2 | SEG_DPL1 |
// SEG_RW | SEG_ACC), // P, DPL=3, S, W, A
SEG_IDT_ENTRY = (SEG_PRE | SEG_INT )
SEG_SYS_CODE = (SEG_PRE | SEG_NOSYS | SEG_CODE | SEG_ACC),
SEG_SYS_DATA = (SEG_PRE | SEG_NOSYS | SEG_RW | SEG_ACC),
SEG_IDT_ENTRY = (SEG_PRE | SEG_INT | SEG_DPL1 | SEG_DPL2)
};
// DPL/RPL for application (user) and system (supervisor) modes
enum {
PL_APP = 3, // GDT, RPL=3
PL_SYS = 0 // GDT, RPL=0
// PL_SYS = 3 // GDT, RPL=0
};
// GDT Layout
......@@ -374,6 +369,32 @@ public:
static Reg32 ntohl(Reg32 v) { return htonl(v); }
static Reg16 ntohs(Reg16 v) { return htons(v); }
static void bts(volatile unsigned int *base, const int bit) {
ASMV("bts %1,%0" : "+m" (*base) : "r" (bit));
}
static void btr(volatile unsigned int *base, const int bit) {
ASMV("btr %1,%0" : "+m" (*base) : "r" (bit));
}
static int bsf(unsigned int & value) {
register unsigned int pos;
ASMV("bsf %1, %0"
: "=a"(pos)
: "m"(value)
: );
return pos;
}
static int bsr(unsigned int & value) {
register int pos = -1;
ASMV("bsr %1, %0"
: "=a"(pos)
: "m"(value)
: );
return pos;
}
static Context * init_stack(
Log_Addr stack, unsigned int size, void (* exit)(),
int (* entry)()) {
......@@ -423,23 +444,6 @@ public:
return new (sp) Context(entry);
}
static void system_call(Log_Addr addr) {
db<IA32>(TRC) << "system_call(" << addr << ") <= "
<< "{MSR[IA32_SYSENTER_CS]=" << IA32::rdmsr(0x174)
<< ",MSR[IA32_SYSENTER_EIP]=" << IA32::rdmsr(0x175)
<< ",MSR[IA32_SYSENTER_ESP]=" << IA32::rdmsr(0x176)
<< "}\n";
// Save return data in clobbered registers and enter kernel
ASMV(" movl %0, %%eax \n"
" movl %%esp, %%ecx \n"
" movl RET, %%edx \n"
" sysenter \n"
"RET: \n" : : "i"(0));
}
static void system_entry();
static void init();
// IA32 specific methods
......
......@@ -21,98 +21,6 @@ public:
void broadcast();
};
// This is an alternative implementation, which does impose ordering
// on threads waiting at "wait". Nontheless, it's still susceptible to counter
// overflow
// class Condition: public Synchronizer_Common
// {
// private:
// typedef Traits<Synchronizer> Traits;
// static const Type_Id TYPE = Type<Condition>::TYPE;
// public:
// Condition() : _wait(0), _signal(0) {
// db<Synchronizer>(TRC) << "Condition() => " << this << "\n";
// }
// ~Condition() {
// db<Synchronizer>(TRC) << "~Condition(this=" << this << ")\n";
// }
// void wait() {
// db<Synchronizer>(TRC) << "Condition::wait(this=" << this
// << ",wt=" << _wait
// << ",sg=" << _signal << ")\n";
// int rank = finc(_wait);
// while(rank >= _signal)
// sleep();
// }
// void signal() {
// db<Synchronizer>(TRC) << "Condition::signal(this=" << this
// << ",wt=" << _wait
// << ",sg=" << _signal << ")\n";
// finc(_signal);
// wakeup();
// }
// void broadcast() { // warning: overflow is not being handled!
// db<Synchronizer>(TRC) << "Condition::broadcast(this=" << this
// << ",wt=" << _wait
// << ",sg=" << _signal << ")\n";
// _signal = _wait + 1;
// wakeup_all();
// }
// static int init(System_Info * si);
// private:
// volatile int _wait;
// volatile int _signal;
// };
// This is an alternative implementation, which does not impose any ordering
// on threads waiting at "wait". In this case, ordering would be implemented
// in "sleep" and "wakeup" through ordered queues.
// class Condition: public Synchronizer_Common
// {
// private:
// typedef Traits<Condition> Traits;
// static const Type_Id TYPE = Type<Condition>::TYPE;
// public:
// Condition() : _not_condition(true), _broadcast(0), _time_stamp(1) {
// db<Condition>(TRC) << "Condition() => " << this << ")\n";
// }
// ~Condition() {
// db<Condition>(TRC) << "Condition() => " << this << ")\n";
// }
// void wait() {
// db<Condition>(TRC) << "Condition::wait(this=" << this
// << ",ts=" << _time_stamp << ")\n";
// int ts = finc(_time_stamp);
// while(tsl(_not_condition) && (ts > _broadcast))
// sleep();
// }
// void signal() {
// db<Condition>(TRC) << "Condition::signal(this=" << this
// << ",ts=" << _time_stamp << ")\n";
// _not_condition = false;
// wakeup();
// }
// void broadcast() {
// db<Condition>(TRC) << "Condition::broadcast(this=" << this
// << ",ts=" << _time_stamp << ")\n";
// _broadcast = finc(_time_stamp);
// wakeup_all();
// }
// static int init(System_Info * si);
// private:
// volatile bool _not_condition;
// volatile int _broadcast;
// volatile int _time_stamp;
// };
// An event handler that triggers a condition variable (see handler.h)
class Condition_Handler: public Handler
......
......@@ -37,6 +37,7 @@ typedef PC_UART UART;
typedef IF<Traits<Serial_Display>::enabled,
Serial_Display, PC_Display>::Result Display;
typedef PC_Ethernet NIC;
typedef PC_Scratchpad Scratchpad;
__END_SYS
......
......@@ -72,5 +72,6 @@ __END_SYS
#include "uart.h"
#include "display.h"
#include "nic.h"
#include "scratchpad.h"
#endif
// EPOS PC Scratchpad Memory Mediator Declarations
#include <scratchpad.h>
#ifndef __pc_scratchpad_h
#define __pc_scratchpad_h
__BEGIN_SYS
class PC_Scratchpad: public Scratchpad_Common
{
private:
static const unsigned int ADDRESS = Traits<PC_Scratchpad>::ADDRESS;
static const unsigned int SIZE = Traits<PC_Scratchpad>::SIZE;
public:
PC_Scratchpad() {}
static void init();
};
__END_SYS
#endif
......@@ -115,6 +115,13 @@ template <> struct Traits<C905>: public Traits<PC_Ethernet>
static const unsigned int RECEIVE_BUFFERS = 8; // per unit
};
template <> struct Traits<PC_Scratchpad>: public Traits<PC_Common>
{
static const bool enabled = false;
static const unsigned int ADDRESS = Traits<PC_Display>::FRAME_BUFFER_ADDRESS;
static const unsigned int SIZE = Traits<PC_Display>::LINES * Traits<PC_Display>::COLUMNS;
};
__END_SYS
#endif
// EPOS Scratchpad Memory Mediator Declarations
#ifndef __scratchpad_h
#define __scratchpad_h
#include <utility/heap.h>
#include <segment.h>
__BEGIN_SYS
enum Scratchpad_Allocator
{
SCRATCHPAD
};
__END_SYS
void * operator new(size_t, const EPOS::Scratchpad_Allocator &);
void * operator new[](size_t, const EPOS::Scratchpad_Allocator &);
__BEGIN_SYS
class Scratchpad_Common
{
friend void * ::operator new(size_t, const EPOS::Scratchpad_Allocator &);
friend void * ::operator new[](size_t, const EPOS::Scratchpad_Allocator &);
public:
static void * alloc(unsigned int bytes) { return _heap->alloc(bytes); }
protected:
static Segment * _segment;
static Heap * _heap;
};
__END_SYS
#ifdef __SCRATCHPAD_H
#include __SCRATCHPAD_H
inline void * operator new(size_t bytes, const EPOS::Scratchpad_Allocator & allocator) {
return EPOS::Scratchpad::_heap->alloc(bytes);
}
inline void * operator new[](size_t bytes, const EPOS::Scratchpad_Allocator & allocator) {
return EPOS::Scratchpad::_heap->alloc(bytes);
}
#endif
#endif
// EPOS Memory Segment Abstraction Declarations
#ifndef __segment_h
#define __segment_h
#include <mmu.h>
__BEGIN_SYS
class Segment: public MMU::Chunk
{
private:
typedef MMU::Chunk Chunk;
public:
typedef MMU::Flags Flags;
typedef CPU::Phy_Addr Phy_Addr;
public:
Segment();
Segment(unsigned int bytes, Flags flags = Flags::APP);
Segment(Phy_Addr phy_addr, unsigned int bytes, Flags flags = Flags::APP);
~Segment();
unsigned int size() const;
Phy_Addr phy_address() const;
int resize(int amount);
};
__END_SYS
#endif
......@@ -4,24 +4,58 @@
#define __system_h
#include <utility/heap.h>
#include <segment.h>
__BEGIN_SYS
//class Machine;
enum System_Allocator
{
SYSTEM
};
__END_SYS
extern "C"
{
void * malloc(size_t);
void free(void *);
}
inline void * operator new(size_t, const EPOS::System_Allocator &);
inline void * operator new[](size_t, const EPOS::System_Allocator &);
__BEGIN_SYS
class System
{
friend class Init_System;
friend class Init_Application;
friend void * ::malloc(size_t);
friend void ::free(void *);
friend void * ::operator new(size_t, const EPOS::System_Allocator &);
friend void * ::operator new[](size_t, const EPOS::System_Allocator &);
friend void ::operator delete(void *);
friend void ::operator delete[](void *);
public:
static System_Info<Machine> * const info();
static Heap * const heap() { return &_heap; }
static void init();
private:
static System_Info<Machine> * _si;
static Segment _heap_segment;
static Heap _heap;
};
__END_SYS
inline void * operator new(size_t bytes, const EPOS::System_Allocator & allocator) {
return EPOS::System::_heap.alloc(bytes);
}
inline void * operator new[](size_t bytes, const EPOS::System_Allocator & allocator) {
return EPOS::System::_heap.alloc(bytes);
}
#endif
......@@ -93,6 +93,8 @@ template <> struct Traits<System>: public Traits<void>
static const bool multithread = true;
static const bool multitask = false && (mode != Traits<Build>::LIBRARY);
static const bool multicore = false && multithread;
static const bool multiheap = (mode != Traits<Build>::LIBRARY)
|| Traits<Scratchpad>::enabled;
static const bool reboot = true;
......@@ -112,6 +114,16 @@ template <> struct Traits<Thread>: public Traits<void>
static const bool trace_idle = false;
};
template <> struct Traits<Address_Space>: public Traits<void>
{
static const bool enabled = Traits<System>::multiheap;
};
template <> struct Traits<Segment>: public Traits<void>
{
static const bool enabled = Traits<System>::multiheap;
};
template <> struct Traits<Alarm>: public Traits<void>
{
static const bool visible = false;
......
......@@ -8,12 +8,6 @@ typedef __SIZE_TYPE__ size_t;
inline void * operator new(size_t s, void * a) { return a; }
inline void * operator new[](size_t s, void * a) { return a; }
void * operator new(size_t bytes);
void * operator new[](size_t bytes);
void operator delete(void * ptr) __attribute__ ((weak));
void operator delete[](void * ptr) __attribute__ ((weak));
__BEGIN_SYS
// Dummy class for incomplete architectures and machines
......@@ -64,6 +58,9 @@ class PC_RTC;
// Hardware Mediators - EEPROM
class PC_EEPROM;
// Hardware Mediators - Scratchpad
class PC_Scratchpad;
// Hardware Mediators - UART
class PC_UART;
......@@ -80,6 +77,10 @@ class E100;
// Abstractions - Process
class Thread;
// Abstractions - Memory
class Segment;
class Address_Space;
// Abstractions - Synchronization
class Synchronizer;
class Mutex;
......@@ -110,12 +111,16 @@ enum
TIMER_ID,
RTC_ID,
EEPROM_ID,
SCRATCHPAD_ID,
UART_ID,
DISPLAY_ID,
NIC_ID,
THREAD_ID,
SEGMENT_ID,
ADDRESS_SPACE_ID,
MUTEX_ID,
SEMAPHORE_ID,
CONDITION_ID,
......
......@@ -3,16 +3,17 @@
#ifndef __thread_h
#define __thread_h
#include <system/kmalloc.h>
#include <utility/queue.h>
#include <utility/handler.h>
#include <cpu.h>
#include <machine.h>
#include <system.h>
__BEGIN_SYS
class Thread
{
friend class Init_First;
friend class Synchronizer_Common;
friend class Alarm;
......@@ -29,8 +30,8 @@ protected:
public:
// Thread State
enum State {
READY,
RUNNING,
READY,
SUSPENDED,
WAITING,
FINISHING
......@@ -58,7 +59,7 @@ public:
{
lock();
_stack = kmalloc(stack_size);
_stack = new (SYSTEM) char[stack_size];
_context = CPU::init_stack(_stack, stack_size,
&implicit_exit, entry);
......@@ -74,7 +75,7 @@ public:
{
lock();
_stack = kmalloc(stack_size);
_stack = new (SYSTEM) char[stack_size];
_context = CPU::init_stack(_stack, stack_size,
&implicit_exit, entry, a1);
......@@ -90,7 +91,7 @@ public:
{
lock();
_stack = kmalloc(stack_size);
_stack = new (SYSTEM) char[stack_size];
_context = CPU::init_stack(_stack, stack_size,
&implicit_exit, entry, a1, a2);
......@@ -106,7 +107,7 @@ public:
{
lock();
_stack = kmalloc(stack_size);
_stack = new (SYSTEM) char[stack_size];
_context = CPU::init_stack(_stack, stack_size,
&implicit_exit, entry, a1, a2, a3);
......@@ -125,7 +126,7 @@ public:
void suspend();
void resume();
static Thread* self() { return running(); }
static Thread * self() { return running(); }
static void yield();
static void exit(int status = 0);
......@@ -169,7 +170,7 @@ protected:
static int idle();
protected:
Log_Addr _stack;
char * _stack;
Context * volatile _context;
volatile State _state;
Queue * _waiting;
......
......@@ -18,7 +18,6 @@ public:
virtual ~Handler() {}
virtual void operator()() = 0;
void operator delete(void * object) {}
};
class Function_Handler: public Handler
......
......@@ -12,6 +12,9 @@ __BEGIN_SYS
// Heap
class Heap: private Grouping_List<char>
{
protected:
static const bool typed = Traits<System>::multiheap;
public:
using Grouping_List<char>::empty;
using Grouping_List<char>::size;
......@@ -38,6 +41,8 @@ public:
while((bytes % sizeof(void *)) != 0)