Add changes from @Og-Rok

This commit is contained in:
valentinbreiz 2020-12-27 19:31:58 +01:00
parent 274c5c8b7a
commit 6bef4e1fa0
14 changed files with 546 additions and 31 deletions

View file

@ -234,6 +234,8 @@ namespace Cosmos.Core {
[AsmMarker(AsmMarker.Type.Int_LastKnownAddress)]
private static uint mLastKnownAddress;
public static uint mStackContext;
/// <summary>
/// IRQ handlers.
/// </summary>
@ -845,6 +847,8 @@ namespace Cosmos.Core {
HandleInterrupt_47(ref xCtx);
HandleInterrupt_48(ref xCtx);
HandleInterrupt_49(ref xCtx);
Processing.ProcessorScheduler.SwitchTask();
Processing.ProcessorScheduler.EntryPoint();
}
}
}

View file

@ -2,6 +2,7 @@
using System.Linq;
using System.Threading.Tasks;
using Cosmos.Core;
using Cosmos.Core.Processing;
using Cosmos.Debug.Kernel;
namespace Cosmos.Core.Memory.Old
@ -19,6 +20,8 @@ namespace Cosmos.Core.Memory.Old
private static uint mLastEntryIndex = 0u;
private static Mutex mMemeoryGate = new Mutex();
private static bool mInitialized = false;
private static void DoInitialize(uint aEndOfRam)
@ -59,6 +62,11 @@ namespace Cosmos.Core.Memory.Old
{
EnsureIsInitialized();
if (mMemeoryGate != null)
{
mMemeoryGate.Lock();
}
DataLookupTable* xCurrentTable = GlobalSystemInfo.GlobalInformationTable->FirstDataLookupTable;
DataLookupTable* xPreviousTable = null;
uint xResult;
@ -81,6 +89,11 @@ namespace Cosmos.Core.Memory.Old
}
}
if (mMemeoryGate != null)
{
mMemeoryGate.Unlock();
}
return xResult;
}
mLastTable = xPreviousTable;
@ -117,6 +130,12 @@ namespace Cosmos.Core.Memory.Old
}
mLastTable = xNextTablePointer;
mLastEntryIndex = 0;
if (mMemeoryGate != null)
{
mMemeoryGate.Unlock();
}
return xResult;
}
finally
@ -129,6 +148,10 @@ namespace Cosmos.Core.Memory.Old
{
//Debugger.DoSend(" Not enabling interrupts, because they weren't enabled yet!");
}
if (mMemeoryGate != null)
{
mMemeoryGate.Unlock();
}
}
}

View file

@ -0,0 +1,19 @@
using IL2CPU.API.Attribs;
using System;
namespace Cosmos.Core
{
public static unsafe class ObjUtilities
{
public static uint GetPointer(Delegate aVal)
{
return (uint)aVal.GetHashCode();
}
[PlugMethod(PlugRequired = true)]
public static uint GetPointer(Object aVal) { return 0; }
[PlugMethod(PlugRequired = true)]
public static uint GetEntryPoint() { return 0; }
}
}

View file

@ -0,0 +1,27 @@
using IL2CPU.API.Attribs;
namespace Cosmos.Core.Processing
{
public unsafe class Mutex
{
public int gate;
[PlugMethod(PlugRequired = true)]
public static void MutexLock(int* mtx) { }
public void Lock()
{
while (gate != 0) { }
gate = 1;
/*fixed (int* p = &gate)
{
MutexLock(p);
}*/
}
public void Unlock()
{
gate = 0;
}
}
}

View file

