Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

nachos- Selftest method for KThread and condition 2 in Java package nachos.threads; import nachos. machine.*; * A KThread is a thread that can be used

nachos- Selftest method for KThread and condition 2 in Java

image text in transcribed

image text in transcribed

image text in transcribed

image text in transcribed

image text in transcribed

package nachos.threads; import nachos. machine.*; * A KThread is a thread that can be used to execute Nachos kernel code. Nachos * allows multiple threads to run concurrently. * To create a new thread of cxccution, first declare a class that implements * the stt>Runnable interface. That class then inplenents the stt>run * method. An instance of the class can then be allocated, passed as an * argument when creating KThread/tt, and forked. For example, a thread that computes pi could be written as follows: *

 class PiRun implements Runnable { public void run() { // compute pi } } * 
*

The following code would then create a thread and start it running: *

 * Pirun p = new PiRun(); new kThreadip).fork(); * 
*/ public class KThread * Get the current thread. * @return the current thread. / public static KThread currentThread() { Lib.assertTrue current Thread != null); return currentThread; } - Allocate a new stt>KThreadIf this is the first KThread/tt>, * create an idle thread as well! () if (currentThread != null) { tcb = new TCB(); } else readyQueue = Threadedkernel.scheduler.newThreadQueue(false); readyQueue. acquire(this); currentThread - this; tcb = TCB. Current TCB(); nane = "main": restoreState(); createIdleThread(); } } /** * Allocate a new KThread. * @param target the object whose method is called. */ public KThread(Runnable target) this(); this.target = target; } / * Set the target of this thread. * @param target the object whose run method is called. * @return this thread. public KThread setTarget(Runnable target) { Lib.assertTruel status -- statusNew); this.target = target: = : return this; ** * Set the name of this thread. This name is used for debugging purposes only. * @param nane the name to give to this thread. * @return this thread. public KThread setName(String name) { this.name = name; return this; } - Get the name of this thread. This name is used for debugging purposes * only. * @return the name given to this thread. public String getName() { return nane; } Get the full name of this thread. This includes its name along with its * numerical ID. This name is used for debugging purposes only. * @return the full name given to this thread. */ public String toString) { return (name = " (*" + 1d + ")"); } /** * Deterministically and consistently compare this thread to another * thread. */ public int compareTo(Object ) { KThread thread - (Thread) o; if (id thread. id) return 1; else return; } * 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 forknethod) and the other thread (which cxccutes * its target's run method). */ public void fork() { Lib.assertTruel status = statusNew); Lib.assert True target != null); Lib.debug (dbgThread, "Farking thread: " + toString() + " Runnable: " + target); boolean intStatus = Machine. interrupt().disable(); tcb.start(new Runnable public void runt) { runThread(); ready(); Machine. interrupt().restorel intStatus); } private void runThread) { begin(); target.run(); finish(); } private void begin() { Lib.debuglebgThread, "Beginning thread: " + toString()); Lib.assertTruel this == currentThread); restoreState(); Machine. interrupt().enable(); ] * 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 * runnethod returns, but it may also be called directly. * The current thread cannot be innediately destrayed because its stack and * other execution state are still in use. Instead, this thread will be * destroyed autonatically by the next thread to run, when it is safe to * delete this thread. */ public static void finish() { Lib.debug(dbathread, "Finishing thread: " + currentThread.toString()); Machine. interrupt().disable(); Machine.autoGrader().finishingcurrentThread(); Lib.assertTrueltoBeDestroyed == null); toBeDestroyed = currentThread; current Thread.status = statusFinished; sleep(); } * 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. *

* Returns innediately if no other thread is ready to run. Otherwise * returns when the current thread is chosen to run again by * readyQueue.nextThread()/tt. * * 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 yield()/to was * called with interrupts disabled. * public static void yield() { Lib.debug(dbgThread, "Yielding thread: " + currentThread.toString()); Lib.assert True current Thread.status == status Running); boolean intStatus = Machine. interrupt().disabled); current Thread.ready(); runNext Thread(); Machine. interrupt().restore{intStatus); ** - Relinquish the CPU, because the current thread has either finished or it is blocked. This thread nust be the current thread. *

