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) { }
+ }
+ }
+}