Interrupts

advertisement
Interrupts
And tips for R3
What is an interrupt?
An interrupt is an electronic signal that indicates an event (possibly caused by
hardware or the program its self) has occurred which results in a deviation
from the normal flow of execution in a process.
In the normal flow of events, when a process is executing a program, execution
proceeds sequentially from one statement to the next, unless a branching
statement is encountered.
The concept of interrupts was introduced, with Atlas, and used to provide some
concurrency in computing by allowing I/O devices to proceed with data
transfers while the CPU performed other tasks instead of constantly polling
the I/O device. An interrupt facility allows the I/O devices to signal the
system only when service of some type is required.
Also interrupts are used to enable the system to keep track of the time of day
and set alarms to time specific events.
#include <stdio.h>
int main(void)
Normal flow is sequential
{
int I;
int sum=0;
for (i=0; i<=10; i++){
sum=sum+I;
}
printf(“the final sum is %d\n”, sum);
}
“the interrupt
handler”
When an interrupt
signal occurs,
execution in the
original program is
suspended, the status
of the program saved,
and control is
transferred to a
special routine called
an interrupt handler
that processes the
interrupt, and then
calls the dispatcher.
The original program
may then resume
execution, or another
may be launched
When an interrupt occurs



The currently executing program is temporarily suspended.
The context/status of the process is saved
Control shifts to a special routine called an interrupt handler.
An interrupt handler is:




A specially written routine whose job is to evaluate the cause of
the interrupt
Perform any special tasks associated with the interrupt
Return control back to the previously executing program at the
EXACT statement which would have normally been executed if
the interrupt had not occurred.
OR to trigger a context switch to give control of the CPU to a
different program/process.
One of the most critical issues with respect to managing
interrupts is that the COMPLETE status of the
suspended process must be correctly saved and
restored.
Interrupts can originate in either hardware or
software.
Programs issue interrupts to request the
operating system’s support
Hardware issues interrupts to notify the
processor that an asynchronous event has
occurred.
For Example: A program might use a system call to generate an interrupt to
signal that it needs data: (Example taken from Operating Systems, a systematic view, by Davis & Rajkumar)
The running program
A requests input
data, this triggers an
interrupt, and control
transfers to the
interrupt handler
Operating System
Dispatcher
PCB’s
channel
Program State
Interrupt
Handler
Routine
A
running
B
ready
disk
The interrupt handler sets the running process to the blocked
state, and begins execution.
Operating System
Dispatcher
PCB’s
channel
Program State
Interrupt
Handler
Routine
A
blocked
B
ready
disk
The interrupt handler, calls the I/O control system, which starts the I/O
operation, before returning control back to the dispatcher
Operating System
Dispatcher
PCB’s
channel
Program State
Interrupt
Handler
Routine
A
blocked
B
ready
disk
The I/O controller will continue with the I/O operation while
the dispatcher launches another process. The I/O controller
may generate multiple interrupts depending on whether
information is transferred character by character or as a
block.
Operating System
Dispatcher
PCB’s
channel
Program State
Interrupt
Handler
Routine
A
blocked
B
running
disk
When the operation is complete, the channel issues an
interrupt, and once again the interrupt handler begins
executing, the waiting process will be unblocked, and again the
dispatcher is called
Operating System
Dispatcher
PCB’s
channel
Program State
Interrupt
Handler
Routine
A
blocked
B
running
disk
What types of interrupts may
occur?
Essentially there are 4 types of hardware
interrupts, and 2 types of software interrupts.

I/O Interrupts:
Generated by I/O devices (via the device interface)
These indicate that service is needed from a software
interrupt handler:



Transferring another character to or from a character by
character device
Servicing the completion of a total I/O request (block of data
being read or written)
Handling of an error condition in the device (paper jam)

Alert Interrupts
These result from unexpected conditions outside
the computer system
Some keyboards contain an “interrupt key” which
can be used to activate the command handler
Or in a Multiprocessor system when one CPU
signals another to signify some condition or service
request from the other CPU

Timer interrupts:
Generated by internal software timers
Can be used to indicated that the last unit of time
placed into a timer has expired, which indicates
that some activity is to occur. (running process is to
be preempted when the CPU time limit expires)
Interrupts may be generated at regular intervals by
a hardware clock

Each interrupt means that another fixed fraction of time
has expired and that the software clocks should be
updated.
Machine fault interrupts

Indicate that a hardware error has occurred
Memory fetch error
I/o device error



