CS 3013 Operating Systems I WPI, A Term 1996
Craig E. Wills Project 4 (25 pts)
Assigned: Monday, October 7, 1996 Due: Friday, October 18, 1996

Introduction

This assignment is intended to help you learn about device drivers by building part of a driver for a clock device, which is actually a Unix process. The clock will be used to handle alarms scheduled using a delta time list. You will use the Unix signal handling mechanism.

Problem

The basic idea of this assignment is to implement a delta time list for a set of time alarms that have been requested. You will write code for only one Unix process and a signal handler. You will use only one semaphore (described later) and NO shared memory in this assignment. The name of your executable should be alarm.

Figure 1 shows the general structure of your program. Instead of a real clock device, it is simulated by a clock device process that sends a software interrupt (using SIGALRM) to the main process every tick. The clock device process ticks every second. The clock device process can be created by using the CreateProcess() routine that we used previously as shown below:

  
Figure 1: Structure of your Program.

int myclock(int);

clockpid = CreateProcess(myclock, mainprocpid);

The clock device process needs to be passed the Unix pid of the main process so it knows where to send interrupts. The code for this process is in /usr/users/cs3013/lib/myclock.o. You should add this file to your Makefile. The routine itself is called myclock().

Your main program will be a scheduler of alarms for this assignment. It should read from standard input a list of ``character processes'' and length of time to wait before an alarm should go off. All alarms should go off the given number of seconds in the future. There will be no more than one alarm for each process. Sample input is given in the following:

C 3
B 6
A 5
D 1
E 5

Your main program should first process each line of input by reading it in and scheduling an alarm by calling a routine AddAlarm(), which you will need to write. This routine takes as its arguments a process represented by a single capital letter and the time this process wants to wait before receiving an alarm. The AddAlarm() routine should place the request in a delta list of alarm events. This list should be global (NOT in shared memory) so all of your code can access it, including the signal handler.

Your main program should continue reading alarm requests and scheduling them with AddAlarm() until EOF is detected. At this point your main program should go into a loop waiting for alarm events to be triggered and printing out each event as it occurs. Your main program should wait on a semaphore initialized to a count of zero. This semaphore should be signalled by the interrupt handler each time an alarm event has expired.

Interrupt Handler

Before beginning to read in input, your main program should set up an interrupt handler for the SIGALRM signal. This interrupt handler will be called each time a SIGALRM interrupt is received by your process from the clock device process. The interrupt handler manages the delta list by decrementing one from the first entry in the list (if there are any) on each SIGALRM signal. If the counter of the first entry reaches zero then the alarm for the corresponding character process (each entry in the list should contain a counter and the character process it corresponds to) has gone off. When an alarm goes off, subsequent entries in the list need to be checked to see if they are also zero. All entries with a count of zero should be removed from the delta list.

For each alarm that has gone off, your handler needs to take two actions. First it needs to add the character process to a process status variable, which is declared globally as follows:

unsigned int procstatus;

This variable should be used as a bit vector where setting the ith bit indicates that the alarm for process i has gone off. In using this bit vector you will need to translate an 'A' to 0, 'B' to 1 and so one by subtracting an 'A' from the character process. For example, to update the procstatus variable for the process stored by variable ch you could use the code:

procstatus = procstatus | 1<<(ch-'A')

The second action needed by your handler for each alarm is to signal the semaphore being waited on by your main program. This action will alert the main program to look in the procstatus variable to determine and print out the character process that has had an alarm go off.

Your main program will need to search in the procstatus variable for the bit that is set. It will need to reset the corresponding bit in the procstatus variable after it prints out the alarm event.

Output

The output of your program should be the order and time at which each of the scheduled alarms goes off. You should print out the character process followed by the current time as a string using time() and ctime(). A sample output for the given input might be as follows.

Process D alarmed at Sun Oct  6 20:54:01 EDT 1996
Process C alarmed at Sun Oct  6 20:54:03 EDT 1996
Process A alarmed at Sun Oct  6 20:54:05 EDT 1996
Process E alarmed at Sun Oct  6 20:54:05 EDT 1996
Process B alarmed at Sun Oct  6 20:54:06 EDT 1996

Clean Up

When your main program has detected that the count of triggered alarm events reaches the number that were originally scheduled then the program is ready to complete. Before exiting your program should terminate the clock device process by sending it a SIGINT signal.

As in previous assignments be aware of leaving unused semaphore resources and processes laying around. Again use ipcs -b and ipcrm -s semid to cleanup semaphores. Use ps aux | grep and kill to locate mysched processes that are not cleaned up properly.

Additional Work

Satisfactory completion of the basic objective of this assignment is worth 22 of the 25 points. For three additional points, you need to implement a revised method of scheduling the alarm events. Your signal handler will not change, but your main program must now be able to handle multiple alarms from a single process. For example, in this part of the assignment the following input is valid:

C 3
B 6
A 5
A 3
D 1
D 4
E 5

Processes A and D each have two alarms. However, the second and subsequent alarms should not be scheduled until the first alarm for the process has completed (no more than one alarm per process should be on the delta list at a time). Thus ``extra'' alarms for a process need to be remembered and scheduled once the previous alarm for the process has gone off. Thus the second alarm for process D would be scheduled at time 1 and go off at time 5.