Comp. Sys. Org. II (V22.0202.003)
Homework 6
Implementation of Semaphores
Assigned: Apr 21
Due: May 3 (no late homework)
Introduction
In this homework, you continue to extend the
toy machine STM. In the previous homework,
you had already extended it to
run multiple processes. Now you need to
get these multiple processes to perform simple
synchronizations.
There are two parts to this assignment:
in the first part, you modify your previous STML
program for GCD so that different processes running
this GCD program will synchronize their input and outputs.
In the second part, you modify STM to support semaphores.
There is an optional part for extra credit.
This homework should be easier than the previous one on STM.
For one thing, it involves writing less code;
for another, you are already familiar with the STM.
Semaphore System
There are 8 semaphores, indexed 0-7. Each semaphore consists of
a value , which is a non-negative integer, and a
FIFO queue of processes waiting for the semaphore.
The operations on the semaphores are defined as follows.
DOWN(s):
{ if (s > 0) s--;
else block the current process --
i.e. take the current process off the ready queue and
put it at the end of the queue of processes waiting for s.
}
UP(s)
{ QW = the queue of processes waiting for s;
if (QW is empty) then s++;
else { P = pop the first process off QW;
push P onto the end of the ready queue.
}
}
Semaphore operations are invoked by STML code by doing traps to the
kernel. Specifically, to execute DOWN(s), load the code 3 into register
R15, load the index of semaphore s into register R14, and execute
the instruction "TRP".
To execute UP(s), load the code 4 into register
R15, load the index of semaphore s into register R14, and execute
the instruction "TRP".
At the start of execution, semaphores are initialized to 1.
Example
The STML file fractionx.stm
has a modified version of "fraction.stm" in which semaphores are used
to enforce mutual exclusion on the reading and the writing section of
the code. Semaphore 0 protects the reading; semaphore 1 protects the writing.
The result is that if several instances of "fractionx.stm" are run
in parallel, the inputs to each process all sequential, and the
outputs are all sequential, whereas hw 5 interspersed reading from
the different processes and interspersed the outputs from the different
processes.
The particular example shown here has the command line
"stm -d DEBUG fractionx.stm fractionx.stm fractionx.stm":
Note:
1/7 base 10 is .142857 ...
13/19 base 100 is .68 42 10 52 63 ...
700/1001 base 1000 is .699 300 699 300 ...
Context switches
A call to UP or DOWN causes a context switch only in the case where
the current process blocks doing a DOWN. Otherwise, the rules for
context switches is the same as in hw 5. Putting these all
together, therefore, the rule for context switches is this:
Let P be the current process, and let Q be the next process on the
ready queue.
- If P terminates either deliberately or due to an error, then Q is
resumed, and P is not placed on any queues;
- else, if P executes DOWN(s) and has to block, then Q becomes the active
process, and P is placed at the end of the queue of processes waiting for s;
- else, if P executes a READ or WRITE or P comes to the end of its
quantum, then Q becomes the active process and P is placed at the end
of the ready queue;
- otherwise, P remains the active process; there is no context switch.
Debugging output
If the debugging flag is 1 or 2, the program should generate a trace statement
each time an UP or DOWN occurs, stating that the operation has occurred.
If the operation causes a process to block or to unblock, that should
be stated.
Part 1: GCD with Semaphores
In the previous homework, you wrote a gcd.stm program.
The program reads two input numbers and outputs their gcd.
The input of these 2 numbers might be interspersed.
To prevent interspersing, we
want you to enclose these two input
operations with a DOWN(0) and UP(0) operation
(using semaphore 0).
For output, you must modify your gcd.stm program
to store in local storage all the intermediate remainders
of computing gcd. E.g., gcd(26, 19)=1 will produce the
following sequence of remainders: 7, 4, 3, 1.
Instead of just outputting a single number "1", you must output
this entire sequence. However, you must ensure
that this sequence is printed without interruption.
So you need to enclose the output of this sequence
by a DOWN(1) and UP(1) operation (using semaphore 1).
REMARK: be sure that DOWN(1), UP(1) applies
only to the output operations, not to the computation
of these remainders.
STML Assembler from David Stewart
Your classmate David has
written an assembler in Perl scripting
language for STML. Here is his README file.
This could speed up your coding in STML.
Part 2: Implementing Semaphors
As usual, the coding should be done using C.
Collaborations are encouraged, but all coding
and write-up must represent your own work.
You can take as your starting point either:
- Your own solution to hw5.
- Any of your classmates' solutions to hw 5, with their permission
You should indicate in a comment who gave you the solution to hw 5.
Of course all the extensions needed to do THIS homework must be your own.
What you mainly need to do is:
- Implement data structures for the semaphores and the waiting queues.
- Write procedures for DOWN and UP, and invoke them from "exec_trap"
- Fix the context switching procedure to handle the new cases.
- Initialize the semaphores at the beginning of execution.
Submitting your work
-
Your solution must be emailed to the grader, Chien-I Liao (cil217@nyu.edu),
but cc to me (yap@cs.nyu.edu).
-
Be sure to include your name, email address,
and ID number in a comment at the top of the source code. This programming
must be done in C; no other programming language will be accepted.
-
All your files should be packaged into a single tar file
called "hw6-xxxx.tar" where xxxx is your last name.
We do not want to handle multiple files.
-
Your submission must include the following files:
(0) a textfile file called README,
(1) a Makefile (with a capital "M") which is just an extension
of the Makefile which we provided,
(2) "gcd.stm" (your gcd program in STML),
(3) "stm-xxxx.c" which is your modified version of stm.c
(where xxxx is your lastname),
(4) the program fractionx.stm. This is to ensure that we
can instantly test your program after unpacking the tar file.
-
Make sure that all your source codes are properly commented.
-
The README file must identify this homework and you, and it must
give an overview of your modifications.
Data structures and important routines must be identified
and explained here.
-
The Makefile should include these targets:
(a) the default target should simply compile stm-xxxx.c.
(b) A target called "gcd" that runs stm-xxxx on one copy of "gcd.stm".
(c) Two targets called "t1" and "t2" that test
stm-xxxx on multiple processes.
Grading
-
This homework is worth 120 points.
-
20 points will be for the "gcd.stm" code.
-
Your stm-xxxx program will be tested on examples other
than those provided here.
If it does not compile, you get a maximum of 25 points.
-
If it only gets as far as beginning execution of each
of the STM modules, you get a maximum of 50 points.
-
Good program structure and adequate commenting are worth 15 points.
-
Following our submission instructions is worth 10 points.
Extra Credit
Please do not attempt this unless you have done the
above requirements.
The input and output of STM only handle numbers.
Let us extend input/output to reading/writing of ascii characters.
The TRP instruction with
R15=5 will cause an input of ascii characters, and
R16=6 will cause an output of ascii characters.
The value of R14 indicate the number of ascii characters
to read or write.
Finally, R13 contains the address of the start of the
input/output buffer area. Of course, you should
reserve a sufficiently large block of memory for this buffer.
To get the full extra credit, you need to implement
this new feature, and also use it in your
gcd.stm program in part 1, as follows:
-
(a) Your gcd program should print "> Arg 1: "
and "> Arg 2: " to precede the requests for input numbers.
Note that prefix the output lines with "> "
to distinguish it from user input lines.
-
(b) Your gcd program should output "> GCD = ..."
instead of simply outputing "..." as the final value.
-
(c) After computing the gcd program,
it should print "> Continue? "
and accept a "Y" or "N" from the user. If "Y", it
should continue to ask for another pair of arguments, compute
their gcd, and so on.
GRADING COMMENTS from Grader Chien-I
-
Remember that you are in an Operating System
with 218 words of memory. So all your
semaphores, queues, process table, etc should use mem[].
That means that some of the memory should be
reserved for the use of the operating system.
-
Some of your programs could not handle the case
where m=n or when m is a multiple of n.