CPSC 213: Assignment 7

Due Fri Nov 9, 6pm


In this assignment you will investigate interrupts and asynchronous programming by reading and modifying a program that uses signals to trigger asynchronous actions. This assignment is closely modeled on the asynchronous disk read example discussed in the lecture and gives you a chance to experience this sort of programming first hand, using a software environment that mimics hardware interrupts. You will be working entirely in C.

Interrupts and Asynchronous Programming

Download the package for this assignment and extract it. You will be modifying the file async.c, a short C program. You should SSH into one of the x86 ugrad.cs.ubc.ca machines (annacis, bowen, deas, lulu) to edit, compile, and debug your code. Compile it with the command

gcc -g -m32 -o async async.c 
and run it with ./async or debug it with gdb async (You should run these commands in the same directory that you compiled the code.) This program ends with an infinite loop; make sure to kill it when it is done by typing Control-C so that it does not run forever! This program uses a Unix OS feature called "signals" to mimic hardware interrupts. In the boot procedure, the program registers interruptServiceRoutine as a signal handler for the SIGALRM signal and then tells the OS to deliver this signal to the program once every second. The program includes a method called doAsync that schedules an asynchronous event, sort of like a disk-read request. These events complete in order, one at a time, each time the SIGALRM is delivered to the program. The doAsync procedure enqueues events on a circular completion queue and interruptServiceRoutine dequeues these completion events when SIGALRMs arrive and delivers the completion by calling the completion routine with two parameters, a pointer and an int, whose meaning is determined by the completion routine. You will note the use of the type void*. This type is called an "opaque pointer" and is used to store pointers of any type. The program includes a small example of the use of this system to asynchronously print three strings. This program is a simplified version of what an I/O controller does: some work is done with doAsync, and then it uses SIGALRM to signal that the work has been completed. In this simple example, the OS isn't really doing anything other than regularly delivering signals.

Task 1: Understand and Comment Existing Code

Your first task is to insert detailed comments in the program to carefully explain every data structure and procedure. You should read, compile, and run the program to understand what it does. Do not add comments to individual lines of code, but ensure that your other comments are detailed enough to fully explain what this code does. Use the man command as necessary to get the documentation for functions such as signal and ualarm, and so on. If man presents you with multiple options, choose the commands from sections 3 and 3p.

Task 2: Modify Code

Your second task is to modify this program to use the doAsync procedure and this framework to implement a program using the asynchronous operations add and subtract. Each should be implemented by a procedure that is never called directly but that is instead caused to run by doAsync. First, define a struct Triple with struct members arg0, arg1, result, and complete that hold the arguments and result for a simple computation. The complete field should indicate whether the computation has been completed. Then, write two simple procedures: 1. add (void* xp, int n) that casts xp to a struct Triple pointer and computes xp->result = xp->arg0 + xp->arg1. 2. sub (void* xp, int n) that casts xp to a struct Triple pointer and computes xp->result = xp->arg0 - xp->arg1. Finally, write a procedure that uses only these two procedures and the doAsync procedure to compute the value of the expression ((A+B)-(C+D))+E, where A, B, C, D, and E are the first through fifth digits of your student number, except with 0 replaced by 10 (e.g. if your student number is 12305678, compute ((1+2)-(3+10))+5.) Store the final result in a global variable, and terminate the program after printing its value. A key challenge here is that some of operations use results from previous operations. You cannot do the subtraction until the additions for (A+B) and (C+D) have completed. You will thus need to synchronize your program to some extent. Implement this synchronization using a shared variable whose value indicates whether the computation can continue and then "spin" on this variable until it has this value. For example, the code while (n != 1) {} waits until the variable n has the value 1. This approach is an example of polling a variable for a value using a spinlock. More sophisticated alternatives will be covered later in the course.


Provided Materials

Handing In

Use the handin program. The assignment directory is a7. Please hand in exactly and only the following files with the specified names.

  1. README.txt that contains
  2. async.c containing your modified version of the provided async.c, as described above

File Format Requirements

Refer to the section of the same name in the second assignment for the file format requirements. All files you handin MUST be plain ASCII text, and all source code MUST compile on the ugrad Linux x86 machines in order to receive credit for it.

Last modified 2012-10-27 18:45