OPERATING SYSTEMS – ASSIGNMENT 2 SCHEDULING Task 1

OPERATING SYSTEMS – ASSIGNMENT 2
SCHEDULING
Task 1: Scheduling Policies
Scheduling is a basic and important facility of any operating system. The scheduler must
satisfy several conflicting objectives: fast process response time, good throughput for
background jobs, avoidance of process starvation, reconciliation of the needs of lowpriority and high-priority processes, and so on. The set of rules used to determine when
and how to select a new process to run is called a scheduling policy.
You first need to understand the current scheduling policy. Locate it in the code and
try to answer the following questions: which process the policy chooses to run, what
happens when a process returns from I/O, what happens when a new process is created
and when/how often the scheduling takes place.
First, change the current scheduling code so that swapping out running processes
will be done every quanta size (measured in clock ticks) instead of every clock tick.
#define QUANTA <int value>
Add this line to param.h and initialize the value of QUANTA to 5.
In the next part of the assignment you will add four different scheduling policies in
addition to the existing policy.
Add these policies by using the C preprocessing abilities.
Tip: You should read about #IFDEF macros. These can be set during
compilation by gcc (see http://gcc.gnu.org/onlinedocs/cpp/Ifdef.html)
Modify the Makefile to support ‘SCHEDFLAG’ – a macro for quick compilation
of the appropriate scheduling scheme. Thus the following line will invoke the xv6
build with Round Robin scheduling:
make qemu SCHEDFLAG=FRR
The default value for SCHEDFLAG should be DEFAULT (in the Makefile).
Tip: you can (and should!) read more about the make utility here:
http://www.opussoftware.com/tutorial/TutMakefile.htm
Policy 0: Default policy (SCHEDFLAG=DEFAULT)
Represents scheduling policy currently implemented at xv6.
Policy 1: FIFO Round Robin (SCHEDFLAG=FRR)
This policy will extend the previous default policy. In this policy the decision of which
process will run next will be on a First In - First Out basis. When a process finishes
running for QUANTA time, created or finishes waiting for I/O it is considered to be
the last process to arrive and wait for its next turn to run.
Policy 2: First Come First Served (SCHEDFLAG=FCFS)
This is a non-preemptive policy. Process that gets CPU runs until it no longer needs the
CPU (yield/finish/blocked). This policy is somewhat like FIFO Round Robin with
infinite quanta.
Policy 3: Multi Level Queues Scheduling (SCHEDFLAG=MLQ)
This policy will maintain three queues and work according to the following rules:



The first queue will hold the high priority processes. 
The second queue will hold medium priority processes.
The third queue will hold low priority processes.
A process with a higher priority will be preferred and run before a process with a
medium/lower priority. This means that no low or medium priority process will be
allowed to run while there are still high priority runnable processes (or running), and no
low priority process will be allowed to run while there are still medium priority runnable
processes.
You must implement system call int set_prioty(uchar priority) in order to have an ability
to change process' priority (where priority can be 0,1 or 2). On creation, the process will
receive a medium priority.
The processes in the first two queues will be scheduled according to FIFO Round Robin.
In the last queue processes will be scheduled in a First Come First Served (nonpreemptive) manner.
To keep things simple we will use same quanta (from policy 1 and 2) for all queues.
To define the priority mechanism for the processes you can change the ‘proc’ struct,
so that it will also support different priorities.
Policy 4: Multi-Core FIFO Round Robin (SCHEDFLAG=MC_FRR)
Scheduling Algorithms can get tricky when more than one CPU is involved. Sometimes,
it would benefit the system performance if the same process would always run on the
same CPU, instead of a different one each time it is scheduled. On other hand, the OS
may achieve even more efficiency on multi-CPU machine if a "smart" scheduling policy
in used. Another issue is multithreading. On a single-CPU system, multithreading (i.e.,
more than one control flow in a single address space) is a fine thing, and if done right can
greatly benefit a system's performance. But on a multiprocessor system, there are even
greater benefits to win - while at the same time it gets harder to achieve them.
One of the problems the OS developer will meet, while developing multi-CPU
scheduling policy, is inter-CPU synchronization. We certainly do not want that the same
process (at the same time) will run on more than one CPU in order to maintain the
system consistency.
Current xv6 implementation supports multi-core CPUs. In order to synchronize between
CPUs a spinlock is used. When one of CPUs searches for a process to run (i.e., executing
scheduler code) no one of other CPUs can execute a scheduler's code. This achieved by
acquiring a ptable spinlock. This approach used to solve former problem, but it hardly
affects OS efficiency: despite the fact that some CPUs can actually execute a process,
they must wait for their turn to get an ability to choose a process to run.
In this assignment we will solve this issue by introducing Multi-Core scheduling policy.
In order to achieve concurrency in multi-CPU scheduling, every CPU will maintain its
own process queue. When a new process created, it will be joined to the queue of the
CPU that the amount of the processes in its queue is minimal (tie-breaking by the CPU
id). At the time a CPU must choose a process to run it will choose the process from its
queue. This way we allow multiple-CPUs to choose a process to run simultaneously. But
such approach has a drawback: when a CPU cannot find a process to run in its queue,
there are may be still processes that can be run at other queues. In such case the CPU
must search other queues for RUNNABLE processes and if it find such process it will
transfer this process to its queue and run it.
Tip: you must use this technique very carefully; a special attention should be
given to inter-CPU synchronization.
Tip: figure out every piece of code that must be protected by an appropriate
spinlock.
For the sake of simplicity, every CPU must use a FIFO round robin scheduling policy. In
addition, to check the consistency of the OS, every process must maintain a set of
records for every time it was scheduled (the tick when its state changed to RUNNING,
the tick when its state changed to RUNNABLE/SLEEPING and the CPU id which
executed the process). You can assume that every process can be scheduled at most
10000 times.
Task 2: Performance Measures
After we have implemented different scheduling policies we will create the
infrastructure that will allow us to examine how they affect performance under different
evaluation metrics.
The first step is to extend the ‘proc’ struct located at proc.h (line 61). Extend the ‘proc’
struct by adding the following fields to it: ctime, etime, wtime and rtime. These will
respectively represent the creation time, end time, the total waiting and running time of
the process.
Tip: These fields retain sufficient information to calculate the turnaround time and
waiting time of each process.
Upon the creation of a new process the kernel will update the process’ creation time. The
run time should be incremented by updating the current process whenever a clock tick
occurs. Waiting time should be updated every clock tick when the state of the process is
SLEEPING. Finally, care should be taken in marking the end time of the process (note: a
process may stay in the ‘ZOMBIE’ state for an arbitrary length of time. Naturally this
should not affect the process’ turnaround time, wait time, etc).
Since all this information is retained by the kernel, we are left with the question of
extracting this information and presenting it to the user. To do so, create a new system
call wait2 which extends the wait system call.
int wait2(int *wtime, int *rtime, int *iotime)
Where the three arguments are pointers to integers to which the wait2 function will
assign:
(1) The aggregated number of clock ticks during which the process waited
(was able to run but did not get CPU)
(2) The aggregated number of clock ticks during which the process was
running
(3) The aggregated number of clock ticks during which the process was
waiting (was not able to run).
The wait2 function shall return the pid of the child process caught or -1 upon failure.
Implement int get_sched_record(int *s_tick, int *e_tick, int *cpu) system call that will
retrieve next record for current process and return start, stop and executing cpu id
accordingly. The system call must advance to next record or yield the process if no such
records exist.
Task 3: Sanity Test
In this section you will add an application which tests the impact of each scheduling
policy.
Add a program called sanity. This program will fork 20 child processes. Each child
process will have a unique id (from 0 to 19) denoted by cid. Every process will get a
priority based on its cid (i.e., the priority can be defined by cid mod 3). All processes
will immediately perform a time-consuming computation. We do not have any
restrictions regarding this computation, but make sure that every process will be
scheduled at least 5 times.
The code of the child processes will print its cid 500 times and will then call exit. The
parent process will wait until its children exit, and then print the average waiting time,
running time and turnaround time of all its children. It will then print the waiting time,
running time and turnaround time of all children in each priority group (i.e the statistics
for each group), followed by the waiting time, running time and turnaround time of each
child process.
Tip: to add a user space program, first write its code (e.g., sanity.c). Next update the Makefile
so that the new program is added to the file system image. The simplest way to achieve this is
by modifying the lines right after "UPROGS=\".
Tip: do not use printf system call in child processes implementation since this system call will
synchronize between the processes.
Tip: you have to call the exit system call to terminate a process' execution.
Tip: ensure the consistency of the system using get_sched_record system call just before
each process termination.
Submission Guidelines
Make sure that your Makefile is properly updated and that your code compiles with no
warnings whatsoever. We strongly recommend documenting your code changes with
comments – these are often handy when discussing your code with the graders.
Due to our constrained resources, assignments are only allowed in pairs. Please note this
important point and try to match up with a partner as soon as possible.
Submissions are only allowed through the submission system. To avoid submitting a large
number of xv6 builds you are required to submit a patch (i.e. a file which patches the
original xv6 and applies all your changes). You may use the following instructions to guide
you through the process:
Back-up your work before proceeding!
Before creating the patch review the change list and make sure it contains all the changes
that you applied and noting more. Modified files are automatically detected by svn but new
files must be added explicitly with the ‘svn add’ command:
> svn add <filename>
In case you need to revert to a previous version:
> svn revert <filename>
At this point you may examine the differences (the patch):
> svn diff
Alternatively, if you have a diff utility such as kompare:
> svn diff | kompare –o Once you are ready to create a patch simply make sure the output is redirected to the
patch file:
> svn diff > ID1_ID2.patch
Tip: Although grades will only apply your latest patch, the submission system supports multiple
uploads. Use this feature often and make sure you upload patches of your current work even if
you haven’t completed the assignment.
Finally, you should note that the graders are instructed to examine your code on lab
computers only!
We advise you to test your code on lab computers prior to submission, and in addition after
submission to download your assignment, apply the patch, compile it, and make sure
everything runs and works.
Enjoy !!!