@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Cosmos.Core.Processing
{
public static unsafe class ProcessContext
{
public enum Thread_State
{
ALIVE = 0,
DEAD = 1,
WAITING_SLEEP = 2,
PAUSED = 3
}
public enum Context_Type
{
THREAD = 0,
PROCESS = 1
}
public class Context
{
public Context next;
public Context_Type type;
public uint tid;
public string name;
public uint esp;
public uint stacktop;
public System.Threading.ThreadStart entry;
public System.Threading.ParameterizedThreadStart paramentry;
public Thread_State state;
public object param;
public int arg;
public uint priority;
public uint age;
public uint parent;
}
public const uint STACK_SIZE = 4096;
public static uint m_NextCID;
public static Context m_CurrentContext;
public static Context m_ContextList;
public static Context GetContext(uint tid)
{
/*for(int i = 0; i < m_ContextList.Count; i++)
{
if(m_ContextList[i].tid == tid)
{
return m_ContextList[i];
}
}*/
Context ctx = m_ContextList;
while (ctx.next != null)
{
if (ctx.tid == tid)
{
return ctx;
}
ctx = ctx.next;
}
if (ctx.tid == tid)
{
return ctx;
}
return null;
}
public static uint* SetupStack(uint* stack)
{
uint origin = (uint)stack;
*--stack = 0xFFFFFFFF; // trash
*--stack = 0xFFFFFFFF; // trash
*--stack = 0xFFFFFFFF; // trash
*--stack = 0xFFFFFFFF; // trash
*--stack = 0x10; // ss ?
*--stack = 0x00000202; // eflags
*--stack = 0x8; // cs
*--stack = ObjUtilities.GetEntryPoint(); // eip
*--stack = 0; // error
*--stack = 0; // int
*--stack = 0; // eax
*--stack = 0; // ebx
*--stack = 0; // ecx
*--stack = 0; // offset
*--stack = 0; // edx
*--stack = 0; // esi
*--stack = 0; // edi
*--stack = origin; //ebp
*--stack = 0x10; // ds
*--stack = 0x10; // fs
*--stack = 0x10; // es
*--stack = 0x10; // gs
return stack;
}
public static uint StartContext(string name, System.Threading.ThreadStart entry, Context_Type type)
{
Context context = new Context();
context.type = type;
context.tid = m_NextCID++;
context.name = name;
context.stacktop = GCImplementation.AllocNewObject(4096);
context.esp = (uint)SetupStack((uint*)(context.stacktop + 4000));
context.state = Thread_State.PAUSED;
context.entry = entry;
if (type == Context_Type.PROCESS)
{
context.parent = 0;
}
else
{
context.parent = m_CurrentContext.tid;
}
Context ctx = m_ContextList;
while (ctx.next != null)
{
ctx = ctx.next;
}
ctx.next = context;
return context.tid;
}
public static uint StartContext(string name, System.Threading.ParameterizedThreadStart entry, Context_Type type, object param)
{
Context context = new Context();
context.type = type;
context.tid = m_NextCID++;
context.name = name;
context.stacktop = GCImplementation.AllocNewObject(4096);
context.esp = (uint)SetupStack((uint*)(context.stacktop + 4000));
context.state = Thread_State.ALIVE;
context.paramentry = entry;
context.param = param;
if (type == Context_Type.PROCESS)
{
context.parent = 0;
}
else
{
context.parent = m_CurrentContext.tid;
}
Context ctx = m_ContextList;
while (ctx.next != null)
{
ctx = ctx.next;
}
ctx.next = context;
return context.tid;
}
}
}

View file

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Text;
using IL2CPU.API.Attribs;
namespace Cosmos.Core.Processing
{
public static unsafe class ProcessorScheduler
{
public static void Initialize()
{
var context = new ProcessContext.Context();
context.type = ProcessContext.Context_Type.PROCESS;
context.tid = ProcessContext.m_NextCID++;
context.name = "Boot";
context.esp = 0;
context.stacktop = 0;
context.state = ProcessContext.Thread_State.ALIVE;
context.arg = 0;
context.priority = 0;
context.age = 0;
context.parent = 0;
ProcessContext.m_ContextList = context;
ProcessContext.m_CurrentContext = context;
IOPort counter0 = new IOPort(0x40);
IOPort cmd = new IOPort(0x43);
int divisor = 1193182 / 25;
cmd.Byte = (0x06 | 0x30);
counter0.Byte = (byte)divisor;
counter0.Byte = (byte)(divisor >> 8);
IOPort pA1 = new IOPort(0xA1);
IOPort p21 = new IOPort(0xA1);
pA1.Byte = 0x00;
p21.Byte = 0x00;
}
public static void EntryPoint()
{
ProcessContext.m_CurrentContext.entry?.Invoke();
ProcessContext.m_CurrentContext.paramentry?.Invoke(ProcessContext.m_CurrentContext.param);
ProcessContext.m_CurrentContext.state = ProcessContext.Thread_State.DEAD;
while (true) { } // remove from thread pool later
}
public static int interruptCount;
public static void SwitchTask()
{
interruptCount++;
if (ProcessContext.m_CurrentContext != null)
{
ProcessContext.Context ctx = ProcessContext.m_ContextList;
ProcessContext.Context last = ctx;
while (ctx != null)
{
if (ctx.state == ProcessContext.Thread_State.DEAD)
{
last.next = ctx.next;
break;
}
last = ctx;
ctx = ctx.next;
}
ctx = ProcessContext.m_ContextList;
while (ctx != null)
{
if (ctx.state == ProcessContext.Thread_State.WAITING_SLEEP)
{
ctx.arg -= 1000 / 25;
if (ctx.arg <= 0)
{
ctx.state = ProcessContext.Thread_State.ALIVE;
}
}
ctx.age++;
ctx = ctx.next;
}
ProcessContext.m_CurrentContext.esp = INTs.mStackContext;
tryagain:;
if (ProcessContext.m_CurrentContext.next != null)
{
ProcessContext.m_CurrentContext = ProcessContext.m_CurrentContext.next;
}
else
{
ProcessContext.m_CurrentContext = ProcessContext.m_ContextList;
}
if (ProcessContext.m_CurrentContext.state != ProcessContext.Thread_State.ALIVE)
{
goto tryagain;
}
ProcessContext.m_CurrentContext.age = ProcessContext.m_CurrentContext.priority;
INTs.mStackContext = ProcessContext.m_CurrentContext.esp;
}
Global.PIC.EoiMaster();
Global.PIC.EoiSlave();
}
}
}

