ECE469 Lab2

EE469 Spring 2004 Lab 2, Due Feb 17 Midnight

Material related to the project

An introduction to programming with threads is an excellent tutorial on the subject. You should find it useful additional reading.

Assignments

  1. Changes to DLXOS: For the purpose of this lab, we have changed the DLXOS to fit our requirements. You will have to copy this new version of DLXOS (version lab2.tar.gz) for these changes to be visible to you. The tar file of this new version of DLXOS is located at /home/shay/g/ee469/labs/common/lab2.tar.gz.
    Specifically, we have made the following three changes:

    1. User Programs: We have modified the main() routine in process.c to load the user-specified executable program with user-specified command-line parameters. Suppose you have a user program called userprog.dlx.obj (it can be any program, the name is not important), you can run it using the following command:

      dlxsim -x os.dlx.obj -a -u userprog.dlx.obj [param1 param2 ...]

      where param1, param2, ... are the optional command-line parameters to the user program. Note that the name of the user program must follow the -u option, and the rest of the parameters from the command line are passed to the user program as command-line arguments. If you have never written any C programs that take command-line arguments, now is the time to go back to your C books.

    2. New APIs: DLXOS does not support threads. In order to solve some of the problems in this lab, eg., the bounded buffer problem, several processes need to share some memory, e.g. used for the shared buffer in the producer-consumer. We have provided you with a primitive implementation of shared memory support for your use. In addition, we have also added user-level access to semaphores, and have provided support for starting user process from a user program. You can download the documentation of these APIs from here.

    3. Examples on using the new APIs: We have provided two example C files: userprog.c and userprog2.c. The Makefile is modified in such a way that these files will automatically be compiled when you type make in the directory, and will then be moved to the directory ../execs. To execute the example, you need to type

      dlxsim -x os.dlx.obj -a -u userprog.dlx.obj number

      where number is any number between 1 through 10. The program in userprog.c creates a shred memory page and two semaphores. It then creates number instances of program in userprog2.c and passes the shared page handle, the two semaphores, and number as command-line arguments to each instance. The program in userprog2.c in turn retrieves these parameters, maps the memory page to it's memory space, prints the number that you had provided, and exits. These files will help you understand how to use the provided APIs.

  2. (15 points) Using the (given) semaphore APIs, implement producer/consumer communication through a bounded buffer, using semaphores. The solution to the bounded buffer problem using semaphores is described in Silberschatz, Peterson and Galvin, and also explained in the class.Test your solution with a multi-character buffer and with multiple producers and consumers. Of course, with multiple producers or consumers, the output display will be gobbledygook. However, note that a correct solution will not produce arbitrary output! Make sure your solution can be run using the command line

    dlxsim -x os.dlx.obj -a -u q2.dlx.obj [numproducers numconsumers]
    The output should be in the form:
    Producer X inserted: Y
    Consumer Z removed: A

    The string to be used is "Hello, world!" i.e. the producers will be producing characters from this string.

  3. (30 points) Implement synchronization primitives - locks and condition variables - using only the semaphores already provided in the system (no spinlocks allowed), to support monitor-like synchronization in DLXOS. The user-level interface is already provided in version lab2.tar.gz. See the file lab2-api.h for more details. Looking at the definition of sem_t, sem_create(int count), sem_wait(sem_t sem), sem_signal(sem_t sem), from the API that we have provided will give you some clues about this part. Note that it is not a good idea to accept or provide pointers to an OS-level construct from or to a user process, as it can cause security loopholes. Hence we always deal with handles, and not pointers.

    All your implementations should be done within synch.c and synch.h by filling up the missing parts. The functions should have all the functionality explained in those files. After your implementation of this part is complete, any user program that calls these functions should be able to execute correctly. In fact we will test your implementation by compiling our programs with your OS implementation.

  4. (15 points) Implement producer/consumer communication through a bounded buffer, using locks and condition variables. Make sure your solution can be run using the command line

    dlxsim -x os.dlx.obj -a -u q4.dlx.obj [numproducers numconsumers]

  5. (40 points) The atmosphere on the planet Krypton consists primarily of the elements Nitrogen and Oxygen and of their compound Nitrogen diOxide (N02). Trace quantities of Ozone (O3) have also been discovered. There are 2 primary chemical reactions that occur in the atmosphere:
    1) N + N -> N2
    2) O + O -> O2
    In addition, depending on the temperature, one(or both) of the following two chemical reactions takes place:
    a) N2 + 2O2 -> 2NO2 (At temperatures BELOW 50 degrees)
    b) 3O2 -> 2O3 (At temperatures ABOVE 100 degrees)
    When the temperature is BETWEEN 50-100 degrees (inclusive), BOTH a) AND b) take place

    The scientists of Krypton have asked us to help out with the terraforming of a new planet, christened Zaza. They require a program that
    a) Injects atoms of Nitrogen and Oxygen into the atmosphere
    b) Monitors the formation of the N2, O2, N02 and O3 molecules
    c) Prints out messages at every stage

    In order to solve this problem, you may think of each atom as a separate thread. Everytime a Nitrogen atom is created, you will have to print out the message "An atom of Nitrogen was created." Similarly, every time an atom of Oxygen is created, print out the message "An atom of Oxygen was created". Every time a molecule of either Nitrogen or Oxygen is created, print out the message "2 atoms of Nitrogen(or oxygen) combined to produce one molecule of N2 (or O2)".

    Depending on the temperature, NO2, O3 or both are created when enough molecules of the requisite compounds are present. Remember that the formation of NO2 and O3 are MOLECULAR and NOT ATOMIC operations. Thus, from equation (a), you need one MOLECULE of nitrogen and 2 MOLECULES of oxygen to produce 2 MOLECULES of NO2. Whenever reaction (a) takes place, print out the message "1 molecule of Nitrogen and 2 molecules of Oxygen combined to produce 2 molecules of Nitrogen diOxide". If, instead, Ozone was created, print out the message "3 molecules of Oxygen combined to produce 2 molecules of Ozone".

    Here is one method of implementing the solution...
    1) Each N atom invokes a procedure called nReady when it's ready to "react"and prints out the appropriate message (see above).
    2) Similarly, each O atom invokes oReady when it's ready to react. Again, print out messages.
    3) A procedure called makeNitrogen should be called when a molecule of Nitrogen is formed. The corresponding procedure for Oxygen is called makeOxygen.
    There are a number of ways of proceeding from this point on. You may think of makeNitrogen and makeOxygen as being both producers and consumers (since they "consume" 2 atoms to make a molecule of N2/O2 and they then "produce" one molecule of N2/2 molecules of O2 for the production of NO2). Another procedure called makeNO2 is then the "consumer" for NO2. You may similarly have a procedure for O3 called makeOzone. The trick is to synchronize appropriately between all of these procedures.

    Feel free to use semaphores or locks and condition variables to effect the synchronization.

    IMPORTANT:
    1) Make sure your solution can be run using the command line:

    dlxsim -x os.dlx.obj -a -u krypton.dlx.obj [# of N atoms] [# of O atoms] [temperature]

    2) Print out the appropriate messages ONLY!!!

    N.B.In the temperature range 50-100 degrees, both NO2 and O3 may be produced. The following rules apply:
    1) If NO2 can be formed, it should be formed IMMEDIATELY. Thus, if you have 2 molecules of Nitrogen and 2 molecules of Oxygen, you should form 1 molecule of NO2 immediately.
    2) Ozone should be formed only if the formation of NO2 is not possible (e.g. if there was one atom of Nitrogen and 7 molecules of Oxygen, 4 molecules of ozone should be formed, leaving one molecule of Oxygen and one atom of nitrogen)
    3) If both Ozone and NO2 can be formed, priority should be given to the NO2.

    What to turn in?

    Make four versions of your codes if necessary and call it lab2_q2, lab2_q3, lab2_q4, and lab2_q5.
    All your modifications have to be saved in the these directories and only these directories should be turned in by

    turnin -c ee469 -p labX-Y lab2_q2 lab2_q3 lab2_q4 lab2_q5 lab2_q5

    lab2_q2:    your dlxos/ directory containing solutions for question 2
    lab2_q3:    another version of the dlxos/ containing solutions for question 3
    lab2_q4:    another version of the dlxos/ containing solutions for question 4
    lab2_q5:    another version of the dlxos/ directory containing solutions for question 5

    Please include all of the files you used to build your project: source code, Makefiles, and any other scripts you may have used. In addition, please include a README file to explain anything unusual to the TA - testing procedures, etc.

    Make sure that each of the directories that you turn in contains an appropriate Makefile. The Makefile should be written in such a way that after typing make in the problem directory, all the executables will automatically be produced. So the Makefile for q2 should be written in such a way that after typing make in the directory q2, it should make all the executables (including os.dlx.obj, q2.dlx.obj, and any other programs you might have) and move the executables to the directory ../execs. Thus after running make in the directory q2, one should be able to execute the following commands and see your program run:

    cd ../execs
    dlxsim -x os.dlx.obj -a -u q2.dlx.obj [nproducers nconsumers]

    The same also holds for other directories. This is the preferred way for this assignment. If for some reason you cannot write such a Makefile, you may put detailed instructions about how to make various programs and how to run them in your README. But in that case you may loose some points depending on the complexity of the instructions. Try to stick to the preferred way so that you will not loose any points. If you do not know how to write a makefile, do man make. If you still do not understand, ask your TA.

    IMPORTANT: do NOT submit object files or other files generated by the DLX compiler or assembler. Every file in the handin directory that could be generated automatically by the DLX compiler or assembler will result in a warning from your TA of a 5-point deduction from your project grade. To do so, you should do 'make clean' before you turn in.


    ece469-tas@cs