Install qemu
. Then run:
$ make clean
$ make qemu-nox SCHEDULER=[OPTION]
Where possible options for SCHEDULER
are RR
(Round robin, also the default), FCFS
(First-come-first-serve), PBS
(Priority based scheduling), MLFQ
(Multilevel feedback queue scheduling)
- The
waitx
system call is similar to the defaultwait
system call, but it also returns the waiting time and running time of the child process. - To implemement this, the
proc
structure defined inproc.h
was modified and the fieldsctime
,etime
andrtime
representing creation time, exit time and runtime were added. ctime
is set to the current value ofticks
when a process is allocated usingallocproc
.etime
andrtime
are set to 0.- At every timer interrupt,
rtime
for all running processes is incremented by 1 (in thetrap
function intrap.c
). - Finally, when a process calls
exit
, theetime
is set to the current value of ticks. waitx
, just likewait
, scans the process table for zombie processes, and on finding one, frees the resources taken up by the process. The process'rtime
is returned as it is andwtime
is calculated aswtime
=etime
-ctime
-rtime
.
time
(defined intime.c
) is similar to the time command found in most shells.- The process forks into a parent and a child. The child process runs the program specified as the argument to
time
while the parent process waits for the child process to terminate usingwaitx
. - When the child process finishes,
waitx
returns in the parent process and copiesrtime
andwtime
to the specified pointers. The parent process then prints this information to the console.
- The
ps
user command is implemented using thepsx
system call inproc.c
. curr_wtime
,n_run
,cur_q
andq[5]
variables are added to theproc
structure.curr_wtime
is the time that the process has been waiting since the last time it ran. It is updated for every runnable process at every timer interrupt.n_run
is the number of times the processs has been picked by a scheduler. It is updated when thesceduler
switches to the process.cur_q
is used in case of MLFQ scheduling. It keeps track of which queue the process is currently in.q[i]
counts the number of ticks the process was runningin a particular queue.- The
ps
command calls thepsx
system call (which is very similar toprocdump
) and prints out the required information for all processes.
- For FCFS scheduling, the scheduler selects a runnable process with the lowest
ctime
. - Unlike Round Robin, scheduling need not happen at every tmer interrupt, so calling of
yield
at every timer interrupt is disabled for FCFS. - Hence, every process runs till it voluntarily gives up the CPU (by sleeping) or exits.
- A
priority
variable is added to theproc
structure. It ranges from 0 to 100. It is initialized to 60 when the process is allocated. - Whenever the scheduler is called, it picks a runnable process with the highes priority (i.e. lowest priority value).
- The
set_priority
system call(defined inproc.c
), accesssible via thesetPriority
user program (defined insetPriority.c
), searches the process table for a process with the given pid. If found, it sets thepriority
of that process to the new priority. If the new priority is higher than the old priority,yield
is called and the cpu enters the scheduler.
- A doubly linked list is used to implement the queues.
QUEUES[5]
is the array of pointers to the heads of each of the 5 queues. - As memory cannot be dynamically allocated for each node at runtime,
NODES[128]
is an array of nodes which can be assigned and deassigned for a process as required. - Functions for pushing to a queue, popping from a queue, deleting a particular element from a queue, assigning and deassigning a queue node are defined in
queue.c
.
- Whenever a process is initialized, or changes its state to
RUNNABLE
, it is pushed to the end of the highest priority queue. - The 5 queues, in decreasing order of priority, have time slices of 1,2,4,8 and 16.
- Each time the scheduler is called,
curr_rtime
is added to theproc
structure to keep track of how long a process has been running in a queue.- Whenever the scheduler is called, it first ages the processes. After that it picks the first runnable process from the highest priority non-empty priority queue.
curr_rtime
is reset for the process. The process is popped from it's queue. - At every timer interrupt,
curr_rtime
is incremented for the process. - The
proc
staructure is also added with the variableto_demote
, which is used to determine if the process needs to be demoted to a lower queue in case of using up its allowed time slic. - After every timer interuupt,
curr_rtime
for the running process is compared with it's allowed time slice. Ifcurr_rtime
is greater, thanto_demote
is set to 1 andyield
is called for rescheduling. - Once back in the scheduler, if the process is still runnable, it is pushed to an appropriate queue. If
to_demote
is set to 1, then the process is pushed to a lower priority queue usingdem_proc
, otherwise it is pushed to its original queue.
- To prevent starvation, aging is implemented.
curr_wtime
is used to determine whether a process should be aged or not. - The process table is scanned for finding runnable processes that should be aged. The criteria is that the
curr_wtime
for the process must be greater than the aging limit(currently 10 ticks). If that is the case, then the process is moved to higher priority queue usingpromote_proc
.
Running benchmark.c
showed the following results for different schedulers:
MLFQ:
Running time - 2024 clock cycles
Waiting time - 9 clock cycles.
PBS (without different priorities):
Running time - 2564 clock cycles
Wating time - 7 clock cycles
PBS (with different priorities):
Running time - 2211 clock cycles
Waiting time - 5 clock cycles
FCFS:
Running time - 2509 clock cycles
Wating time - 7 clock cycles
RR(Default):
Running time - 2004 clock cycles
Waiting time - 5 clock cycles