/** * The exception handler. This handler is called by the processor whenever * a user instruction causes a processor exception. * * <p> * When the exception handler is invoked, interrupts are enabled, and the * processor's cause register contains an integer identifying the cause of * the exception (see the <tt>exceptionZZZ</tt> constants in the * <tt>Processor</tt> class). If the exception involves a bad virtual * address (e.g. page fault, TLB miss, read-only, bus error, or address * error), the processor's BadVAddr register identifies the virtual address * that caused the exception. */ public void exceptionHandler() { Lib.assert(KThread.currentThread() instanceof UThread); UserProcess process = ((UThread) KThread.currentThread()).process; int cause = Machine.processor().readRegister(Processor.regCause); process.handleException(cause); }
public void run() { Lib.debug('t', "### Try to listen from " + KThread.currentThread().toString()); int res = comm.listen(); Lib.debug('t', "### listened " + res + " from " + KThread.currentThread().toString()); }
/** * 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(); }
public void run() { lock.acquire(); System.out.print(KThread.currentThread().getName() + " acquired lock\n"); condition.sleep(); System.out.print(KThread.currentThread().getName() + " acquired lock again\n"); lock.release(); System.out.print(KThread.currentThread().getName() + " released lock \n"); }
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); }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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(); }
/** * Create the idle thread. Whenever there are no threads ready to be run, and * <tt>runNextThread()</tt> is called, it will run the idle thread. The idle thread must never * block, and it will only be allowed to run when all other threads are blocked. * * <p>Note that <tt>ready()</tt> never adds the idle thread to the ready set. */ private static void createIdleThread() { Lib.assertTrue(idleThread == null); idleThread = new KThread( new Runnable() { public void run() { while (true) yield(); } }); idleThread.setName("idle"); Machine.autoGrader().setIdleThread(idleThread); idleThread.fork(); }
/** Test if this module is working. */ public static void selfTest() { System.out.print("Enter Condition2.selfTest\n"); Lock lock = new Lock(); Condition2 condition = new Condition2(lock); KThread t[] = new KThread[10]; for (int i = 0; i < 10; i++) { t[i] = new KThread(new Condition2Test(lock, condition)); t[i].setName("Thread" + i).fork(); } KThread.yield(); lock.acquire(); System.out.print("condition.wake();\n"); condition.wake(); System.out.print("condition.wakeAll();\n"); condition.wakeAll(); lock.release(); System.out.print("Leave Condition2.selfTest\n"); t[9].join(); }
/** * 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; } }
/** * Start running user programs, by creating a process and running a shell * program in it. The name of the shell program it must run is returned by * <tt>Machine.getShellProgramName()</tt>. * * @see nachos.machine.Machine#getShellProgramName */ public void run() { super.run(); UserProcess process = UserProcess.newUserProcess(); String shellProgram = Machine.getShellProgramName(); Lib.assert(process.execute(shellProgram, new String[] { })); KThread.currentThread().finish(); }
/** * 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(); }
/** * 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(); }
/** * 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); }
public static void selfTest() { final Lock lock = new Lock(); final Condition2 empty = new Condition2(lock); final LinkedList<Integer> list = new LinkedList<>(); KThread consumer = new KThread( new Runnable() { public void run() { lock.acquire(); while (list.isEmpty()) { empty.sleep(); } Lib.assertTrue(list.size() == 5, "List should have 5 values."); while (!list.isEmpty()) { System.out.println("Removed " + list.removeFirst()); } lock.release(); } }); KThread producer = new KThread( new Runnable() { public void run() { lock.acquire(); for (int i = 0; i < 5; i++) { list.add(i); System.out.println("Added " + i); } empty.wake(); lock.release(); } }); consumer.setName("Consumer"); producer.setName("Producer"); consumer.fork(); producer.fork(); consumer.join(); producer.join(); }
private void handleExit(int status) { if (myChildProcess != null) { myChildProcess.status = status; } // close all the opened files for (int i = 0; i < 16; i++) { handleClose(i); } // part2 implemented this.unloadSections(); if (this.process_id == ROOT) { Kernel.kernel.terminate(); } else { KThread.finish(); Lib.assertNotReached(); } }
/** * 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); }
/** * 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 }
/** * Returns the current process. * * @return the current process, or <tt>null</tt> if no process is current. */ public static UserProcess currentProcess() { if (!(KThread.currentThread() instanceof UThread)) return null; return ((UThread) KThread.currentThread()).process; }
public static void selfTest() { comm = new Communicator(); KThread t6 = new KThread(new TestListener()).setName("Listener 1"); t6.fork(); KThread t7 = new KThread(new TestListener()).setName("Listener 2"); t7.fork(); KThread t8 = new KThread(new TestListener()).setName("Listener 3"); t8.fork(); KThread t9 = new KThread(new TestListener()).setName("Listener 4"); t9.fork(); KThread t10 = new KThread(new TestListener()).setName("Listener 5"); t10.fork(); KThread t1 = new KThread(new TestSpeaker(123)).setName("Speaker 1"); t1.fork(); KThread t2 = new KThread(new TestSpeaker(456)).setName("Speaker 2"); t2.fork(); KThread t3 = new KThread(new TestSpeaker(789)).setName("Speaker 3"); t3.fork(); KThread t4 = new KThread(new TestSpeaker(101112)).setName("Speaker 4"); t4.fork(); KThread t5 = new KThread(new TestSpeaker(131415)).setName("Speaker 5"); t5.fork(); t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); t6.join(); t7.join(); t8.join(); t9.join(); t10.join(); KThread.yield(); }
public void run() { Lib.debug('t', "### Speak " + word + " from " + KThread.currentThread().toString()); comm.speak(word); }
public void run() { for (int i = 0; i < 5; i++) { System.out.println("*** thread " + which + " looped " + i + " times"); currentThread.yield(); } }
/** Determine the next thread to run, then dispatch the CPU to the thread using <tt>run()</tt>. */ private static void runNextThread() { KThread nextThread = readyQueue.nextThread(); if (nextThread == null) nextThread = idleThread; nextThread.run(); }