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 processing part (a part in which T-Kernel functions are actually called from within a function that represents a system call) of the system call interface is implemented as a library written in assembly language. This is called an interface library. In consideration of portability, C language macros, in-line functions, in-line assembly codes, etc. are not used for implementation of the interface library.
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.
Enable const
by the specification in Makefile. (Recommended)
In T-Kernel 2.0 or later, it is strongly recommended that CONST is used explicit by in a program and the check for const
is enabled in development.
![]() | Difference from T-Kernel 1.0 |
---|---|
CONST is added to the C language interface of system calls, and the check using |
The following system calls can be issued from a task-independent portion and in dispatch disabled state:
System call name | Summary description |
---|---|
tk_sta_tsk | Start Task |
tk_wup_tsk | Wakeup Task |
tk_rel_wai | Release Wait |
tk_sus_tsk | Suspend Task |
tk_sig_sem | Signal Semaphore |
tk_set_flg | Set Event Flag |
tk_sig_tev | Signal Task Event |
tk_rot_rdq | Rotate Ready Queue |
tk_get_tid | Get Task Identifier |
tk_sta_cyc | Start Cyclic Handler |
tk_stp_cyc | Stop Cyclic Handler |
tk_sta_alm | Start Alarm Handler |
tk_sta_alm_u | Start Alarm Handler (in microseconds) |
tk_stp_alm | Stop Alarm Handler |
tk_ref_tsk | Reference Task Status |
tk_ref_tsk_u | Reference Task Status (Microseconds) |
tk_ref_cyc | Reference Cyclic Handler Status |
tk_ref_cyc_u | Reference Cyclic Handler Status (Microseconds) |
tk_ref_alm | Reference Alarm Handler Status |
tk_ref_alm_u | Reference Alarm Handler Status (Microseconds) |
tk_ref_sys | Reference System Status |
tk_ret_int | Return from Interrupt Handler (can be issued only from an interrupt handler written in an assembly language) |
Whether system calls 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 T-Kernel Extension, to prevent tasks that use the functions of T-Kernel extension from directly accessing T-Kernel functions. It allows T-Kernel to be used as a micro-kernel.
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. It is not allowable, however, to change the data types and order of information defined in the standard specification or to delete any of this information. When implementation-dependent information is added, it must be positioned after the standard defined information.
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 ensure that a program developed within the scope of the standard specification will be able to run on an OS with implementation-dependent functional extensions, simply by recompiling.
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. Since T-Kernel/OS does not use a sub error code, these bits are always 0.
#define MERCD(er) ( (ER)(er) >> 16 ) /* Main error code */ #define SERCD(er) ( (H)(er) ) /* sub error codes */ #define ERCD(mer, ser) ( (ER)(mer) << 16 | (ER)(UH)(ser) )
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).
![]() | 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.) |
Actual time resolution in T-Kernel time management functions uses one that is specified by the "timer interrupt interval" (TTimPeriod) in the Section called Standard System Configuration Information in the Chapter called T-Kernel/SM Functions. By default, the "timer interrupt interval" (TTimPeriod) is set to 10 milliseconds. Actually settable range and operable range are implementation-dependent.
As the "timer interrupt interval" decreases, system overhead by the timer interrupt increases and a clock error may increase due to the constraints on the clock or hardware provided for the timer.