currentThread->registers.PC = resume; // Set the next PC to the "resume" label below in this method. readyQueue.enqueue(currentThread); // Put this thread back onto the ready queue for later execution. Thread* otherThread = readyQueue.dequeue(); // Remove and get the next thread to run from the ready queue. currentThread = otherThread; // Replace the global current-thread pointer value so it is ready for the next thread. // Restore the registers from currentThread/otherThread, including a jump to the stored PC of the other thread // (at "resume" below). Again, the details of how this is done are beyond this scope. restoreRegisters(otherThread.registers); // *** Now running "otherThread" (which is now "currentThread")! The original thread is now "sleeping". *** resume: // This is where another contextSwitch() call needs to set PC to when switching context back here. // Return to where otherThread left off. threadingSystemBusy = false; // Must be an atomic assignment. systemCall_enableInterrupts(); // Turn pre-emptive switching back on on this core. } // Thread sleep method: // On current CPU core, a synchronous context switch to another thread without putting // the current thread on the ready queue. // Must be holding "threadingSystemBusy" and disabled interrupts so that this method // doesn't get interrupted by the thread-switching timer which would call contextSwitchISR(). // After returning from this method, must clear "threadingSystemBusy". public method threadSleep() { // Get all of the registers of the currently-running process. // For Program Counter (PC), we will need the instruction location of // the "resume" label below. Getting the register values is platform-dependent and may involve // reading the current stack frame, JMP/CALL instructions, etc. (The details are beyond this scope.) currentThread->registers = getAllRegisters(); // Store the registers in the "currentThread" object in memory. currentThread->registers.PC = resume; // Set the next PC to the "resume" label below in this method. // Unlike contextSwitchISR(), we will not place currentThread back into readyQueue. // Instead, it has already been placed onto a mutex's or condition variable's queue. Thread* otherThread = readyQueue.dequeue(); // Remove and get the next thread to run from the ready queue. currentThread = otherThread; // Replace the global current-thread pointer value so it is ready for the next thread. // Restore the registers from currentThread/otherThread, including a jump to the stored PC of the other thread // (at "resume" below). Again, the details of how this is done are beyond this scope. restoreRegisters(otherThread.registers); // *** Now running