CIS-332 -- Principles of Operating Systems

Professor: Franz J. Kurfess

Home page:http://www.cis.njit.edu/franz   E-mail:franz@cis.njit.edu 

Programming Assignment 2 --- Process Control Block (cont.)

Due on Thursday, March 13, 1997.

In this phase of project we will build upon the procedures and functions we wrote earlier to create a program that simulates the processing of various events generated by a process during its lifetime. Our objective is to study the performance of various scheduling algorithms.

The lifetime of a process is the time period between the arrival of a process and its termination. During this time the process will move around among three states: the ready queue, running, and waiting in a blocked state (device queue).

There are several events that occur during the lifetime of a process:
(1) The arrival of a new process,
(2) The termination of a running process,
(3) The blocking of a running process, and
(4) The unblocking of a previously blocked process.

When a process moves into the ready queue, the scheduler is called to perform the insertion based on some scheduling algorithm. For instance, when the First-Come-First-Served (FCFS) scheduling algorithm is used the scheduler always inserts the process at the end of the ready queue. It is this scheduling algorithm that determines the order in which the processes that are in the ready queue will use the CPU.

You are given a procedure called `NextEvent', whose listing appears at the end of this document, that generates events for your program. Every time `NextEvent' is called, your program will be told about an event that occured. Your program must then handle each event by taking the appropriate actions as described in the following section.

The Event Generator:

The procedure NextEvent will produce 5 types of events. The following is a list of these events along with the necessary actions to take for each:

0: No Event.

This event means that nothing has happened. No action needs to be taken in this case. An exception to this rule is when using the Round-Robin scheduling algorithm. When the quantum of a process expires then the running process must be rescheduled and the next process in the ready queue is dispatched.

1: Process Arrival.

This event indicates that a new process has arrived. The name of the newly arrived process is returned by the procedure `NextEvent' through the parameter `name'. The type of the new process is passed through the parameter `ptype' (when ptype = 0 it is a user process and when ptype = 1 it is a SYSTEM process). For this event the actions by your program should be to get a new PCB, store the relevant information in the PCB (by calling BUILD_PCB), and then call the scheduler to insert the PCB into the ready queue.

2: Process Termination.

This event indicates that the currently running process has just terminated. The PCB of this process should now be removed from the ready queue and then deallocated. The dispatcher should then be called to start running the next process in the ready queue.

3: Process Blocking.

This event indicates that the currently running process has blocked. The PCB of this process must now be removed from the ready queue and inserted into the I/O queue. It does not matter what insertion method is used since blocked processes in the I/O queue are not unblocked in any specific order. The dispatcher should then be called to start running the next process in the ready queue.

4: Process Unblocking.

This event indicates that a process that had previously blocked is no longer blocked. The PCB for this process is removed from the I/O queue and inserted into the ready queue by calling the dispatcher. Please note that since the PCB we are removing from the IO queue can be anywhere in the list (and not necessarily at the head of the list) it is necessary to write an additional remove procedure (different from the one you wrote in the first phase). This remove procedure takes the name of a process to be removed (from the IO queue), removes it and returns the index of this removed PCB.

The procedure `NextEvent' is declared as follows:

		procedure NextEvent(RunProc: String8; Var event: Integer;
                            Var name: String8; Var Ptype: Integer);

The parameter `RunProc' should be set (by your program) to the name of the currently running process prior to calling `NextEvent'. If no process is currently running then `RunProc' should be set to the empty string `' (please note there is no blank space between the two quotes). The procedure `NextEvent' will return an integer in the parameter `event' (0 through 4) that corresponds to the event that took place. `NextEvent' will assign a value to the parameter `name' in two cases:
1) when event is 1, `name' will be name of the newly arrived process; and
2) when event is 4, `name' is the name of the parameter `ptype' only in the case when event = 1.
The value of `ptype' will be 0 if the new process is a USER process, and `ptype' will be 1 if the new process is a SYSTEM process.

The Scheduler:

 The procedure `Scheduler' is called whenever we need to insert a process
 into the ready queue. The scheduler uses a scheduling algorithm to
 ddecide where to insert the new process in the ready queue. 
 When the scheduler is called it should also check to see
 if there are any processes currently running.
 If no process is running when the scheduler is called, 
 the scheduler should call the dispatcher after it has inserted 
 the new PCB in the ready queue. The procedure scheduler should
 be defined as follows:

Procedure Scheduler(i: Integer)

Where the parameter `i' is the index of the PCB to be inserted in the ready queue.

The Dispatcher:

The dispatcher procedure is called whenever the CPU becomes idle. The CPU becomes idle after one of the following occurs: the currently running process terminates, the currently running process is blocked, or the currently running process has used up its quantum. In addition, the scheduler will call the dispatcher if while inserting a PCB into the ready queue it notices that there are no processes running. The Procedure dispatcher is defined as follows:

	 Procedure Dispatcher;

