- Thus far, we have seen that:
- When program P1 performs an IO operation
that causes the program to become not ready,
the OS stops the program by saving its context in the
corresponding PCB structure variable, removes the program
from the Ready Queue, puts it in the DMA device queue and
then resume with another ready program
- The program P1 that has requested an IO transfer operation
will remain not ready as long as the IO transfer is
not completed.
But as soon as the DMA has completed the IO transfer operation,
the program P1 is again ready (because it can then
continue with its execution without causing any errors).
Therefore, as soon as the DMA has completed the IO transfer operation,
the PCB of program P1 (which can be found in the DMA queue),
must be removed from the DMA queue and insert back into
the Ready Queue (so that it can (re)claim the use of the CPU).
- The question is how can the CPU tell if the DMA is done with
the transfer operation....
Well, one simple solution is to have the CPU read the status
register of the DMA from time to time to see if the DMA has
become idle.
But this apporach is inferior to the commonly used solution
that uses interrupt signals
- An interrupt is a special signal on the control bus
that is used by IO devices (DMA) to request the attention
of the CPU:
- The instruction execution cycle (see CS255 class note:
click here)
has in fact one more phase !
The complete instruction execution cycle is as follows:
- Fetch (assembler) instruction from memory at address PC and
increment PC (to point to the next instruction)
- Decode instruction fetched.
- Fetch operands needed to execute the instruction
- Execute the instruction
- Check for interrupt signal(s)
- When the CPU detects that the interrupt signal is
raised (i.e., some IO device is sending an interrupt request),
then the CPU will make a (unprogrammed) subroutine call
to a location in memory given by a special
Interrupt Base Register (IBR).
- I will first present a simplified version
of how the CPU processes an interrupt
signal (because giving the full details of the operation of
vector interrupts may make you miss the main issue at hand):
- I will assume that there is only one IO device
(controled by 1 DMA).
- The Interrupt Base Register IBR
contains the starting of a routine and from the
description above, the CPU will make a
(unprogrammed) subroutine call to this routine when
the DMA raises the interrupt.
- To give you an idea what it "feels" like to have a program
make "unprogrammed subroutine calls", I have created the
following C program that prints "." repeatedly in a while loop:
click here.
Compile it with:
cc interrupt.c
and run it using:
a.out
The main loop looks like this:
while (1)
{
for (i = 0; i < 999999; i++); // Slows the program down a bit...
putchar('.'); // Print "."
fflush(stdout); // Make sure the character is displayed
}
If you run the program, it will print:
.................................................
.................................................
.................................................
.................................................
and so on....
You can force this program to make a "unprogrammed" function call
to the function Int_Handler by typing Control-C.
It will print the text:
Hello, I'm your firendly interrupt handler. Times called: 0
and then return to the while loop and continue to print ".".
You can force it to call Int_Handler over and over again,
but typeing Control-C.
- Let us get back to the IO communication problem, part II:
how to reclaim the CPU when the IO operation finishes.
Recall the situation prior to the completion of the IO operation:
Make sure you understand what you want to achieve:
- The IO transfer initialized by Program P1 has completed.
- So program P1 has become ready
- We need to move program P1's PCB back to the Ready Queue
- We can achieve by writing a routine that moves the PCB from the
DMA queue back to the Ready Queue and
have the CPU execute this routine
when the DMA rasies the interrupt
Recall that the CPU will make an "unprogrammed" subroutine call
to the memory location given by the IBR when
the CPU detects an interrupt.
The following picture depicts the "reclaim the CPU" solution:
While program P3 was running on the CPU (i.e., CPU fetches and executes
instructions from program P3), the DMA completes the data transfer operation.
When the DMA finishes the IO transfer, it will raise the interrupt
signal.
The sequence of events that follows is:
- CPU finishes executing an instruction from program P3
- CPU detects the interrupt signal, as a result, makes an subroutine
call to the address given by IBR (in this example, IBR = 17000,
so CPU runs the subroutine at 17000)
- The subroutine at 170000 is given in the figure.
The subroutine will contain program instructions
that instruct the CPU to do the following:
- CPU sends out the INTA
(Interrupt Acknowledge) signal - there is an assembler instruction
"IA" that instruct the CPU to do this (not covered in CS255
because there was no need to then).
- Save the context information from the CPU (register, PC and PSR)
into the PCB at the head of the ready queue.
- Move the PCB from the DMA queue back into the ready queue
(the PCB pertains to the program that requested the DMA IO operation,
now that the DMA is finished, this program has become ready.
So it is only proper to move the PCB back to the ready queue
where it now belongs).
Usually, the PCB from the DMA queue is inserted at the head
of the ready queue.
So the PCB of program P1 will be at the head of ready queue
after this step.
- Finally: restore the context from the head of the ready queue.
Because the PCB of program P1 is at the head of the ready queue,
the program P1 will be resumed.
Therefore, program P1 has reclaimed the use of the CPU - exactly when
the DMA finishes the IO operation on behave of program P1.