μT-Kernel adopts C as the standard high-level language, and standardizes interfaces for system call execution from C language routines.
The method for interfacing with the assembly language shall be implementation-dependent. Calling by means of a C language interface is recommended even when an assembly language is used. In this way, portability is assured for programs written in assembly language even if the OS changes, so long as the CPU is the same.
The following common rules are established for system call interfaces.
All system calls are defined as C language functions.
A function return code of 0 or a positive value indicates normal completion, while negative values are used for error codes.
The implementation of the system call interface is not standardized, and is implementation-dependent. For example, we can use C language macros, inline functions, inline assembly language description, etc.
Among C language interfaces for system calls, those which pass parameters using a packet or pointer have CONST modifier attached to explicitly indicate that μT-Kernel does not overwrite a parameter referred to by the pointer.
CONST is intended to be the C language const
modifier equivalent. This alias for const
is used so that the compiler check can be disabled by using #define macro function when any program that does not support const
modifier mixes in.
Specific usage of CONST is as follows: Details, however, depend on the development environment.
Include the following descriptions in the common include file:
/* If TKERNEL_CHECK_CONST definition exists, enable the check for const */ #ifdef TKERNEL_CHECK_CONST #define CONST const #else #define CONST #endif
Describe a function definition or system call definition in the program by using CONST.
In μT-Kernel 3.0 or later, it is strongly recommended that CONST is used explicitly in a program and the check for const
is enabled in the configuration.
The following system calls of μT-Kernel/OS can be issued from a task-independent portion and in dispatch disabled state:
System call name | Summary description |
---|---|
tk_sta_tsk | Start Task |
tk_ref_tsk | Reference Task Status |
tk_wup_tsk | Wakeup Task |
tk_rel_wai | Release Wait |
tk_sus_tsk | Suspend Task |
tk_sig_tev | Signal Task Event |
tk_sig_sem | Signal Semaphore |
tk_set_flg | Set Event Flag |
tk_sta_cyc | Start Cyclic Handler |
tk_stp_cyc | Stop Cyclic Handler |
tk_ref_cyc | Reference Cyclic Handler Status |
tk_ref_cyc_u | Reference Cyclic Handler Status (Microseconds) |
tk_sta_alm | Start Alarm Handler |
tk_sta_alm_u | Start Alarm Handler (Microseconds) |
tk_stp_alm | Stop Alarm Handler |
tk_ref_alm | Reference Alarm Handler Status |
tk_ref_alm_u | Reference Alarm Handler Status (Microseconds) |
tk_ret_int | Return from Interrupt Handler (can be issued only from an interrupt handler written in an assembly language) |
tk_rot_rdq | Rotate Ready Queue |
tk_get_tid | Get Task Identifier |
tk_ref_sys | Reference System Status |
The following APIs of μT-Kernel/SM can be issued from a task-independent portion and in dispatch disabled state:
API name | Summary description |
---|---|
DI | Disable External Interrupts |
EI | Enable External Interrupts |
isDI | Get Interrupt Disable Status |
SetCpuIntLevel | Set CPU Interrupt Mask Level |
GetCpuIntLevel | Get CPU Interrupt Mask Level |
EnableInt | Enable Interrupts |
DisableInt | Disable Interrupts |
ClearInt | Clear Interrupt |
EndOfInt | Issue EOI to Interrupt Controller |
CheckInt | Check Interrupt |
SetIntMode | Set Interrupt Mode |
SetCtrlIntLevel | Set Interrupt Controller Interrupt Mask Level |
GetCtrlIntLevel | Get Interrupt Controller Interrupt Mask Level |
out_b | Write to I/O Port (in Bytes) |
out_h | Write to I/O Port (in Half-words) |
out_w | Write to I/O Port (in Words) |
out_d | Write to I/O Port (in Double-words) |
in_b | Read from I/O Port (in Bytes) |
in_h | Read from I/O Port (in Half-words) |
in_w | Read from I/O Port (in Words) |
in_d | Read from I/O Port (in Double-words) |
WaitUsec | Micro Wait (Microseconds) |
WaitNsec | Micro Wait (Nanoseconds) |
SetOBJNAME | Set Object Name |
All system calls of μT-Kernel/DS can be issued from a task-independent portion and in dispatch disabled state.
Whether system calls or APIs other than those above can be issued from a task-independent portion or in dispatch disabled state is implementation-dependent.
The protection levels at which a system call is invokable can be restricted. In this case, if a system call is issued from a task (task portion) running at lower privilege than the specified protection level, the error code E_OACV is returned.
Extended SVC calling cannot be restricted.
If, for example,issuing a system call from a level with lower privilege than level 1 is prohibited, system calls cannot be made from tasks running at protection levels 2 and 3. Tasks running at those levels will only be able to make extended SVC calls, and are programmed using subsystem functions only.
This kind of restriction is used when μT-Kernel is combined with middleware that offers process management function and other functions, to prevent tasks (as part of user process, etc.) that use the functions of such middleware (process management, etc.) from directly accessing μT-Kernel functions. It allows μT-Kernel to be used as a micro-kernel. The idea is that the user process cannot control the micro-kernel directly via available process API, and only the middleware can control the micro-kernel directly.
The protection level restriction on system call invocation is set using the system configuration information management functions. (see the Section called System Configuration Information Management Functions in the Chapter called μT-Kernel/SM Functions).
Some parameters passed to system calls use packet format. The packet format parameters are of two kinds, either input parameters passing information to a system call (e.g., T_CTSK) or output parameters returning information from a system call (e.g., T_RTSK).
Additional information that is implementation-dependent can be added to a parameter packet. When implementation-dependent information is added, it must be positioned after the standard defined information. It is permitted to delete only parameters that are declared ineffective by the service profile, and other parameters shall not be deleted. It is not allowed, however, to change the data types and order of information defined in the standard specification.
When implementation-dependent information is added to a packet of input information passed to a system call (T_CTSK, etc.), if the system call is invoked while this additional information is not yet initialized (memory content is indeterminate), the system call must still function normally.
Ordinarily a flag indicating that valid values are set in the additional information is defined in the implementation-dependent area of attribute flag included in the standard specification. When that flag is set (1), the additional information is to be used; and when the flag is not set (0), the additional information is not initialized (memory content is indeterminate) and the default values are to be used instead.
The reason for this specification is to make sure we can run the same application program merely by recompiling, irrespective of whether implementation dependent function extension is added to an implementation of the specification.
Porting Guideline | |
---|---|
A care must be taken now for parameter packet initialization since the parameter may be deleted by declaring it to be ineffective by service profile. For example, it is not recommended to initialize T_CTSK structure in the following manner from the viewpoint f portability. T_CTSK ctsk = { NULL, TA_HLNG|TA_RNG0|TA_USERBUF, task, 10, 2048, "", buf }; Instead, it is recommended to perform initialization using the syntax specified in ISO/IEC 9899:1999 as follows. T_CTSK ctsk = { .exinf = NULL, .tskatr = TA_HLNG|TA_RNG0|TA_USERBUF, .task = task, .itskpri = 10, .stksz = 2048, .bufptr = buf }; |
Function codes are numbers assigned to each system call and used to identify the system call.
The system call function codes are not specified here but are to be defined in implementation.
See tk_def_ssy on extended SVC function codes.
System call return codes are in principle to be signed integers. When an error occurs, a negative error code is returned; and if processing is completed normally, E_OK (= 0) or a positive value is returned. The meaning of returned values in the case of normal completion is specified individually for each system call. An exception to this principle is that there are some system calls that do not return when called. A system call that does not return is declared in the C language interface as having no return code (i.e., a void type function).
An error code consists of the main error code and sub error code. The low 16 bits of the error code are the sub error code, and the remaining high bits are the main error code. Main error codes are classified into error classes based on the necessity of their detection, the circumstances in which they occur and other factors.
#define MERCD(er) ( (ER)(er) >> 16 ) /* main error code */ #define SERCD(er) ( (H)(er) ) /* sub error code */ #define ERCD(mer, ser) ( (ER)(mer) << 16 | (ER)(UH)(ser) )
Note that, in an environment where ER is 16-bit data type, sub error code can be omitted and main error code can be returned as the error code. In this case, SERCD macro shall not be defined.
#define MERCD(er) ( (ER)(er) ) /* main error code */ #define ERCD(mer, ser) ( (ER)(mer) )
A system call that may enter WAITING state has a timeout function. If processing is not completed by the time the specified timeout interval has elapsed, the processing is canceled and the system call returns error code E_TMOUT.
In accordance with the principle that there should be no side-effects from calling a system call if that system call returns an error code, the calling of a system call that times out should in principle result in no change in system state. An exception to this is when the functioning of the system call is such that it cannot return to its original state if processing is canceled. This is indicated in the system call description.
If the timeout interval is set to 0, a system call does not enter even when a situation arises in which it would ordinarily go to WAITING state. In other words, a system call with timeout set to 0 when it is invoked has no possibility of entering WAITING state. Invoking a system call with timeout set to 0 is called polling; i.e., a system call that performs polling has no chance of entering WAITING state.
The descriptions of individual system calls as a rule describe the behavior when there is no timeout (in other words, when an eternal wait occurs). Even if the system call description states that the system call "enters WAITING state" or "is put in WAITING state," if a timeout is set and that time interval elapses before processing is completed, the WAITING state is released and the system call returns error code E_TMOUT. In the case of polling, the system call returns E_TMOUT without entering WAITING state.
Timeout (TMO and TMO_U types) is given as a positive integer, or as TMO_POL=0 for polling, or as TMO_FEVR (= -1) for eternal wait. If a timeout interval is set, the timeout processing must be guaranteed to take place after the specified interval from the system call issuing has elapsed.
Additional Notes | |
---|---|
Since a system call that performs polling does not enter WAITING state, there is no change in the precedence of the task calling it. In a general implementation, when the timeout is set to 1, timeout processing takes place on the second timer interrupt (sometimes called "time tick") after a system call is invoked. Since a timeout of 0 cannot be specified (0 being allocated to TMO_POL ), in this kind of implementation timeout does not occur on the initial timer interrupt after the system call is invoked. |
When the time of an event occurrence is specified relative to another time, such as the time when a system call was invoked, relative time (RELTIM or RELTIM_U type) is used. If relative time is used to specify event occurrence time, it is necessary to guarantee that the event processing will take place after the specified time has elapsed from the time base. Relative time (RELTIM or RELTIM_U type) is also used for e.g. event occurrence. In such cases the method of interpreting the specified relative time is determined for each case. When time is specified as an absolute value, system time (SYSTIM or SYSTIM_U type) is used. The μT-Kernel provides a function for setting system time, but even if the system time is changed using this function, there is no change in the real world time (actual time) at which an event occurs that was specified using relative time. What changes is the system time at which an event occurs that was specified as relative time.
Time base 1 millisecond, 64-bit signed integer
typedef struct systim { W hi; /* High 32 bits */ UW lo; /* Low 32 bits */ } SYSTIM;
Time base 1 microsecond, 64-bit signed integer
typedef D SYSTIM_U; /* 64-bit */
Time base 1 millisecond, 32-bit unsigned integer (UW)
typedef UW RELTIM;
Time base 1 microsecond, 64-bit unsigned (UD) integer
typedef UD RELTIM_U; /* Relative time in microseconds with 64-bit integer */
Time base 1 millisecond, 32-bit signed integer (W)
typedef W TMO;
Eternal wait can be specified as TMO_FEVR (= -1).
Time base 1 microsecond, 64-bit signed (D) integer
typedef D TMO_U; /* Timeout in microseconds with 64-bit integer */
Eternal wait can be specified as TMO_FEVR (= -1).
Related Service Profile Items | |
---|---|
TMO_U, RELTIM_U, and SYSTEM_U dealing with date and relative time in microsecond resolution are guaranteed to be usable only when the following service profile items are set to be effective. |
Additional Notes | |
---|---|
Timeout or other such processing must be guaranteed to occur after the time specified as RELTIM, RELTIM_U, TMO, or TMO_U has elapsed. For example, if the timer interrupt interval is 1 ms and a timeout of 1 ms is specified, timeout occurs on the second timer interrupt after system call invocation. (The first timer interrupt does not exceed 1 ms.) When a system time (SYSTIM_U) value that may overflow internally in kernel is specified as an argument, the system call behavior is undefined. |