Interrupt Management Functions

Interrupt management functions are for defining and manipulating handlers for external interrupts and CPU exceptions.

An interrupt handler runs as a task-independent portion. System calls can be invoked in a task-independent portion in the same way as in a task portion, but the following restriction applies to system call issuing in a task-independent portion.

During task-independent portion execution, task switching (dispatching) does not occur. If system call processing results in a dispatch request, the dispatch is delayed until processing leaves the task-independent portion. This is called delayed dispatching.

tk_def_int - Define Interrupt Handler

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_def_int (UINT dintno , CONST T_DINT *pk_dint );

Parameter

UINT dintno Interrupt Handler NumberInterrupt handler number
CONST T_DINT* pk_dint Packet to Define Interrupt HandlerInterrupt handler definition information

pk_dint Detail:

ATR intatr Interrupt Handler AttributeInterrupt handler attribute
FP inthdr Interrupt Handler AddressInterrupt handler address
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ER ercd Error CodeError code

Error Codes

E_OK Normal completion
E_NOMEM Insufficient memory (memory for control block cannot be allocated)
E_RSATR Reserved attribute (intatr is invalid or cannot be used)
E_PAR Parameter error (dintno, pk_dint, or inthdr is invalid or cannot be used)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

"Interrupts" include both external interrupts from devices and interrupts due to CPU exceptions.

Defines an interrupt handler for the interrupt handler number dintno to enable use of the interrupt handler. This system call maps the interrupt handler number indicated in dintno to the address and attributes of the interrupt handler.

dintno is the number used to distinguish between different interrupt handlers. Its specific meaning is defined for each implementation, but generally the interrupt vector defined by the interrupt handling in the CPU hardware is used as it is, or any number that can be mapped to the interrupt vector is used. To get the interrupt handler number dintno from the interrupt vector, use the T-Kernel/SM DINTNO().

intatr indicates system attributes in its lower bits and implementation-dependent attributes in its higher bits. The system attribute part of intatr is specified as follows.

intatr := (TA_ASM || TA_HLNG)

TA_ASM The handler is written in assembly language
TA_HLNG The handler is written in high-level language

#define TA_ASM          0x00000000      /* assembly language program */
#define TA_HLNG         0x00000001      /* high-level language program */

As a rule, the kernel is not involved in the starting of a TA_ASM attribute interrupt handler. When an interrupt is raised, the interrupt handling function in the CPU hardware directly starts the interrupt handler defined by this system call (depending on the implementation, processing by program may be included). Accordingly, processing for saving and restoring registers used by the interrupt handler is necessary at the beginning and end of the interrupt handler. An interrupt handler is terminated by execution of the tk_ret_int system call or by the CPU interrupt return instruction (or an equivalent mechanism).

Support of a mechanism for return from an interrupt handler without using tk_ret_int and hence without kernel intervention is mandatory. Note that if tk_ret_int is not used, delayed dispatching does not need to be performed.

Support for return from an interrupt handler using tk_ret_int is also mandatory, and in this case delayed dispatching must be performed.

When the TA_HLNG attribute is specified, the interrupt handler is started via a high-level language support routine. The high-level language support routine takes care of saving and restoring register values. The interrupt handler terminates by a return from a C language function. The interrupt handler takes the following format when the TA_HLNG attribute is specified.

void inthdr( UINT dintno )
{
        /*
                Interrupt Handling
        */

        return; /* Exit interrupt handler */
}

The parameter dintno passed to an interrupt handler is the interrupt handler number identifying the interrupt that was raised, and is the same as that specified with tk_def_int. Depending on the implementation, other information about the interrupt may be passed in addition to dintno. If such information is used, it must be defined for each implementation in a second parameter or subsequent parameters passed to the interrupt handler.

If the TA_HLNG attribute is specified, it is assumed that the CPU interrupt flag will be set to interrupts disabled state from the time the interrupt is raised until the interrupt handler is called. In other words, as soon as an interrupt is raised, multiple interrupts are disabled, and this state remains when the interrupt handler is called. If multiple interrupts are to be allowed, the interrupt handler must include processing that handles multiple interrupts by manipulating the CPU interrupt flag.

Also in the case of the TA_HLNG attribute, upon entry into the interrupt handler, issuing system call must be possible. Note, however, that assuming standard provision of the functionality described above, extensions are allowed such as adding a function for entering an interrupt handler with multiple interrupts enabled.

When the TA_ASM attribute is specified, the state upon entry into the interrupt handler shall be defined for each implementation. Such matters as the stack and register status upon interrupt handler entry, whether system calls can be made, the method of invoking system calls, and the method of returning from the interrupt handler without kernel intervention must all be defined explicitly.

In the case of the TA_ASM attribute, depending on the implementation there may be cases where interrupt handler execution is not considered to be a task-independent portion. In such a case the following points need to be noted carefully.

  • If interrupts are enabled, there is a possibility that task dispatching will occur.

  • When a system call is invoked, it will be processed as having been called from a task portion or quasi-task portion.

