Subsystem Management Functions

Subsystem management functions extends the functions of μT-Kernel itself by adding a user-defined function called "subsystem" to the kernel in order to implement middleware and others running on the μT-Kernel. Some functions provided by μT-Kernel/SM are also implemented by utilizing the subsystem management functions.

A subsystem consists of extended SVC handlers to execute user-defined system calls (called "extended SVCs"), a break function that performs the required processing when any exception occurs, and an event handling function that performs the required processing when any event is raised from devices, etc. (Figure 10)

Figure 10. μT-Kernel Subsystems

The extended SVC handler directly accepts requests from applications and others. A break function and event processing function are so-called callback type functions and accept requests from the kernel.

NoteAdditional Notes
 

Generally speaking, upper layer middleware including the process management functions and the file management functions are also implemented by utilizing the subsystem management functions. Other examples of middleware that are implemented by utilizing the subsystem management functions include TCP/IP manager, USB manager, and PC card manager.

Though subsystem management functions are meant to allow users to add custom system calls (SVC: SuperVisor Calls) as the primary purpose, they can be used to build complex and advanced middleware through not only the addition of just user-defined system calls but also through provision of exception processing functions to handle the exceptions, which are required for the added system calls.

In addition to the subsystem management functions, μT-Kernel also provides the device driver functions in order to extend itself. Both subsystems and device drivers are function modules independent from μT-Kernel itself. They can be used by loading their corresponding binary programs and then calling them from a task on μT-Kernel. Both run at the protection level 0. While API is limited to using open/close and read/write type when calling a device driver, API for calling a subsystem can be defined without any restriction.

Subsystems are identified by subsystem IDs (ssid), more than one subsystem can be defined and used at the same time. One subsystem can be called and used from within another subsystem.

tk_def_ssy - Define Subsystem

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_def_ssy(ID ssid, CONST T_DSSY *pk_dssy);

Parameter

ID ssid Subsystem IDSubsystem ID
CONST T_DSSY* pk_dssy Packet to Define SubsystemSubsystem definition information

pk_dssy Detail:

ATR ssyatr Subsystem AttributesSubsystem attributes
PRI ssypri Subsystem PrioritySubsystem priority
FP svchdr Extended SVC Handler AddressExtended SVC handler address
FP breakfn Break Function AddressBreak function address
FP eventfn Event Handling Function AddressEvent handling function address
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (ssid is invalid or cannot be used)
E_NOMEM Insufficient memory (memory for control block cannot be allocated)
E_RSATR Reserved attribute (ssyatr is invalid or cannot be used)
E_PAR Parameter error (pk_dssy is invalid or cannot be used)
E_OBJ ssid is already defined (when pk_dssyNULL)
E_NOEXS ssid is not defined (when pk_dssy = NULL)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Related Service Profile Items

Only when all the service profile items below are set to be effective, this system call can be used.

TK_SUPPORT_SUBSYSTEM Support of subsystem management functions

When the service profile items below is set to be effective, subsystem priority (ssypri) can be specified.

TK_SUPPORT_SSYEVENT Support of event processing of subsystems

Only when the service profile items below are set to be effective, break function can be specified.

TK_SUPPORT_TASKEXCEPTION Support of task exception handling functions

Description

Defines subsystem specified in ssid.

One subsystem ID must be assigned to one subsystem without overlapping with other subsystems. The kernel does not have a function for assigning subsystem IDs automatically.

Subsystem IDs 1 to 9 are reserved for μT-Kernel use. 10 to 255 are numbers used by middleware, etc. The maximum usable subsystem ID value is implementation-dependent and may be lower than 255 in some implementations.

ssyatr indicates system attributes in its lower bits and implementation-dependent attributes in its higher bits. The system attribute in ssyatr are not assigned in this version, and no system attributes are used.

ssypri indicates the subsystem priority. The startup function, cleanup function, and event handling function are called in order of priority. The calling order is undefined when these subsystems have the same priority. Subsystem priority 1 is the highest priority, with larger numbers indicating lower priorities. The range of priorities that can be specified is implementation-dependent, but it must be possible to assign at least priorities 1 to 16.

NULL can be specified in breakfn and eventfn, in which case the corresponding function will not be called.

Specifying pk_dssy = NULL deletes a subsystem definition.

  • Extended SVC handler

    An extended SVC handler accepts requests from applications and other programs as an application programming interface (API) for a subsystem. It can be called in the same way as an ordinary system call, and is normally invoked using a trap instruction or the like.

    The format of an extended SVC handler is as follows.

    