These interrupts typically can not be masked
or ignored.
Many OS’s simply report these errors and
terminate
Others, if resources permit, try to isolate the
offending hardware and try to continue
execution.
Software generated interrupts
Software Interrupts are usually implemented as
instructions in the instruction set which cause a context
switch to the interrupt handler similar to a hardware
interrupt
System request interrupts:





Result when processes request service from the OS through the
use of special instructions which generate a system request
interrupt.
The system call instruction is provided via the OS’s program
interface
Execution of this command causes a transfer of control to the
OS
Parameters may be used to transfer arguments to the OS,
identifying the type of service requested.
The OS will analyze the request, possibly blocking the process
requesting the service until the service is complete.
Program Fault Interrupts

Abnormal conditions that arise within the
running program
Divide by zero
Underflow/overflow during an arithmetic operation
Invalid memory reference

For these category of interrupts users can
supply the address of a special routine to
execute when the error occurs otherwise the
OS will execute a default routine (typically
reporting the error and terminating execution
of the program)
Software interrupts (or exceptions) are
synchronous interrupts which are generated
when the processor detects a predefined
condition, such as division by 0. The exception
occurs during the machine cycle which is driven
by a clock tick, and since they are caused by the
program itself there is a precise point within the
program at which the transfer of control to the
interrupt handler should occur.
Others are Asynchronous because even though
they should be serviced ASAP, the exact point at
which the program should be interrupted isn’t
predetermined.. May be immediately after the
execution of the current machine instruction (at
the next clock tick), or later. These are raised by
hardware devices at unpredictable times.
Interrupt Generation
Many interrupts begin as a signal sent to the
processor when an event occurs. (interruptrequest line)
Usually the interrupt signal is recorded when it
occurs by setting a flag (bit) in a special
processor register (program status word). The #
of actual flags vary from architecture to
architecture, sometimes multiple interrupts must
share the same flags.
Once the interrupt is “raised” it is the job of the
CPU to “catch” the interrupt, interpret it, and
“dispatch” the appropriate interrupt handler. The
handler then “clears” the interrupt by processing
the request (clearing the flag).
To successfully manage interrupts we need 3
facilities



The ability to defer interrupt handling during critical
processing.
We need an efficient way to dispatch to the proper
interrupt handler without polling every device to see
which one initiated the interrupt
We need multilevel interrupts so that the operating
system can service interrupts in order of importance if
multiple interrupts occur simultaneously.
Dispatching the interrupt handler
When an interrupt occurs we need to transfer
control immediately to the appropriate interrupt
handler.
When this transfer occurs it is CRITICAL that
some capability is provided to save the status
(context) of the executing process.
The contents of every CPU register and the
status flags must be saved (possibly on the
current stack) so that they can be restored when
the suspended process is resumed.
IF interrupt
THEN
save execution address (PC)
save status information
transfer control to interrupt handler
END
The exact transfer mechanism varies
slightly from architecture to architecture
but most associate each interrupt with a
small data structure in “low memory”
called an interrupt vector. This structure
contains:


The address of the Interrupt handler
(maybe) a location to store the return address
and the status of the interrupted program.
FOR EXAMPLE:

In MS-DOS, interrupt
processing uses an
interrupt vector table
that occupies the first
1K bytes of memory.
(Example taken from Operating Systems, a systematic view,
by Davis & Rajkumar)
Most of the actual
routines are found
in IO.sys or
MSDOS.sys
Interrupt Vectors
Address of interrupt x
routine
Address of interrupt y
routine
Address of interrupt z
routine
The interrupt consists of an electronic
pulse and the address of an interrupt
vector.
When the interrupt occurs hardware
immediately copies the instruction
pointer register (and a few other
registers) to the stack!
It then loads the starting address
specified in the interrupt vector into the
IP.
With the next machine cycle the first
instruction in the interrupt routine is
fetched.
Once the interrupt is processed, the
contents of the stack are copied back
into the IP and the original program
resumes processing.
Instruction pointer
stack
Interrupt Vectors
Address of
interrupt x
routine
Address of
interrupt y
routine
Address of
interrupt z
routine
A fully vectored interrupt mechanism
provides a distinct interrupt vector for each
interrupt. This reduces the need for a
single interrupt handler to search all
possible sources of interrupts to determine
which one needs service.
IBM-PC is fully vectored. With distinct interrupt
vectors for each interrupt
IF interrupt
THEN
save execution address (Program Counter)
save status (Program Status Word)
CASE interrupt IS
WHEN device1: transfer control to
WHEN device2: transfer control to
WHEN device3: transfer control to
WHEN device4: transfer control to
ENDCASE
device1 interrupt handler
device2 interrupt handler
device3 interrupt handler
device4 interrupt handler
ENDIF
/* In this case the cause of the interrupt can be determine without further
program execution */
Other architectures allow multiple interrupts to share the same interrupt
vector, by creating a limited set of interrupt categories: IBM/370
Here control passes to the same first level interrupt handler, which must
then test an addtional special register to determine which device
caused the interrupt.
FLIH:
save registers
read interrupt_status_register
CASE interrupt_status_register IS
WHEN device1: call device1_SLIH
WHEN device2: call device2_SLIH
WHEN device3: call device3_SLIH
ENDCASE
restore registers
RETURN from interrupt
Ordering of Interrupts by priority
Typically different categories of interrupts are
assigned designated priorities.
This allows the CPU to defer the handling of lowpriority interrupts without masking ALL interrupts
Makes it possible for a high priority interrupt to
preempt the execution of a low priority interrupt.
If interrupts are masked it is imperative that
interrupts be unblocked as soon as possible.
IE: The interrupts for an I/O device can be
turned off while servicing an interrupt for that
device.
Structure of an Interrupt handler
There are several ways in which the
structure and design of an interrupt
handler must be different than that of an
ordinary procedure:
1. A linkage must be created between the
physical interrupt and the handler, so that the
handler will be invoked when the interrupt
occurs:



Each interrupt handler is linked to the appropriate
physical interrupt by storing its starting address in
the associated interrupt vector location.
During system initialization the OS is responsible for
setting up the interrupt vectors with the address of
default interrupt handlers
When the interrupt occurs special hardware
mechanisms access the contents of the vector,
perhaps save some brief status data, and transfer to
the specified handler
2) Since interrupts may occur at unpredictable points in
program execution, the complete system state must be
preserved during interrupt handling. This means that
after the interrupt the content of all machine registers
must be exactly as before; moreover, all memory used
by the running process, including "hidden" areas such
as a stack, must be undisturbed.




Save all registers which could be modified by the interrupt
handler onto the stack or in a private memory area.
The hardware itself may save some critical registers such as
the status register along with the return address.
The handler software is then expected to immediately save all
other registers that might be used.
At termination of the handler the software must restore all
registers save by software and the hardware restores those
saved by hardware.
3) Parameters cannot be passed to an
interrupt handler in the usual way


Interrupt handlers are not called via the
normal call mechanism, so parameters can
not be passes via the normal mechanism
If an handler requires data to be passed into
it, then that information must be placed in a
special place such as a special register or on
the stack.
4) Because interrupt handling is a temporary
deviation from the normal execution of a
running process, the handler may be
severely restricted in the resources it may
use, and in the subprograms it may call

The interrupt handler should not make use of
resources that could be allocated to another
process. They should not normally access
data files or I/O devices. Nor should they
allocate memory or use any memory other
than their own.
5) Interrupt handlers must allow for the appropriate
handling of other interrupts while the handler is
in progress.




Typically a computer many need to process
thousands of interrupts per second
When an interrupt occurs, the hardware automatically
disables other interrupts. This is necessary to avoid
confusion during the initial saving of the system state.
Interrupts should be re-enabled as soon as possible.
IF the interrupt handler is VERY short then interrupts
may be left disabled until the handler terminates
6) Interrupt handlers must complete their
work in the shortest possible time, leaving
more complex follow up tasks to other
system or application software.


The interrupt handler should complete its
work and terminate in the shortest possible
time.
In many cases it should do as little as setting
an event flag which subsequent software
could review and process.
7) Interrupt handling is subject to errors that
are hard to reproduce, and cannot often
be debugged by normal means.


