-
Notifications
You must be signed in to change notification settings - Fork 552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Multithreading #1610
base: master
Are you sure you want to change the base?
Implement Multithreading #1610
Changes from 1 commit
6bef4e1
63b4fcc
e9e32aa
f2716cf
7f1d9f7
d7f5026
c3540b0
72c6861
727a090
30a1b98
aeacb31
52e5308
0b263d9
e48cda5
ca9bf96
68dc3e0
0c5fdfd
66fe85b
d36bfd4
ebe5302
7eec507
8ae051b
5eb0fe7
fd497d1
78f9e08
72c1436
af2a785
485c468
106ec6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) { } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should yield here so we dont waste as much cpu time |
||
gate = 1; | ||
/*fixed (int* p = &gate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the commented code be removed? |
||
{ | ||
MutexLock(p); | ||
}*/ | ||
} | ||
|
||
public void Unlock() | ||
{ | ||
gate = 0; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. idk, but 4096 bytes seems too small. maybe 16KiB? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kernel's stack is 320kib and thread's is 4kib. we need to extend stack |
||
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; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Find a way to use another port or something else than Pit (APIC timer?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe use PIT implemented in Cosmos, not IOPort PIT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AsertCreator they are one in the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe you can implement the nanosecond time in RTC, and use RTC to approximate? or maybe (pure speculation, as a junior dev who knows nothing about low level) reimplement PIT wait to tally up the number of times IRQ 0 has been triggered since the os was powered on, and use this to wait x amount of time. in the case of the second option, it would be possible to implement a system where multiple things can use PIT wait at the same time. see osdev wiki. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RTC is too slow for scheduling and idk if we could make interrupts with that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact RTC may not be a bad idea until we have HPET or local APIC timers, it indeed can generate IRQs. I'll try, I hope this won't mess up date time There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I can get no more than 60Hz but it's possible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that function as a stopgap until APIC gets finished? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh. I just looked at the commit and it appears y'all got the APIC timer working. Ok then. |
||
|
||
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(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have
Cosmos/source/Cosmos.Core/GCImplementation.cs
Line 108 in f7fd569
If you need a uint we also have
Cosmos/source/Cosmos.Core/GCImplementation.cs
Line 115 in f7fd569