INT svchdr( void *pk_para, FN fncd )
    {
            /*
                    branching by fncd
            */
    
            return retcode; /* exit extended SVC handler */
    }
    

    fncd is a function code. The lower 8 bits of the instruction code are the subsystem ID. The remaining higher bits can be used in any way by the subsystem. Ordinarily they are used as a function code inside the subsystem. A function code must be a positive value, so the most significant bit is always 0.

    pk_para points to a packet of parameters passed to this system call. The packet format can be decided by the subsystem. Generally a format like the stack passed to a C language function is used, which in many cases is the same format as a C language structure.

    The return code passed from an extended SVC handler is passed to the caller transparently as the function return code. As a rule, negative values are error codes and 0 or positive values are the return code for normal completion. If an extended SVC call fails for some reason, the error code (negative value) set by T-Kernel is returned to the caller without invoking the extended SVC handler, so it is best to avoid confusion with these values.

    The format by which an extended SVC is called is dependent on the kernel implementation. As a subsystem API, however, it must be specified in a C language function format independent of the kernel implementation. The subsystem must provide an interface library for converting from the C language function format to the kernel-dependent extended SVC calling format.

    An extended SVC handler runs as a quasi-task portion.

    It can be called from a task-independent portion, and in this case the extended SVC handler also runs as a task-independent portion.

  • Break function

    A break function is a function called when a task exception is raised for a task while an extended SVC handler is executing.

    When a break function is called, the processing by the extended SVC handler running at the time the task exception was raised must be stopped promptly and control must be returned from the extended SVC handler to its caller. The role of a break function is to abort the processing of the currently running extended SVC handler.

    The format of a break function is as follows.

    
void breakfn( ID tskid )
    {
            /*
                    stop the running extended SVC handler
            */
    }
    

    tskid is the ID of the task in which the task exception was raised.

    A break function is called when a task exception is raised by tk_ras_tex. If extended SVC handler calls are nested, then when the nesting level of the extended SVC handler is decreased by the return from the latest extended SVC handler, the break function corresponding to the former extended SVC handler to which the control will be returned next, is called.

    A break function is called only once for one extended SVC handler per one task exception.

    If another nested extended SVC call is made while a task exception is raised, no break function is called for the called extended SVC handler.

    A break function runs as a quasi-task portion. Its requesting task is identified as follows: If a break function is called by tk_ras_tex, it runs as a quasi-task portion of the task that issued tk_ras_tex. On the other hand, when the nesting level of extended SVC handler is decreased, the break function runs as a quasi-task portion of the task that raised the task exception (the task running the extended SVC handler). This means that the task executing the break function may be different from the task executing the extended SVC handler. In such a case, the break function and extended SVC handler run concurrently as controlled by task scheduling.

    It is thus conceivable that the extended SVC handler will return to its caller before the break function finished executing, but in that case the extended SVC handler waits at the point right before returning, until the break function completes. How this waiting state maps to the task state transitions is implementation-dependent, but preferably it should remain in READY state (a READY state that does not go to RUNNING state). The precedence of a task may change while it is waiting for a break function to complete, but how task precedence is treated is implementation-dependent.

    Similarly, an extended SVC handler cannot call an extended SVC until break function execution completes.

    In other words, during the time from the raising of a task interrupt until the break function completes, the affected task must stay in the extended SVC handler that was executing at the time of the task exception.

    In the case where the requesting task of the break function differs from that of the extended SVC handler, that is, where the break function and the extended SVC handler run in different task contexts, the task priority of the break function is raised to the same as that of the extended SVC handler only while the break handler is executing if the former is lower than the latter. On the other hand, if the break function task priority is the same as or higher than that of the extended SVC handler, the priority does not change. The priority that gets changed is the current priority; the base priority stays the same.

    The change in priority occurs only immediately before entry into the break function; any changes after that of the extended SVC handler task priority are not followed by further changes in priority of the break function task. In no case does a change in the break function priority while a break function is running results in a priority change in the extended SVC handler task. At the same time, there is no restriction on priority changes due to a running break function.

    When the break function completes, the current priority of its task reverts to base priority. If a mutex was locked, however, the priority reverts to that as adjusted by the mutex. (In other words, the ability is provided to adjust the current priority at the entry and exit of the break function only; other than that, the priority is the same as when an ordinary task is running.)

  • Event handling function

    An event handling function is called by issuing the tk_evt_ssy system call.

    It processes various requests made to a subsystem.

    Note that it has to process all requests for all subsystems. If processing is not required, it can simply return E_OK without performing any operation.

    The format of an event handling function is as follows.

    
ER eventfn( INT evttyp, INT info )
    {
            /*
                    event processing
            */
    
            return ercd;
    }
    

    evttyp indicates the request type and info is a parameter that can be used freely. These parameters are specified in tk_evt_ssy.

    If processing completes normally, E_OK is passed in the return code; otherwise an error code (negative value) is returned.

    The following event types evttyp are defined. For more details, see the Section called Device Management Functions in the Chapter called μT-Kernel/SM Functions.

    
#define TSEVT_SUSPEND_BEGIN     1       /* before suspending device */
    #define TSEVT_SUSPEND_DONE      2       /* after suspending device */
    #define TSEVT_RESUME_BEGIN      3       /* before resuming device */
    #define TSEVT_RESUME_DONE       4       /* after resuming device */
    #define TSEVT_DEVICE_REGIST     5       /* device registration notice */
    #define TSEVT_DEVICE_DELETE     6       /* device deletion notice */
    

    An event handling function runs as a quasi-task portion of the task that issued tk_evt_ssy.

Additional Notes

Extended SVC handlers as well as break functions and event handling functions all have the equivalent of the TA_HLNG attribute only. There is no means of specifying the TA_ASM attribute.