- If the current thread is blocked on a synchronization primitive, i.c. * a Semaphore, Lock, or Condition), eventually - some thread will wake this thread up, putting it back on the ready queue * so that it can be rescheduled. Otherwise, stb>finish() 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; runNext Thread(); } * Moves this thread to the ready state and adds this to the scheduler's * ready queue public void ready ) { L1b.debug(dbgThread, "Ready thread: " + toString()); " + L1b.assertTrue (Nachine. interrupt().disabled()); Lib.assertTrue status != statusReady); status = statusRcady: if (this != idleThread) readyQucuc.waitForAccess(this); Machine.autoGrader().readyThread(this); } - 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(dbg Thread, "Joining to thread:" + toString()); Lib.assertTrue this != currentThread); if(this.status == statusFinished) { return; } } jainlock.acquire(); joinCondition.sleep(); jainlock. release(); } . * Create the idle thread. Whenever there are no threads ready to be run, * and ready() never adds the idle thread to the ready set. private static void createIdleThread() { { Lib.assertTruc idleThread == null; idleThread - new KIhread(new Runnable() { public void run() { while (true) yield(); } idleThread.setName("idle"); ) Machine.autoGrader().setIdleThread(idleThread); idleThread. fork(): } * Deternine the next thread ta run, then dispatch the CPU to the thread * using run()private static void runNext Thread() { KThread nextThread = readyQueue.nextThread(); it next Thread == null) next Thread = idleThread; nextThread.run(); } * Dispatch the CPU to this thread. Save the state of the current thread, * switch to the new thread by calling DTCB.context switch), and * load the state of the new thread. The new thread becomes the current * thread. * *

