public static void SwitchProcess(uint processId, int threadId) { //Switch the current memory layout across. // Don't touch register state etc, just the memory layout bool dontSwitchOutIn = false; if (CurrentProcess != null && CurrentProcess.Id == processId) { if (CurrentThread != null && (CurrentThread.Id == threadId || threadId == THREAD_DONT_CARE)) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (1)"); #endif return; } else { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (2)"); #endif dontSwitchOutIn = true; } } if (!dontSwitchOutIn) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.Write("Switching out: "); BasicConsole.WriteLine(CurrentProcess.Name); #endif CurrentProcess.UnloadHeap(); CurrentProcess.UnloadMemLayout(); CurrentProcess = GetProcessById(processId); // Process not found if (CurrentProcess == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Process not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.Write("Switching in: "); BasicConsole.WriteLine(CurrentProcess.Name); #endif CurrentProcess.LoadMemLayout(); CurrentProcess.LoadHeap(); } CurrentThread = null; CurrentThread_State = null; if (threadId == THREAD_DONT_CARE) { if (CurrentProcess.Threads.Count > 0) { CurrentThread = (Thread)CurrentProcess.Threads[0]; } } else { CurrentThread = GetThreadById((uint)threadId, CurrentProcess); } // No threads in the process (?!) or process not found if (CurrentThread == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread found."); #endif CurrentThread_State = CurrentThread.State; #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread state updated."); #endif }
public Thread(Process AnOwner, ThreadStartMethod StartMethod, uint AnId, bool UserMode, FOS_System.String AName) { LastActiveState = ActiveStates.NotStarted; Owner = AnOwner; #if THREAD_TRACE BasicConsole.WriteLine("Constructing thread object..."); #endif //Init thread state #if THREAD_TRACE BasicConsole.WriteLine("Allocating state memory..."); #endif State = (ThreadState *)FOS_System.Heap.Alloc((uint)sizeof(ThreadState), "Thread : Thread() (1)"); // Init Id and EIP // Set EIP to the first instruction of the main method #if THREAD_TRACE BasicConsole.WriteLine("Setting thread info..."); #endif Id = AnId; Name = AName; State->StartEIP = (uint)Utilities.ObjectUtilities.GetHandle(StartMethod); // Allocate kernel memory for the kernel stack for this thread // Used when this thread is preempted or does a sys call. Stack is switched to // this thread-specific kernel stack #if THREAD_TRACE BasicConsole.WriteLine("Allocating kernel stack..."); #endif State->KernelStackTop = (byte *)FOS_System.Heap.Alloc(0x1000, 4) + 0xFFC; //4KiB, 4-byte aligned // Allocate free memory for the user stack for this thread // Used by this thread in normal execution #if THREAD_TRACE BasicConsole.WriteLine("Mapping thread stack page..."); #endif State->UserMode = UserMode; State->ThreadStackTop = (byte *)Hardware.VirtMemManager.MapFreePage( UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None : Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly) + 4092; //4 KiB, page-aligned // Set ESP to the top of the stack - 4 byte aligned, high address since x86 stack works // downwards #if THREAD_TRACE BasicConsole.WriteLine("Setting ESP..."); #endif State->ESP = (uint)State->ThreadStackTop; // TimeToRun and TimeToRunReload are set up in Scheduler.InitProcess which // is called when a process is registered. // Init SS // Stack Segment = User or Kernel space data segment selector offset // Kernel data segment selector offset (offset in GDT) = 0x10 (16) // User data segment selector offset (offset in GDT) = 0x23 (32|3) // User data segment selector must also be or'ed with 3 for User Privilege level #if THREAD_TRACE Console.Default.WriteLine(" > > > Setting SS..."); #endif State->SS = UserMode ? (ushort)0x23 : (ushort)0x10; // Init Started // Not started yet so set to false #if THREAD_TRACE Console.Default.WriteLine(" > > > Setting started..."); #endif State->Started = false; // Init Exception State State->ExState = (ExceptionState *)FOS_System.Heap.AllocZeroed((uint)sizeof(ExceptionState), "Thread : Thread() (2)"); }
/// <remarks> /// Specifying threadId=-1 accepts any thread from the specified process. /// No guarantees are made about the thread chosen. This is used when you /// mainly want to switch process context and don't care about the specific /// thread context e.g. during an interrupt. /// </remarks> public static void SwitchProcess(uint processId, int threadId) { //Switch the current memory layout across. // Don't touch register state etc, just the memory layout bool dontSwitchOutIn = false; if (CurrentProcess != null && CurrentProcess.Id == processId) { if (CurrentThread != null && (CurrentThread.Id == threadId || threadId == -1)) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (1)"); #endif return; } else { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (2)"); #endif dontSwitchOutIn = true; } } if (!dontSwitchOutIn) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Switching out: " + CurrentProcess.Name); #endif CurrentProcess.UnloadMemLayout(); CurrentProcess = null; for (int i = 0; i < Processes.Count; i++) { if (((Process)Processes[i]).Id == processId) { CurrentProcess = ((Process)Processes[i]); break; } } // Process not found if (CurrentProcess == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Process not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Process found. " + CurrentProcess.Name); #endif } CurrentThread = null; CurrentThread_State = null; if (threadId == -1) { if (CurrentProcess.Threads.Count > 0) { CurrentThread = (Thread)CurrentProcess.Threads[0]; } } else { for (int i = 0; i < CurrentProcess.Threads.Count; i++) { if (((Thread)CurrentProcess.Threads[i]).Id == threadId) { CurrentThread = (Thread)CurrentProcess.Threads[i]; break; } } } // No threads in the process (?!) or process not found if (CurrentThread == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread found."); #endif CurrentThread_State = CurrentThread.State; #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread state updated."); #endif if (!dontSwitchOutIn) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Switching in: " + CurrentProcess.Name); #endif CurrentProcess.LoadMemLayout(); } }
public Thread(Process AnOwner, ThreadStartMethod StartMethod, uint AnId, bool UserMode, FOS_System.String AName) { #if THREAD_TRACE BasicConsole.WriteLine("Constructing thread object..."); #endif LastActiveState = ActiveStates.NotStarted; Owner = AnOwner; //Init thread state #if THREAD_TRACE BasicConsole.WriteLine("Allocating state memory..."); #endif State = (ThreadState*)FOS_System.Heap.Alloc((uint)sizeof(ThreadState), "Thread : Thread() (1)"); // Init Id and EIP // Set EIP to the first instruction of the main method #if THREAD_TRACE BasicConsole.WriteLine("Setting thread info..."); #endif Id = AnId; Name = AName; State->StartEIP = (uint)Utilities.ObjectUtilities.GetHandle(StartMethod); // Allocate kernel memory for the kernel stack for this thread // Used when this thread is preempted or does a sys call. Stack is switched to // this thread-specific kernel stack #if THREAD_TRACE BasicConsole.WriteLine("Allocating kernel stack..."); #endif // TODO: Allocate using virt mem manager not the heap (see ThreadStackTop below) State->KernelStackTop = (byte*)FOS_System.Heap.Alloc(0x1000, 4) + 0xFFC; //4KiB, 4-byte aligned // Allocate free memory for the user stack for this thread // Used by this thread in normal execution #if THREAD_TRACE BasicConsole.WriteLine("Mapping thread stack page..."); #endif State->UserMode = UserMode; State->ThreadStackTop = (byte*)Hardware.VirtMemManager.MapFreePage( UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None : Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly) + 4092; //4 KiB, page-aligned // Set ESP to the top of the stack - 4 byte aligned, high address since x86 stack works // downwards #if THREAD_TRACE BasicConsole.WriteLine("Setting ESP..."); #endif State->ESP = (uint)State->ThreadStackTop; // TimeToRun and TimeToRunReload are set up in Scheduler.InitProcess which // is called when a process is registered. // Init SS // Stack Segment = User or Kernel space data segment selector offset // Kernel data segment selector offset (offset in GDT) = 0x10 (16) // User data segment selector offset (offset in GDT) = 0x23 (32|3) // User data segment selector must also be or'ed with 3 for User Privilege level #if THREAD_TRACE BasicConsole.WriteLine("Setting SS..."); #endif State->SS = UserMode ? (ushort)0x23 : (ushort)0x10; // Init Started // Not started yet so set to false #if THREAD_TRACE BasicConsole.WriteLine("Setting started..."); #endif State->Started = false; #if THREAD_TRACE BasicConsole.WriteLine("Allocating exception state..."); #endif //TODO: This is currently incorrectly allocated from the current process's heap instead of the heap of the owner process // Init Exception State State->ExState = (ExceptionState*)FOS_System.Heap.AllocZeroed((uint)sizeof(ExceptionState), "Thread : Thread() (2)"); #if THREAD_TRACE BasicConsole.WriteLine("Done."); #endif }