diff --git a/source/Cosmos.Core/Cosmos.Core.csproj b/source/Cosmos.Core/Cosmos.Core.csproj index c3261b546..61ec6f882 100644 --- a/source/Cosmos.Core/Cosmos.Core.csproj +++ b/source/Cosmos.Core/Cosmos.Core.csproj @@ -2,7 +2,7 @@ netstandard2.0 - True + true diff --git a/source/Cosmos.Core/INTs.cs b/source/Cosmos.Core/INTs.cs index 71cce306c..2643a8cad 100644 --- a/source/Cosmos.Core/INTs.cs +++ b/source/Cosmos.Core/INTs.cs @@ -87,7 +87,8 @@ namespace Cosmos.Core { } [StructLayout(LayoutKind.Explicit, Size = 80)] - public struct IRQContext { + public struct IRQContext + { [FieldOffset(0)] public unsafe MMXContext* MMXContext; @@ -138,6 +139,8 @@ namespace Cosmos.Core { [AsmMarker(AsmMarker.Type.Int_LastKnownAddress)] private static uint mLastKnownAddress; + public static uint mStackContext; + private static IRQDelegate[] mIRQ_Handlers = new IRQDelegate[256]; // We used to use: @@ -494,6 +497,7 @@ namespace Cosmos.Core { if (xTest) { unsafe { + mStackContext = 0; var xCtx = new IRQContext(); HandleInterrupt_Default(ref xCtx); HandleInterrupt_00(ref xCtx); @@ -544,6 +548,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 13c55a4a2..c017e64ff 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 void DoInitialize(uint aEndOfRam) { mLastTableIndex = 0u; @@ -57,7 +60,10 @@ namespace Cosmos.Core.Memory.Old try { EnsureIsInitialized(); - + if(mMemeoryGate != null) + { + mMemeoryGate.Lock(); + } var xCurrentTableIdx = mLastTableIndex; DataLookupTable* xCurrentTable = GlobalSystemInfo.GlobalInformationTable->FirstDataLookupTable; DataLookupTable* xPreviousTable = null; @@ -75,6 +81,10 @@ namespace Cosmos.Core.Memory.Old { } } + if (mMemeoryGate != null) + { + mMemeoryGate.Unlock(); + } return xResult; } xCurrentTableIdx++; @@ -112,6 +122,10 @@ namespace Cosmos.Core.Memory.Old } mLastTableIndex = xCurrentTableIdx; mLastEntryIndex = 0; + if (mMemeoryGate != null) + { + mMemeoryGate.Unlock(); + } return xResult; } finally @@ -124,6 +138,10 @@ namespace Cosmos.Core.Memory.Old { //mDebugger.Trace(" 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..1fc909a5f --- /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..f85a65f7d --- /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..b39cdad31 --- /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..c13c820af 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) @@ -73,41 +73,76 @@ namespace Cosmos.Core_Asm { XS.Label("__ISR_Handler_" + j.ToString("X2")); XS.Call("__INTERRUPT_OCCURRED__"); - if (Array.IndexOf(xInterruptsWithParam, j) == -1) { 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(); + } + 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.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.Add(ESP, 8); XS.Label("__ISR_Handler_" + j.ToString("X2") + "_END"); 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..9f36204fb --- /dev/null +++ b/source/Cosmos.Core_Asm/ObjUtilitiesImpl.cs @@ -0,0 +1,39 @@ +using Cosmos.Core; +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 48d81902a..08ec401da 100644 --- a/source/Cosmos.Core_Plugs/System/DelegateImpl.cs +++ b/source/Cosmos.Core_Plugs/System/DelegateImpl.cs @@ -8,7 +8,7 @@ namespace Cosmos.Core_Plugs.System [Plug(Target = typeof(Delegate), Inheritable = true)] [PlugField(FieldType = typeof(int), FieldId = "$$ArgSize$$")] [PlugField(FieldType = typeof(int), FieldId = "$$ReturnsValue$$")] - public static class DelegateImpl + public static unsafe class DelegateImpl { public static bool Equals(Delegate aThis, object aThat) { @@ -38,5 +38,10 @@ namespace Cosmos.Core_Plugs.System } return xResultAddr; } + + 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_Plugs/System/Threading/ThreadImpl.cs b/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs index 3aa0ec06d..bc89a40e9 100644 --- a/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs +++ b/source/Cosmos.Core_Plugs/System/Threading/ThreadImpl.cs @@ -1,5 +1,6 @@ using System.Threading; using IL2CPU.API.Attribs; +using Console = System.Console; namespace Cosmos.Core_Plugs.System.Threading { @@ -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 b4436ef5c..fd6df7719 100644 --- a/source/Cosmos.HAL2/Global.cs +++ b/source/Cosmos.HAL2/Global.cs @@ -1,21 +1,41 @@ using System; +using System.Threading; using System.Collections.Generic; - using Cosmos.Core; using Cosmos.Debug.Kernel; using Cosmos.HAL.BlockDevice; namespace Cosmos.HAL { - public static class Global + public static class Global + { + public static readonly Debugger mDebugger = new Debugger("HAL", "Global"); + + static public PIT PIT = new PIT(); + // Must be static init, other static inits rely on it not being null + + public static TextScreenBase TextScreen = new TextScreen(); + public static PCI Pci; + + static public void Init(TextScreenBase textScreen) { - public static readonly Debugger mDebugger = new Debugger("HAL", "Global"); + if (textScreen != null) + { + TextScreen = textScreen; + } - static public PIT PIT = new PIT(); - // Must be static init, other static inits rely on it not being null + mDebugger.Send("Before Core.Global.Init"); + Core.Global.Init(); - public static TextScreenBase TextScreen = new TextScreen(); - public static PCI Pci; + //TODO Redo this - Global init should be other. + // Move PCI detection to hardware? Or leave it in core? Is Core PC specific, or deeper? + // If we let hardware do it, we need to protect it from being used by System. + // Probably belongs in hardware, and core is more specific stuff like CPU, memory, etc. + //Core.PCI.OnPCIDeviceFound = PCIDeviceFound; + + //TODO: Since this is FCL, its "common". Otherwise it should be + // system level and not accessible from Core. Need to think about this + // for the future. public static PS2Controller PS2Controller = new PS2Controller(); @@ -26,22 +46,25 @@ namespace Cosmos.HAL TextScreen = textScreen; } - mDebugger.Send("Before Core.Global.Init"); - Core.Global.Init(); + Console.WriteLine("Finding PCI Devices"); + mDebugger.Send("PCI Devices"); + PCI.Setup(); - //TODO Redo this - Global init should be other. - // Move PCI detection to hardware? Or leave it in core? Is Core PC specific, or deeper? - // If we let hardware do it, we need to protect it from being used by System. - // Probably belongs in hardware, and core is more specific stuff like CPU, memory, etc. - //Core.PCI.OnPCIDeviceFound = PCIDeviceFound; + Console.WriteLine("Starting ACPI"); + mDebugger.Send("ACPI Init"); + ACPI.Start(); + + Console.WriteLine("Finding ATA Devices"); + mDebugger.Send("ATA Devices"); + IDE.InitDriver(); + AHCI.InitDriver(); + //EHCI.InitDriver(); - //TODO: Since this is FCL, its "common". Otherwise it should be - // system level and not accessible from Core. Need to think about this - // for the future. + Console.WriteLine("Starting Processor Scheduler"); + mDebugger.Send("Processor Scheduler"); + Core.Processing.ProcessorScheduler.Initialize(); - Console.WriteLine("Finding PCI Devices"); - mDebugger.Send("PCI Devices"); - PCI.Setup(); + mDebugger.Send("Done initializing Cosmos.HAL.Global"); Console.WriteLine("Starting ACPI"); mDebugger.Send("ACPI Init"); @@ -57,14 +80,22 @@ namespace Cosmos.HAL AHCI.InitDriver(); //EHCI.InitDriver(); - mDebugger.Send("Done initializing Cosmos.HAL.Global"); + public static void EnableInterrupts() + { + CPU.EnableInterrupts(); + } - } + public static bool InterruptsEnabled => CPU.mInterruptsEnabled; - public static void EnableInterrupts() - { - CPU.EnableInterrupts(); - } + 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); public static bool InterruptsEnabled => CPU.mInterruptsEnabled; @@ -102,4 +133,5 @@ namespace Cosmos.HAL return xMouseDevices; } } + } } diff --git a/source/Cosmos.System2/Thread.cs b/source/Cosmos.System2/Thread.cs new file mode 100644 index 000000000..f3f62d026 --- /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) { } + } + } +}