public static int SyscallHandler(uint syscallNumber, uint param1, uint param2, uint param3, ref uint Return2, ref uint Return3, ref uint Return4, uint callerProcesId, uint callerThreadId) { SystemCallResults result = SystemCallResults.Unhandled; switch ((SystemCallNumbers)syscallNumber) { case SystemCallNumbers.RegisterPipeOutpoint: BasicConsole.WriteLine("WM > IH > Actioning Register Pipe Outpoint system call..."); Pipes.PipeClasses Class = (Pipes.PipeClasses)param1; Pipes.PipeSubclasses Subclass = (Pipes.PipeSubclasses)param2; if (Class == Pipes.PipeClasses.Standard && Subclass == Pipes.PipeSubclasses.Standard_Out) { BasicConsole.WriteLine("WM > IH > Register Pipe Outpoint has desired pipe class and subclass."); result = SystemCallResults.RequestAction_WakeThread; Return2 = InputProcessingThreadId; InputProcessingThreadAwake = true; } break; } return((int)result); }
public static int SyscallHandler(uint syscallNumber, uint param1, uint param2, uint param3, ref uint Return2, ref uint Return3, ref uint Return4, uint callerProcessId, uint callerThreadId) { SystemCallResults result = HandleSystemCallForKernel(syscallNumber, param1, param2, param3, ref Return2, ref Return3, ref Return4, callerProcessId, callerThreadId); if (result == SystemCallResults.Deferred || result == SystemCallResults.Deferred_PermitActions) { //BasicConsole.WriteLine("Deferring syscall..."); //BasicConsole.WriteLine("Popping unqueued info object..."); DeferredSyscallInfo info = (DeferredSyscallInfo)DeferredSyscallsInfo_Unqueued.Pop(); //BasicConsole.WriteLine("Setting info..."); info.ProcessId = callerProcessId; info.ThreadId = callerThreadId; //BasicConsole.WriteLine("Queuing info object..."); DeferredSyscallsInfo_Queued.Push(info); //BasicConsole.WriteLine("Waking deferred syscalls thread..."); DeferredSyscallsThread._Wake(); } return((int)result); }
/// <summary> /// Waits for a pipe to connect to the outpoint. /// </summary> /// <returns>The Id of the newly connected pipe.</returns> public int WaitForConnect() { int aPipeId; SystemCallResults SysCallResult = SystemCalls.WaitOnPipeCreate(Class, Subclass, out aPipeId); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicOutPipe > WaitOnPipeCreate: Unhandled!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Wait On Pipe Create unhandled!")); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicOutPipe > WaitOnPipeCreate: Failed!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Wait On Pipe Create failed!")); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicOutPipe > WaitOnPipeCreate: Succeeded."); //BasicConsole.Write("BasicOutPipe > New pipe id: "); //BasicConsole.WriteLine(aPipeId); break; default: //BasicConsole.WriteLine("BasicOutPipe > WaitOnPipeCreate: Unexpected system call result!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Wait On Pipe Create unexpected result!")); break; } return(aPipeId); }
/// <summary> /// Creates and registers a new outpoint of the specified class and subclass. /// </summary> /// <param name="aClass">The class of pipe allowed to connect to the outpoint.</param> /// <param name="aSubclass">The subclass of pipe allowed to connect to the outpoint.</param> /// <param name="MaxConnections"> /// The maximum number of connections allowed. Use <see cref="PipeConstants.UnlimitedConnections"/> for unlimited connections. /// </param> public BasicOutpoint(PipeClasses aClass, PipeSubclasses aSubclass, int MaxConnections) { Class = aClass; Subclass = aSubclass; SystemCallResults SysCallResult = SystemCalls.RegisterPipeOutpoint(Class, Subclass, MaxConnections); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicOutPipe > RegisterPipeOutpoint: Unhandled!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Register Pipe Outpoint system call unhandled!")); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicOutPipe > RegisterPipeOutpoint: Failed!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Register Pipe Outpoint system call failed!")); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicOutPipe > RegisterPipeOutpoint: Succeeded."); break; default: //BasicConsole.WriteLine("BasicOutPipe > RegisterPipeOutpoint: Unexpected system call result!"); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicOutPipe : Register Pipe Outpoint system call unexpected result!")); break; } }
/// <summary> /// Reads up to the specified length of data into the specified buffer at the specified offset in the buffer. /// </summary> /// <param name="Data">The buffer to read into.</param> /// <param name="Offset">The offset in the buffer to write data to.</param> /// <param name="Length">The maximum length of data to read.</param> /// <param name="Blocking">Whether the read should be blocking or non-blocking.</param> /// <returns>The actual number of bytes read.</returns> public int Read(byte[] Data, int Offset, int Length, bool Blocking) { int BytesRead = 0; Pipes.ReadPipeRequest *ReadPipeRequestPtr = (Pipes.ReadPipeRequest *)Heap.AllocZeroed((uint)sizeof(Pipes.ReadPipeRequest), "BasicInPipe : Alloc ReadPipeRequest"); try { if (ReadPipeRequestPtr != null) { ReadPipeRequestPtr->PipeId = PipeId; ReadPipeRequestPtr->Offset = Offset; ReadPipeRequestPtr->Length = FOS_System.Math.Min(Data.Length - Offset, Length); ReadPipeRequestPtr->OutBuffer = (byte *)Utilities.ObjectUtilities.GetHandle(Data) + FOS_System.Array.FieldsBytesSize; ReadPipeRequestPtr->Blocking = Blocking; SystemCallResults SysCallResult = SystemCalls.ReadPipe(ReadPipeRequestPtr, out BytesRead); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicInPipe > ReadPipe: Unhandled!"); ExceptionMethods.Throw(new Exceptions.RWUnhandledException("BasicInPipe : Read Pipe unexpected unhandled!")); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicInPipe > ReadPipe: Failed!"); if (Blocking) { ExceptionMethods.Throw(new Exceptions.RWFailedException("BasicInPipe : Write Pipe unexpected failed! (Blocking call)")); } else { ExceptionMethods.Throw(new Exceptions.RWFailedException("BasicInPipe : Write Pipe failed. (Non-blocking call)")); } break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicInPipe > ReadPipe: Succeeded."); break; default: //BasicConsole.WriteLine("BasicInPipe > ReadPipe: Unexpected system call result!"); ExceptionMethods.Throw(new Exceptions.RWUnhandledException("BasicInPipe : Read Pipe unexpected result!")); break; } } else { ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicInPipe : Couldn't allocate memory to read from pipe!")); } } finally { if (ReadPipeRequestPtr != null) { Heap.Free(ReadPipeRequestPtr); } } return(BytesRead); }
/// <summary> /// Gets the number of available outpoints of the specified class and subclass. /// </summary> /// <param name="numOutpoints">Out : The number of outpoints (correct iff SysCallResult is OK).</param> /// <param name="SysCallResult">Out : The result of the system call. Check this is set to OK.</param> /// <param name="Class">The class of pipe to search for.</param> /// <param name="Subclass">The subclass of pipe to search for.</param> public static void GetNumPipeOutpoints(out int numOutpoints, out SystemCallResults SysCallResult, Pipes.PipeClasses Class, Pipes.PipeSubclasses Subclass) { SysCallResult = SystemCalls.GetNumPipeOutpoints(Class, Subclass, out numOutpoints); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicServerHelpers > GetNumPipeOutpoints: Unhandled!"); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicServerHelpers > GetNumPipeOutpoints: Failed!"); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicServerHelpers > GetNumPipeOutpoints: Succeeded."); //BasicConsole.Write("BasicServerHelpers > Num pipe outpoints: "); //BasicConsole.WriteLine(numOutpoints); break; default: //BasicConsole.WriteLine("BasicServerHelpers > GetNumPipeOutpoints: Unexpected system call result!"); break; } }
//private static Pipes.Standard.StandardInpoint StdIn; public static void Main() { BasicConsole.WriteLine("Device Manager started."); Hardware.Processes.ProcessManager.CurrentProcess.InitHeap(); SystemCallResults SysCallResult = SystemCalls.StartThread(GCCleanupTask.Main, out GCThreadId); if (SysCallResult != SystemCallResults.OK) { BasicConsole.WriteLine("Device Manager: GC thread failed to create!"); } try { StdOut = new Pipes.Standard.StandardOutpoint(true); int StdOutPipeId = StdOut.WaitForConnect(); //int numOutpoints; //Pipes.BasicOutpoint.GetNumPipeOutpoints(out numOutpoints, out SysCallResult, Pipes.PipeClasses.Standard, Pipes.PipeSubclasses.Standard_In); //if (SysCallResult == SystemCallResults.OK && numOutpoints > 0) //{ // Pipes.PipeOutpointDescriptor[] OutpointDescriptors; // Pipes.BasicOutpoint.GetOutpointDescriptors(numOutpoints, out SysCallResult, out OutpointDescriptors, Pipes.PipeClasses.Standard, Pipes.PipeSubclasses.Standard_In); // // if (SysCallResult == SystemCallResults.OK) // { // for (int i = 0; i < OutpointDescriptors.Length; i++) // { // Pipes.PipeOutpointDescriptor Descriptor = OutpointDescriptors[i]; // //TODO: Filter to target // StdIn = new Pipes.Standard.StandardInpoint(Descriptor.ProcessId, false); // } // } //} uint loops = 0; while (!Terminating) { try { //StdOut.Write(StdOutPipeId, "Hello, world! (" + (FOS_System.String)loops++ + ")\n", true); SystemCalls.SleepThread(-1); } catch { BasicConsole.WriteLine("DM > Error writing to StdOut!"); BasicConsole.WriteLine(ExceptionMethods.CurrentException.Message); } SystemCalls.SleepThread(1000); } } catch { BasicConsole.WriteLine("DM > Error initialising!"); BasicConsole.WriteLine(ExceptionMethods.CurrentException.Message); } }
public static void EndDeferredSystemCall(Thread CallerThread, SystemCallResults result, uint Return2, uint Return3, uint Return4) { CallerThread.Return1 = (uint)result; CallerThread.Return2 = Return2; CallerThread.Return3 = Return3; CallerThread.Return4 = Return4; CallerThread._Wake(); }
public static void DeferredSyscallsThread_Main() { while (!Terminating) { if (DeferredSyscallsInfo_Queued.Count == 0) { Thread.Sleep_Indefinitely(); } while (DeferredSyscallsInfo_Queued.Count > 0) { // Scheduler must be disabled during pop/push from circular buffer or we can // end up in an infinite lock. Consider what happens if a process invokes // a deferred system call during the pop/push here and at the end of this loop. //BasicConsole.WriteLine("DSC: Pausing scheduler..."); //Scheduler.Disable(); //BasicConsole.WriteLine("DSC: Popping queued info object..."); DeferredSyscallInfo info = (DeferredSyscallInfo)DeferredSyscallsInfo_Queued.Pop(); //BasicConsole.WriteLine("DSC: Resuming scheduler..."); //Scheduler.Enable(); //BasicConsole.WriteLine("DSC: Getting process & thread..."); Process CallerProcess = ProcessManager.GetProcessById(info.ProcessId); Thread CallerThread = ProcessManager.GetThreadById(info.ThreadId, CallerProcess); //BasicConsole.WriteLine("DSC: Getting data & calling..."); uint Return2 = CallerThread.Return2; uint Return3 = CallerThread.Return3; uint Return4 = CallerThread.Return4; SystemCallResults result = HandleDeferredSystemCall( CallerProcess, CallerThread, (SystemCallNumbers)CallerThread.SysCallNumber, CallerThread.Param1, CallerThread.Param2, CallerThread.Param3, ref Return2, ref Return3, ref Return4); //BasicConsole.WriteLine("DSC: Ending call..."); if (result != SystemCallResults.Deferred) { EndDeferredSystemCall(CallerThread, result, Return2, Return3, Return4); } //BasicConsole.WriteLine("DSC: Resetting info object..."); info.ProcessId = 0; info.ThreadId = 0; // See comment at top of loop for why this is necessary //BasicConsole.WriteLine("DSC: Pausing scheduler..."); //Scheduler.Disable(); //BasicConsole.WriteLine("DSC: Queuing info object..."); DeferredSyscallsInfo_Unqueued.Push(info); //BasicConsole.WriteLine("DSC: Resuming scheduler..."); //Scheduler.Enable(); } } }
/// <summary> /// Gets the outpoint desciptors of the available outpoints of the specified class and subclass. /// </summary> /// <param name="numOutpoints">The known number of available outpoints. Use GetNumPipeOutpoints to obtain this number.</param> /// <param name="SysCallResult">Out : The result of the system call. Check this is set to OK.</param> /// <param name="OutpointDescriptors">Out : The array of outpoint descriptors.</param> /// <param name="Class">The class of pipe to search for.</param> /// <param name="Subclass">The subclass of pipe to search for.</param> public static void GetOutpointDescriptors(int numOutpoints, out SystemCallResults SysCallResult, out Pipes.PipeOutpointDescriptor[] OutpointDescriptors, Pipes.PipeClasses Class, Pipes.PipeSubclasses Subclass) { OutpointDescriptors = new Pipes.PipeOutpointDescriptor[numOutpoints]; Pipes.PipeOutpointsRequest *RequestPtr = (Pipes.PipeOutpointsRequest *)Heap.AllocZeroed((uint)sizeof(Pipes.PipeOutpointsRequest), "BasicServerHelpers : Alloc PipeOutpointsRequest"); if (RequestPtr != null) { try { RequestPtr->MaxDescriptors = numOutpoints; RequestPtr->Outpoints = (Pipes.PipeOutpointDescriptor *)((byte *)Utilities.ObjectUtilities.GetHandle(OutpointDescriptors) + FOS_System.Array.FieldsBytesSize); if (RequestPtr->Outpoints != null) { SysCallResult = SystemCalls.GetPipeOutpoints(Class, Subclass, RequestPtr); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Unhandled!"); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Failed!"); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Succeeded."); break; default: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Unexpected system call result!"); break; } } else { SysCallResult = SystemCallResults.Fail; //BasicConsole.WriteLine("BasicServerHelpers > RequestPtr->Outpoints null! No memory allocated."); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicServerHelpers : Couldn't allocate memory outpoints list in outpoints request!")); } } finally { Heap.Free(RequestPtr); } } else { SysCallResult = SystemCallResults.Fail; //BasicConsole.WriteLine("BasicServerHelpers > RequestPtr null! No memory allocated."); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicServerHelpers : Couldn't allocate memory get outpoints request!")); } }
/// <summary> /// Creates and connects a new pipe to the specified target process. /// </summary> /// <param name="anOutProcessId">The target process to connect to.</param> /// <param name="aClass">The class of pipe to create.</param> /// <param name="aSubclass">The subclass of pipe to create.</param> /// <param name="aBufferSize">The size of buffer to use within the core OS.</param> public BasicInpoint(uint anOutProcessId, PipeClasses aClass, PipeSubclasses aSubclass, int aBufferSize) { OutProcessId = anOutProcessId; Class = aClass; Subclass = aSubclass; BufferSize = aBufferSize; Pipes.CreatePipeRequest *RequestPtr = (Pipes.CreatePipeRequest *)Heap.AllocZeroed((uint)sizeof(Pipes.CreatePipeRequest), "BasicInPipe : Alloc CreatePipeRequest"); if (RequestPtr != null) { try { RequestPtr->BufferSize = aBufferSize; RequestPtr->Class = aClass; RequestPtr->Subclass = aSubclass; SystemCallResults SysCallResult = SystemCalls.CreatePipe(anOutProcessId, RequestPtr); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicInPipe > CreatePipe: Unhandled!"); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicInPipe > CreatePipe: Failed!"); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicInPipe > CreatePipe: Succeeded."); PipeId = RequestPtr->Result.Id; //BasicConsole.Write("BasicInPipe > CreatePipe: New pipe id = "); //BasicConsole.WriteLine(PipeId); break; default: //BasicConsole.WriteLine("BasicInPipe > CreatePipe: Unexpected system call result!"); break; } } finally { Heap.Free(RequestPtr); } } else { ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicInPipe : Couldn't allocate memory to create pipe!")); //BasicConsole.WriteLine("BasicInPipe > RequestPtr null! No memory allocated."); } }
/// <summary> /// Main interrupt handler routine for system calls. /// </summary> /// <remarks> /// Prevents direct invocation of the Receive Message system call, since that's not allowed. /// </remarks> public static void InterruptHandler() { #if SYSCALLS_TRACE BasicConsole.WriteLine(); BasicConsole.WriteLine("----- Syscall -----"); BasicConsole.WriteLine(ProcessManager.CurrentProcess.Name); #endif Process currProcess = ProcessManager.CurrentProcess; Thread currThread = ProcessManager.CurrentThread; bool switched = false; #if SYSCALLS_TRACE BasicConsole.WriteLine("Getting param values..."); #endif uint syscallNumber = currThread.SysCallNumber; uint param1 = currThread.Param1; uint param2 = currThread.Param2; uint param3 = currThread.Param3; SystemCallResults result = SystemCallResults.Unhandled; uint Return2 = 0; uint Return3 = 0; uint Return4 = 0; if (syscallNumber != (uint)SystemCallNumbers.ReceiveMessage) { Process handlerProcess = null; #if SYSCALLS_TRACE BasicConsole.WriteLine("Enumerating processes..."); #endif bool PermitActionResulted = false; for (int i = 0; i < ProcessManager.Processes.Count; i++) { handlerProcess = (Process)ProcessManager.Processes[i]; if (handlerProcess.SyscallsToHandle.IsSet((int)syscallNumber)) { ProcessManager.SwitchProcess(handlerProcess.Id, ProcessManager.THREAD_DONT_CARE); switched = true; #if SYSCALLS_TRACE BasicConsole.WriteLine("Calling handler..."); //if (process == null) //{ // BasicConsole.WriteLine(" > process is null?!"); //} //else if (process.SyscallHandler == null) //{ // BasicConsole.WriteLine(" > process.SysCallHandler is null?!"); //} #endif uint TempReturn2 = 0; uint TempReturn3 = 0; uint TempReturn4 = 0; SystemCallResults tempResult = (SystemCallResults)handlerProcess.SyscallHandler(syscallNumber, param1, param2, param3, ref TempReturn2, ref TempReturn3, ref TempReturn4, currProcess.Id, currThread.Id); if (tempResult == SystemCallResults.RequestAction_WakeThread) { #if SYSCALLS_TRACE asicConsole.WriteLine("System calls : Performing action - wake thread"); #endif ProcessManager.WakeThread(handlerProcess, TempReturn2); tempResult = SystemCallResults.Unhandled; } if (tempResult != SystemCallResults.Unhandled && !PermitActionResulted) { #if SYSCALLS_TRACE BasicConsole.WriteLine("Result achieved."); #endif Return2 = TempReturn2; Return3 = TempReturn3; Return4 = TempReturn4; if (tempResult == SystemCallResults.OK_PermitActions) { result = SystemCallResults.OK; PermitActionResulted = true; } else if (tempResult == SystemCallResults.Deferred_PermitActions) { result = SystemCallResults.Deferred; PermitActionResulted = true; } else { result = tempResult; break; } } } } if (switched) { #if SYSCALLS_TRACE BasicConsole.WriteLine("Switching back..."); #endif ProcessManager.SwitchProcess(currProcess.Id, (int)currThread.Id); } } #if SYSCALLS_TRACE BasicConsole.WriteLine("Setting result values..."); #endif if (result == SystemCallResults.Deferred) { #if SYSCALLS_TRACE BasicConsole.WriteLine("Deferring thread (by indefinite sleep)..."); #endif currThread._EnterSleep(Thread.IndefiniteSleep); } else { currThread.Return1 = (uint)result; currThread.Return2 = Return2; currThread.Return3 = Return3; currThread.Return4 = Return4; } if (currThread.TimeToSleep != 0) { #if SYSCALLS_TRACE BasicConsole.WriteLine("Updating thread state..."); #endif Scheduler.UpdateCurrentState(); } #if SYSCALLS_TRACE BasicConsole.WriteLine("Syscall handled."); BasicConsole.WriteLine("---------------"); #endif }
/// <summary> /// Special handler method for system calls recognised/handlded by the kernel task. /// </summary> /// <param name="syscallNumber">The system call number that has been invoked.</param> /// <param name="param1">The value of the first parameter.</param> /// <param name="param2">The value of the second parameter.</param> /// <param name="param3">The value of the third parameter.</param> /// <param name="Return2">Reference to the second return value.</param> /// <param name="Return3">Reference to the third return value.</param> /// <param name="Return4">Reference to the fourth return value.</param> /// <param name="callerProcesId">The Id of the process which invoked the system call.</param> /// <param name="callerThreadId">The Id of the thread which invoked the system call.</param> /// <returns>A system call result indicating what has occurred and what should occur next.</returns> /// <remarks> /// Executes within the interrupt handler. Usual restrictions apply. /// </remarks> public static SystemCallResults HandleSystemCallForKernel(uint syscallNumber, uint param1, uint param2, uint param3, ref uint Return2, ref uint Return3, ref uint Return4, uint callerProcesId, uint callerThreadId) { SystemCallResults result = SystemCallResults.Unhandled; switch ((SystemCallNumbers)syscallNumber) { case SystemCallNumbers.SleepThread: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Sleep Thread"); #endif SysCall_Sleep((int)param1, callerProcesId, callerThreadId); result = SystemCallResults.OK; break; case SystemCallNumbers.WakeThread: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Wake Thread"); #endif SysCall_Wake(callerProcesId, param1); result = SystemCallResults.OK; break; case SystemCallNumbers.RegisterISRHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Register ISR Handler"); #endif if (SysCall_RegisterISRHandler((int)param1, param2, callerProcesId)) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } break; case SystemCallNumbers.DeregisterISRHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Deregister ISR Handler"); #endif SysCall_DeregisterISRHandler((int)param1, callerProcesId); result = SystemCallResults.OK; break; case SystemCallNumbers.RegisterIRQHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Register IRQ Handler"); #endif if (SysCall_RegisterIRQHandler((int)param1, param2, callerProcesId)) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } break; case SystemCallNumbers.DeregisterIRQHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Deregister IRQ Handler"); #endif SysCall_DeregisterIRQHandler((int)param1, callerProcesId); result = SystemCallResults.OK; break; case SystemCallNumbers.RegisterSyscallHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Register Syscall Handler"); #endif if (SysCall_RegisterSyscallHandler((int)param1, param2, callerProcesId)) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } break; case SystemCallNumbers.DeregisterSyscallHandler: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Deregister Syscall Handler"); #endif SysCall_DeregisterSyscallHandler((int)param1, callerProcesId); result = SystemCallResults.OK; break; case SystemCallNumbers.StartThread: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Start Thread"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.RegisterPipeOutpoint: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Register Pipe Outpoint"); #endif result = SystemCallResults.Deferred_PermitActions; break; case SystemCallNumbers.GetNumPipeOutpoints: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Get Num Pipe Outpoints"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.GetPipeOutpoints: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Get Pipe Outpoints"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.CreatePipe: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Create Pipe"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.WaitOnPipeCreate: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Wait On Pipe Create"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.ReadPipe: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Read Pipe"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.WritePipe: #if SYSCALLS_TRACE BasicConsole.WriteLine("System call : Write Pipe"); #endif result = SystemCallResults.Deferred; break; case SystemCallNumbers.SendMessage: #if SYSCALLS_TRACE BasicConsole.WriteLine("Syscall: Send message"); #endif result = SysCall_SendMessage(callerProcesId, callerThreadId, param1, param2, param3) ? SystemCallResults.OK : SystemCallResults.Fail; break; case SystemCallNumbers.ReceiveMessage: #if SYSCALLS_TRACE BasicConsole.WriteLine("Syscall: Receive message"); #endif Tasks.KernelTask.ReceiveMessage(callerProcesId, param1, param2); break; //#if SYSCALLS_TRACE default: BasicConsole.WriteLine("System call unrecognised/unhandled by Kernel Task."); break; //#endif } return(result); }
public static void EndDeferredSystemCall(Process CallerProcess, Thread CallerThread, SystemCallResults result, uint Return2, uint Return3, uint Return4) { ProcessManager.EnableKernelAccessToProcessMemory(CallerProcess); CallerThread.Return1 = (uint)result; CallerThread.Return2 = Return2; CallerThread.Return3 = Return3; CallerThread.Return4 = Return4; ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); CallerThread._Wake(); }
public static unsafe SystemCallResults HandleDeferredSystemCall( Process CallerProcess, Thread CallerThread, SystemCallNumbers syscallNumber, uint Param1, uint Param2, uint Param3, ref uint Return2, ref uint Return3, ref uint Return4) { SystemCallResults result = SystemCallResults.Unhandled; switch (syscallNumber) { case SystemCallNumbers.StartThread: #if DSC_TRACE BasicConsole.WriteLine("DSC: Start Thread"); #endif Return2 = CallerProcess.CreateThread((ThreadStartMethod)Utilities.ObjectUtilities.GetObject((void *)Param1), "[From sys call]").Id; #if DSC_TRACE BasicConsole.WriteLine("DSC: Start Thread - done."); #endif result = SystemCallResults.OK; break; case SystemCallNumbers.RegisterPipeOutpoint: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Register Pipe Outpoint"); #endif Pipes.PipeOutpoint outpoint; bool registered = Pipes.PipeManager.RegisterPipeOutpoint(CallerProcess.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (int)Param3, out outpoint); if (registered) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Register Pipe Outpoint - done."); #endif } break; case SystemCallNumbers.GetNumPipeOutpoints: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints"); #endif int numOutpoints; bool obtained = Pipes.PipeManager.GetNumPipeOutpoints((Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, out numOutpoints); if (obtained) { result = SystemCallResults.OK; Return2 = (uint)numOutpoints; } else { result = SystemCallResults.Fail; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Get Num Pipe Outpoints - done"); #endif } break; case SystemCallNumbers.GetPipeOutpoints: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Get Pipe Outpoints"); #endif bool obtained = Pipes.PipeManager.GetPipeOutpoints(CallerProcess, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2, (Pipes.PipeOutpointsRequest *)Param3); if (obtained) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Get Pipe Outpoints - done"); #endif } break; case SystemCallNumbers.CreatePipe: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Create Pipe"); #endif bool created = Pipes.PipeManager.CreatePipe(CallerProcess.Id, Param1, (Pipes.CreatePipeRequest *)Param2); if (created) { result = SystemCallResults.OK; } else { result = SystemCallResults.Fail; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Create Pipe - done"); #endif } break; case SystemCallNumbers.WaitOnPipeCreate: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Wait On Pipe Create"); #endif bool waiting = Pipes.PipeManager.WaitOnPipeCreate(CallerProcess.Id, CallerThread.Id, (Pipes.PipeClasses)Param1, (Pipes.PipeSubclasses)Param2); if (waiting) { result = SystemCallResults.Deferred; } else { result = SystemCallResults.Fail; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Wait On Pipe Create - done"); #endif } break; case SystemCallNumbers.ReadPipe: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Read Pipe"); #endif // Need access to calling process' memory to be able to read values from request structure ProcessManager.EnableKernelAccessToProcessMemory(CallerProcess); Pipes.ReadPipeRequest *RequestPtr = (Pipes.ReadPipeRequest *)Param1; int PipeId = RequestPtr->PipeId; bool Blocking = RequestPtr->Blocking; ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); Pipes.PipeManager.RWResults RWResult = Pipes.PipeManager.ReadPipe(PipeId, Blocking, CallerProcess, CallerThread); if (RWResult == Pipes.PipeManager.RWResults.Error) { result = SystemCallResults.Fail; } else { // Returning Deferred state from here will leave the caller thread // in whatever state ReadPipe decided it should be in. result = SystemCallResults.Deferred; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Read Pipe - done"); #endif } break; case SystemCallNumbers.WritePipe: { #if DSC_TRACE BasicConsole.WriteLine("DSC: Write Pipe"); #endif // Need access to calling process' memory to be able to read values from request structure ProcessManager.EnableKernelAccessToProcessMemory(CallerProcess); Pipes.ReadPipeRequest *RequestPtr = (Pipes.ReadPipeRequest *)Param1; int PipeId = RequestPtr->PipeId; bool Blocking = RequestPtr->Blocking; ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); Pipes.PipeManager.RWResults RWResult = Pipes.PipeManager.WritePipe(PipeId, Blocking, CallerProcess, CallerThread); if (RWResult == Pipes.PipeManager.RWResults.Error) { result = SystemCallResults.Fail; } else { // Returning Deferred state from here will leave the caller thread // in whatever state WritePipe decided it should be in. result = SystemCallResults.Deferred; } #if DSC_TRACE BasicConsole.WriteLine("DSC: Write Pipe - done"); #endif } break; default: #if DSC_TRACE BasicConsole.WriteLine("DSC: Unrecognised call number."); BasicConsole.WriteLine((uint)syscallNumber); #endif break; } return(result); }
public static void DeferredSyscallsThread_Main() { while (!Terminating) { if (DeferredSyscallsInfo_Queued.Count == 0) { SystemCalls.SleepThread(SystemCalls.IndefiniteSleepThread); } while (DeferredSyscallsInfo_Queued.Count > 0) { // Scheduler must be disabled during pop/push from circular buffer or we can // end up in an infinite lock. Consider what happens if a process invokes // a deferred system call during the pop/push here and at the end of this loop. #if DSC_TRACE BasicConsole.WriteLine("DSC: Pausing scheduler..."); #endif Scheduler.Disable(/*"DSC 1"*/); #if DSC_TRACE BasicConsole.WriteLine("DSC: Popping queued info object..."); #endif DeferredSyscallInfo info = (DeferredSyscallInfo)DeferredSyscallsInfo_Queued.Pop(); #if DSC_TRACE BasicConsole.WriteLine("DSC: Resuming scheduler..."); #endif Scheduler.Enable(); #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting process & thread..."); #endif Process CallerProcess = ProcessManager.GetProcessById(info.ProcessId); Thread CallerThread = ProcessManager.GetThreadById(info.ThreadId, CallerProcess); #if DSC_TRACE BasicConsole.Write("DSC: Process: "); BasicConsole.WriteLine(CallerProcess.Name); BasicConsole.Write("DSC: Thread: "); BasicConsole.WriteLine(CallerThread.Name); #endif ProcessManager.EnableKernelAccessToProcessMemory(CallerProcess); #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting data..."); #endif SystemCallNumbers SysCallNumber = (SystemCallNumbers)CallerThread.SysCallNumber; uint Param1 = CallerThread.Param1; uint Param2 = CallerThread.Param2; uint Param3 = CallerThread.Param3; uint Return2 = CallerThread.Return2; uint Return3 = CallerThread.Return3; uint Return4 = CallerThread.Return4; #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting data done."); #endif ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); #if DSC_TRACE BasicConsole.WriteLine("DSC: Calling..."); #endif SystemCallResults result = HandleDeferredSystemCall( CallerProcess, CallerThread, SysCallNumber, Param1, Param2, Param3, ref Return2, ref Return3, ref Return4); #if DSC_TRACE BasicConsole.WriteLine("DSC: Ending call..."); #endif if (result != SystemCallResults.Deferred) { EndDeferredSystemCall(CallerProcess, CallerThread, result, Return2, Return3, Return4); } #if DSC_TRACE BasicConsole.WriteLine("DSC: Resetting info object..."); #endif info.ProcessId = 0; info.ThreadId = 0; // See comment at top of loop for why this is necessary #if DSC_TRACE BasicConsole.WriteLine("DSC: Pausing scheduler..."); #endif Scheduler.Disable(/*"DSC 2"*/); #if DSC_TRACE BasicConsole.WriteLine("DSC: Queuing info object..."); #endif DeferredSyscallsInfo_Unqueued.Push(info); #if DSC_TRACE BasicConsole.WriteLine("DSC: Resuming scheduler..."); #endif Scheduler.Enable(); } } }
/// <summary> /// Gets the outpoint desciptors of the available outpoints of the specified class and subclass. /// </summary> /// <param name="numOutpoints">The known number of available outpoints. Use GetNumPipeOutpoints to obtain this number.</param> /// <param name="SysCallResult">Out : The result of the system call. Check this is set to OK.</param> /// <param name="OutpointDescriptors">Out : The array of outpoint descriptors.</param> /// <param name="Class">The class of pipe to search for.</param> /// <param name="Subclass">The subclass of pipe to search for.</param> public static void GetOutpointDescriptors(int numOutpoints, out SystemCallResults SysCallResult, out Pipes.PipeOutpointDescriptor[] OutpointDescriptors, Pipes.PipeClasses Class, Pipes.PipeSubclasses Subclass) { OutpointDescriptors = new Pipes.PipeOutpointDescriptor[numOutpoints]; Pipes.PipeOutpointsRequest* RequestPtr = (Pipes.PipeOutpointsRequest*)Heap.AllocZeroed((uint)sizeof(Pipes.PipeOutpointsRequest), "BasicServerHelpers : Alloc PipeOutpointsRequest"); if (RequestPtr != null) { try { RequestPtr->MaxDescriptors = numOutpoints; RequestPtr->Outpoints = (Pipes.PipeOutpointDescriptor*)((byte*)Utilities.ObjectUtilities.GetHandle(OutpointDescriptors) + FOS_System.Array.FieldsBytesSize); if (RequestPtr->Outpoints != null) { SysCallResult = SystemCalls.GetPipeOutpoints(Class, Subclass, RequestPtr); switch (SysCallResult) { case SystemCallResults.Unhandled: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Unhandled!"); break; case SystemCallResults.Fail: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Failed!"); break; case SystemCallResults.OK: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Succeeded."); break; default: //BasicConsole.WriteLine("BasicServerHelpers > GetPipeOutpoints: Unexpected system call result!"); break; } } else { SysCallResult = SystemCallResults.Fail; //BasicConsole.WriteLine("BasicServerHelpers > RequestPtr->Outpoints null! No memory allocated."); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicServerHelpers : Couldn't allocate memory outpoints list in outpoints request!")); } } finally { Heap.Free(RequestPtr); } } else { SysCallResult = SystemCallResults.Fail; //BasicConsole.WriteLine("BasicServerHelpers > RequestPtr null! No memory allocated."); ExceptionMethods.Throw(new FOS_System.Exceptions.ArgumentException("BasicServerHelpers : Couldn't allocate memory get outpoints request!")); } }