mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
454 lines
17 KiB
C#
454 lines
17 KiB
C#
////////////////////////////////////////
|
|
// Add you name here when you change to add to this class
|
|
//
|
|
// Class made by: Craig Lee Mark Adams
|
|
//
|
|
//
|
|
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Cosmos.Core.Managed_Memory_System
|
|
{
|
|
|
|
// Some code come from Cosmos.Core.Heap.
|
|
|
|
public static class ManagedMemory
|
|
{
|
|
public static bool EnableDebug = true;
|
|
private static uint mStart;
|
|
private static uint mStartAddress;
|
|
private static uint mLength;
|
|
private static uint mEndOfRam;
|
|
private static bool setup = false;
|
|
private static int startMemoryMap = 0;
|
|
private static int amountObject;
|
|
|
|
private static List<ObjectMemory> kernalMemoryArea;
|
|
private static List<int> freeMemoryArea;
|
|
|
|
|
|
// private static uint mAmountHeapAlloc = 500; //set the amount of memory that can be allocate in one go.
|
|
|
|
|
|
public static uint GetmStartAddress
|
|
{
|
|
get
|
|
{
|
|
return mStartAddress;
|
|
}
|
|
}
|
|
public static uint GetmEndOfRam
|
|
{
|
|
get
|
|
{
|
|
return mEndOfRam;
|
|
}
|
|
}
|
|
|
|
public static List<ObjectMemory> GetOjectMemory
|
|
{
|
|
get
|
|
{
|
|
return kernalMemoryArea;
|
|
}
|
|
}
|
|
|
|
|
|
private static uint kernalOjectAreaSize = 1800; //Say the limit of a object size can be.
|
|
|
|
private static uint memorySetUpAreaEnd; //Area that is use for memory set up objects.
|
|
|
|
private static uint rootKernalEnd;
|
|
|
|
private static void DoInitialize(uint aStartAddress, uint aEndOfRam)
|
|
{
|
|
mStart = mStartAddress = aStartAddress + (4 - (aStartAddress % 4));
|
|
mLength = aEndOfRam - aStartAddress;
|
|
mLength = (mLength / 4) * 4;
|
|
mStartAddress += 1024;
|
|
mEndOfRam = aEndOfRam;
|
|
mStartAddress = (mStartAddress / 4) * 4;
|
|
mLength -= 1024;
|
|
memorySetUpAreaEnd = mStartAddress + 7051893; // May need changing
|
|
|
|
rootKernalEnd = mEndOfRam;
|
|
UpdateDebugDisplay();
|
|
}
|
|
|
|
private static bool mInitialized = false;
|
|
internal static void Initialize()
|
|
{
|
|
if (!mInitialized)
|
|
{
|
|
mInitialized = true;
|
|
DoInitialize(CPU.GetEndOfKernel(), (CPU.GetAmountOfRAM() - 1) * 1024 * 1024);
|
|
}
|
|
}
|
|
|
|
private static void ClearMemory(uint aStartAddress, uint aLength)
|
|
{
|
|
//TODO: Move to memory. Internal access only...
|
|
Global.CPU.ZeroFill(aStartAddress, aLength);
|
|
}
|
|
|
|
private static void WriteNumber(uint aNumber, byte aBits)
|
|
{
|
|
uint xValue = aNumber;
|
|
byte xCurrentBits = aBits;
|
|
Console.Write("0x");
|
|
while (xCurrentBits >= 4) {
|
|
xCurrentBits -= 4;
|
|
byte xCurrentDigit = (byte)((xValue >> xCurrentBits) & 0xF);
|
|
string xDigitString = null;
|
|
switch (xCurrentDigit) {
|
|
case 0:
|
|
xDigitString = "0";
|
|
goto default;
|
|
case 1:
|
|
xDigitString = "1";
|
|
goto default;
|
|
case 2:
|
|
xDigitString = "2";
|
|
goto default;
|
|
case 3:
|
|
xDigitString = "3";
|
|
goto default;
|
|
case 4:
|
|
xDigitString = "4";
|
|
goto default;
|
|
case 5:
|
|
xDigitString = "5";
|
|
goto default;
|
|
case 6:
|
|
xDigitString = "6";
|
|
goto default;
|
|
case 7:
|
|
xDigitString = "7";
|
|
goto default;
|
|
case 8:
|
|
xDigitString = "8";
|
|
goto default;
|
|
case 9:
|
|
xDigitString = "9";
|
|
goto default;
|
|
case 10:
|
|
xDigitString = "A";
|
|
goto default;
|
|
case 11:
|
|
xDigitString = "B";
|
|
goto default;
|
|
case 12:
|
|
xDigitString = "C";
|
|
goto default;
|
|
case 13:
|
|
xDigitString = "D";
|
|
goto default;
|
|
case 14:
|
|
xDigitString = "E";
|
|
goto default;
|
|
case 15:
|
|
xDigitString = "F";
|
|
goto default;
|
|
default:
|
|
if (xDigitString == null) {
|
|
System.Diagnostics.Debugger.Break();
|
|
}
|
|
Console.Write(xDigitString);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool mDebugDisplayInitialized = false;
|
|
|
|
// This method displays the used/total memory of the heap on the first line of the text screen
|
|
private static void UpdateDebugDisplay()
|
|
{
|
|
//if (EnableDebug)
|
|
//{
|
|
// if (!mDebugDisplayInitialized)
|
|
// {
|
|
// mDebugDisplayInitialized = true;
|
|
// int xOldPositionLeft = Console.CursorLeft;
|
|
// int xOldPositionTop = Console.CursorTop;
|
|
// Console.CursorLeft = 0;
|
|
// Console.CursorTop = 0;
|
|
// Console.Write("[Heap Usage: ");
|
|
// WriteNumber(mStartAddress,
|
|
// 32);
|
|
// Console.Write("/");
|
|
// WriteNumber(mEndOfRam,
|
|
// 32);
|
|
// Console.Write("] bytes");
|
|
// while (Console.CursorLeft < (Console.WindowWidth-1))
|
|
// {
|
|
// Console.Write(" ");
|
|
// }
|
|
// Console.CursorLeft = xOldPositionLeft;
|
|
// Console.CursorTop = xOldPositionTop;
|
|
// }
|
|
// else
|
|
// {
|
|
// int xOldPositionLeft = Console.CursorLeft;
|
|
// int xOldPositionTop = Console.CursorTop;
|
|
// Console.CursorLeft = 13;
|
|
// Console.CursorTop = 0;
|
|
// WriteNumber(mStartAddress,
|
|
// 32);
|
|
// Console.CursorLeft = xOldPositionLeft;
|
|
// Console.CursorTop = xOldPositionTop;
|
|
// }
|
|
//}
|
|
}
|
|
|
|
// This should get call after initualize is done
|
|
public static void SetUpMemoryArea()
|
|
{
|
|
uint temp = memorySetUpAreaEnd + 1; //space of 1 between memory areas
|
|
kernalMemoryArea = new List<ObjectMemory>();
|
|
freeMemoryArea = new List<int>();
|
|
while (temp < rootKernalEnd)
|
|
{
|
|
amountObject++;
|
|
if ((temp + kernalOjectAreaSize) > rootKernalEnd)
|
|
{
|
|
kernalMemoryArea.Add(new ObjectMemory(temp, rootKernalEnd, true));
|
|
}
|
|
else
|
|
{
|
|
kernalMemoryArea.Add(new ObjectMemory(temp, (temp + kernalOjectAreaSize), false));
|
|
}
|
|
temp = temp + kernalOjectAreaSize + 1; //space of 1 between memory areas
|
|
}
|
|
setup = true;
|
|
|
|
|
|
//temp = rootKernalEnd + 1; //space of 1 between memory areas
|
|
//while (temp < mEndOfRam)
|
|
//{
|
|
// if ((temp + memoryAreaSize) > (mStart + mLength))
|
|
// {
|
|
// memoryAreas.Add(new ObjectMemory(temp, mLength, true)); //This allocation the lest bit of memory.
|
|
// }
|
|
// else
|
|
// {
|
|
// memoryAreas.Add(new ObjectMemory(temp, memoryAreaSize, false));
|
|
// }
|
|
|
|
// temp = temp + memoryAreaSize + 1; //space of 1 between memory areas
|
|
//}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Allocation object that use to set up the system.
|
|
public static uint SetUpMemoryAlloc(uint aLength)
|
|
{
|
|
Initialize();
|
|
uint xTemp = mStartAddress;
|
|
if ((xTemp + aLength) > memorySetUpAreaEnd)
|
|
{
|
|
WriteNumber(aLength, 32);
|
|
while (true)
|
|
;
|
|
}
|
|
mStartAddress += aLength;
|
|
UpdateDebugDisplay();
|
|
ClearMemory(xTemp, aLength);
|
|
return xTemp;
|
|
}
|
|
|
|
public static bool SetUpDone
|
|
{
|
|
get
|
|
{
|
|
return setup;
|
|
}
|
|
}
|
|
|
|
// Allocation objects
|
|
public static uint KernelMemAlloc(uint aLength)
|
|
{
|
|
uint allocationStartArea;
|
|
int i = 0;
|
|
bool found = false;
|
|
|
|
while (found != true)
|
|
{
|
|
if (startMemoryMap < amountObject)
|
|
{
|
|
i = startMemoryMap;
|
|
if ((aLength + kernalMemoryArea[i].ObjectStart) <= kernalMemoryArea[i].ObjectEndAddress)
|
|
{
|
|
allocationStartArea = kernalMemoryArea[i].ObjectStart;
|
|
kernalMemoryArea[i].MemoryFull = true;
|
|
ClearMemory(allocationStartArea, aLength);
|
|
found = true;
|
|
startMemoryMap++;
|
|
return allocationStartArea;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
i = freeMemoryArea[0];
|
|
freeMemoryArea.RemoveAt(i);
|
|
if ((aLength + kernalMemoryArea[i].ObjectStart) <= kernalMemoryArea[i].ObjectEndAddress)
|
|
{
|
|
allocationStartArea = kernalMemoryArea[i].ObjectStart;
|
|
kernalMemoryArea[i].MemoryFull = true;
|
|
ClearMemory(allocationStartArea, aLength);
|
|
found = true;
|
|
return allocationStartArea;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//public static uint HeapAlloc()
|
|
//{
|
|
// bool found = false;
|
|
// uint allocationStartArea = 0;
|
|
|
|
// for (int i = 0; i > (memoryAreas.Count - 1) || found == true; i++)
|
|
// {
|
|
// if (memoryAreas[i].MemoryFull == false)
|
|
// {
|
|
// if (memoryAreas[i].MemorySmall == false)
|
|
// {
|
|
// allocationStartArea = memoryAreas[i].ObjectStart;
|
|
// memoryAreas[i].MemoryFull = true;
|
|
// found = true;
|
|
// }
|
|
// }
|
|
// }
|
|
// if (found == true)
|
|
// {
|
|
// ClearMemory(allocationStartArea, mAmountHeapAlloc);
|
|
// }
|
|
// return allocationStartArea;
|
|
|
|
//}
|
|
|
|
//public unsafe static uint* StackAlloc(uint stackSize)
|
|
//{
|
|
// bool found = false;
|
|
// uint* allocationStartArea = stackalloc uint[2]; //pointer is use so that objects are not put on the heap.
|
|
// allocationStartArea[0] = 0;
|
|
// allocationStartArea[1] = 0;
|
|
|
|
// for (int i = 0; i > (memoryAreas.Count - 1) || found == true; i++)
|
|
// {
|
|
// if (memoryAreas[i].MemoryFull == false)
|
|
// {
|
|
// if (memoryAreas[i].MemorySmall == false)
|
|
// {
|
|
// if (stackSize <= memoryAreaSize)
|
|
// {
|
|
|
|
// allocationStartArea[0] = memoryAreas[i].ObjectStart;
|
|
// allocationStartArea[1] = memoryAreas[i].ObjectEndAddress;
|
|
// memoryAreas[i].MemoryFull = true;
|
|
// found = true;
|
|
// }
|
|
// else
|
|
// {
|
|
// bool thisFound = false;
|
|
|
|
// for (int stacks = 1; thisFound == true; stacks++)
|
|
// {
|
|
// if (memoryAreas[i + stacks].MemoryFull == false)
|
|
// {
|
|
// if (stackSize <= (memoryAreaSize * (stacks + 1)))
|
|
// {
|
|
// allocationStartArea[0] = memoryAreas[i].ObjectStart;
|
|
// allocationStartArea[1] = memoryAreas[i + stacks].ObjectEndAddress;
|
|
// for (int eachMemoryArea = i; eachMemoryArea > stacks; eachMemoryArea++)
|
|
// {
|
|
// memoryAreas[eachMemoryArea].MemoryFull = true;
|
|
// }
|
|
|
|
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// uint thisLength = memoryAreas[i].ObjectEndAddress - memoryAreas[i].ObjectStart;
|
|
// thisLength = (thisLength / 4) * 4;
|
|
// if (stackSize < thisLength)
|
|
// {
|
|
|
|
// allocationStartArea[0] = memoryAreas[i].ObjectStart;
|
|
// allocationStartArea[1] = memoryAreas[i].ObjectEndAddress;
|
|
// memoryAreas[i].MemoryFull = true;
|
|
// found = true;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// if (found == true)
|
|
// {
|
|
// ClearMemory(allocationStartArea[0], allocationStartArea[1]);
|
|
// }
|
|
// return allocationStartArea;
|
|
|
|
//}
|
|
|
|
public static void KernalMemDeallocate(uint address)
|
|
{
|
|
bool found = false;
|
|
for (int i = 0; i > amountObject || found == true; i++)
|
|
{
|
|
if (kernalMemoryArea[i].ObjectStart < address && kernalMemoryArea[i].ObjectEndAddress > address)
|
|
{
|
|
kernalMemoryArea[i].MemoryFull = false;
|
|
found = true;
|
|
freeMemoryArea.Add(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
//public static void MemDeallocate(uint startAddress, uint endAddress)
|
|
//{
|
|
// bool found = false;
|
|
// for (int i = 0; i > (memoryAreas.Count - 1) || found == true; i++)
|
|
// {
|
|
// if (memoryAreas[i].ObjectStart == startAddress)
|
|
// {
|
|
// if (memoryAreas[i].ObjectEndAddress >= endAddress)
|
|
// {
|
|
// memoryAreas[i].MemoryFull = false;
|
|
// }
|
|
// else
|
|
// {
|
|
// bool thisFound = false;
|
|
// for (int stacks = 1; thisFound == true; stacks++)
|
|
// {
|
|
// if (endAddress <= memoryAreas[i + stacks].ObjectEndAddress)
|
|
// {
|
|
// memoryAreas[i].MemoryFull = false;
|
|
// thisFound = true;
|
|
// }
|
|
// else
|
|
// {
|
|
// memoryAreas[i].MemoryFull = false;
|
|
// }
|
|
// }
|
|
// }
|
|
// kernalMemoryArea[i].MemoryFull = false;
|
|
// found = true;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
}
|
|
}
|