From 6bef4e1fa0cebfa94cdad6b734a0c23d2c0da5af Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Sun, 27 Dec 2020 19:31:58 +0100 Subject: [PATCH] Add changes from @Og-Rok --- source/Cosmos.Core/INTs.cs | 4 + source/Cosmos.Core/Memory/Old/Old_Heap.cs | 23 +++ source/Cosmos.Core/ObjUtilities.cs | 19 +++ source/Cosmos.Core/Processing/Mutex.cs | 27 +++ .../Cosmos.Core/Processing/ProcessContext.cs | 154 ++++++++++++++++++ .../Processing/ProcessorScheduler.cs | 102 ++++++++++++ source/Cosmos.Core_Asm/CPU/CPUUpdateIDTAsm.cs | 91 +++++++---- source/Cosmos.Core_Asm/DelegateImpl.cs | 7 +- source/Cosmos.Core_Asm/MutexImpl.cs | 36 ++++ source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs | 40 +++++ .../Cosmos.Core_Plugs/System/DelegateImpl.cs | 7 +- .../System/Threading/ThreadImpl.cs | 6 + source/Cosmos.HAL2/Global.cs | 16 +- source/Cosmos.System2/Thread.cs | 45 +++++ 14 files changed, 546 insertions(+), 31 deletions(-) create mode 100644 source/Cosmos.Core/ObjUtilities.cs create mode 100644 source/Cosmos.Core/Processing/Mutex.cs create mode 100644 source/Cosmos.Core/Processing/ProcessContext.cs create mode 100644 source/Cosmos.Core/Processing/ProcessorScheduler.cs create mode 100644 source/Cosmos.Core_Asm/MutexImpl.cs create mode 100644 source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs create mode 100644 source/Cosmos.System2/Thread.cs diff --git a/source/Cosmos.Core/INTs.cs b/source/Cosmos.Core/INTs.cs index 38d26cd87..3bcd1585a 100644 --- a/source/Cosmos.Core/INTs.cs +++ b/source/Cosmos.Core/INTs.cs @@ -234,6 +234,8 @@ namespace Cosmos.Core { [AsmMarker(AsmMarker.Type.Int_LastKnownAddress)] private static uint mLastKnownAddress; + public static uint mStackContext; + /// /// IRQ handlers. /// @@ -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(); } } } diff --git a/source/Cosmos.Core/Memory/Old/Old_Heap.cs b/source/Cosmos.Core/Memory/Old/Old_Heap.cs index c89fbd7eb..11bca292c 100644 --- a/source/Cosmos.Core/Memory/Old/Old_Heap.cs +++ b/source/Cosmos.Core/Memory/Old/Old_Heap.cs @@ -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(); + } } } diff --git a/source/Cosmos.Core/ObjUtilities.cs b/source/Cosmos.Core/ObjUtilities.cs new file mode 100644 index 000000000..0de530713 --- /dev/null +++ b/source/Cosmos.Core/ObjUtilities.cs @@ -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; } + } +} diff --git a/source/Cosmos.Core/Processing/Mutex.cs b/source/Cosmos.Core/Processing/Mutex.cs new file mode 100644 index 000000000..6cf4a5178 --- /dev/null +++ b/source/Cosmos.Core/Processing/Mutex.cs @@ -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; + } + } +} diff --git a/source/Cosmos.Core/Processing/ProcessContext.cs b/source/Cosmos.Core/Processing/ProcessContext.cs new file mode 100644 index 000000000..4259f3701 --- /dev/null +++ b/source/Cosmos.Core/Processing/ProcessContext.cs @@ -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; + } + } +} diff --git a/source/Cosmos.Core/Processing/ProcessorScheduler.cs b/source/Cosmos.Core/Processing/ProcessorScheduler.cs new file mode 100644 index 000000000..54ebde7e7 --- /dev/null +++ b/source/Cosmos.Core/Processing/ProcessorScheduler.cs @@ -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(); + } + } +} diff --git a/source/Cosmos.Core_Asm/CPU/CPUUpdateIDTAsm.cs b/source/Cosmos.Core_Asm/CPU/CPUUpdateIDTAsm.cs index 2fa715b9a..b8e3fad5c 100644 --- a/source/Cosmos.Core_Asm/CPU/CPUUpdateIDTAsm.cs +++ b/source/Cosmos.Core_Asm/CPU/CPUUpdateIDTAsm.cs @@ -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(); diff --git a/source/Cosmos.Core_Asm/DelegateImpl.cs b/source/Cosmos.Core_Asm/DelegateImpl.cs index 627cb0b53..2db320525 100644 --- a/source/Cosmos.Core_Asm/DelegateImpl.cs +++ b/source/Cosmos.Core_Asm/DelegateImpl.cs @@ -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(); + } } } diff --git a/source/Cosmos.Core_Asm/MutexImpl.cs b/source/Cosmos.Core_Asm/MutexImpl.cs new file mode 100644 index 000000000..1fb7a23fe --- /dev/null +++ b/source/Cosmos.Core_Asm/MutexImpl.cs @@ -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"); + } + } +} diff --git a/source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs b/source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs new file mode 100644 index 000000000..f757352cd --- /dev/null +++ b/source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs @@ -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); + } + } +} diff --git a/source/Cosmos.Core_Plugs/System/DelegateImpl.cs b/source/Cosmos.Core_Plugs/System/DelegateImpl.cs index 0bc8d281f..343424d8a 100644 --- a/source/Cosmos.Core_Plugs/System/DelegateImpl.cs +++ b/source/Cosmos.Core_Plugs/System/DelegateImpl.cs @@ -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)] diff --git a/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs b/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs index 9c28ca3ef..2c62d7a32 100644 --- a/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs +++ b/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs @@ -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 diff --git a/source/Cosmos.HAL2/Global.cs b/source/Cosmos.HAL2/Global.cs index 540fc81bc..0354e57dc 100644 --- a/source/Cosmos.HAL2/Global.cs +++ b/source/Cosmos.HAL2/Global.cs @@ -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 /// 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); + } + /// /// Get keyboard devices. /// diff --git a/source/Cosmos.System2/Thread.cs b/source/Cosmos.System2/Thread.cs new file mode 100644 index 000000000..16d9607ec --- /dev/null +++ b/source/Cosmos.System2/Thread.cs @@ -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) { } + } + } +}