If a method is provided for performing some kind of operation in an interrupt handler to detected whether it runs as task-independent portion, that method shall be announced for each implementation.

Whether the TA_HLNG or TA_ASM attribute is specified, upon entry into an interrupt handler, the logical memory space at the time the interrupt occurred is retained. No processing takes place upon return from the interrupt handler for restoring the logical memory space to its state at the time the interrupt was raised. Switching logical memory spaces inside the interrupt handler is not prohibited, but the kernel is not aware of the effect of such logical memory space switching.

Even if a system call is invoked from an interrupt handler and this causes the task in RUNNING state up to that time to go to another state, with a different task going to RUNNING state, dispatching (task switching) does not occur while the interrupt handler is running. Completion of execution of the interrupt handler has precedence even if dispatching is necessary; only when the interrupt handler terminates does the dispatch take place. In other words, a dispatch request that is generated while an interrupt handler is running is not processed immediately, but is delayed until the interrupt handler terminates. This is called delayed dispatching.

An interrupt handler runs as a task-independent portion. As such, it is not possible to call in an interrupt handler a system call that can enter WAITING state, or one that is intended for the invoking task.

When pk_dint = NULL is set, a previously defined interrupt handler is canceled. When the handler definitions are canceled, the default handler defined by the system is used.

It is possible to redefine an interrupt handler for an interrupt handler number that is already defined. It is not necessary first to cancel the definition for that number. Defining a new handler for a dintno already having an interrupt handler defined does not return error.

Additional Notes

The various specifications governing the TA_ASM attribute are mainly concerned with realizing an interrupt hook. For example, when an exception is raised due to illegal address access, ordinarily an interrupt handler defined in a higher-level program detects this and performs the error processing; but in the case of debugging, in place of error processing by a higher-level program, the default interrupt handler defined by the system may perform the processing and starts a debugger. In this case, the interrupt handler defined by high-level program hooks the default interrupt handler defined by the system. And, according to the situation, the handler either passes the interrupt handling to a system program such as a debugger, or it just processes it for itself.

tk_ret_int - Return from Interrupt Handler

C Language Interface

#include <tk/tkernel.h>

void tk_ret_int ( void );

Although this system call is defined in the form of a C language interface, it will not be called in this format if a high-level language support routine is used.

Return Parameter

Does not return to the context issuing the system call.

Error Codes

The following kind of error may be detected, but no return is made to the context issuing the system call even if the error is detected. For this reason the error code cannot be passed directly as a system call return parameter. The behavior in case an error occurs is implementation-dependent.

E_CTX Context error (issued from other than an interrupt handler (implementation-dependent error))

Valid Context

Task portionQuasi-task portionTask-independent portion
NONOYES

Description

Exits from an interrupt handler.

System calls invoked from an interrupt handler do not result in dispatching while the handler is running; instead, the dispatching is delayed until tk_ret_int is called ending the interrupt handler processing(delayed dispatching). Accordingly, tk_ret_int results in the processing of all dispatch requests made while the interrupt handler was running.

tk_ret_int is invoked only if the interrupt handler was defined specifying the TA_ASM attribute. In the case of a TA_HLNG attribute interrupt handler, the functionality equivalent to tk_ret_int is executed implicitly in the high-level language support routine, so tk_ret_int is not (must not be) called explicitly.

As a rule, the kernel is not involved in the starting of a TA_ASM attribute interrupt handler. When an interrupt is raised, the defined interrupt handler is started directly by the CPU hardware interrupt processing function. The saving and restoring of registers used by the interrupt handler must therefore be taken care of in the interrupt handler.

For the same reason, the stack and register states at the time tk_ret_int is issued must be the same as those at the time of entry into the interrupt handler. Because of this, in some cases function codes cannot be used in tk_ret_int, in which case tk_ret_int can be implemented using a trap instruction of another vector separate from that used for other system calls.

Additional Notes

tk_ret_int is a system call that does not return to the context from which it was called. Even if an error code is returned when an error of some kind is detected, normally no error checking is performed in the context from which the system call was invoked, leaving the possibility that the program will hang. For this reason these system calls do not return even if error is detected.

Using an assembly language return-from-interrupt instruction instead of tk_ret_int to exit the interrupt handler is possible if it is clear no dispatching will take place on return from the handler (the same task is guaranteed to continue executing), or if there is no need for dispatching to take place.

Depending on the CPU architecture and method of implementing the kernel, it may be possible to perform delayed dispatching even when an interrupt handler exits using an assembly language return-from-interrupt instruction. In such cases, it is permissible for the assembly language return-from-interrupt instruction to be interpreted as if it were a tk_ret_int system call.

Performing of E_CTX error checking when tk_ret_int is called from a time event handler is implementation-dependent. Depending on implementation, control may return from a different type of handler immediately.