saveState(), context Switch(), and * true if the current thread 15 finished, and should be destroyed by the new thread. ** private void run() { Lib.assertTrue(Nachine. interrupt().disabled()); Machine.yleld(); currentThread. saveState(); Lib.debug IdboThread, "Switching from: " + currentThread.toString() to: " + toString()); currentThread = this; tcb.context switch(); currentThread.restoreState(); ) } * 7 * Prepare this thread to be run. Set stt>status to * statusRunning and check toBeDestroyed. protected void restoreState() { Lib.debug(dogThread, "Running thread: " + currentThread.toString()); Lib.assertTrue (Nachine. interrupt().disabled()); Lib.assert Truel this -- current Thread); Lib.assertTrueltcb = TCB.currentTCB{}); Machine.autoGrader().runningThread(this); status = statusRunning; if (toBebestroyed != null) { taBeDestroyed. tcb.destroy); tabelestroyed, tcb = null; toBeDestroyed = null; } } 112* * Prepare this thread to give up the processar. Kernel threads do not need to do anything here. */ protected void saveState() { Lib.assert True Machine interrupt().disabled()); Lib.assert True this -- current Thread); } private static class PingTest implements Runnable { PingTest{ int which) { this.which - which; } public void run() ( for (int i=0; i; i++) { Systen.out.println("est thread " + which + " looped + i + " tines"); currentThread yield(); } private int which; } / * Tests whether this module is working. public static void selfTest() { Lib.debugdboThread, "Enter KThread.selfTest"); new kThread(new PingTest(1)).setNane("forked thread").fork(); new PingTest().run(); } private static final char dbg Thread = 't'; 10 * Additional state used by schedulers. * esce nachos.threads.PriorityScheduler.ThreadState */ public Object schedulingState = null; private static final int statusNew = B; private static final int statusReady = 1; private static final int statusRunning = 2; private static final int statusBlocked = 3; private static final int statusFinished = 4; /** * The status of this thread. A thread can either be new (not yet forked), * ready (on the ready queue but not running), running, or blocked (not * on the ready queue and not running). */ private int status = statusNew; private String name = "(unnamed thread)"; private Runnable target; private TCB tcb; /** * Unique identifer for this thread. Used to deterministically compare * threads. */ private int id = numCreated++; /** Number of times the KThread constructor was called. */ private static int numCreated = 0; private static ThreadQueue readyQueue = null; private static KThread currentThread = null; private static KThread toBeDestroyed = null; private static KThread idleThread = null; public Lock joinLock = new Lock(); public Condition2 joinCondition = new Condition2(joinLock); } package nachos.threads; import nachos. machine.*; * A KThread is a thread that can be used to execute Nachos kernel code. Nachos * allows multiple threads to run concurrently. * To create a new thread of cxccution, first declare a class that implements * the stt>Runnable interface. That class then inplenents the stt>run * method. An instance of the class can then be allocated, passed as an * argument when creating KThread/tt, and forked. For example, a thread that computes pi could be written as follows: *

 class PiRun implements Runnable { public void run() { // compute pi } } * 
*

The following code would then create a thread and start it running: *

 * Pirun p = new PiRun(); new kThreadip).fork(); * 
*/ public class KThread * Get the current thread. * @return the current thread. / public static KThread currentThread() { Lib.assertTrue current Thread != null); return currentThread; } - Allocate a new stt>KThreadIf this is the first KThread/tt>, * create an idle thread as well! () if (currentThread != null) { tcb = new TCB(); } else readyQueue = Threadedkernel.scheduler.newThreadQueue(false); readyQueue. acquire(this); currentThread - this; tcb = TCB. Current TCB(); nane = "main": restoreState(); createIdleThread(); } } /** * Allocate a new KThread. * @param target the object whose method is called. */ public KThread(Runnable target) this(); this.target = target; } / * Set the target of this thread. * @param target the object whose run method is called. * @return this thread. public KThread setTarget(Runnable target) { Lib.assertTruel status -- statusNew); this.target = target: = : return this; ** * Set the name of this thread. This name is used for debugging purposes only. * @param nane the name to give to this thread. * @return this thread. public KThread setName(String name) { this.name = name; return this; } - Get the name of this thread. This name is used for debugging purposes * only. * @return the name given to this thread. public String getName() { return nane; } Get the full name of this thread. This includes its name along with its * numerical ID. This name is used for debugging purposes only. * @return the full name given to this thread. */ public String toString) { return (name = " (*" + 1d + ")"); } /** * Deterministically and consistently compare this thread to another * thread. */ public int compareTo(Object ) { KThread thread - (Thread) o; if (id thread. id) return 1; else return; } * 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 forknethod) and the other thread (which cxccutes * its target's run method). */ public void fork() { Lib.assertTruel status = statusNew); Lib.assert True target != null); Lib.debug (dbgThread, "Farking thread: " + toString() + " Runnable: " + target); boolean intStatus = Machine. interrupt().disable(); tcb.start(new Runnable public void runt) { runThread(); ready(); Machine. interrupt().restorel intStatus); } private void runThread) { begin(); target.run(); finish(); } private void begin() { Lib.debuglebgThread, "Beginning thread: " + toString()); Lib.assertTruel this == currentThread); restoreState(); Machine. interrupt().enable(); ] * 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 * runnethod returns, but it may also be called directly. * The current thread cannot be innediately destrayed because its stack and * other execution state are still in use. Instead, this thread will be * destroyed autonatically by the next thread to run, when it is safe to * delete this thread. */ public static void finish() { Lib.debug(dbathread, "Finishing thread: " + currentThread.toString()); Machine. interrupt().disable(); Machine.autoGrader().finishingcurrentThread(); Lib.assertTrueltoBeDestroyed == null); toBeDestroyed = currentThread; current Thread.status = statusFinished; sleep(); } * 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. *

* Returns innediately if no other thread is ready to run. Otherwise * returns when the current thread is chosen to run again by * readyQueue.nextThread()/tt. * * 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 yield()/to was * called with interrupts disabled. * public static void yield() { Lib.debug(dbgThread, "Yielding thread: " + currentThread.toString()); Lib.assert True current Thread.status == status Running); boolean intStatus = Machine. interrupt().disabled); current Thread.ready(); runNext Thread(); Machine. interrupt().restore{intStatus); ** - Relinquish the CPU, because the current thread has either finished or it is blocked. This thread nust be the current thread. *

