/// <summary> /// Sets the task sleeping until a given time /// </summary> /// <param name="fullTicks">Full ticks</param> /// <param name="subTicks">Sub ticks</param> /// <returns>The amount of time the task still needs to sleep (only if interrupted)</returns> public uint SleepUntil(uint fullTicks, uint subTicks) { m_sleepUntilFullTicks = fullTicks; m_sleepUntilSubTicks = subTicks; /** * If we're the only thread that and we are sleeping, we have nowhere to switch to * when we have a taskswitch that happens. * This case can only happen if we're the KernelTask with all threads sleeping but this one, so we just wait here */ if (OwningTask == Tasking.KernelTask && OwningTask.ThreadCount == OwningTask.SleepingThreadCount + 1) { while (!hasSleepTimeExpired()) { // Wait for all interrupts, not just a task switch... CPU.HLT(); } } else { AddFlag(ThreadFlags.SLEEPING); OwningTask.SleepingThreadCount++; // Will return when waiting is done Tasking.Yield(); } return(0); }
/// <summary> /// Forks this current task (actually takes the current thread) /// </summary> /// <returns>The new PID (zero for child, >0 for childs PID)</returns> public int Fork() { Task newTask = Clone(); newTask.AddThread(CurrentThread.Clone()); Tasking.ScheduleTask(newTask); return(newTask.PID != PID ? newTask.PID : 0); }
/// <summary> /// Processes a signal /// </summary> /// <param name="action">The action</param> /// <returns>The signal context</returns> public void ProcessSignal(SignalAction action) { while (m_currentSignalContext != null) { Tasking.Yield(); } m_signalMutex.Lock(); m_currentSignalContext = Context.ProcessSignal(action); m_signalMutex.Unlock(); }
/// <summary> /// Processes a signal /// </summary> /// <param name="signal">The signal</param> /// <returns>The errorcode</returns> public unsafe ErrorCode ProcessSignal(Signal signal) { if (signal <= 0 || (int)signal >= Signals.NSIG) { return(ErrorCode.EINVAL); } // Get handler, if no handler is set, use default handler SignalAction action = m_signalActions[(int)signal]; if (action == null) { Signals.DefaultAction defaultAction = Signals.DefaultActions[(int)signal]; switch (defaultAction) { case Signals.DefaultAction.Continue: RemoveFlag(TaskFlag.STOPPED); break; case Signals.DefaultAction.Stop: AddFlag(TaskFlag.STOPPED); // Do a task switch because the task may not run until a continue is received Tasking.Yield(); break; case Signals.DefaultAction.Core: case Signals.DefaultAction.Terminate: Console.WriteLine(Signals.SignalNames[(int)signal]); Tasking.RemoveTaskByPID(PID); break; } } else { if (action.Sigaction.Handler != (void *)Signals.SIG_IGN) { CurrentThread.ProcessSignal(action); } } return(ErrorCode.SUCCESS); }