Upload
lynne-carroll
View
217
Download
0
Embed Size (px)
Citation preview
BrickOS SchedulingBrickOS Scheduling
Solving The Low-Priority Solving The Low-Priority Starvation ProblemStarvation Problem
IntroductionIntroduction
Jon RogersJon Rogers
Robbie EdwardsRobbie Edwards
Melanie SparksMelanie Sparks
Project DescriptionProject Description
Investigate the way the scheduling Investigate the way the scheduling algorithm is currently implemented. algorithm is currently implemented. Change it so that higher priority processes Change it so that higher priority processes cannot starve the low priority processes.cannot starve the low priority processes.
Project FacetsProject Facets
1 Researching the problem1 Researching the problem
2 Defining a solution2 Defining a solution
3 Building a development environment3 Building a development environment
4 Modifying the source code4 Modifying the source code
5 Testing and verification5 Testing and verification
Researching The ProblemResearching The Problem
Research the operating system schedulerResearch the operating system scheduler
Identify the relevant source codeIdentify the relevant source code
Determine the current scheduling Determine the current scheduling implementation implementation
Researching The Problem - Researching The Problem - ResultsResults
BrickOS employs a preemptive scheduler BrickOS employs a preemptive scheduler with a prioritized round-robin algorithm for with a prioritized round-robin algorithm for choosing the next process to run.choosing the next process to run.
Researching The Problem - Researching The Problem - Detailed ResultsDetailed Results
Each process is given a default time slice Each process is given a default time slice of 20ms to run before being interrupted by of 20ms to run before being interrupted by the OS and another process is allowed to the OS and another process is allowed to runrun
In choosing the next process to run, the In choosing the next process to run, the OS searches through each process OS searches through each process queue, beginning with the highest priority queue, beginning with the highest priority queue, and runs the first READY processqueue, and runs the first READY process
Hence The Problem -Hence The Problem -
If there are always processes of higher If there are always processes of higher priority that are ready to run, lower priority priority that are ready to run, lower priority processes will be starved outprocesses will be starved out
Defining A SolutionDefining A Solution
The Challenge: to prevent starvation while The Challenge: to prevent starvation while preserving process prioritypreserving process priorityThe Solution: Chain Wait, another The Solution: Chain Wait, another selection parameterselection parameterChain Wait will numerically represent the Chain Wait will numerically represent the maximum number of scheduler executions maximum number of scheduler executions for which a particular priority chain will be for which a particular priority chain will be exempt (e.g. no processes from this exempt (e.g. no processes from this priority chain will be chosen: waiting)priority chain will be chosen: waiting)
The AlgorithmThe Algorithm
Initialization: All chain wait values will be set Initialization: All chain wait values will be set to zeroto zero
Scheduler will do a linear search through the Scheduler will do a linear search through the priority chains for runnable processespriority chains for runnable processes
Upon running a process, the chain wait for Upon running a process, the chain wait for its priority queue will be set to 20-P+1, its priority queue will be set to 20-P+1, where P is the numeric priority and where P is the numeric priority and scheduler will resume its linear searchscheduler will resume its linear search
The AlgorithmThe Algorithm
For each priority queue with a chain wait For each priority queue with a chain wait greater than zero, decrement the chain greater than zero, decrement the chain wait and move to the next queue ignoring wait and move to the next queue ignoring ready processes from this queueready processes from this queue
If the linear search is complete and no If the linear search is complete and no runnable processes are found, all chain runnable processes are found, all chain waits are reset to 0waits are reset to 0
Building A Development Building A Development EnvironmentEnvironment
Installation of Cygwin on the target Windows Installation of Cygwin on the target Windows machinemachineBuilding the Hitachi-H8 cross-compiler : a trivial Building the Hitachi-H8 cross-compiler : a trivial initialization followed by a very long compile initialization followed by a very long compile processprocessInstalling BrickOSInstalling BrickOSInstalling the USB tower and driversInstalling the USB tower and driversTesting the environment : Testing the environment :
Hello World and Play Song Hello World and Play Song Testing the environment, part II : creating a test Testing the environment, part II : creating a test program that counts down and plays a songprogram that counts down and plays a song
Changing The Source Code – Changing The Source Code – Additions To tm.hAdditions To tm.h
Implementation begins with adding a new function, Implementation begins with adding a new function, "tm_clear_waits()", that will (as advertised) clear the chain "tm_clear_waits()", that will (as advertised) clear the chain waits, resetting them to zero.waits, resetting them to zero.
void tm_clear_waits() {void tm_clear_waits() {pchain_t* priority;pchain_t* priority;priority = priority_head;priority = priority_head;while((int) priority->priority >= PRIO_LOWEST) while((int) priority->priority >= PRIO_LOWEST)
{{priority->chain_wait = 0;priority->chain_wait = 0;priority = priority->next;priority = priority->next;
}}}}
Changing The Source Code – Changing The Source Code – Additions To tm.cAdditions To tm.c
Implementation of the solution continues with the Implementation of the solution continues with the introduction of a new field, an integer "chain_wait", to the introduction of a new field, an integer "chain_wait", to the existing data structure struct _pchain_t, in the tm.h existing data structure struct _pchain_t, in the tm.h header fileheader file
struct _pchain_t {struct _pchain_t {
priority_t priority; // numeric priority levelpriority_t priority; // numeric priority level
struct _pchain_t *next; // lower priority chainstruct _pchain_t *next; // lower priority chain
struct _pchain_t *prev; // higher priority chainstruct _pchain_t *prev; // higher priority chain
struct _tdata_t *ctid; // current task in chainstruct _tdata_t *ctid; // current task in chain
int chain_wait; // # of times to be ignored by schedulerint chain_wait; // # of times to be ignored by scheduler
};};
Changing The Source Code - Changing The Source Code - Changes To tm.c Changes To tm.c
We modified tm.c inside the function "size_t We modified tm.c inside the function "size_t *tm_scheduler(size_t *old_sp)" at the point *tm_scheduler(size_t *old_sp)" at the point where the next process must be chosenwhere the next process must be chosen
This scheduler function is called by the process This scheduler function is called by the process switcher which in turn is called by a yield switcher which in turn is called by a yield functionfunction
Yield is called by an function that becomes a Yield is called by an function that becomes a zombie [through "exit(..)"], when a process has zombie [through "exit(..)"], when a process has used its timeslice [through systime_handler(..)], used its timeslice [through systime_handler(..)], or when a process sleeps [through or when a process sleeps [through wait_event(..)].wait_event(..)].
Original CodeOriginal CodeThe original code, in which we will choose the next process..The original code, in which we will choose the next process..
while(1) {while(1) { if(next->tstate==T_SLEEPING) if(next->tstate==T_SLEEPING) // if the next task is SLEEPING // if the next task is SLEEPING break;break; // we just run it // we just run it if(next->tstate==T_WAITING) {if(next->tstate==T_WAITING) { // if it's WAITING, wake it and run it // if it's WAITING, wake it and run it ...... break;break; }} }} if(next == priority->ctid) {if(next == priority->ctid) { // if done searching this priority queue // if done searching this priority queue ...... priority = priority->next;priority = priority->next; // search the next priority queue// search the next priority queue ...... next=priority->ctid->next;next=priority->ctid->next; // move to the next one in line in that priority// move to the next one in line in that priority } } else next=next->next;else next=next->next; // otherwise we're still searching this queue// otherwise we're still searching this queue }}
New CodeNew Code
Inside the while loop that searches for the next process, the code is Inside the while loop that searches for the next process, the code is modified as follows:modified as follows:
while(1) {while(1) {
if(priority->chain_wait > 0) {if(priority->chain_wait > 0) { // If there is a chain wait for this priority level// If there is a chain wait for this priority level --(priority->chain_wait);--(priority->chain_wait); // then decrement the wait.// then decrement the wait. if(priority->next != NULL) {if(priority->next != NULL) {
if((int) priority->next->priority < PRIO_LOWEST) if((int) priority->next->priority < PRIO_LOWEST)
{{ // If we have ignored the lowest priority // If we have ignored the lowest priority levellevel tm_clear_waits();tm_clear_waits(); // then clear all chain waits and begin the// then clear all chain waits and begin the priority=priority_head;priority=priority_head; // search for a process again at the highest// search for a process again at the highest next=priority->ctid->next;next=priority->ctid->next; // priority level.// priority level.}}
New CodeNew Code
else {else { priority = priority->next; priority = priority->next; // Otherwise, // Otherwise, next = priority->ctid->next; next = priority->ctid->next; }} //search the next priority //search the next priority
level.level.
}}...... // debugging code omitted // debugging code omitted else priority = priority_head;else priority = priority_head;...... }}
New CodeNew Code
else {else {
if(next->tstate==T_SLEEPING)if(next->tstate==T_SLEEPING) // if the next task is SLEEPING,// if the next task is SLEEPING, break;break; // we just run it// we just run it if(next->tstate==T_WAITING) { if(next->tstate==T_WAITING) { // if it's WAITING // if it's WAITING
......
break;break; // wake it and run it// wake it and run it
}} // sound familiar?// sound familiar? }}
... ... // the remainder of the code// the remainder of the code }} // inside the while loop is unmodified// inside the while loop is unmodified
Changing The Source CodeChanging The Source Code
Upon exiting the while loop that selects the next Upon exiting the while loop that selects the next process to run, set the process' priority level's process to run, set the process' priority level's chain wait. chain wait.
priority->chain_wait = ((int) PRIO_HIGHEST - (int) priority->priority) + 1;priority->chain_wait = ((int) PRIO_HIGHEST - (int) priority->priority) + 1;
For example, if PRIO_HIGHEST is 20 and the For example, if PRIO_HIGHEST is 20 and the process to be executed is of priority 10, then the process to be executed is of priority 10, then the chain wait for priority level 10 will be set to (20-chain wait for priority level 10 will be set to (20-10)+1 = 11.10)+1 = 11.
Changing The Source CodeChanging The Source Code
And the last bit of code added, within the And the last bit of code added, within the process "tid_t execi(..)" upon initializing a process "tid_t execi(..)" upon initializing a new priority queue the chain_wait must new priority queue the chain_wait must also be setalso be set
......
newpchain->priority=priority;newpchain->priority=priority;
newpchain->chain_wait = 0; // initialize chain_wait to 0newpchain->chain_wait = 0; // initialize chain_wait to 0
newpchain->ctid=td;newpchain->ctid=td;
......
Testing And VerificationTesting And Verification
Loading the new operating systemLoading the new operating system
Documenting the lack of starvationDocumenting the lack of starvation
Showing that all threads run no matter the Showing that all threads run no matter the prioritypriority
Testing And Verification - CodeTesting And Verification - Code
The test program: gizmo.cThe test program: gizmo.c
pid2=execi(&motor_driver, 0, NULL, 20, pid2=execi(&motor_driver, 0, NULL, 20, DEFAULT_STACK_SIZE);DEFAULT_STACK_SIZE);
pid3=execi(&foo1, 0, NULL, 20, DEFAULT_STACK_SIZE);pid3=execi(&foo1, 0, NULL, 20, DEFAULT_STACK_SIZE);
pid4=execi(&foo2, 0, NULL, 20, DEFAULT_STACK_SIZE); pid4=execi(&foo2, 0, NULL, 20, DEFAULT_STACK_SIZE);
pid5=execi(&foo3, 0, NULL, 10, DEFAULT_STACK_SIZE);pid5=execi(&foo3, 0, NULL, 10, DEFAULT_STACK_SIZE);
Testing And Verification - CodeTesting And Verification - Code
In the old brickOS, this process would have In the old brickOS, this process would have been starved out. But not in ours.been starved out. But not in ours.
pid6=execi(&playSong, 0, NULL, 1, pid6=execi(&playSong, 0, NULL, 1, DEFAULT_STACK_SIZE);DEFAULT_STACK_SIZE);
You know the scheduler is working correctly You know the scheduler is working correctly when you hear the song playing.when you hear the song playing.
Testing And Verification - Testing And Verification - ResultsResults
The song played repeatedly, indicating that The song played repeatedly, indicating that the forked process with priority zero was the forked process with priority zero was not starved out by the higher priority not starved out by the higher priority processes. All processes were shown to processes. All processes were shown to have been scheduled.have been scheduled.
Thank You And Good Night Thank You And Good Night