- If the current thread is blocked on a synchronization primitive, i.c. * a Semaphore, Lock, or Condition), eventually - some thread will wake this thread up, putting it back on the ready queue * so that it can be rescheduled. Otherwise, stb>finish() 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; runNext Thread(); } * Moves this thread to the ready state and adds this to the scheduler's * ready queue public void ready ) { L1b.debug(dbgThread, "Ready thread: " + toString()); " + L1b.assertTrue (Nachine. interrupt().disabled()); Lib.assertTrue status != statusReady); status = statusRcady: if (this != idleThread) readyQucuc.waitForAccess(this); Machine.autoGrader().readyThread(this); } - 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(dbg Thread, "Joining to thread:" + toString()); Lib.assertTrue this != currentThread); if(this.status == statusFinished) { return; } } jainlock.acquire(); joinCondition.sleep(); jainlock. release(); } . * Create the idle thread. Whenever there are no threads ready to be run, * and ready() never adds the idle thread to the ready set. private static void createIdleThread() { { Lib.assertTruc idleThread == null; idleThread - new KIhread(new Runnable() { public void run() { while (true) yield(); } idleThread.setName("idle"); ) Machine.autoGrader().setIdleThread(idleThread); idleThread. fork(): } * Deternine the next thread ta run, then dispatch the CPU to the thread * using run()private static void runNext Thread() { KThread nextThread = readyQueue.nextThread(); it next Thread == null) next Thread = idleThread; nextThread.run(); } * Dispatch the CPU to this thread. Save the state of the current thread, * switch to the new thread by calling DTCB.context switch), and * load the state of the new thread. The new thread becomes the current * thread. * *

saveState(), context Switch(), and * true if the current thread 15 finished, and should be destroyed by the new thread. ** private void run() { Lib.assertTrue(Nachine. interrupt().disabled()); Machine.yleld(); currentThread. saveState(); Lib.debug IdboThread, "Switching from: " + currentThread.toString() to: " + toString()); currentThread = this; tcb.context switch(); currentThread.restoreState(); ) } * 7 * Prepare this thread to be run. Set stt>status to * statusRunning and check toBeDestroyed. protected void restoreState() { Lib.debug(dogThread, "Running thread: " + currentThread.toString()); Lib.assertTrue (Nachine. interrupt().disabled()); Lib.assert Truel this -- current Thread); Lib.assertTrueltcb = TCB.currentTCB{}); Machine.autoGrader().runningThread(this); status = statusRunning; if (toBebestroyed != null) { taBeDestroyed. tcb.destroy); tabelestroyed, tcb = null; toBeDestroyed = null; } } 112* * Prepare this thread to give up the processar. Kernel threads do not need to do anything here. */ protected void saveState() { Lib.assert True Machine interrupt().disabled()); Lib.assert True this -- current Thread); } private static class PingTest implements Runnable { PingTest{ int which) { this.which - which; } public void run() ( for (int i=0; i; i++) { Systen.out.println("est thread " + which + " looped + i + " tines"); currentThread yield(); } private int which; } / * Tests whether this module is working. public static void selfTest() { Lib.debugdboThread, "Enter KThread.selfTest"); new kThread(new PingTest(1)).setNane("forked thread").fork(); new PingTest().run(); } private static final char dbg Thread = 't'; 10 * Additional state used by schedulers. * esce nachos.threads.PriorityScheduler.ThreadState */ public Object schedulingState = null; private static final int statusNew = B; private static final int statusReady = 1; private static final int statusRunning = 2; private static final int statusBlocked = 3; private static final int statusFinished = 4; /** * The status of this thread. A thread can either be new (not yet forked), * ready (on the ready queue but not running), running, or blocked (not * on the ready queue and not running). */ private int status = statusNew; private String name = "(unnamed thread)"; private Runnable target; private TCB tcb; /** * Unique identifer for this thread. Used to deterministically compare * threads. */ private int id = numCreated++; /** Number of times the KThread constructor was called. */ private static int numCreated = 0; private static ThreadQueue readyQueue = null; private static KThread currentThread = null; private static KThread toBeDestroyed = null; private static KThread idleThread = null; public Lock joinLock = new Lock(); public Condition2 joinCondition = new Condition2(joinLock); }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions

Question

4. Identify cultural variations in communication style.

Answered: 1 week ago