View file

@ -13,7 +13,7 @@ namespace Cosmos.Core_Asm
{
public class CPUUpdateIDTAsm : AssemblerMethod
{
private static MethodBase GetMethodDef(Assembly aAssembly, string aType, string aMethodName, bool aErrorWhenNotFound)
public static MethodBase GetMethodDef(Assembly aAssembly, string aType, string aMethodName, bool aErrorWhenNotFound)
{
Type xType = aAssembly.GetType(aType, false);
if (xType != null)
@ -79,36 +79,71 @@ namespace Cosmos.Core_Asm
XS.Push(0);
}
XS.Push((uint)j);
XS.PushAllRegisters();
XS.Sub(ESP, 4);
XS.Set(EAX, ESP); // preserve old stack address for passing to interrupt handler
// store floating point data
XS.And(ESP, 0xfffffff0); // fxsave needs to be 16-byte alligned
XS.Sub(ESP, 512); // fxsave needs 512 bytes
XS.SSE.FXSave(ESP, isIndirect: true); // save the registers
XS.Set(EAX, ESP, destinationIsIndirect: true);
XS.Push(EAX); //
XS.Push(EAX); // pass old stack address (pointer to InterruptContext struct) to the interrupt handler
XS.JumpToSegment(8, "__ISR_Handler_" + j.ToString("X2") + "_SetCS");
XS.Label("__ISR_Handler_" + j.ToString("X2") + "_SetCS");
MethodBase xHandler = GetInterruptHandler((byte)j);
if (xHandler == null)
if (j != 0x20)
{
xHandler = GetMethodDef(typeof(Cosmos.Core.INTs).Assembly, typeof(Cosmos.Core.INTs).FullName, "HandleInterrupt_Default", true);
XS.PushAllRegisters();
XS.Sub(ESP, 4);
XS.Set(EAX, ESP); // preserve old stack address for passing to interrupt handler
// store floating point data
XS.And(ESP, 0xfffffff0); // fxsave needs to be 16-byte alligned
XS.Sub(ESP, 512); // fxsave needs 512 bytes
XS.SSE.FXSave(ESP, isIndirect: true); // save the registers
XS.Set(EAX, ESP, destinationIsIndirect: true);
XS.Push(EAX); //
XS.Push(EAX); // pass old stack address (pointer to InterruptContext struct) to the interrupt handler
XS.JumpToSegment(8, "__ISR_Handler_" + j.ToString("X2") + "_SetCS");
XS.Label("__ISR_Handler_" + j.ToString("X2") + "_SetCS");
MethodBase xHandler = GetInterruptHandler((byte)j);
if (xHandler == null)
{
xHandler = GetMethodDef(typeof(Cosmos.Core.INTs).Assembly, typeof(Cosmos.Core.INTs).FullName, "HandleInterrupt_Default", true);
}
XS.Call(LabelName.Get(xHandler));
XS.Pop(EAX);
XS.SSE.FXRestore(ESP, isIndirect: true);
XS.Set(ESP, EAX); // this restores the stack for the FX stuff, except the pointer to the FX data
XS.Add(ESP, 4); // "pop" the pointer
XS.PopAllRegisters();
}
XS.Call(LabelName.Get(xHandler));
XS.Pop(EAX);
XS.SSE.FXRestore(ESP, isIndirect: true);
XS.Set(ESP, EAX); // this restores the stack for the FX stuff, except the pointer to the FX data
XS.Add(ESP, 4); // "pop" the pointer
XS.PopAllRegisters();
else
{
new LiteralAssemblerCode("pushad");
new LiteralAssemblerCode("mov eax, ds");
new LiteralAssemblerCode("push eax");
new LiteralAssemblerCode("mov eax, es");
new LiteralAssemblerCode("push eax");
new LiteralAssemblerCode("mov eax, fs");
new LiteralAssemblerCode("push eax");
new LiteralAssemblerCode("mov eax, gs");
new LiteralAssemblerCode("push eax");
new LiteralAssemblerCode("mov ax, 0x10");
new LiteralAssemblerCode("mov ds, ax");
new LiteralAssemblerCode("mov es, ax");
new LiteralAssemblerCode("mov fs, ax");
new LiteralAssemblerCode("mov gs, ax");
new LiteralAssemblerCode("mov eax, esp");
XS.Set("static_field__Cosmos_Core_INTs_mStackContext", EAX, destinationIsIndirect: true);
XS.Call(LabelName.Get(GetMethodDef(typeof(Cosmos.Core.Processing.ProcessorScheduler).Assembly, typeof(Cosmos.Core.Processing.ProcessorScheduler).FullName, "SwitchTask", true)));
XS.Set(EAX, "static_field__Cosmos_Core_INTs_mStackContext", sourceIsIndirect: true);
new LiteralAssemblerCode("mov esp, eax");
new LiteralAssemblerCode("pop eax");
new LiteralAssemblerCode("mov gs, eax");
new LiteralAssemblerCode("pop eax");
new LiteralAssemblerCode("mov fs, eax");
new LiteralAssemblerCode("pop eax");
new LiteralAssemblerCode("mov es, eax");
new LiteralAssemblerCode("pop eax");
new LiteralAssemblerCode("mov ds, eax");
new LiteralAssemblerCode("popad");
}
XS.Add(ESP, 8);
XS.Label("__ISR_Handler_" + j.ToString("X2") + "_END");
XS.InterruptReturn();

View file

@ -4,7 +4,7 @@ using IL2CPU.API.Attribs;
namespace Cosmos.Core_Asm
{
[Plug(Target = typeof(Delegate), Inheritable = true)]
public static class DelegateImpl
public static unsafe class DelegateImpl
{
[PlugMethod(Assembler = typeof(DelegateCtorAsm), IsWildcard = true, WildcardMatchParameters = true)]
public static void Ctor(Delegate aThis, object aTarget, IntPtr aMethod)
@ -28,5 +28,10 @@ namespace Cosmos.Core_Asm
{
throw new NotImplementedException();
}
public static int GetHashCode(Delegate aThis, [FieldAccess(Name = "System.IntPtr System.Delegate._methodPtr")] ref IntPtr aAddress)
{
return (int)aAddress.ToPointer();
}
}
}

View file

@ -0,0 +1,36 @@
using Cosmos.Core.Processing;
using IL2CPU.API.Attribs;
using XSharp;
using XSharp.Assembler;
namespace Cosmos.Core_Asm
{
[Plug(Target = typeof(Mutex))]
public static unsafe class MutexImpl
{
[PlugMethod(Assembler = typeof(MutexLockASM))]
public static void MutexLock(int* mtx) { }
}
public class MutexLockASM : AssemblerMethod
{
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
{
new LiteralAssemblerCode("lock_asm:");
new LiteralAssemblerCode("mov eax, [esp + 8]");
new LiteralAssemblerCode("mov ebx, 0");
new LiteralAssemblerCode("lock bts[eax], ebx");
new LiteralAssemblerCode("jc.spin_wait");
new LiteralAssemblerCode("mov ebx, 1");
new LiteralAssemblerCode("mov dword[eax], ebx");
new LiteralAssemblerCode("jmp .finished");
new LiteralAssemblerCode(".spin_wait:");
new LiteralAssemblerCode("mov ebx, 1");
new LiteralAssemblerCode("test dword[eax], ebx");
new LiteralAssemblerCode("pause");
new LiteralAssemblerCode("jnz.spin_wait");
new LiteralAssemblerCode("jmp lock_asm");
new LiteralAssemblerCode(".finished");
}
}
}

View file

@ -0,0 +1,40 @@
using Cosmos.Core;
using IL2CPU.API;
using IL2CPU.API.Attribs;
using System;
using XSharp;
using XSharp.Assembler;
namespace Cosmos.Core_Asm
{
[Plug(Target = typeof(ObjUtilities))]
public static unsafe class ObjUtilitiesImpl
{
[PlugMethod(Assembler = typeof(ObjUtilitiesGetPointer))]
public static uint GetPointer(Delegate aVal) { return 0; }
[PlugMethod(Assembler = typeof(ObjUtilitiesGetPointer))]
public static uint GetPointer(Object aVal) { return 0; }
[PlugMethod(Assembler = typeof(ObjUtilitiesGetEntry))]
public static uint GetEntryPoint() { return 0; }
}
public class ObjUtilitiesGetPointer : AssemblerMethod
{
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
{
XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 0x8);
XS.Push(XSRegisters.EAX);
}
}
public class ObjUtilitiesGetEntry : AssemblerMethod
{
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
{
XS.Set(XSRegisters.EAX, LabelName.Get(CPUUpdateIDTAsm.GetMethodDef(typeof(Cosmos.Core.Processing.ProcessorScheduler).Assembly, typeof(Cosmos.Core.Processing.ProcessorScheduler).FullName, "EntryPoint", true)));
XS.Push(XSRegisters.EAX);
}
}
}

View file

@ -6,7 +6,7 @@ using IL2CPU.API.Attribs;
namespace Cosmos.Core_Plugs.System
{
[Plug(Target = typeof(Delegate))]
public static class DelegateImpl
public static unsafe class DelegateImpl
{
[PlugMethod(Signature = "System_Boolean__System_Delegate_Equals_System_Object_")]
public static bool Equals(Delegate aThis, object aThat)
@ -24,6 +24,11 @@ namespace Cosmos.Core_Plugs.System
return xTypeA == xTypeB;
}
public static int GetHashCode(Delegate aThis, [FieldAccess(Name = "System.IntPtr System.Delegate._methodPtr")] ref IntPtr aAddress)
{
return (int)aAddress.ToPointer();
}
}
[Plug(Target = typeof(Delegate), Inheritable = true)]

View file

@ -1,3 +1,4 @@
using System;
using System.Threading;
using IL2CPU.API.Attribs;
@ -16,6 +17,11 @@ namespace Cosmos.Core_Plugs.System.Threading
}
public static void Ctor(ThreadStart aThis, ThreadStart aEntry)
{
Console.WriteLine("Thread started");
}
// public static void SleepInternal(int ms)
// {
// // Implementation of http://referencesource.microsoft.com/#mscorlib/system/threading/thread.cs,6a577476abf2f437,references

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cosmos.Core;
using Cosmos.Debug.Kernel;
using Cosmos.HAL.BlockDevice;
@ -63,6 +63,10 @@ namespace Cosmos.HAL
AHCI.InitDriver();
//EHCI.InitDriver();
Console.WriteLine("Starting Processor Scheduler");
mDebugger.Send("Processor Scheduler");
Core.Processing.ProcessorScheduler.Initialize();
mDebugger.Send("Done initializing Cosmos.HAL.Global");
}
@ -80,6 +84,16 @@ namespace Cosmos.HAL
/// </summary>
public static bool InterruptsEnabled => CPU.mInterruptsEnabled;
public static uint SpawnThread(ThreadStart aStart)
{
return Core.Processing.ProcessContext.StartContext("", aStart, Core.Processing.ProcessContext.Context_Type.THREAD);
}
public static uint SpawnThread(ParameterizedThreadStart aStart, object param)
{
return Core.Processing.ProcessContext.StartContext("", aStart, Core.Processing.ProcessContext.Context_Type.THREAD, param);
}
/// <summary>
/// Get keyboard devices.
/// </summary>

