Question: Objective: To implement Thread scheduling on the OSP2 simulator using a version of the Linux constant time strategy. You will implement the module ThreadCB.java to
Objective: To implement Thread scheduling on the OSP2 simulator using a version of the Linux constant time strategy. You will implement the module ThreadCB.java to further your understanding of CPU scheduling.
Building and Executing the simulation: As in the previous assignment, I suggest that you create a new directory. Copy your files from the previous cpu scheduling project and starting with that version of ThreadCB.java modify it to create the Linux constant time scheduling solution. The only file you should have to modify is ThreadCB.java. Modifying the other files will probably "break" OSP2. The changes you need to make to your code from the previous project are:
1) You will need to create two priority arrays of queues: an active array and an expired array (see figure 5.16 on page 212 of Silbershatz). In our case we will simplify and have only priority values of 0 to 9, i.e. the active array and expired array will each be comprised of 10 queues.
2) In do_create(), the newly created thread will be assigned the default priority value 4 and be placed in the expired array in the queue for threads having priority 4.
3) In do_resume(), when inserting a thread into the readyQueue, if the priority of the thread is not already at the highest level (0), then it is raised by decrementing it. (recall that 0 is the highest priority). The thread is then placed in appropriate queue of the expired array. This is how threads have their priority raised.
4) In do_dispatch() when the current thread is preempted, you need to check if the reason that it is being preempted is because its quantum has expired. Do this by calling HTimer.get(). This returns the time left until the timer interrupts. If the return value is less than 1, then the timer has interrupted indicating that this thread has exceeded its quantum. If this is the case, then lower the priority of the thread by incrementing its priority value. Then insert it into the appropriate queue of the expired array. This is how threads have their priority lowered. If on the other hand the value returned from HTimer is positive nonzero, then the thread has not exceeded its quantum and should be keep its current priority. In this case, place it in the corresponding queue of the expired array.
5) In do_dispatch(), threads with priority values in the range 0-4 should dispatched with a quantum value of 40 and threads with priority values in the range 5-9 should be dispatched with a quantum value of 20.
6) When do_dispatch()is invoked, you will look in the active array for a thread to dispatch. Start with the highest priority queue (priority 0). If it is empty, then look at the next highest priority queue. Continue until either you find a thread to dispatch or you determine that the active array is completely empty. If the active array is completely empty, then swap the active array and the expired array and start the search for a thread to launch all over again. Only if both the active array and the expired array are empty should you idle the CPU by setting PTBR to null and returning FAILURE. Suggestion: write a method to return the next thread from the active array or null if the active array is empty. This will be a lot cleaner than inserting the corresponding code into do_dispatch().
Here is the code that needs to be modified:
package osp.Threads;
import java.util.Vector;
import java.util.Enumeration;
import osp.Utilities.*;
import osp.IFLModules.*;
import osp.Tasks.*;
import osp.EventEngine.*;
import osp.Hardware.*;
import osp.Devices.*;
import osp.Memory.*;
import osp.Resources.*;
/**
This class is responsible for actions related to threads, including
creating, killing, dispatching, resuming, and suspending threads.
@OSPProject Threads
*/
public class ThreadCB extends IflThreadCB
{
/**
The thread constructor. Must call
super();
as its first statement.
@OSPProject Threads
*/
static GenericList readyQueue;
public ThreadCB()
{
//called super(); because it is the first statement
super();
}
/**
This method will be called once at the beginning of the
simulation. The student can set up static variables here.
@OSPProject Threads
*/
public static void init()
{
readyQueue = new GenericList();
}
/**
Sets up a new thread and adds it to the given task.
The method must set the ready status
and attempt to add thread to task. If the latter fails
because there are already too many threads in this task,
so does this method, otherwise, the thread is appended
to the ready queue and dispatch() is called.
The priority of the thread can be set using the getPriority/setPriority
methods. However, OSP itself doesn't care what the actual value of
the priority is. These methods are just provided in case priority
scheduling is required.
@return thread or null
@OSPProject Threads
*/
static public ThreadCB do_create(TaskCB task1)
{
//Checks to see if the task is null, and if it is, then the code calls the dispatcher
if(task1 == null)
{
dispatch();
return null;
}
/** if task already have the max # of threads it calls dispatcher
and returns null.
*/
if(task1.getThreadCount() == MaxThreadsPerTask)
{
dispatch();
return null;
}
//Creates a new thread for the readyQueue
ThreadCB NewThread = new ThreadCB();
NewThread.setPriority(task1.getPriority());
NewThread.setStatus(ThreadReady);
NewThread.setTask(task1);
if (task1.addThread(NewThread)==0)
{
dispatch();
return null;
}
readyQueue.append(NewThread);
dispatch();
return NewThread;
}
/**
Kills the specified thread.
The status must be set to ThreadKill, the thread must be
removed from the task's list of threads and its pending IORBs
must be purged from all device queues.
If some thread was on the ready queue, it must removed, if the
thread was running, the processor becomes idle, and dispatch()
must be called to resume a waiting thread.
@OSPProject Threads
*/
public void do_kill()
{
//checks up on the status of current thread
if(this.getStatus() == ThreadReady)
{
readyQueue.remove(this);
}
else if(this.getStatus() == ThreadRunning)
{
if(MMU.getPTBR().getTask().getCurrentThread() == this)
{
MMU.getPTBR().getTask().setCurrentThread(null);
MMU.setPTBR(null);
}
}
this.getTask().removeThread(this);
this.setStatus(ThreadKill);
for(int i = 0; i { Device.get(i).cancelPendingIO(this); } ResourceCB.giveupResources(this); ThreadCB.dispatch(); if(this.getTask().getThreadCount() == 0) { this.getTask().kill(); } } /** Suspends the thread that is currently on the processor on the specified event. Note that the thread being suspended doesn't need to be running. It can also be waiting for completion of a page fault and be suspended on the IORB that is bringing the page in. Thread's status must be changed to ThreadWaiting or higher, the processor set to idle, the thread must be in the right waiting queue, and dispatch() must be called to give CPU control to some other thread. @param event - event on which to suspend this thread. @OSPProject Threads */ public void do_suspend(Event event1) { if(this.getStatus() == ThreadRunning) { if(MMU.getPTBR().getTask().getCurrentThread() == this) { MMU.getPTBR().getTask().setCurrentThread(null); MMU.setPTBR(null); } this.setStatus(ThreadWaiting); } else if (this.getStatus() >= ThreadWaiting) { this.setStatus(this.getStatus()+1); } if(ThreadCB.readyQueue.contains(this)) { ThreadCB.readyQueue.remove(this); } event1.addThread(this); ThreadCB.dispatch(); } /** Resumes the thread. Only a thread with the status ThreadWaiting or higher can be resumed. The status must be set to ThreadReady or decremented, respectively. A ready thread should be placed on the ready queue. @OSPProject Threads */ public void do_resume() { //continues the 'ThreadWaiting' status of a thread if(getStatus() { MyOut.print(this," is attempting to resume " + this + ";" + "which wasn't waiting"); return; } MyOut.print(this, "Continues" + this); if(getStatus() == ThreadWaiting) { setStatus(ThreadReady); } else if(getStatus() > ThreadWaiting) { setStatus(getStatus()-1); //getstatus() minus 1 } if(getStatus() == ThreadReady) { readyQueue.append(this); } dispatch(); } /** Selects a thread from the run queue and dispatches it. If there is just one the read ready to run, reschedule the thread currently on the processor. In addition to setting the correct thread status it must update the PTBR. @return SUCCESS or FAILURE @OSPProject Threads */ public static int do_dispatch() { //chooses a thread and dispatches it ThreadCB Thread2= null; try { Thread2 = MMU.getPTBR().getTask().getCurrentThread(); } catch(NullPointerException e) { e.printStackTrace(); } if(Thread2 != null) { Thread2.getTask().setCurrentThread(null); MMU.setPTBR(null); Thread2.setStatus(ThreadReady); readyQueue.append(Thread2); } if(readyQueue.isEmpty()) { MMU.setPTBR(null); return FAILURE; } else { Thread2 = (ThreadCB)readyQueue.removeHead(); MMU.setPTBR(Thread2.getTask().getPageTable()); Thread2.getTask().setCurrentThread(Thread2); Thread2.setStatus(ThreadRunning); } HTimer.set(50); return SUCCESS; } /** Called by OSP after printing an error message. The student can insert code here to print various tables and data structures in their state just after the error happened. The body can be left empty, if this feature is not used. @OSPProject Threads */ public static void atError() { // dont need code here } /** Called by OSP after printing a warning message. The student can insert code here to print various tables and data structures in their state just after the warning happened. The body can be left empty, if this feature is not used. @OSPProject Threads */ public static void atWarning() { //dont need code here } /* Feel free to add methods/fields to improve the readability of your code */ } /* Feel free to add local classes to improve the readability of your code */
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