There are no parameters for this procedure.

The Main program

 The outline of the main program should be as follows:

 program main;

       Uses EventGen;
       Var Time: Integer;

       {  ...other declarations ...}

       procedure Dispatcher;
       var
         ...
       begin
         ...
       end;

       procedure Scheduler( i: Integer);
       var
             ...
       begin
             ...
       end;

    Begin
       ...
       Time := 0;
       While Time < MaxTime do
       begin
            NextEvent(RunProc, event, name, ptype);
            Case event of
               0:  Writeln(time,' : No event.');
               1:  begin
                      writeln(time,' : Process Arrival - ', name);
                           ...
                    end;
               2:  begin
                      writeln(time,' : Process Termination -', RunProc);
                           ...
                    end;
               3:  begin
                      writeln(time,' : Process Blocks - ', RunProc);
                           ...
                    end;
               4:  begin
                      writeln(time,' : Process Unblocks - ', name);
                           ...
                    end;
            end;
            time := time + 1;
       end;
    END.

The Output:

You should run your program for two different scheduling algorithms: FCFS and Round-Robin. The output generated by your program should include a line of output for every event that takes place showing the event and the name of the process involved in the event. In addition your program should compute the average turnaround time and the average waiting time for a sample of processes (about 50 processes). This can be done by three more fields to the PCB record: Arrival time, CPU time, and Termination time. The arrival time of the process is recorded when the process first arrives. The CPU time is the cumulative time that the process spent running on the CPU (this field will be incremented every time the process gets the CPU). The termination time is recorded when the process terminates. Please note that for a process:

		  Wait_time = Termination_time - Arrival_time - CPU-time,
                  Turnaround_Time = Termination_time - Arrival_time


The EventGen.pas file:

This is the listing of the procedure NextEvent. It is written as Turbo Pascal unit. There is also a conversion to C (updated 3-20-97) done by Gabriel Spil (Thanks!), which even comes with Eventgen.h, Eventgen.readme, and Main.cpp files. The routine IntToA to convert an integer to an alphanumeric string, which is not available on megahertz, was provided by Bruce Baxter. In the meantime, I received another conversion to C from Bruce Carothers which seems to be closer to the original Pascal version. Save it in a file called `eventgen.pas'. This means that you will have two files: one containing your own code and the other one containing the code on tis page. Please note that the statement "Uses EventGen;" (shown in the outline of the main program) is the only thing that is needed to link the two programs. When you compile your program, the compiler will automatically compile the code in the file eventgen.pas and link it to your program.

  Unit EventGen;
 Interface
   type
      string8 = string[8]
      procedure NextEvent(RunProc: string8; var event: Integer;
                var name: string8; var ptype: Integer);
 Implementation
 var
    Bprocs: array[1..50] of string8;
    Ucount, Scount, Bcount: Integer;

    procedure NextEvent(RunProc: String8; var event: Integer;
       var name: string8; var ptype: Integer);
    var
       r: real;
       S: string[3];
       B: Integer;

 begin
    r := random;
    if Bcount > 5 then r := 0.1;
    if r < 0.2 then
    begin
       if Bcount = 0 then event:=0
       else
       begin
           event := 4;
           B := random(Bcount) + 1;
           name := Bprocs[B];
           Bprocs[B] := Bprocs[Bcount];
           Bcount := Bcount - 1;
      end
    end
    else if r < 0.4 then
    begin
       event := 1;
       ptype := Trunc( random + 0.5);
       if ptype = 0 then
       begin
           Ucount := Ucount + 1;
           Str(Ucount, S);
           name := 'USER' + S;
       end
       else
       begin
          Scount := Scount + 1;
          Str(Scount,S);
          name := 'sys' + S;
       end;

    end
    elseif r < 0.6 then
    begin
       event := 2;
       name  := Runproc
    end
    else if r < 0.8 then
    begin
       if RunProc = '' then event := 0
       else
       begin
          event := 3;
          Bcount := Bcount + 1;
          Bprocs[Bcount] := RunProc;
          name := RunProc;
       end;
    end
    else
       event := 0
 end;

 Begin
    Ucount := 0;
    Scount := 0;
    Bcount := 0;
 End.

Hand in this assignment via electronic mail; also keep a copy of the assignment in your computer for future use. The program must be well documented. Documentation is a very important part of a software product. The TA will run you program on megahertz, so before handing it in you should test your program on megahertz. You can include some information about how to compile you program on megahertz, the parameters, etc. This assignment will contribute 20 points towards your homework/assignment score. Late submission or copying other student's code will be penalized. Please send your answers via electronic mail to the CIS 332 class account cis332fk@cis.njit.edu. It is easier for us to handle if you don't split it up into too many messages, and if you include plain ASCII files in your mail (instead of attachments).