View file

@ -0,0 +1,45 @@
using st = System.Threading;
namespace Cosmos.System
{
public class Thread
{
public uint ThreadID;
private Cosmos.Core.Processing.ProcessContext.Context Data;
public Thread(st.ThreadStart start)
{
ThreadID = Cosmos.HAL.Global.SpawnThread(start);
ThreadFinalSetup();
}
public Thread(st.ParameterizedThreadStart start, object param)
{
ThreadID = Cosmos.HAL.Global.SpawnThread(start, param);
ThreadFinalSetup();
}
private void ThreadFinalSetup()
{
Data = Cosmos.Core.Processing.ProcessContext.GetContext(ThreadID);
Data.state = Core.Processing.ProcessContext.Thread_State.PAUSED;
}
public void Start()
{
Data.state = Core.Processing.ProcessContext.Thread_State.ALIVE;
}
public void Stop()
{
Data.state = Core.Processing.ProcessContext.Thread_State.PAUSED;
}
public static void Sleep(int ms)
{
Cosmos.Core.Processing.ProcessContext.m_CurrentContext.arg = ms;
Cosmos.Core.Processing.ProcessContext.m_CurrentContext.state = Core.Processing.ProcessContext.Thread_State.WAITING_SLEEP;
while (Cosmos.Core.Processing.ProcessContext.m_CurrentContext.state == Core.Processing.ProcessContext.Thread_State.WAITING_SLEEP) { }
}
}
}