The timing of interrupts is often not
repeatable.
Sometimes only in the certain ordering of
interrupts do problems occur and can be
difficult to solve because the exact ordering of
interrupts can not be easily observed or
repeated.
Tips for R3: Process Initialization
When we create processes to represent
our 5 test procedures we must correctly
initialize its context by placing values into
its stack, data segment and extra
segment.
1) We need to define a special global structure to
represent the “context” of a process which is
automatically saved onto the processes stack
when the process is interrupted:
typedef struct context {
unsigned int BP, DI, SI, DS, ES; unsigned int
DX, CX, BX, AX;
unsigned int IP, CS, FLAGS;
} context;
context *context_p;
Recall that:
When an interrupt occurs the HARDWARE saves the
flags register (PSW), CS (code segment), IP (instruction
pointer) onto the stack in this order!!!!!
Next because of the interrupt keyword being specified in
the implementation of our interrupt handler:
void interrupt sys_call_handler()
Assembler instructions will be added to the routine to
automatically save the following registers onto the stack:
AX, BX, CX, DX, ES, DS, SI, DI, AND BP
Code will also be automatically added at the end of the
routine to restore these!!!!!
We need to set up the initial context of each process by
initializing the contents of its stack.
The declaration of the PCB should contain
a pointer to a stack of size 1k, which
should initially be initialized to all zeros!!
The stack pointer should be initialized to
the “highest” address in your stack (stack
address +1024) (remember that the stack
grows from high memory down.)
We need to store the initial context of the
process in the top portion of the stack!
Pcb.stack_p = pcb.stack_base +
pcb.stack_size – sizeof(context);
Context_p = (context *)pcb.stack_p;
context_p->DS = _DS;
context_p->ES = _ES;
context_p->CS = FP_SEG(&testn_R3);
context_p->IP = FP_OFF(&testn_R3);
context_p->FLAGS = 0x200
Process cause interrupts by:
Each process will voluntarily give up control of
the CPU using a call to “sys_req” which will
generate a system call interrupt. Processes call
“sys_req” with two possible op_code values:


IDLE: which will return the process to the ready
queue
EXIT: which is a request to terminate the process, and
free the PCB.
This call to sys_req will result in an interrupt
being generated which should be processed by
our “sys_call_hander”
Setting up “sys_call_handler”
During initialization you must set the “sys_call” vector to
contain the address of your interrupt handler. It has the
prototype:
int sys_set_vec (void (*handler)());
The single parameter handler is a pointer to your system
call handler. If your handler has the name sys_call, then
it should have the prototype:
void sys_call (void);
Your call to sys_set_vec, which should occur during
initialization, will have the form
sys_set_vec(sys_call);
Sys_req passes a single parameter to your sys_call_handler, via the stack
(previous stack contents)
Buffer length pointer parameter (*count)
Buffer address parameter (*buffer)
Device_id parameter
Op_code parameter
Flag
CS
IP
AX
BX
CX
DX
ES
DS
SI
DI
BP
We will need to retrieve the contents of the 1st four parameters to identify the type of
request made by the calling process.
To access these parameters we define
another structure similar to the “context”
structure:
typedef struct params {
int op_code;
int device_id;
byte *buf_addr;
int *count_addr;
} params;
We gain access to the op_code by:
The stack structure must be a named type. A pointer to this
structure is also required:
params *param_p;
Finally, the following assignment will set the pointer to the
address of the actual stack frame to be accessed:
param_p = (params*)(MK_FP(_SS,_SP) + sizeof(context));
It is now possible to refer to the op_code value as
param_p->op_code.
We then need to interpret this code and take the appropriate action!
First save a copy of the SS and SP and switch to another temporary stack. (local variables should
be declared as static)
#define SYS_STACK_SIZE 200
byte sys_stack[SYS_STACK_SIZE];
unsigned short ss_save;
unsigned short sp_save;
unsigned short new_ss;
unsigned short new_sp;
/* in syscall*/
ss_save = _SS;
sp_save = _SP;
new_ss = FP_SEG(sys_stack);
new_sp = FP_OFF(sys_stack);
new_sp += SYS_STACK_SIZE;
_SS = new_ss;
SP = new_sp;
set param_p point to the correct place:
cop->stack_ptr = (unsigned char *) MK_FP(_SS, _SP);
param_p = (params *)(cop->stack_ptr + sizeof(context));
if parm_p->op_code is IDLE
change the state of cop to ready
insert cop to ready queue by priority
else if param_p->op_code is EXIT
delete the pcb
set cop to NULL
else set context_p->AX to error code.
call dispatch()
In the dispatcher
Automatically saves the data registers
onto the temporary stack for the calling
process
Then a complete outline for the dispatcher
is:
if sp_save is null,
ss_save = _SS
sp_save = _SP
remove the PCB at the head of the ready queue
if a PCB was found set cop to this PCB
set _SS and _SP to the PCB's stack pointer
else
set cop to NULL
set _SS to ss_save
set _SP to sp_save
end if
"return from interrupt"
Download