Executing the scheduler
Your program will be a single executable "scheduler" that takes no
command line arguments. Since this means you can't specify any file
names, your scheduler must take its input from the UNIX standard input
and print to the standard output.
Input
The input to your program will be an ASCII stream of job control commands.
Each job is identified by a positive integer, and has a duration and a
"niceness" value. (The higher the niceness, the less attention the job
will get.)
The first line of the input will contain the maximum job number. While
no job number will ever exceed this maximum, it may be possible for
more than this number of jobs to be submitted by reusing the numbers of
jobs that have completed. The test data that we will supply (in the
directory /usr/class/cs161/project/data) will never submit a
new job with the same id as an active job, so if your program detects
such a request, it's an indication that something's wrong with your job
queue.
Each subsequent line of the input will be one of the following:
tick RUN job duration niceness
tick KILL job
tick NICE job niceness
tick TOP
The tick numbers indicate the time at which the command has been
submitted. They will always appear in non-decreasing order.
The job numbers are positive integers.
The other numeric arguments are non-negative integers.
The RUN command submits a new job to put into the queue. The KILL
command indicates that a job should be removed from the queue
immediately. The NICE command causes a job's "niceness" to be set to
the specified value and its priority to be re-evaluated. The TOP
command shows the job at the top of the priority queue.
Library routines
The main objective of this project is to implement an efficient
priority queue structure. So that you can concentrate on that aspect,
we will provide you with a library of routines that handle I/O and the
job priority and aging computations. When we evaluate the performance
of your program, the running times of these routines will be subtracted
out and only the time spent in your own code will be counted.
The library /usr/class/cs161/project/lib/projlib.a contains the
following routines:
- newPriority(int CPUusage,int nice)
- computes a job's priority based on it's "niceness" and its CPU usage so far
- compare(unsigned long long a,unsigned long long b)
- compares two priorities, returning -1/0/1 if a's priority
value is lower than/equal to/higher than b's. If two
priorities are equal, you should break the tie yourself by pretending
that the job with the lower job id number had the lower priority.
- ageCPUusage(int CPUusage,int nice)
- "ages" a job, giving a modified estimate of its recent CPU usage
- initialize(void)
- must be called at the start of your program
- finalize(void)
- must be the last function called at the end of your
program. Reports the number of comparisons made and then exits the
program.
- readCommand(void)
- reads a command line from stdin. Puts the first letter
of the command (in upper case) into the global variable
cmdletter. Puts the command time, job id, job duration, and
job niceness in cmdtick, cmdjobid,
cmdduration, cmdnice respectively, when appropriate.
When the input is exhausted, cmdletter becomes '\0'
- printTop(int jobid,int duration,int nice,int heapsize)
- Prints a line on stdout indicating the clock time, the
queue size, and the parameters of the job at the top of the queue.
This should be called when a TOP command is issued, and also when a job
is completed. If the job queue is empty when a TOP command is issued, you should use 0 for the jobid parameter.
If you add your own diagnostic output on
stdout, please begin each line with a # character so
that it can be easily discarded when analyzing the output.
- warn(char *s)
- reports the command number, the clock time, and the supplied error
message.
- die(char *s)
- reports the command number, the clock time, and the supplied error
message, then exits the program.
- pritostr(unsigned long long p)
- returns a hexadecimal representation of the priority p.
The returned pointer is to a static storage area. (Shouldn't be
needed)
- strtopri(char *s)
- converts a hexadecimal string to an unsigned long long.
(Also shouldn't be needed)
Prototypes for these procedures are in the header file
/usr/class/cs161/project/src/projlib.h. You do not need the
directory prefix if you use the standard makefile.
Handling Priorities
The values returned by newPriority are scrambled in such a way as
to be meaningless to anyone except the compare routine. There
is really no need for you to know the exact values of the priorities,
only their relative order, so this shouldn't present a problem. You
can substitute your own functions to replace newPriority and
compare during testing if you feel it's necessary, but the
program you submit has to use the library routines,
otherwise you won't be using the right priority values.
The Scheduler
In /usr/class/cs161/project/src/scheduler.c we have provided
you with the skeleton of our own scheduler.
Most of the details of the code are missing, but it should give you a
precise idea of what the operation of the scheduler should be. You do
not have to adhere to this code's structure (and some changes could
definitely make it more efficient), but your scheduler must produce the
same results.
The one part of the supplied scheduler that must be preserved is the
constant CPU_PER_TICK. This is defined in the
projlib.h header file.
Preparing your account
You must have an account on the elaine machines in Sweet Hall
to do the project. All of the materials we will supply for the project will
reside in the directory /usr/class/cs161/project.
You can arrange your workspace any way you like. When the time comes
for you to submit your project, just make sure your project directory
contains all the necessary project files/directories. Only the approved
source and documentation files will be submitted. See the submission page for details.
We recommend that you add /usr/class/cs161/project/bin to
your PATH environment variable, so that you can omit the
whole directory prefix when executing our scripts.
Compiling
Your code must compile on one of the elaine machines in Sweet Hall,
using the Makefile found in /usr/class/cs161/project/src/Makefile.
This means that you must supply your code in two files
"scheduler.c" and "pqops.c", plus any of your own
header files that you need to include.
The command /usr/class/cs161/project/bin/161make will run this
makefile for you.
Verifying and Evaluating
An executable of our (highly inefficient) scheduler is in
/usr/class/cs161/project/bin/161scheduler. If your program is
working correctly, this program's output will be identical to yours.
Remember that your program will be judged on the correctness of the output,
the number of comparisons performed, and the out-of-library running time. We
have supplied a script /usr/class/cs161/project/bin/161run that runs
a scheduler some number of times and computes the average running time (total
time and out-of-library time). You can use this script to measure the efficiency
of your program versus ours. This script leaves output files and profiling data
in your directory, which you can clean out with the command /usr/class/cs161/project/bin/161clean.
Submitting
NOTE: There is a separate submission web page with a much more detailed description of the submission requirements.
When you are ready to submit your program, clear your directory of
unnecessary files and run the
/usr/class/cs161/project/bin/161submit script. The script
will ignore the usual output files and profile data when it can.
Please do not submit other large files or profile data, as there is
limited space in the class directory. All you really need to submit
are your writeup and source files, since we will recompile everything
for evaluation. We will be using the same Makefile we supplied to you,
so be sure your program compiles properly with it.
Your writeup should contain the names of everyone in your project
group, and each group should only make one submission. If you need to
re-submit, make sure you do so from the same user's account as before.