nachos threads system road map through the code lab 3
DESCRIPTION
Important Classes Thread : resembles PCB that contains info about the thread, status and registers. List : a simple linked list with elements that points to void*, thus it can contain any element type (in our case it will be Thread ). Scheduler : contains the ready queue which is an instance of the List class.TRANSCRIPT
NachOS
Threads System
Road Map through the Code
Lab 3
./threads Directory Files
• copyright.h scheduler.cc synch.cc• system.ccthreadtest.cc list.cc• scheduler.h synch.h system.h• utility.cc list.h switch.h• synchlist.cc thread.cc utility.h• main.cc switch.s synchlist.h• thread.h
Important Classes
• Thread : resembles PCB that contains info about the thread, status and registers.
• List : a simple linked list with elements that points to void* , thus it can contain any element type (in our case it will be Thread).
• Scheduler : contains the ready queue which is an instance of the List class.
Important Classes
• Interrupt : the interrupt vector (interrupt status).
• Statistics : the object that will collect statistics about the system operations.
• Timer : resembles the hardware timer (in this lab you will implement the alarm clock class from it).
Important Objects
• NachOS –specifically threads lab- contain some important global objects.
• These objects are defined to be extern.• extern objects are accessible from all
places in the program.• They are made extern so that they will
be dealt as a container.
Important Objects
• These objects are defined in the system.cc file, and to use them you have include system.h file in each file that uses these objects.
• These objects are defined as pointers to objects not as regular objects.
Important Objects• extern Thread * currentThread;• extern Thread * threadToBeDestroyed;• extern Scheduler * scheduler;• extern Interrupt * interrupt;• extern Statistics * stats;• extern Timer * timer;
• The file also contains other objects that may be instantiated if you are working on other labs.
• An important something that has to be noticed that thread systems (source code) lab is used in other labs, i.e. in the multiprogramming lab.
currentThread Object
• It points to the thread that is grabbing the CPU now.
• This thread is out of the ready queue.• Its status is RUNNING.
threadToBeDestroyed Object
• It points to the thread that is to be destroyed after calling the Finish method on that thread object.
• Its status is BLOCKED.• Initially it is pointing to NULL.
scheduler Object• It points to the scheduler object.• Contains the ready queue.• Its function members represents the
scheduling algorithm that is used (now it is FCFS).
interrupt Object• interrupt This pointer points to the
interrupt vector of the processor. It will be always turned off whenever the kernel is taking the control of the processor, i.e. in the case of context switching.
stats + timer Object• stats :This pointer points to an object of
type Statistics, this object will store some statistical information about the operation of the system such as the number of characters read or sent by a socket.
• timer :resembles the hardware of timer.
Class Thread• Important Public Members:
– Thread (char * name);– ~Thread();– void Yield();– void Sleep();– void Finish();– void CheckOverflow();– void setStatus();
Class Thread• Important Private Members:
– int * stackTop;– int * stack;– int machineState[machineStateSize];– ThreadStatus status;– char * name;– // some members if running user programs– AddressSpace * space;– int userResgisters[NumTotalRegs];– Void SaveUserState();– Void RestoreUserSpace();
Class Thread• One must be aware of the difference
between:– Process and a Thread.– Thread scheduling and Process scheduling.– Context switching of a Threads and Context
switching of a Processes.
Thread::Thread(char * name)
• Initialize the thread name.• Set its state to JUST_CREATED;
Thread::~Thread()
• Deallocate the initialized stack.
Thread::Fork(VoidFunctionPtr, int arg)
• Allocate the stack for the thread. • If we are running a user process we have to
allocate an address space for the process and registers to be used by the kernel.
• Set its state to READY.• Put this thread on the rear of the ready
queue.
Thread::Yield()
• Find next thread to allocate the CPU for it.• Put the currentThread on the rear of the
ready queue.• Initiates the current thread to run
Thread::CheckOverFlow()
• After doing context switching it is preferable to check if the stack overflowed or not.
• The stackSize is defined to be 1024 * 4 bytes.
• If there is an overflow an ASSERT –assertion failure- will occur.
• If this happens just increase the stackSize to a greater integer.
Thread::Finish()
• Set the pointer thradToBeDestroyed to the calling thread.
• Call Sleep() method.
Thread::Sleep()
• Set the state of the thread to BLOCKED .• Find the next thread from the ready queue
and initiates it to run.
Class Scheduler• Important Public Members:
– Scheduler();– ~ Scheduler();– void ReadyToRun(Thread * thread);– Thread * FindNextToRun();– void Run();– void Print();
Class Scheduler• Important Private Members:
– List * readyList;
Scheduler::Scheduler()• Constructor create a pointer to readyList
via new operator.
Scheduler::~Scheduler()• Destructor delete the pointer readyList via delete operator.
void Scheduler::ReadyToRun(Thread * thread)
• Make the thread state to READY.• Append the thread to the rear of the ready
queue
Thread * Scheduler::FindNextToRun()
• Returns a pointer to the thread at the head of the ready queue after removing it from the queue.
void Scheduler::Run(Thread * nextThread)
• Do the context switching between the currentThread and nextThread.
• Then it will check for overflow.• Set the state of the currentThread to
RUNNING.• If we running a user thread we have ti save
the user space
Class Interupt• One method of class Interrupt is important
to know:– IntSatus Interrpt::SetLevel(IntSatus satus );
• This method set the interrupt vector to the status value and returns the old value of the vector.
• There is an enum data type IntOff that turns off all interrupts.
NachOS code executionmain.cc
# include “system.h”
NachOS code executionmain.cc
# include “system.h”
NachOS code executionmain.cc
# include “system.h”system.cc
Thread * currentThread;Thread * threadToBeDestroyed;Scheduler * scheduler;Interrupt * interrupt;Statistics * stats;Timer * timer;
NachOS code executionmain.cc
# include “system.h”system.cc
Thread * currentThread;Thread * threadToBeDestroyed;Scheduler * scheduler;Interrupt * interrupt;Statistics * stats;Timer * timer;
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);
system.ccThread * currentThread;Thread * threadToBeDestroyed;Scheduler * scheduler;Interrupt * interrupt;Statistics * stats;Timer * timer;
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);
system.ccvoid Initialize(int argc, char
** argv){// execute some parsing code// to get the debug flagsDebugInit (debugArgs);stats = new Statistics();interrupt = new Interrupt();acheduler = new Scheduler();If (some condition in debug flags)
timer = new Timer();currentThread = new Thread(“main”);currentThread->setStatus(RUNNING);interrupt->Enable();
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);
system.ccvoid Initialize(int argc, char
** argv){// execute some parsing code// to get the debug flagsDebugInit (debugArgs);Stats = new Statistics();Interrupt = new Interrupt();Scheduler = new Scheduler();If (some condition in debug flags)
timer = new Timer();currentThread = new Thread(“main”);currentThread->setStatus(RUNNING);interrupt->Enable();
}
This will create a thread named “main”
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);
system.ccvoid Initialize(int argc, char
** argv){// execute some parsing code// to get the debug flagsDebugInit (debugArgs);Stats = new Statistics();Interrupt = new Interrupt();Scheduler = new Scheduler();If (some condition in debug flags)
timer = new Timer();currentThread = new Thread(“main”);currentThread->setStatus(RUNNING);interrupt->Enable();
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
This will create a thread named “forked thread”
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
1- This will allocate a stack for this thread by executing SimpleThread function and passing 1 as a parameter to the function.
2- Put t thread on the ready queue.
3- set its status to READY.
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
This will execute SimpleThread in the thread main with an argument of 0
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
Thread * Scheduler::FindNextToRun(){
return (Thread *)readyList->Remove();}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
Thread * Scheduler::FindNextToRun(){
return (Thread *)readyList->Remove();}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
Thread * Scheduler::FindNextToRun(){
return (Thread *)readyList->Remove();}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
void Scheduler::ReadyToRun(Thread * thread){
thread->setStatus(READY);readyList->Append((void *)thread);
}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
void Scheduler::ReadyToRun(Thread * thread){
thread->setStatus(READY);readyList->Append((void *)thread);
}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
void Scheduler::Run(Thread * nextThread){
Thread * oldThread = currentThread;// save status if using another user programoldThread->CheckOverflow();currentThread = nextThread; currentThread->setStatus(RUNNING);SWITCH(oldThread,nextThread); // this will do CSif (threadToBeDestroyed!=NULL){
delete threadToBeDestroyed; threadToBeDestroyed = NULL;
}// restore new thread space if using another user// program
}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
void Scheduler::Run(Thread * nextThread){
Thread * oldThread = currentThread;// save status if using another user programoldThread->CheckOverflow();currentThread = nextThread; currentThread->setStatus(RUNNING);SWITCH(oldThread,nextThread); // this will do CSif (threadToBeDestroyed!=NULL){
delete threadToBeDestroyed; threadToBeDestroyed = NULL;
}// restore new thread space if using another user// program
}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionthread.cc
void Thread::Yield(){
Thread * nextThread;IntStatus oldState = interrupt->SetLevel(IntOff);nextThread = scheduler->FindNextToRun();if(nextThread!=NULL){
scheduler->ReadyToRun(this);scheduler->Run(nextThread);
}interrupt->SetLevel(oldStatus);
}
void Scheduler::Run(Thread * nextThread){
Thread * oldThread = currentThread;// save status if using another user programoldThread->CheckOverflow();currentThread = nextThread; currentThread->setStatus(RUNNING);SWITCH(oldThread,nextThread); // this will do CSif (threadToBeDestroyed!=NULL){
delete threadToBeDestroyed; threadToBeDestroyed = NULL;
}// restore new thread space if using another user// program
}
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
Now start executing in the thread “forked thread” at the start of the function (the value of that thread PC)
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
Keep on this tone until thread “main” reaches num=5 then it will exits
SimpleTest function and returb to the main function
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();....currentThread->Finish();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();....currentThread->Finish();
threadtest.ccvoid SimpleThread(int which){
for(num=0;num<5;++num){
printf(“*** thread %d looped %d times\n”,which,num);
currentThread->Yield();
}}void ThreadTest(){
Thread * t = new Thread(“forked thread”);t->Fork(SimpleThread,1);SimpleThread(0);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();....currentThread->Finish();
thread.ccvoid Thread::Finish(){
interrupt->SetLevel(IntOff);threadToBeDestroyed = currentThread;Sleep();
}
Void Thread::Sleep(){
Thread * nextThread;status = BLOCKED;while ((nextThread=scheduler->FindNextToRun())==NULL)
interrupt->Idle();scheduler->Run(nextThread);
}
NachOS code executionmain.cc
# include “system.h”Initialize(argc,argv);ThreadTest();....currentThread->Finish();
thread.ccvoid Thread::Finish(){
interrupt->SetLevel(IntOff);threadToBeDestroyed = currentThread;Sleep();
}
Void Thread::Sleep(){
Thread * nextThread;status = BLOCKED;while ((nextThread=scheduler->FindNextToRun())==NULL)
interrupt->Idle();scheduler->Run(nextThread);
}
NachOS code executionscheduler.cc
void Scheduler::Run(Thread * nextThread){
Thread * oldThread = currentThread;// save status if using another user programoldThread->CheckOverflow();currentThread = nextThread;currentThread->setStatus(RUNNING);SWITCH(oldThread,nextThread); // this will // do CSif (threadToBeDestroyed!=NULL){
delete threadToBeDestroyed; threadToBeDestroyed = NULL;
}// restore new thread space if using another user// program
}
thread.ccvoid Thread::Finish(){
interrupt->SetLevel(IntOff);threadToBeDestroyed = currentThread;Sleep();
}
Void Thread::Sleep(){
Thread * nextThread;status = BLOCKED;while ((nextThread=scheduler->FindNextToRun())==NULL)
interrupt->Idle();scheduler->Run(nextThread);
}
NachOS code executionscheduler.cc
void Scheduler::Run(Thread * nextThread){
Thread * oldThread = currentThread;// save status if using another user programoldThread->CheckOverflow();currentThread = nextThread;currentThread->setStatus(RUNNING);SWITCH(oldThread,nextThread); // this will // do CSif (threadToBeDestroyed!=NULL){
delete threadToBeDestroyed; threadToBeDestroyed = NULL;
}// restore new thread space if using another user// program
}
thread.ccvoid Thread::Finish(){
interrupt->SetLevel(IntOff);threadToBeDestroyed = currentThread;Sleep();
}
Void Thread::Sleep(){
Thread * nextThread;status = BLOCKED;while ((nextThread=scheduler->FindNextToRun())==NULL)
interrupt->Idle();scheduler->Run(nextThread);
}
At this point “forked thread” finds that it has
reached at the end of its program so it returns the
control to the kernel which will be the
scheduler
Assignment # 3
• In the assignment you are required to solve questions 1,2,4,8 and 10 from the assignment posted on the website.
• The assignment is due to next Thursday 6/5/2004.