It is possible to issue a system call that enters WAITING state in the extended SVC handler, but in that case the program must be designed so that it can be stopped by calling a break function. The specific processing flow is as follows: If tk_ras_tex is issued for the caller task while an extended SVC handler is executing, it is necessary to stop the running extended SVC handler as soon as possible and return a stop error to the caller task. For this purpose the break function is used. In order to stop the running extended SVC handler immediately, the break function must forcibly release the WAITING state, even if the system call is in WAITING state during processing the extended SVC handler. For this purpose, the tk_dis_wai system call is generally used. tk_dis_wai can prevent the system call from entering WAITING state until the control returns from the extended SVC handler to the caller task, but the implementor should also make it possible to stop the program of the extended SVC handler by calling a break function. For example, leaving from WAITING state with the error code E_DISWAI can mean that the execution is stopped by a break function. So it is best to stop the extended SVC handler immediately and return a stop error to the caller task, without continuing to execute the subsequent processing.

An extended SVC handler may be called concurrently by multiple tasks. If the tasks share same resources, the mutual exclusion control must be performed in the extended SVC handler.

Porting Guideline

Note that, in an environment where INT data type is 16 bits, part of function code that can be used for subsystem function code is only 7 bits wide (0-127), and care must be taken.

tk_evt_ssy - Call Event Function

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_evt_ssy(ID ssid, INT evttyp, ID resid, INT info);

Parameter

ID ssid Subsystem IDSubsystem ID
INT evttyp Event TypeEvent request type
INT info InformationAny parameter

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (ssid is invalid or cannot be used)
E_NOEXS Object does not exist (the subsystem specified in ssid is not defined)
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)
OtherError code returned by the event handling function

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Related Service Profile Items

Only when all the service profile items below are set to be effective, this system call can be used.

TK_SUPPORT_SUBSYSTEM Support of subsystem management functions
TK_SUPPORT_SSYEVENT Support of event processing of subsystems

Description

Calls the event handling function of the subsystem specified in ssid.

Specifying ssid = 0 makes the system call applied to all currently defined subsystems. In this case the event handling function of each subsystem is called in sequence.

When evttyp is an odd number:

Calls subsystems in descending order of priority.

When evttyp is an even number:

Calls subsystems in ascending order of priority.

The calling order is undefined wheren these subsystems have the same priority.

If this system call is issued for a subsystem with no event handling function defined, the function is simply not called; no error results.

If the event handling function returns an error, the error code is passed transparently in the system call return code. When ssid = 0 and an event handler returns an error, the event handling functions of all other subsystems continue to be called. In the system call return code, only one error code is returned even if more than one event handling function returned an error. It is not possible to know which subsystem's event handling function returned the error.

If a task exception is raised for the task that called tk_evt_ssy, during the execution of event handling function, the task exception is held until the event handling function completes its processing.

Additional Notes

An example of using an event handling function is to perform the suspend/resume processing for the power management functions. Specifically, when the system enters the power-off state (device suspended state) due to power failure or other reason, it notifies each subsystem of its transition to suspended state. Then the event handling function of each subsystem is called to perform the appropriate processing for it. In μT-Kernel/SM, tk_evt_ssy is executed for this purpose during the processing of tk_sus_dev. The event handling function of each subsystem performs any necessary operations before going to suspended state, such as saving the data. On the other hand, when the system returns (resumes) from the suspended state due to power on or other reason, it notifies each subsystem of its return from suspended state. Then the event handling function of each subsystem is called again to perform the appropriate processing for it. For more details, see the description of tk_sus_dev.

For another example, when a new device is registered by tk_def_dev, the system notifies each subsystem of the registration, and the event handling function of each subsystem is called to perform the appropriate processing for it. In μT-Kernel/SM, tk_evt_ssy is executed for this purpose during the processing of tk_def_dev.

Porting Guideline

Note that info is INT type, and its value range is implementation-dependent, so care must be taken.

tk_ref_ssy - Reference Subsystem Status

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_ref_ssy(ID ssid, T_RSSY *pk_rssy);

Parameter

ID ssid Subsystem IDSubsystem ID
T_RSSY* pk_rssy Packet to Return Subsystem StatusPointer to the area to return the subsystem definition information

Return Parameter

ER ercd Error CodeError code

pk_rssy Detail:

PRI ssypri Subsystem PrioritySubsystem priority
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_OK Normal completion
E_ID Invalid ID number (ssid is invalid or cannot be used)
E_NOEXS Object does not exist (the subsystem specified in ssid is not defined)
E_PAR Parameter error (invalid pk_rssy)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Related Service Profile Items

Only when all the service profile items below are set to be effective, this system call can be used.

TK_SUPPORT_SUBSYSTEM Support of subsystem management functions

When the service profile items below is set to be effective, subsystem priority (ssypri) can be acquired.

TK_SUPPORT_SSYEVENT Support of event processing of subsystems

Description

References information about the subsystem specified in ssid.

ssypri returns the subsystem priority specified in tk_def_ssy.

If the subsystem specified in ssid is not defined, E_NOEXS is returned.