/** * Wake up at most one thread sleeping on this condition variable. The current thread must hold * the associated lock. */ public void wake() { Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean intStatus = Machine.interrupt().disable(); // +hy+ ((KThread) waitQueue.removeFirst()).ready(); // +hy+ Machine.interrupt().restore(intStatus); // +hy+ }
public void wakeJoinedThreads() { boolean oldInterruptStatus = Machine.interrupt().disable(); KThread thread = null; do { thread = waitingKThreadListToJoin.nextThread(); if (thread != null) { thread.ready(); } } while (thread != null); Machine.interrupt().restore(oldInterruptStatus); }
/** * Atomically release the associated lock and go to sleep on this condition variable until another * thread wakes it using <tt>wake()</tt>. The current thread must hold the associated lock. The * thread will automatically reacquire the lock before <tt>sleep()</tt> returns. */ public void sleep() { Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean intStatus = Machine.interrupt().disable(); conditionLock.release(); waitQueue.waitForAccess(KThread.currentThread()); KThread.sleep(); conditionLock.acquire(); Machine.interrupt().restore(intStatus); }
/** * Wake up at most one thread sleeping on this condition variable. The current thread must hold * the associated lock. */ public void wake() { Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean intStatus = Machine.interrupt().disable(); KThread thread = waitQueue.nextThread(); if (thread != null) { thread.ready(); } Machine.interrupt().restore(intStatus); }
/** * Relinquish the CPU if any other thread is ready to run. If so, put the current thread on the * ready queue, so that it will eventually be rescheuled. * * <p>Returns immediately if no other thread is ready to run. Otherwise returns when the current * thread is chosen to run again by <tt>readyQueue.nextThread()</tt>. * * <p>Interrupts are disabled, so that the current thread can atomically add itself to the ready * queue and switch to the next thread. On return, restores interrupts to the previous state, in * case <tt>yield()</tt> was called with interrupts disabled. */ public static void yield() { Lib.debug(dbgThread, "Yielding thread: " + currentThread.toString()); Lib.assertTrue(currentThread.status == statusRunning); boolean intStatus = Machine.interrupt().disable(); currentThread.ready(); runNextThread(); Machine.interrupt().restore(intStatus); }
/** * Waits for this thread to finish. If this thread is already finished, return immediately. This * method must only be called once; the second call is not guaranteed to return. This thread must * not be the current thread. */ public void join() { Lib.debug(dbgThread, "Joining to thread: " + toString()); // FIXME Touhid :: join() edit starts boolean intStatus = Machine.interrupt().setStatus(false); if (status != statusFinished) { // Joinee is not finished yet waitingKThreadListToJoin.waitForAccess(currentThread()); KThread.sleep(); } Machine.interrupt().restore(intStatus); // join() edit ends Lib.assertTrue(this != currentThread); }
/** * Waits for this thread to finish. If this thread is already finished, return immediately. This * method must only be called once; the second call is not guaranteed to return. This thread must * not be the current thread. */ public void join() { boolean intStatus = Machine.interrupt().disable(); Lib.debug(dbgThread, "Joining to thread: " + toString()); Lib.assertTrue(this != currentThread); if (cont == 0) { cont = 1; if (this.status == statusFinished) { return; } else { this.joinList.add(currentThread); currentThread.sleep(); } } Machine.interrupt().restore(intStatus); }
/** * Relinquish the CPU, because the current thread has either finished or it is blocked. This * thread must be the current thread. * * <p>If the current thread is blocked (on a synchronization primitive, i.e. a <tt>Semaphore</tt>, * <tt>Lock</tt>, or <tt>Condition</tt>), eventually some thread will wake this thread up, putting * it back on the ready queue so that it can be rescheduled. Otherwise, <tt>finish()</tt> should * have scheduled this thread to be destroyed by the next thread to run. */ public static void sleep() { Lib.debug(dbgThread, "Sleeping thread: " + currentThread.toString()); Lib.assertTrue(Machine.interrupt().disabled()); if (currentThread.status != statusFinished) currentThread.status = statusBlocked; runNextThread(); }
private void begin() { Lib.debug(dbgThread, "Beginning thread: " + toString()); Lib.assertTrue(this == currentThread); restoreState(); Machine.interrupt().enable(); }
/** * Wait for a thread to speak through this communicator, and then return the <i>word</i> that * thread passed to <tt>speak()</tt>. * * @return the integer transferred. */ public int listen() { boolean intStatus = Machine.interrupt().disable(); condLock.acquire(); listenCount++; speakCond.wake(); if (msgList.isEmpty()) listenCond.sleep(); condLock.release(); Machine.interrupt().restore(intStatus); // Must have msg if reach here. return msgList.remove(0); }
/** * Causes this thread to begin execution. The result is that two threads are running concurrently: * the current thread (which returns from the call to the <tt>fork</tt> method) and the other * thread (which executes its target's <tt>run</tt> method). */ public void fork() { Lib.assertTrue(status == statusNew); Lib.assertTrue(target != null); Lib.debug(dbgThread, "Forking thread: " + toString() + " Runnable: " + target); boolean intStatus = Machine.interrupt().disable(); tcb.start( new Runnable() { public void run() { runThread(); } }); ready(); Machine.interrupt().restore(intStatus); }
/** * Wait for a thread to listen through this communicator, and then transfer <i>word</i> to the * listener. * * <p>Does not return until this thread is paired up with a listening thread. Exactly one listener * should receive <i>word</i>. * * @param word the integer to transfer. */ public void speak(int word) { boolean intStatus = Machine.interrupt().disable(); condLock.acquire(); if (listenCount == 0) { speakCond.sleep(); } listenCount--; msgList.add(word); listenCond.wake(); condLock.release(); Machine.interrupt().restore(intStatus); }
/** * Waits for this thread to finish. If this thread is already finished, return immediately. This * method must only be called once; the second call is not guaranteed to return. This thread must * not be the current thread. */ public void join() { Lib.debug(dbgThread, "Joining to thread: " + toString()); // Precondition: this thread must not be the current thread. Moreover, // return if this thread is already finished. Lib.assertTrue(this != currentThread); if (this.status == this.statusFinished) return; // Calling sleep on a KThread requires interrupts to be disabled. We // will restore the status after we put the current thread to sleep. boolean intStatus = Machine.interrupt().disable(); // Add the current thread into the buffer to indicate that it's blocked // before this thread is finished. this.waitedThreadList.add(this.currentThread); // Put the current thread to sleep, and restore the interrupt. currentThread.sleep(); Machine.interrupt().restore(intStatus); }
/** Moves this thread to the ready state and adds this to the scheduler's ready queue. */ public void ready() { Lib.debug(dbgThread, "Ready thread: " + toString()); Lib.assertTrue(Machine.interrupt().disabled()); Lib.assertTrue(status != statusReady); status = statusReady; if (this != idleThread) readyQueue.waitForAccess(this); Machine.autoGrader().readyThread(this); }
/** * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called * directly. * * <p>The current thread cannot be immediately destroyed because its stack and other execution * state are still in use. Instead, this thread will be destroyed automatically by the next thread * to run, when it is safe to delete this thread. */ public static void finish() { Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString()); Machine.interrupt().disable(); Machine.autoGrader().finishingCurrentThread(); Lib.assertTrue(toBeDestroyed == null); toBeDestroyed = currentThread; currentThread.status = statusFinished; sleep(); }
/** * Put the current thread to sleep for at least <i>x</i> ticks, waking it up in the timer * interrupt handler. The thread must be woken up (placed in the scheduler ready set) during the * first timer interrupt where * * <p> * * <blockquote> * * (current time) >= (WaitUntil called time)+(x) * * </blockquote> * * @param x the minimum number of clock ticks to wait. * @see nachos.machine.Timer#getTime() */ public void waitUntil(long x) { // disable interrupts Machine.interrupt().disable(); // let's see if this works? DAC DEBUG // calculate wakeTime long wakeTime = Machine.timer().getTime() + x; // create AlarmBucket AlarmBucket Abuck = new AlarmBucket(wakeTime, KThread.currentThread()); // add current thread (alarm bucket) to waitQueue waitQueue.add(Abuck); // put current thread to sleep KThread.currentThread().sleep(); return; }
/** * Dispatch the CPU to this thread. Save the state of the current thread, switch to the new thread * by calling <tt>TCB.contextSwitch()</tt>, and load the state of the new thread. The new thread * becomes the current thread. * * <p>If the new thread and the old thread are the same, this method must still call * <tt>saveState()</tt>, <tt>contextSwitch()</tt>, and <tt>restoreState()</tt>. * * <p>The state of the previously running thread must already have been changed from running to * blocked or ready (depending on whether the thread is sleeping or yielding). * * @param finishing <tt>true</tt> if the current thread is finished, and should be destroyed by * the new thread. */ private void run() { Lib.assertTrue(Machine.interrupt().disabled()); Machine.yield(); currentThread.saveState(); Lib.debug(dbgThread, "Switching from: " + currentThread.toString() + " to: " + toString()); currentThread = this; tcb.contextSwitch(); currentThread.restoreState(); }
/** * Prepare this thread to be run. Set <tt>status</tt> to <tt>statusRunning</tt> and check * <tt>toBeDestroyed</tt>. */ protected void restoreState() { Lib.debug(dbgThread, "Running thread: " + currentThread.toString()); Lib.assertTrue(Machine.interrupt().disabled()); Lib.assertTrue(this == currentThread); Lib.assertTrue(tcb == TCB.currentTCB()); Machine.autoGrader().runningThread(this); status = statusRunning; if (toBeDestroyed != null) { toBeDestroyed.tcb.destroy(); toBeDestroyed.tcb = null; toBeDestroyed = null; } }
/** * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called * directly. * * <p>The current thread cannot be immediately destroyed because its stack and other execution * state are still in use. Instead, this thread will be destroyed automatically by the next thread * to run, when it is safe to delete this thread. */ public static void finish() { Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString()); // FIXME Touhid :: Wake threads that have joined the currently running // thread currentThread.wakeJoinedThreads(); Machine.interrupt().disable(); Machine.autoGrader().finishingCurrentThread(); Lib.assertTrue(toBeDestroyed == null); toBeDestroyed = currentThread; currentThread.status = statusFinished; sleep(); }
/** * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called * directly. * * <p>The current thread cannot be immediately destroyed because its stack and other execution * state are still in use. Instead, this thread will be destroyed automatically by the next thread * to run, when it is safe to delete this thread. */ public static void finish() { Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString()); Machine.interrupt().disable(); Machine.autoGrader().finishingCurrentThread(); Lib.assertTrue(toBeDestroyed == null); toBeDestroyed = currentThread; currentThread.status = statusFinished; // When this thread is finished, we need to reset the status of all // waited/blocked thread to ready state. while (!currentThread.waitedThreadList.isEmpty()) { KThread threadToRestore = currentThread.waitedThreadList.remove(0); threadToRestore.ready(); } sleep(); }
/** * The timer interrupt handler. This is called by the machine's timer periodically (approximately * every 500 clock ticks). Causes the current thread to yield, forcing a context switch if there * is another thread that should be run. */ public void timerInterrupt() { // disable interrupts (maybe not necessary) Machine.interrupt().disable(); // let's see if this works? // get current time long currentTime = Machine.timer().getTime(); // go through waitQueue and put each thread that is "less than" current wait time on ready queue AlarmBucket placeholder = null; int count = waitQueue.size(); while (count > 0) { placeholder = waitQueue.peek(); if (placeholder.getTime() <= currentTime) { placeholder = waitQueue.poll(); placeholder.getKThread().ready(); count = waitQueue.size(); } else { count = 0; } } // yield current thread KThread.currentThread().yield(); // Machine.interrupt().enable(); //let's see if this works? DAC DEBUG }
/** * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called * directly. * * <p>The current thread cannot be immediately destroyed because its stack and other execution * state are still in use. Instead, this thread will be destroyed automatically by the next thread * to run, when it is safe to delete this thread. */ public static void finish() { Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString()); Machine.interrupt().disable(); Machine.autoGrader().finishingCurrentThread(); Lib.assertTrue(toBeDestroyed == null); toBeDestroyed = currentThread; currentThread.status = statusFinished; KThread aux = null; if (joinList.size() > 0) { aux = joinList.getFirst(); } if (aux != null) { aux.ready(); joinList.removeFirst(); } sleep(); }
/** * Prepare this thread to give up the processor. Kernel threads do not need to do anything here. */ protected void saveState() { Lib.assertTrue(Machine.interrupt().disabled()); Lib.assertTrue(this == currentThread); }