コード例 #1
0
        public static void ClockInterrupt(ref IDTStack stackSate)
        {
            Interlocked.Increment(ref clockTicks);

            if (!Enabled)
            {
                return;
            }

            // check if current thread should get more time
            var currentThreadID = GetCurrentThreadID();
            var th = GetCurrentThread();

            if (th != null)
            {
                if (th.Priority != 0)
                {
                    if (th.Priority > 0)
                    {
                        if (++th.PriorityInterrupts <= th.Priority)
                        {
                            return;
                        }
                    }
                    th.PriorityInterrupts = 0;
                }
            }

            // Save current stack state
            SaveThreadState(currentThreadID, ref stackSate);

            ScheduleNextThread(currentThreadID);
        }
コード例 #2
0
ファイル: SysCallManager.cs プロジェクト: djlw78/abanu
        /// <summary>
        /// Syscall interrupt handler. Dispatcher for every SysCall.
        /// </summary>
        private static void InterruptHandler(ref IDTStack stack, SysCallCallingType callingMethod)
        {
            var args = new SystemMessage
            {
                Target = (SysCallTarget)stack.EAX,
                Arg1   = stack.EBX,
                Arg2   = stack.ECX,
                Arg3   = stack.EDX,
                Arg4   = stack.ESI,
                Arg5   = stack.EDI,
                Arg6   = stack.EBP,
            };

            var commandNum = GetCommandNum(args.Target);

            if (KConfig.Log.SysCall)
            {
                KernelMessage.WriteLine("Got SysCall cmd={0} arg1={1:X8} arg2={2:X8} arg3={3:X8} arg4={4:X8} arg5={5:X8} arg6={6:X8}", (uint)args.Target, args.Arg1, args.Arg2, args.Arg3, args.Arg4, args.Arg5, args.Arg6);
            }

            Scheduler.SaveThreadState(Scheduler.GetCurrentThread().ThreadID, ref stack);

            var info = Commands[commandNum];

            if (info == null)
            {
                Panic.Error("Undefined SysCall");
            }

            var ctx = new SysCallContext
            {
                CallingType = callingMethod,
                Debug       = info.Debug,
            };

            if (info.Debug)
            {
                KDebug.DumpStats();
                Debug.Nop();
            }

            var result = info.Handler(ref ctx, ref args);

            if (KConfig.Log.SysCall)
            {
                KernelMessage.WriteLine("Result of Syscall cmd={0}: {1:X8}", (uint)args.Target, result);
            }

            stack.EAX = result;
        }
コード例 #3
0
        /// <summary>
        /// Saves the current thread state, so we can switch to another thread.
        /// </summary>
        public static unsafe void SaveThreadState(int threadID, ref IDTStack stackState)
        {
            //Assert.True(threadID < MaxThreads, "SaveThreadState(): invalid thread id > max");
            var stackStatePtr = (IDTStack *)Unsafe.AsPointer(ref stackState);

            var thread = Threads[threadID];

            if (thread.Status != ThreadStatus.Running)
            {
                return; // New threads doesn't have a stack in use. Take the initial one.
            }
            //Assert.True(thread != null, "SaveThreadState(): thread id = null");

            if (thread.User)
            {
                Assert.IsSet(thread.StackState, "thread.StackState is null");
                *thread.StackState = *(IDTTaskStack *)stackStatePtr;
            }
            else
            {
                thread.StackState = (IDTTaskStack *)stackStatePtr;
            }

            if (KConfig.Log.TaskSwitch)
            {
                KernelMessage.Write("Task {0}: Stored ThreadState from {1:X8} stored at {2:X8}, EIP={3:X8}", (uint)threadID, (uint)stackStatePtr, (uint)thread.StackState, thread.StackState->Stack.EIP);
                if (thread.User)
                {
                    KernelMessage.WriteLine(" ESP={0:X8}", thread.StackState->TASK_ESP);
                }
                else
                {
                    KernelMessage.WriteLine();
                }
            }
        }
コード例 #4
0
ファイル: SysCallManager.cs プロジェクト: djlw78/abanu
 /// <summary>
 /// Syscall interrupt handler for asynchronous calls.
 /// </summary>
 private static void ActionInterruptHandler(ref IDTStack stack)
 {
     InterruptHandler(ref stack, SysCallCallingType.Async);
 }
コード例 #5
0
ファイル: IDT.cs プロジェクト: djlw78/abanu
        /// <summary>
        /// Entry point into the ISR (Interrupt Service Routine)
        /// </summary>
        /// <param name="stack">Pointer to the ISR stack</param>
        private static unsafe void ProcessInterrupt(ref IDTStack stack)
        {
            // Switch to Kernel segments
            ushort dataSelector = KnownSegments.KernelData;

            Native.SetSegments(dataSelector, dataSelector, KnownSegments.KernelThreadStorage, dataSelector, dataSelector);

            // Switch to Kernel Adresse space
            var block = (InterruptControlBlock *)Address.InterruptControlBlock;

            Native.SetCR3(block->KernelPageTableAddr);

            // Get the IRQ
            var irq = stack.Interrupt;

            // Get the pagetable address of the interrupted process
            uint pageTableAddr = 0;
            var  thread        = Scheduler.GetCurrentThread();

            if (thread != null)
            {
                dataSelector  = (ushort)thread.DataSelector;
                pageTableAddr = thread.Process.PageTable.GetPageTablePhysAddr();
            }

            // If the IDTManager is not initialized yet or hard disabled, we return now
            if (!IDTManager.Enabled)
            {
                PIC.SendEndOfInterrupt(irq);
                return;
            }

            // Get interrupt info for the IRQ
            var interruptInfo = IDTManager.Handlers[irq];

            if (KConfig.Log.Interrupts && interruptInfo.Trace && thread != null)
            {
                KernelMessage.WriteLine("Interrupt {0}, Thread {1}, EIP={2:X8} ESP={3:X8}", irq, (uint)thread.ThreadID, stack.EIP, stack.ESP);
            }

            // Some statistics

            IDTManager.RaisedCount++;

            if (interruptInfo.CountStatistcs)
            {
                IDTManager.RaisedCountCustom++;
            }

            if (KConfig.Log.Interrupts)
            {
                if (interruptInfo.Trace)
                {
                    KernelMessage.WriteLine("Interrupt: {0}", irq);
                }

                var col = Screen.Column;
                var row = Screen.Row;
                Screen.Column = 0;
                Screen.Goto(2, 35);
                Screen.Write("Interrupts: ");
                Screen.Write(IDTManager.RaisedCount);
                Screen.Goto(3, 35);
                Screen.Write("IntNoClock: ");
                Screen.Write(IDTManager.RaisedCountCustom);
                Screen.Row    = row;
                Screen.Column = col;
            }

            // This should never happen
            if (irq < 0 || irq > 255)
            {
                Panic.Error("Invalid Interrupt");
            }

            // Invoke handlers

            if (interruptInfo.PreHandler != null)
            {
                interruptInfo.PreHandler(ref stack);
            }

            if (interruptInfo.Handler == null)
            {
                Panic.Error("Handler is null");
            }
            else
            {
            }

            interruptInfo.Handler(ref stack);

            // Important! Otherwise we will get any more interrupts of this kind
            PIC.SendEndOfInterrupt(irq);

            // Switch to original address space
            if (pageTableAddr > 0)
            {
                Native.SetCR3(pageTableAddr);
            }

            // Switch to original segments
            Native.SetSegments(dataSelector, dataSelector, KnownSegments.UserThreadStorage, dataSelector, KnownSegments.KernelData);

            // ISR is completed. The upper ISR stub will re-enable interrupts and resume the original process
        }