Extended Synchronization and Communication Functions

Extended synchronization and communication functions use objects independent of tasks to realize more sophisticated synchronization and communication between tasks. The functions specified here include mutex, message buffer, and rendezvous functions.

Mutex

A mutex is an object for mutual exclusion control among tasks that use shared resources. Priority inheritance mutexes and priority ceiling mutexes are supported, as a mechanism to prevent the problem of unbounded priority inversion that can occur in mutual exclusion control.

Functions are provided for creating and deleting a mutex, locking and unlocking a mutex, and referencing mutex status. A mutex is identified by an ID number. The ID number for the mutex is called a mutex ID.

A mutex has a status (locked or unlocked) and a queue for tasks waiting to lock the mutex. For each mutex, T-Kernel keeps track of the tasks locking it; and for each task, it keeps track of the mutexes it has locked. Before a task uses a resource, it locks a mutex associated with that resource. If the mutex is already locked by another task, the task waits for the mutex to become unlocked. Tasks in mutex lock waiting state are put in the mutex queue. When a task finishes with a resource, it unlocks the mutex.

A mutex with TA_INHERIT (= 0x02) specified as mutex attribute supports priority inheritance protocol while one with TA_CEILING (= 0x03) specified supports priority ceiling protocol. When a mutex with TA_CEILING attribute is created, a ceiling priority is assigned to it, indicating the base priority of the task having the highest base priority among the tasks that will lock that mutex. If a task having a higher base priority than the ceiling priority of the mutex with TA_CEILING attribute tries to lock it, error code E_ILUSE is returned. If tk_chg_pri is issued in an attempt to set the base priority of a task having locked a mutex with TA_CEILING attribute to a value higher than the ceiling priority of that mutex, E_ILUSE is returned by the tk_chg_pri system call.

When these protocols are used, unbounded priority inversion is prevented by automatically changing the current priority of a task in a mutex operation. Strict adherence to the priority inheritance protocol and priority ceiling protocol requires that the task current priority must always be changed to match the peak value of the following priorities. This is called strict priority control.

Note that when the current priority of a task waiting for a mutex with TA_INHERIT attribute changes as the result of a base priority change brought about by mutex operation or tk_chg_pri, it may become necessary to change the current priority of the task locking that mutex. This is called dynamic priority inheritance. Further, if this task is waiting for another mutex with TA_INHERIT attribute, dynamic priority inheritance processing may become necessary also for the task locking that mutex.

The T-Kernel defines, in addition to the above strict priority control, a simplified priority control limiting the situations in which the current priority is changed. The choice between the two is implementation-dependent. In the simplified priority control, whereas all changes in the direction of raising the task current priority are carried out, changes in the direction of lowering that priority are made only when a task is no longer locking any mutexes. (In this case the task current priority reverts to the base priority.) More specifically, processing to change the current priority is needed only in the following circumstances.

When the current priority of a task is changed in connection with a mutex operation, the following processing is performed.

If the task whose priority changed is in a run state, the task precedence is changed in accordance with the new priority. Its precedence among other tasks having the same priority is implementation-dependent. Likewise, if the task whose priority changes is waiting in a queue of some kind, its order in that queue is changed based on its new priority. Its order among other tasks having the same priority is implementation-dependent. When a task terminates and there are mutexes still locked by that task, all the mutexes are unlocked. The order in which multiple locked mutexes are unlocked is implementation-dependent. See the description of tk_unl_mtx for the specific processing involved.

NoteAdditional Notes
 

TA_TFIFO attribute mutex or TA_TPRI attribute mutex has functionality equivalent to that of a semaphore with a maximum of one resource (binary semaphore). The main differences are that a mutex can be unlocked only by the task that locked it, and a mutex is automatically unlocked when the task locking it terminates.

The term "priority ceiling protocol" is used here in a broad sense. The protocol described here is not the same as the algorithm originally proposed. Strictly speaking, it is what is otherwise referred to as a highest locker protocol or by other names.

When the change in current priority of a task due to a mutex operation results in that task's order being changed in a priority-based queue, it may be necessary to release the waiting state of other tasks waiting for that task or for that queue.

NoteRationale for the Specification
 

The precedence of tasks having the same priority as the result of a change in task current priority in a mutex operation is left as implementation-dependent, for the following reason. Depending on the application, the mutex function may lead to frequent changes in current priority. It would not be desirable for this to result in constant task switching, which is what would happen if the precedence were made the lowest each time among tasks of the same priority. Ideally task precedence rather than priority should be inherited, but that results in large overhead in implementation. This aspect of the specification is therefore made an implementation-dependent matter.

tk_cre_mtx - Create Mutex

C Language Interface

#include <tk/tkernel.h>

ID mtxid = tk_cre_mtx (CONST T_CMTX *pk_cmtx );

Parameter

CONST T_CMTX* pk_cmtx Packet to Create MutexInformation about the mutex to be created

pk_cmtx Detail:

void* exinf Extended InformationExtended information
ATR mtxatr Mutex AttributeMutex attributes
PRI ceilpri Ceiling Priority of MutexMutex ceiling priority
UB dsname[8] DS Object nameDS object name
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ID mtxid Mutex IDMutex ID
orError CodeError code

Error Code

E_NOMEM Insufficient memory (memory for control block cannot be allocated)
E_LIMIT Number of mutexes exceeds the system limit
E_RSATR Reserved attribute (mtxatr is invalid or cannot be used)
E_PAR Parameter error (pk_cmtx or ceilpri is invalid)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Creates a mutex, assigning to it a mutex ID. This system call allocates a control block, etc. for the created mutex.

exinf can be used freely by the user to set miscellaneous information about the created mutex. The information set in this parameter can be referenced by tk_ref_mtx. If a larger area is needed for indicating user information, or if the information may need to be changed after the message buffer is created, this can be done by allocating separate memory for this purpose and putting the memory packet address in exinf. The kernel pays no attention to the contents of exinf.

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

mtxatr:= (TA_TFIFO || TA_TPRI || TA_INHERIT || TA_CEILING) | [TA_DSNAME] | [TA_NODISWAI]

TA_TFIFO Tasks are queued in FIFO order
TA_TPRI Tasks are queued in priority order
TA_INHERIT Priority inheritance protocol
TA_CEILING Priority ceiling protocol
TA_DSNAME Specifies DS object name
TA_NODISWAI Disabling of wait by tk_dis_wai is prohibited

When the TA_TFIFO attribute is specified, the order of the mutex task queue is FIFO. If TA_TPRI, TA_INHERIT, or TA_CEILING is specified, tasks are ordered by their priority. TA_INHERIT indicates that priority inheritance protocol is used, and TA_CEILING specifies priority ceiling protocol.

Only when TA_CEILING is specified, ceilpri is valid and specifies the mutex ceiling priority.

When TA_DSNAME is specified, dsname is valid and specifies the DS object name. DS object name is used to identify objects by debugger, and it is handled only by T-Kernel/DS API, td_ref_dsname and td_set_dsname. For more details, see the description of td_ref_dsname and td_set_dsname. If TA_DSNAME is not specified, dsname is ignored. Then td_ref_dsname and td_set_dsname return E_OBJ error.

#define TA_TFIFO        0x00000000      /* manage queue by FIFO */
#define TA_TPRI         0x00000001      /* manage queue by priority */
#define TA_INHERIT      0x00000002      /* priority inheritance protocol */
#define TA_CEILING      0x00000003      /* priority ceiling protocol */
#define TA_DSNAME       0x00000040      /* DS object name */
#define TA_NODISWAI     0x00000080      /* reject request to disable wait */

tk_del_mtx - Delete Mutex

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_del_mtx (ID mtxid );

Parameter

ID mtxid Mutex IDMutex ID

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mtxid is invalid or cannot be used)
E_NOEXS Object does not exist (the mutex specified in mtxid does not exist)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Deletes the mutex specified in mtxid.

Issuing this system call releases the mutex ID and control block memory space allocated to the mutex.

This system call completes normally even if there are tasks waiting to lock the deleted mutex, but error code E_DLT is returned to each of the tasks in WAITING state.

When a mutex is deleted, a task locking the mutex will have one fewer locked mutexes. If the mutex to be deleted was a priority inheritance mutex (TA_INHERIT) or priority ceiling mutex (TA_CEILING), then deleting the mutex might change the priority of the task that has locked it.

tk_loc_mtx - Lock Mutex

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_loc_mtx (ID mtxid , TMO tmout );

Parameter

ID mtxid Mutex IDMutex ID
TMO tmout TimeoutTimeout (ms)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mtxid is invalid or cannot be used)
E_NOEXS Object does not exist (the mutex specified in mtxid does not exist)
E_PAR Parameter error (tmout ≦ (-2))
E_DLT The object being waited for was deleted (the mutex was deleted while waiting for a lock)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)
E_ILUSE Illegal use (multiple lock, or upper priority limit exceeded)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Locks the mutex specified in mtxid. If the mutex can be locked immediately, the task issuing this system call continue executing without entering WAITING state, and the mutex goes to locked status. If the mutex cannot be locked, the task issuing this system call enters WAITING state. That is, the task is put in the queue of this mutex.

A maximum wait time (timeout) can be set in tmout. If the tmout time elapses before the wait release condition is met, the system call terminates, returning timeout error code E_TMOUT.

Only positive values can be set in tmout. The time unit for tmout (time unit) is the same as that for system time (= 1 ms).

When TMO_POL = 0 is set in tmout, this means 0 was specified as the timeout value, and E_TMOUT is returned without entering WAITING state even if the resource cannot be locked. When TMO_FEVR (= -1) is set in tmout, this means infinity was specified as the timeout value, and the task continues wait to until the resource is locked.

If the invoking task has already locked the specified mutex, error code E_ILUSE (multiple lock) is returned.

If the specified mutex is a priority ceiling mutex (TA_CEILING) and the base priority[1]of the invoking task is higher than the ceiling priority of the mutex, error code E_ILUSE (upper priority limit exceeded) is returned.

Additional Notes

  • Priority inheritance mutex (TA_INHERIT attribute)

    If the invoking task is waiting to lock a mutex and the current priority of the task currently locking that mutex is lower than that of the invoking task, the priority of the locking task is raised to the same level as the invoking task. If the wait ends before the waiting task can obtain a lock (timeout or other reason), the priority of the task locking that mutex can be lowered to the highest of the following three priorities. Whether this lowering takes place is implementation-dependent.

    1. The highest priority among the current priorities of tasks waiting to lock the mutex.

    2. The highest priority among all the other mutexes locked by the task currently locking this mutex.

    3. The base priority of the locking task.

  • Priority ceiling mutex (TA_CEILING attribute)

    If the invoking task obtains a lock and its current priority is lower than the mutex ceiling priority, the priority of the invoking task is raised to the mutex ceiling priority.

tk_loc_mtx_u - Lock Mutex (in microseconds)

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_loc_mtx_u (ID mtxid , TMO_U tmout_u );

Parameter

ID mtxid Mutex IDMutex ID
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mtxid is invalid or cannot be used)
E_NOEXS Object does not exist (the mutex specified in mtxid does not exist)
E_PAR Parameter error (tmout_u ≦ (-2))
E_DLT The object being waited for was deleted (the mutex was deleted while waiting for a lock)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)
E_ILUSE Illegal use (multiple lock, or upper priority limit exceeded)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This system call takes 64-bit tmout_u in microseconds instead of the parameter tmout of tk_loc_mtx.

The specification of this system call is same as that of tk_loc_mtx, except that the parameter is replaced with tmout_u. For more details, see the description of tk_loc_mtx.

Difference from T-Kernel 1.0

This system call was added in T-Kernel 2.0.

tk_unl_mtx - Unlock Mutex

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_unl_mtx (ID mtxid );

Parameter

ID mtxid Mutex IDMutex ID

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mtxid is invalid or cannot be used)
E_NOEXS Object does not exist (the mutex specified in mtxid does not exist)
E_ILUSE Illegal use (not a mutex locked by the invoking task)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Unlocks the mutex specified in mtxid.

If there are tasks waiting to lock the mutex, the WAITING state of the task at the head of the queue for that mutex is released and that task locks the mutex.

If a mutex that was not locked by the invoking task is specified, error code E_ILUSE is returned.

Additional Notes

If the unlocked mutex is a priority inheritance mutex (TA_INHERIT) or priority ceiling mutex (TA_CEILING), task priority must be lowered as follows.

If as a result of this operation the invoking task no longer has any locked mutexes, the invoking task priority is lowered to its base priority.

If the invoking task continues to have locked mutexes after the operation above, the invoking task priority is lowered to whichever of the following priority is highest.

  1. The highest priority among the current priority of the tasks in the queue of the mutex with the TA_INHERIT attribute locked by the invoking task

  2. The highest priority among the ceiling priority of the mutexes with the TA_CEILING attribute locked by the invoking task

  3. Base priority of the invoking task

Note that the lowering of priority when locked mutexes remain is implementation-dependent.

If a task terminates (goes to DORMANT state or NON-EXISTENT state) without explicitly unlocking mutexes, all its locked mutexes are automatically unlocked by T-Kernel.

tk_ref_mtx - Refer Mutex Status

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_ref_mtx (ID mtxid , T_RMTX *pk_rmtx );

Parameter

ID mtxid Mutex IDMutex ID
T_RMTX* pk_rmtx Packet to Return Mutex StatusPointer to the area to return the mutex status

Return Parameter

ER ercd Error CodeError code

pk_rmtx Detail:

void* exinf Extended InformationExtended information
ID htsk Locking Task IDID of task locking the mutex
ID wtsk Lock Waiting Task IDID of tasks waiting to lock the mutex
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_OK Normal completion
E_ID Invalid ID number (mtxid is invalid or cannot be used)
E_NOEXS Object does not exist (the mutex specified in mtxid does not exist)
E_PAR Parameter error (invalid pk_rmtx)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

References the status of the mutex specified in mtxid, passing in the return parameters the task currently locking the mutex (htsk), tasks waiting to lock the mutex (wtsk), and extended information (exinf).

htsk indicates the ID of the task locking the mutex. If no task is locking it, htsk = 0 is returned.

wtsk indicates the ID of a task waiting to lock the mutex. If there are two or more such tasks, the ID of the task at the head of the queue is returned. If there are no waiting tasks, wtsk = 0 is returned.

If the specified mutex does not exist, error code E_NOEXS is returned.

Message Buffer

A message buffer is an object for achieving synchronization and communication by the passing of variable-size messages. Functions are provided for creating and deleting a message buffer, sending and receiving messages using a message buffer, and referencing message buffer status. A message buffer is an object identified by an ID number. The ID number for the message buffer is called a message buffer ID.

A message buffer keeps a queue of tasks waiting to send a message (send queue) and a queue of tasks waiting for receive a message (receive queue). It also has a message buffer space for holding sent messages. The message sender (the side posting event notification) copies a message it wants to send to the message buffer. If there is insufficient space in the message buffer area, the task trying to send the message is queued for sending until enough space is available.

A task waiting to send a message to the message buffer is put in the send queue. On the message receive side (waiting for event notification), one message is fetched from the message buffer. If the message buffer has no messages, the task enters WAITING state until the next message is sent. A task waiting for receiving a message from a message buffer is put in the receive queue of that message buffer.

A synchronous message function can be realized by setting the message buffer space size to 0. In that case both the sending task and receiving task wait for a system call to be invoked by each other, and the message is passed when both sides issue system calls.

NoteAdditional Notes
 

The message buffer behavior when the size of the message buffer space is set to 0 is explained here using the example in Figure 3. In this example Task A and Task B run asynchronously.

  • If Task A calls tk_snd_mbf first, it goes to WAITING state until Task B calls tk_rcv_mbf. In this case Task A is put in the message buffer send queue [Figure 3 (a)]

  • If Task B calls tk_rcv_mbf first, on the other hand, Task B goes to WAITING state until Task A calls tk_snd_mbf. Task B is put in the message buffer receive queue [Figure 3 (b)].

  • At the point where both Task A has called tk_snd_mbf and Task B has called tk_rcv_mbf, a message is passed from Task A to Task B; Thereafter both tasks enter a run state.

Figure 3. Synchronous Communication by Message Buffer

Tasks waiting to send to a message buffer send messages in their queued order. Suppose Task A wanting to send a 40-byte message to a message buffer, and Task B wanting to send a 10-byte message, are queued in that order. If another task receives a message opening 20 bytes of space in the message buffer, Task B is still required to wait until Task A sends its message.

A message buffer is used to pass variable-size messages by copying them. It is the copying of messages that makes this function different from the mailbox function.

It is assumed that the message buffer will be implemented as a ring buffer.

tk_cre_mbf - Create Message Buffer

C Language Interface

#include <tk/tkernel.h>

ID mbfid = tk_cre_mbf (CONST T_CMBF *pk_cmbf );

Parameter

CONST T_CMBF* pk_cmbf Packet to Create Message BufferMessage buffer creation information

pk_cmbf Detail:

void* exinf Extended InformationExtended information
ATR mbfatr Message Buffer AttributeMessage buffer attribute
INT bufsz Buffer SizeMessage buffer size (in bytes)
INT maxmsz Max Message SizeMaximum message size (in bytes)
UB dsname[8] DS Object nameDS object name
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ID mbfid Message Buffer IDMessage buffer ID
orError CodeError code

Error Code

E_NOMEM Insufficient memory (memory for control block or ring buffer area cannot be allocated)
E_LIMIT Number of message buffers exceeds the system limit
E_RSATR Reserved attribute (mbfatr is invalid or cannot be used)
E_PAR Parameter error (pk_cmbf is invalid, or bufsz or maxmsz is negative or invalid)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Creates a message buffer, assigning to it a message buffer ID. This system call allocates a control block to the created message buffer. Based on the information specified in bufsz, it allocates a ring buffer area for message queue use (for messages waiting to be received).

A message buffer is an object for managing the sending and receiving of variable-size messages. If differs from a mailbox (mbx) in that the contents of the variable-size messages are copied when the message is sent and received. It also has a function for putting the sending task in WAITING state when the buffer is full.

exinf can be used freely by the user to set miscellaneous information about the created message buffer. The information set in this parameter can be referenced by tk_ref_mbf. If a larger area is needed for indicating user information, or if the information may need to be changed after the message buffer is created, this can be done by allocating separate memory for this purpose and putting the memory packet address in exinf. The kernel pays no attention to the contents of exinf.

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

mbfatr:= (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_NODISWAI]

TA_TFIFO Tasks waiting on call are queued in FIFO order
TA_TPRI Tasks waiting on call are queued in priority order
TA_DSNAME Specifies DS object name
TA_NODISWAI Disabling of wait by tk_dis_wai is prohibited

The queuing order of tasks waiting for sending a message when the buffer is full can be specified in TA_TFIFO or TA_TPRI. If the attribute is TA_TFIFO, tasks are ordered by FIFO, whereas TA_TPRI specifies queuing of tasks in order of their priority setting. Messages themselves are queued in FIFO order only.

Tasks waiting for receiving a message from a message buffer are queued in FIFO order only.

When TA_DSNAME is specified, dsname is valid and specifies the DS object name. DS object name is used to identify objects by debugger, and it is handled only by T-Kernel/DS API, td_ref_dsname and td_set_dsname. For more details, see the description of td_ref_dsname and td_set_dsname. If TA_DSNAME is not specified, dsname is ignored. Then td_ref_dsname and td_set_dsname return E_OBJ error.

#define TA_TFIFO        0x00000000      /* manage task queue by FIFO */
#define TA_TPRI         0x00000001      /* manage task queue by priority */
#define TA_DSNAME       0x00000040      /* DS object name */
#define TA_NODISWAI     0x00000080      /* reject request to disable wait */

Additional Notes

When there are multiple tasks waiting to send messages, the order in which their messages are sent when buffer space becomes available is always in their queued order.

If, for example, a Task A wanting to send a 30-byte message is queued with a Task B wanting to send a 10-byte message, in the order A-B, even if 20 bytes of message buffer space becomes available, Task B never sends its message before Task A.

The ring buffer in which messages are queued also contains information for managing each message. For this reason the total size of queued messages will ordinarily not be identical to the ring buffer size specified in bufsz. Normally the total message size will be smaller than bufsz. In this sense bufsz does not strictly represent the total message capacity.

It is possible to create a message buffer with bufsz = 0. In this case communication using the message buffer is completely synchronous between the sending and receiving tasks. That is, if either tk_snd_mbf or tk_rcv_mbf is executed ahead of the other, the task executing the first system call goes to WAITING state. When the other system call is executed, the message is passed (copied), then both tasks resume running.

In the case of a bufsz = 0 message buffer, the specific functioning is as follows.

  1. In Figure 4, Task A and Task B operate asynchronously. If Task A arrives at point (1) first and executes tk_snd_mbf(mbfid), Task A goes to send waiting state until Task B arrives at point (2). If tk_ref_tsk is issued for Task A in this state, tskwait=TTW_SMBF is returned. If, on the other hand, Task B gets to point (2) first and calls tk_rcv_mbf(mbfid), Task B goes to receive waiting state until Task A gets to point (1). If tk_ref_tsk is issued for Task B in this state, tskwait=TTW_RMBF is returned.

  2. At the point where both Task A has executed tk_snd_mbf(mbfid) and Task B has executed tk_rcv_mbf(mbfid), a message is passed from Task A to Task B, their wait states are released and both tasks resume running.

Figure 4. Synchronous Communication Using Message Buffer of bufsz = 0

tk_del_mbf - Delete Message Buffer

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_del_mbf (ID mbfid );

Parameter

ID mbfid Message Buffer IDMessage buffer ID

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Deletes the message buffer specified in mbfid.

Issuing this system call releases the corresponding message buffer and control block memory space, as well as the message buffer space.

This system call completes normally even if there were tasks queued in the message buffer for message receipt or message sending, but error code E_DLT is returned to the tasks in WAITING state. If there are messages left in the message buffer when it is deleted, the message buffer is deleted anyway. No error code is returned and the messages are discarded.

tk_snd_mbf - Send Message to Message Buffer

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_snd_mbf (ID mbfid , CONST void *msg , INT msgsz , TMO tmout );

Parameter

ID mbfid Message Buffer IDMessage buffer ID
CONST void* msg Send MessageStart address of send message
INT msgsz Send Message SizeSend message size (in bytes)
TMO tmout TimeoutTimeout (ms)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)
E_PAR Parameter error (msgsz ≦ 0, msgsz > maxmsz, invalid msg, or tmout ≦ (-2))
E_DLT The object being waited for was deleted (message buffer was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO(* Available in some circumstances)

Description

tk_snd_mbf sends the message at the address specified in msg to the message buffer indicated in mbfid. The message size is specified in msgsz. This system call copies msgsz bytes starting from msg to the message queue of message buffer mbfid. The message queue is assumed to be implemented as a ring buffer.

If msgsz is larger than the maxmsz specified in tk_cre_mbf, error code E_PAR is returned.

If there is not enough available buffer space to accommodate message msg in the message queue, the task issuing this system call goes to send waiting state and is put in the send queue of the message buffer waiting for buffer space to become available. Waiting tasks are queued in either FIFO or priority order, depending on the attribute specified in tk_cre_mbf.

A maximum wait time (timeout) can be set in tmout. If the tmout time elapses before the wait release condition is met (before there is sufficient buffer space), the system call terminates, returning timeout error code E_TMOUT.

Only positive values can be set in tmout. The time unit for tmout (time unit) is the same as that for system time (= 1 ms).

When TMO_POL = 0 is specified in tmout, it means 0 is specified as the timeout value, and if there is not enough buffer space, then E_TMOUT is returned without entering WAITING state. When TMO_FEVR (= -1) is specified in tmout, this means infinity was specified as the timeout value, and the task continues to wait for buffer space to become available, without timing out.

A message of size 0 cannot be sent. When msgsz ≦ 0, error code E_PAR is returned.

When this system call is invoked from a task-independent portion or in dispatch disabled state, error code E_CTX is returned; but in the case of tmout = TMO_POL, there may be implementations where execution from a task-independent portion or in dispatch disabled state is possible.

tk_snd_mbf_u - Send Message to Message Buffer (in microseconds)

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_snd_mbf_u (ID mbfid , CONST void *msg , INT msgsz , TMO_U tmout_u );

Parameter

ID mbfid Message Buffer IDMessage buffer ID
CONST void* msg Send MessageStart address of send message
INT msgsz Send Message SizeSend message size (in bytes)
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)
E_PAR Parameter error (msgsz ≦ 0, msgsz > maxmsz, invalid msg, or tmout_u ≦ (-2))
E_DLT The object being waited for was deleted (message buffer was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO(* Available in certain circumstance)

Description

This system call takes 64-bit tmout_u in microseconds instead of the parameter tmout of tk_snd_mbf.

The specification of this system call is same as that of tk_snd_mbf, except that the parameter is replaced with tmout_u. For more details, see the description of tk_snd_mbf.

Difference from T-Kernel 1.0

This system call was added in T-Kernel 2.0.

tk_rcv_mbf - Receive Message from Message Buffer

C Language Interface

#include <tk/tkernel.h>

INT msgsz = tk_rcv_mbf (ID mbfid , void *msg , TMO tmout );

Parameter

ID mbfid Message Buffer IDMessage buffer ID
void* msg Receive MessageAddress of the receive message
TMO tmout TimeoutTimeout (ms)

Return Parameter

INT msgsz Receive Message SizeReceived message size (in bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)
E_PAR Parameter error (invalid msg, or tmout ≦ (-2))
E_DLT The object being waited for was deleted (message buffer was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

tk_rcv_mbf receives a message from the message buffer specified in mbfid, copying it in the location specified in msg. This system call copies the contents of the first queued message in the message buffer specified in mbfid, and copies it to an area of msgsz bytes starting at address msg.

If no message has been sent to the message buffer specified in mbfid (the message queue is empty), the task issuing this system call goes to WAITING state and is put in the receive queue of the message buffer to wait for message arrival. Tasks in the receive queue are ordered by FIFO only.

A maximum wait time (timeout) can be set in tmout. If the tmout time elapses before the wait release condition is met (before a message arrives), the system call terminates, returning timeout error code E_TMOUT.

Only positive values can be set in tmout. The time unit for tmout (time unit) is the same as that for system time (= 1 ms).

When TMO_POL = 0 is set in tmout, this means 0 was specified as the timeout value, and E_TMOUT is returned without entering WAITING state even if there is no message. When TMO_FEVR (= -1) is set in tmout, this means infinity was specified as the timeout value, and the task continues to wait for message arrival without timing out.

tk_rcv_mbf_u - Receive Message from Message Buffer (in microseconds)

C Language Interface

#include <tk/tkernel.h>

INT msgsz = tk_rcv_mbf_u (ID mbfid , void *msg , TMO_U tmout_u );

Parameter

ID mbfid Message Buffer IDMessage buffer ID
void* msg Receive MessageAddress of the receive message
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

INT msgsz Receive Message SizeReceived message size (in bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)
E_PAR Parameter error (invalid msg, or tmout_u ≦ (-2))
E_DLT The object being waited for was deleted (message buffer was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This system call takes 64-bit tmout_u in microseconds instead of the parameter tmout of tk_rcv_mbf.

The specification of this system call is same as that of tk_rcv_mbf, except that the parameter is replaced with tmout_u. For more details, see the description of tk_rcv_mbf.

Difference from T-Kernel 1.0

This system call was added in T-Kernel 2.0.

tk_ref_mbf - Reference Message Buffer Status

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_ref_mbf (ID mbfid , T_RMBF *pk_rmbf );

Parameter

ID mbfid Message Buffer IDMessage buffer ID
T_RMBF* pk_rmbf Packet to Return Message Buffer StatusPointer to the area to return the message buffer status

Return Parameter

ER ercd Error CodeError code

pk_rmbf Detail:

void* exinf Extended InformationExtended information
ID wtsk Wait Task InformationReceive wait task ID
ID stsk Send Task InformationSend wait task ID
INT msgsz Message SizeSize of the next message to be received (in bytes)
INT frbufsz Free Buffer SizeFree buffer size (in bytes)
INT maxmsz Maximum Message SizeMaximum message size (in bytes)
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_OK Normal completion
E_ID Invalid ID number (mbfid is invalid or cannot be used)
E_NOEXS Object does not exist (the message buffer specified in mbfid does not exist)
E_PAR Parameter error (invalid pk_rmbf)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

References the status of the message buffer specified in mbfid, passing in the return parameters the send waiting task ID( stsk), the size of the next message to be received (msgsz), free buffer size (frbufsz), maximum message size (maxmsz), receive waiting task ID (wtsk), and extended information (exinf).

wtsk indicates the ID of a task waiting to receive a message from the message buffer. stsk indicates the ID of a task waiting to send a message to the message buffer. If multiple tasks are waiting in the message buffer queues, the ID of the task at the head of the queue is returned. If no tasks are waiting, 0 is returned.

If the specified message buffer does not exist, error code E_NOEXS is returned.

The size of the message at the head of the queue (the next message to be received) is returned in msgsz. If there are no queued messages, msgsz = 0 is returned. A message of size 0 cannot be sent.

At least one of msgsz = 0 and wtsk = 0 is always true for this system call.

frbufsz indicates the free space in the ring buffer of which the message queue consists. This value indicates the approximate size of messages that can be sent.

The maximum message size as specified in tk_cre_mbf is returned to maxmsz.

Rendezvous

Rendezvous is a function to perform synchronized communication between tasks that are in a relationship of server and client. Specifically, rendezvous includes a function that enables both the client and server side tasks wait for the acceptance of processing, a function that enables the client side task send a message requesting a processing (call message) to the server side task, a function that enables the client side task wait for the completion of processing of server side task, and a function that enables the server side task reply a message of processing result (reply message) to the client side task. A series of processing steps listed above can be achieved easily by using system calls for rendezvous. Rendezvous works on the object that is called a rendezvous port.

Figure 5. Rendezvous operation between a client task and server task

Functions are provided for creating and deleting a rendezvous port, issuing a processing request to a rendezvous port (call rendezvous), accepting a processing request from a rendezvous port (accept rendezvous), returning the processing result (reply rendezvous), forwarding an accepted processing request to another rendezvous port (forward rendezvous to other port), and referencing rendezvous port status and rendezvous status. A rendezvous port is identified by an ID number. The ID number for the rendezvous port is called a rendezvous port ID.

A task issuing a processing request to a rendezvous port (the client-side task) calls a rendezvous, specifying a message (called a call message) with information about the rendezvous port, the rendezvous conditions, and the processing being requested. The task accepting a processing request on a rendezvous port (the server-side task) accepts the rendezvous, specifying the rendezvous port and rendezvous conditions.

The rendezvous conditions are indicated in a bit pattern. If the bitwise logical AND of the bit patterns on both sides (the rendezvous condition bit pattern of the task calling a rendezvous for a rendezvous port and the rendezvous condition bit pattern of the accepting task) is not 0, the rendezvous is established. The state of the task calling the rendezvous is WAITING on rendezvous call until the rendezvous is established. The state of the task accepting a rendezvous is WAITING on rendezvous acceptance until the rendezvous is established.

When a rendezvous is established, a call message is passed from the task that called the rendezvous to the accepting task. The state of the task calling the rendezvous goes to WAITING for rendezvous completion until the requested processing is completed. The task accepting the rendezvous is released from WAITING state and it performs the requested processing. Upon completion of the requested processing, the task accepting the rendezvous passes the result of the processing in a reply message to the calling task and ends the rendezvous. At this point the WAITING state of the task that called the rendezvous is released.

The above operation is explained using the example shown in Figure 6. In this example Task A and Task B run asynchronously.

Figure 6. Rendezvous Operation

A rendezvous port has separate queues for tasks waiting on rendezvous call (call queue) and tasks waiting on rendezvous acceptance (accept queue). Note, however, that after a rendezvous is established, both tasks that formed the rendezvous are detached from the rendezvous port. In other words, a rendezvous port does not have a queue for tasks waiting for rendezvous completion. Nor does it keep information about the task performing the requested processing.

T-Kernel assigns a unique number called a rendezvous number to identify each rendezvous when more than one is established at the same time. The method of assigning rendezvous numbers is implementation-dependent, but at a minimum, information must be included for specifying the task that called the rendezvous. Even if the same task makes multiple rendezvous calls, the first rendezvous and second rendezvous must have different rendezvous numbers assigned.

NoteAdditional Notes
 

An example of the method to assign a rendezvous number is to use the ID number of the task that called a rendezvous to the lower bits of the rendezvous number, and put a serial number to the higher bits.

NoteRationale for the Specification
 

The name "rendezvous" of this function is based on the fact that a client side task and a server side task have a rendezvous between them. When rendezvous was included in T-Kernel specification, Rendezvous in Ada programming language and CSP (Communicating Sequential Processes) from which Ada derived affected it. However, the rendezvous function provided by T-Kernel is not the same as that of Ada language.

While it is true that the rendezvous functionality can be achieved through a combination of other synchronization and communication functions, better efficiency and ease of programming are achieved

by having a dedicated function for cases where the communication involves an acknowledgment. One advantage of the rendezvous function is that since both tasks wait until message passing is completed, no memory space needs to be allocated for storing messages.

The reason for assigning unique rendezvous numbers even when the same task does the calling is as follows. It is possible that a task, after establishing a rendezvous and going to WAITING state for its completion, will have its WAITING state released due to timeout or forcible release by another task, then again call a rendezvous and have that rendezvous established. If the same number were assigned to both the first and second rendezvous, attempting to terminate the first rendezvous would end up terminating the second rendezvous. If separate numbers are assigned to the two rendezvous and the task in WAITING state for rendezvous completion is made to remember the unique number of the rendezvous for which it is waiting, error will be returned when the attempt is made to terminate the first rendezvous.

tk_cre_por - Create Port for Rendezvous

C Language Interface

#include <tk/tkernel.h>

ID porid = tk_cre_por (CONST T_CPOR *pk_cpor );

Parameter

CONST T_CPOR* pk_cpor Packet to Create PortRendezvous port creation information

pk_cpor Detail:

void* exinf Extended InformationExtended information
ATR poratr Port AttributeRendezvous port attributes
INT maxcmsz Max Call Message SizeMaximum call message size (in bytes)
INT maxrmsz Max Reply Message SizeMaximum reply message size (in bytes)
UB dsname[8] DS Object nameDS object name
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ID porid Port IDRendezvous port ID
orError CodeError code

Error Code

E_NOMEM Insufficient memory (memory for control block cannot be allocated)
E_LIMIT Number of rendezvous ports exceeds the system limit
E_RSATR Reserved attribute (poratr is invalid or cannot be used)
E_PAR Parameter error (pk_cpor is invalid; maxcmsz or maxrmsz is negative or invalid)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Creates a rendezvous port, assigning to it a rendezvous port ID number. This specification allocates a control block to the created rendezvous port. A rendezvous port is an object used as an OS primitive for implementing a rendezvous capability.

exinf can be used freely by the user to set miscellaneous information about the created rendezvous port. The information set in this parameter can be referenced by tk_ref_por. If a larger area is needed for indicating user information, or if the information may need to be changed after the message buffer is created, this can be done by allocating separate memory for this purpose and putting the memory packet address in exinf. The kernel pays no attention to the contents of exinf.

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

poratr:= (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_NODISWAI]

TA_TFIFO Tasks waiting on call are queued in FIFO order
TA_TPRI Tasks waiting on call are queued in priority order
TA_DSNAME Specifies DS object name
TA_NODISWAI Disabling of wait by tk_dis_wai is prohibited

TA_TFIFO and TA_TPRI specify the queuing order of tasks waiting on a rendezvous call. Tasks waiting on rendezvous acceptance are queued in FIFO order only.

When TA_DSNAME is specified, dsname is valid and specifies the DS object name. DS object name is used to identify objects by debugger, and it is handled only by T-Kernel/DS API, td_ref_dsname and td_set_dsname. For more details, see the description of td_ref_dsname and td_set_dsname. If TA_DSNAME is not specified, dsname is ignored. Then td_ref_dsname and td_set_dsname return E_OBJ error.

#define TA_TFIFO        0x00000000      /* manage queue by FIFO */
#define TA_TPRI         0x00000001      /* manage queue by priority */
#define TA_DSNAME       0x00000040      /* DS object name */
#define TA_NODISWAI     0x00000080      /* reject request to disable wait */

maxcmsz specifies the maximum size (bytes) of the message passed at rendezvous call. maxcmsz can be 0. When maxcmsz is 0, the size of the message passed at rendezvous calling is limited to 0, and thus it is used only for synchronization without message.

maxrmsz specifies the maximum size (bytes) of the message passed at rendezvous return. maxrmsz can be 0. When maxrmsz is 0, the size of the message passed at rendezvous return is limited to 0.

tk_del_por - Delete Port for Rendezvous

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_del_por (ID porid );

Parameter

ID porid Port IDRendezvous port ID

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Deletes the rendezvous port specified in porid.

Issuing this system call releases the ID number and control block space allocated to the rendezvous port.

This system call completes normally even if there are tasks waiting on rendezvous acceptance (tk_acp_por) or rendezvous port call (tk_cal_por) at the specified rendezvous port, but error code E_DLT is returned to the tasks in WAITING state.

Deletion of a rendezvous port by tk_del_por does not affect tasks for which rendezvous is already established. In this case, nothing is reported to the task accepting the rendezvous (not in WAITING state), and the state of the task calling the rendezvous (WAITING for rendezvous completion) remains unchanged. When the task accepting the rendezvous issues tk_rpl_rdv, that tk_rpl_rdv will execute normally even if the port on which the rendezvous was established has been deleted.

tk_cal_por - Call Port for Rendezvous

C Language Interface

#include <tk/tkernel.h>

INT rmsgsz = tk_cal_por (ID porid , UINT calptn , void *msg , INT cmsgsz , TMO tmout );

Parameter

ID porid Port IDRendezvous port ID
UINT calptn Call Bit PatternCall bit pattern (indicating conditions of the caller)
void* msg MessageAddress of the message
INT cmsgsz Call Message SizeCall message size (bytes)
TMO tmout TimeoutTimeout (ms)

Return Parameter

INT rmsgsz Reply Message SizeReply message size (in bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (cmsgsz < 0, cmsgsz > maxcmsz, calptn = 0, invalid msg, or tmout ≦ (-2))
E_DLT The object being waited for was deleted (the rendezvous port was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Issues a rendezvous call for a rendezvous port.

The specific operation of tk_cal_por is as follows. A rendezvous is established if there is a task waiting to accept a rendezvous at the port specified in porid and rendezvous conditions between that task and the task issuing tk_cal_por. In this case, the task waiting to accept the rendezvous enters READY state while the state of the task issuing tk_cal_por is WAIT for rendezvous completion. The task waiting for rendezvous completion is released from WAITING state when the other (accepting) task executes tk_rpl_rdv. The tk_cal_por system call completes at this time.

If there is no task waiting to accept a rendezvous at the port specified in porid, or if there is a task but conditions for establishing a rendezvous are not satisfied, the task issuing tk_cal_por is placed at the end of the call queue of that port and enters WAITING state on rendezvous call. The order of tasks in the call queue is either FIFO or priority order, depending on the attribute made when calling tk_cre_por.

The decision on rendezvous establishment is made by checking conditions in the bit patterns acpptn of the accepting task and calptn of the calling task. A rendezvous is established if the bitwise logical AND of these two bit patterns is not 0. Parameter error E_PAR is returned if calptn is 0, since no rendezvous can be established in that case.

When a rendezvous is established, the calling task can send a message (a call message) to the accepting task. The size of the call message is specified in cmsgsz. In this operation, cmsgsz bytes starting at address msg specified by the calling task when calling tk_cal_por are copied to address msg as specified by the accepting task when calling tk_acp_por.

Similarly, when the rendezvous completes, the accepting task may send a message (reply message) to the calling task. In this operation, the contents of a reply message specified by the accepting task when calling tk_rpl_rdv are copied to address msg as specified by the calling task when calling tk_cal_por. The size of the reply message rmsgsz is set in a tk_cal_por return parameter. The original content of the message area passed in msg by tk_cal_por ends up being overwritten by the reply message received when tk_rpl_rdv executes.

Note that it is possible message content will be destroyed when a rendezvous is forwarded, since an area no larger than maxrmsz starting from the address msg as specified with tk_cal_por is used as a buffer. It is therefore necessary to reserve a memory space of at least maxrmsz starting from msg, regardless of the expected size of the reply message, whenever there is any possibility that a rendezvous requested by tk_cal_por might be forwarded(See the description of tk_fwd_por for details).

Error code E_PAR is returned when cmsgsz exceeds the size maxcmsz specified with tk_cre_por. This error checking is made before a task enters WAITING state on rendezvous call; and if error is detected, the task executing tk_cal_por does not enter WAITING state.

A maximum wait time (timeout) until rendezvous establishment can be set in tmout. If the tmout time elapses before the wait release condition is met (rendezvous is not established), the system call terminates, returning timeout error code E_TMOUT.

Only positive values can be set in tmout. The time unit for tmout (time unit) is the same as that for system time (= 1 ms).

When TMO_POL = 0 is set in tmout, this means 0 was specified as the timeout value, and E_TMOUT is returned without entering WAITING state if there is no task waiting on a rendezvous at the rendezvous port, or if the rendezvous conditions are not met.

When TMO_FEVR (= -1) is set in tmout, this means infinity was specified as the timeout value, and the task continues to wait for a rendezvous to be established without timing out.

tmout indicates the time allowed for a rendezvous to be established, and does not apply to the time from rendezvous establishment to rendezvous completion.

tk_cal_por_u - Call Port for Rendezvous (in microseconds)

C Language Interface

#include <tk/tkernel.h>

INT rmsgsz = tk_cal_por_u (ID porid , UINT calptn , void *msg , INT cmsgsz , TMO_U tmout_u );

Parameter

ID porid Port IDRendezvous port ID
UINT calptn Call Bit PatternCall bit pattern (indicating conditions of the caller)
void* msg MessageAddress of the message
INT cmsgsz Call Message SizeCall message size (bytes)
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

INT rmsgsz Reply Message SizeReply message size (in bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (cmsgsz < 0, cmsgsz > maxcmsz, calptn = 0, invalid msg, or tmout_u ≦ (-2))
E_DLT The object being waited for was deleted (the rendezvous port was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This system call takes 64-bit tmout_u in microseconds instead of the parameter tmout of tk_cal_por.

The specification of this system call is same as that of tk_cal_por, except that the parameter is replaced with tmout_u. For more details, see the description of tk_cal_por.

Difference from T-Kernel 1.0

This system call was added in T-Kernel 2.0.

tk_acp_por - Accept Port for Rendezvous

C Language Interface

#include <tk/tkernel.h>

INT cmsgsz = tk_acp_por (ID porid , UINT acpptn , RNO *p_rdvno , void *msg , TMO tmout );

Parameter

ID porid Port IDRendezvous port ID
UINT acpptn Accept Bit PatternAccept bit pattern (indicating conditions for acceptance)
RNO* p_rdvno Pointer to Rendezvous NumberPointer to the area to return the return parameter rdvno
void* msg Packet of Call MessageAddress of call message packet
TMO tmout TimeoutTimeout (ms)

Return Parameter

RNO rdvno Rendezvous NumberRendezvous number
INT cmsgsz Call Message SizeCall message size (bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (acpptn = 0, invalid msg, or tmout ≦ (-2))
E_DLT The object being waited for was deleted (the rendezvous port was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Accepts a rendezvous on a rendezvous port.

The specific operation of tk_acp_por is as follows. A rendezvous is established if there is a task queued for a rendezvous call at the port specified in porid and if rendezvous conditions of that task and the task issuing this call overlap. In this case, the task queued for a rendezvous call is removed from the queue, and its state changes from WAIT on rendezvous call to WAIT for rendezvous completion. The task issuing tk_acp_por continues executing.

If there is no task waiting to call a rendezvous at the port specified in porid, or if there is a task but conditions for establishing a rendezvous are not satisfied, the task issuing tk_acp_por will enter WAITING state on rendezvous acceptance for that port. No error results if there is already another task in WAITING state on rendezvous acceptance at this time; the task issuing tk_acp_por is placed in the accept queue. It is possible to conduct multiple rendezvous operations on the same port at the same time. Accordingly, no error results even if the next rendezvous is carried out while another task is still conducting a rendezvous (before tk_rpl_rdv is called for a previously established rendezvous) at the port specified in porid.

The decision on rendezvous establishment is made by checking conditions in the bit patterns acpptn of the accepting task and calptn of the calling task. A rendezvous is established if the bitwise logical AND of these two bit patterns is not 0. If the first task does not satisfy these conditions, each subsequent task in the call queue is checked in succession. If calptn and acpptn are assigned the same non-zero value, rendezvous is established unconditionally. Parameter error E_PAR is returned if acpptn is 0, since no rendezvous can be established in that case. All processing before a rendezvous is established is fully symmetrical on the calling and accepting sides.

When a rendezvous is established, the calling task can send a message (a call message) to the accepting task. The contents of the message specified by the calling task are copied to an area starting from msg specified by the accepting task when tk_acp_por is called. The call message size cmsgsz is passed in return value of tk_acp_por.

A task accepting rendezvous can establish more than one rendezvous at a time. That is, a task that has accepted one rendezvous using tk_acp_por may execute tk_acp_por again before executing tk_rpl_rdv on the first rendezvous. The port specified for the second tk_acp_por call at this time may be the same port as the first rendezvous or a different one. It is even possible for a task already conducting a rendezvous on a given port to execute tk_acp_por again on the same port and conduct multiple rendezvous on the same port at the same time. Of course, the calling tasks will be different in each case.

The return parameter rdvno passed by tk_acp_por is information used to distinguish different rendezvous when more than one has been established at a given time. It is used as a return parameter by tk_rpl_rdv when a rendezvous completes. It is also passed as a parameter to tk_fwd_por when forwarding a rendezvous. Although the exact contents of rdvno are implementation-dependent, it is expected to include information specifying the calling task on the other side of the rendezvous.

A maximum wait time (timeout) can be set in tmout. If the tmout time elapses before the wait release condition is met (rendezvous is not established), the system call terminates, returning timeout error code E_TMOUT.

Only positive values can be set in tmout. The time unit for tmout (time unit) is the same as that for system time (= 1 ms).

When TMO_POL = 0 is set in tmout, this means 0 was specified as the timeout value, and E_TMOUT is returned without entering WAITING state if there is no task waiting for a rendezvous call at the rendezvous port, or if the rendezvous conditions are not met. When TMO_FEVR (= -1) is set in tmout, this means infinity was specified as the timeout value, and the task continues to wait for a rendezvous to be established without timing out.

Additional Notes

The ability to queue tasks accepting rendezvous is useful when multiple servers perform the same processing concurrently. This capability also takes advantage of the task-independent nature of ports.

If a task accepting a rendezvous terminates abnormally for some reason before completing its rendezvous (before issuing tk_rpl_rdv), the task calling for the rendezvous by issuing tk_cal_por will continue waiting indefinitely for rendezvous completion without being released. To avoid such a situation, tasks accepting rendezvous should execute a tk_rpl_rdv or tk_rel_wai call when they terminate abnormally, as well as notifying the task calling for the rendezvous that the rendezvous ended in error.

rdvno contains information specifying the calling task in the rendezvous, but unique numbers should be assigned as much as possible. Even if different rendezvous are conducted between the same tasks, a different rdvno value should be assigned to the first and second rendezvous to avoid problems like the following.

If a task that called tk_cal_por and is waiting for rendezvous completion has its WAITING state released by tk_rel_wai or by tk_ter_tsk + tk_sta_tsk or the like, conceivably it may execute tk_cal_por a second time, resulting in establishment of a rendezvous. If the same rdvno value is assigned to the first rendezvous and the subsequent one, then if tk_rpl_rdv is executed for the first rendezvous it will end up terminating the second one. By assigning rdvno numbers uniquely and having the task in WAITING state for rendezvous completion remember the number of the expected rdvno, it will be possible to detect the error when tk_rpl_rdv is called for the first rendezvous.

One possible method of assigning rdvno numbers is to put the ID number of the task calling the rendezvous in the lower byte of rdvno, using the higher byte for a serial number.

The capability of setting rendezvous conditions in calptn and acpptn can be applied to implement a rendezvous selective acceptance function like the Ada select function. A specific approach equivalent to an Ada select statement sample (Figure 7) is shown in Figure 8.

Figure 7. Sample Ada-like Program Using select Statement

select
    when condition_A
        accept entry_A do ... end;
or
    when condition_B
        accept entry_B do ... end;
or
    when condition_C
        accept entry_C do ... end;
end select;

Figure 8. Using Rendezvous to Implement Ada select Function

  • Rather than entry_A, entry_B, and entry_C each corresponding to one rendezvous port, the entire select statement corresponds to one rendezvous port.

  • entry_A, entry_B, and entry_C correspond to calptn and acpptn bits 2^0, 2^1, and 2^2.

  • A select statement in a typical Ada program will look like the following:

    ptn := 0;
    if condition_A then ptn := ptn + 2^0 endif;
    if condition_B then ptn := ptn + 2^1 endif;
    if condition_C then ptn := ptn + 2^2 endif;
    tk_acp_por(acpptn := ptn);
  • If the program contains a simple entry_A accept with no select in addition to the select statement shown above,

    tk_acp_por(acpptn := 2^0);
    can be executed. If it is desired to have entry_A, entry_B, and entry_C wait unconditionally in parallel (using OR)
    tk_acp_por(acpptn := 2^2+2^1+2^0);
    can be executed.

  • If the caller can call entry_A by the following

    tk_cal_por(calptn := 2^0);
    and if the call is for entry_C,
    tk_cal_por(calptn := 2^2);
    can be executed.

The Ada select function is provided only on the accepting side, but it is also possible to implement a select function on the calling side by specifying multiple bits in calptn .

Rationale for the Specification

The reason for specifying separate system calls tk_cal_por and tk_acp_por even though the conditions for establishing a rendezvous mirror each other on the calling and accepting sides is because processing required after a rendezvous is established differs for the tasks on each side. That is, whereas the calling task enters WAITING state after the rendezvous is established, the accepting task enters READY state.

tk_acp_por_u - Accept Port for Rendezvous (in microseconds)

C Language Interface

#include <tk/tkernel.h>

INT cmsgsz = tk_acp_por_u (ID porid , UINT acpptn , RNO *p_rdvno , void *msg , TMO_U tmout_u );

Parameter

ID porid Port IDRendezvous port ID
UINT acpptn Accept Bit PatternAccept bit pattern (indicating conditions for acceptance)
RNO* p_rdvno Pointer to Rendezvous NumberPointer to the area to return the return parameter rdvno
void* msg Packet of Call MessageAddress of call message packet
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

RNO rdvno Rendezvous NumberRendezvous number
INT cmsgsz Call Message SizeCall message size (bytes)
orError CodeError code

Error Code

E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (acpptn = 0, invalid msg, or tmout_u ≦ (-2))
E_DLT The object being waited for was deleted (the rendezvous port was deleted while waiting)
E_RLWAI Waiting state released (tk_rel_wai received in waiting state)
E_DISWAI Wait released due to disabling of wait
E_TMOUT Polling failed or timeout
E_CTX Context error (issued from task-independent portion, or in dispatch disabled state)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This system call takes 64-bit tmout_u in microseconds instead of the parameter tmout of tk_acp_por.

The specification of this system call is same as that of tk_acp_por, except that the parameter is replaced with tmout_u. For more details, see the description of tk_acp_por.

Difference from T-Kernel 1.0

This system call was added in T-Kernel 2.0.

tk_fwd_por - Forwards rendezvous to other port

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_fwd_por (ID porid , UINT calptn , RNO rdvno , void *msg , INT cmsgsz );

Parameter

ID porid Port IDDestination rendezvous port ID
UINT calptn Call Bit PatternCall bit pattern (indicating conditions of the caller)
RNO rdvno Rendezvous NumberRendezvous number before transmission
void* msg Call MessageAddress of forwarded message packet
INT cmsgsz Call Message SizeForwarded message size (in bytes)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (cmsgsz < 0, cmsgsz > maxcmsz after forwarding, cmsgsz > maxrmsz before forwarding, calptn = 0, or invalid msg)
E_OBJ Invalid object state (invalid rdvno, or maxrmsz after forwarding > maxrmsz before forwarding)
E_CTX Context error (issued from task-independent portion (implementation-dependent error))
E_DISWAI Wait released due to disabling of wait

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Forward an accepted rendezvous to another rendezvous port.

The task issuing this system call (here "Task X") must have accepted the rendezvous specified in porid; i.e., this system call can be issued only after executing tk_acp_por. In the discussion that follows, the rendezvous calling task is "Task Y," and the rendezvous number passed in a return parameter by tk_acp_por is rdvno. After tk_fwd_por is issued in this situation, the rendezvous between Task X and Task Y is released, and all processing thereafter is the same as if Task Y had called for a rendezvous on another port (rendezvous port B) passed to this system call in porid.

The specific operations of tk_fwd_por are as follows.

  1. The rendezvous specified in rdvno is released.

  2. Task Y goes to WAITING state on rendezvous call for the rendezvous port specified in porid. The bit conditions representing the call select conditions in this case are not those specified in calptn by Task Y when it called tk_cal_por, but those specified by Task X when it called tk_fwd_por. The state of Task Y goes from WAIT for rendezvous completion back to WAIT on rendezvous call.

  3. Then if a rendezvous for the rendezvous port specified in porid is accepted, a rendezvous is established between the accepting task and Task Y. Naturally, if there is a task already waiting to accept a rendezvous on the rendezvous port specified in porid and the rendezvous conditions are met, executing tk_fwd_por will immediately cause a rendezvous to be established. Here too, as with calptn, the message sent to the accepting task when the rendezvous is established is that specified in tk_fwd_por by Task X, not that specified in tk_cal_por by Task Y.

  4. After the new rendezvous has completed, the reply message returned to the calling task by tk_rpl_rdv is copied to the area specified in the msg parameter passed to tk_cal_por by Task Y, not to the area specified in the msg parameter passed to tk_fwd_por by Task X.

Essentially the following situation:

Executing tk_fwd_por (porid=portB, calptn=ptnB, msg=mesB) after tk_cal_por (porid=portA, calptn=ptnA, msg=mesA)

is the same as the following:

Executing tk_cal_por (porid=portB, calptn=ptnB, msg=mesB).

As the result, the kernel does not have to remember the history of rendezvous forwarding.

If tk_ref_tsk is executed for a task that has returned to WAITING on rendezvous call due to tk_fwd_por execution, the value returned in tskwait is TTW_CAL. Here wid is the ID of the rendezvous port to which the rendezvous was forwarded.

tk_fwd_por execution completes immediately; in no case does this system call go to the WAITING state. A task issuing tk_fwd_por loses any relationship to the rendezvous port on which the forwarded rendezvous was established, the forwarding destination (the port specified in porid), and the tasks conducting rendezvous on these ports.

Error code E_PAR is returned if cmsgsz is larger than maxcmsz of the rendezvous port after forwarding. This error is checked before the rendezvous is forwarded. If this error occurs, the rendezvous is not forwarded and the rendezvous specified in rdvno is not released.

The send message specified by tk_fwd_por is copied to another memory area (such as the message area specified by tk_cal_por) when tk_fwd_por is executed. Accordingly, even if the contents of the message area specified in the msg parameter passed to tk_fwd_por are changed before the forwarded rendezvous is established, the forwarded rendezvous will not be affected.

When a rendezvous is forwarded by tk_fwd_por, maxrmsz of the rendezvous port after forwarding (specified in porid) must be no larger than maxrmsz of the rendezvous port on which the rendezvous was established before forwarding. If maxrmsz of the rendezvous port after forwarding is larger than maxrmsz of the rendezvous port before forwarding, this means the destination rendezvous port was not suitable, and error code :E_OBJ is returned. The task calling the rendezvous prepares a reply message receiving area based on the maxrmsz of the rendezvous port before forwarding. If the maximum size for the reply message increases when the rendezvous is forwarded, this may indicate that an unexpectedly large reply message is being returned to the calling rendezvous port, which would cause problems. For this reason a rendezvous cannot be forwarded to a rendezvous port having a larger maxrmsz.

Similarly, cmsgsz indicating the size of the message sent by tk_fwd_por must be no larger than maxrmsz of the rendezvous port on which the rendezvous was established before forwarding. This is because it is assumed that the message area specified with tk_cal_por will be used as a buffer in implementing tk_fwd_por. If cmsgsz is larger than maxrmsz of the rendezvous port before forwarding, error code E_PAR is returned (See Additional Notes for details).

It is not necessary to issue tk_fwd_por and tk_rpl_rdv from a task-independent portion, but it is possible to issue tk_fwd_por or tk_rpl_rdv from dispatch disabled or interrupts disabled state. This capability can be used to perform processing that is inseparable from tk_fwd_por or tk_rpl_rdv. Whether or not error checking is made for issuing of tk_fwd_por or tk_rpl_rdv from a task-independent portion is implementation-dependent.

When as a result of tk_fwd_por Task Y that was in WAITING state for rendezvous completion reverts to WAITING on rendezvous call, the timeout until rendezvous establishment is always treated as Wait forever(TMO_FEVR).

The rendezvous port being forwarded to may be the same port used for the previous rendezvous (the rendezvous port on which the rendezvous specified in rdvno was established). In this case, tk_fwd_por cancels the previously accepted rendezvous. Even in this case, however, the call message and calptn parameters are changed to those passed to tk_fwd_por by the accepting task, not those passed to tk_cal_por by the calling task.

It is possible to forward a rendezvous that has already been forwarded.

Additional Notes

A server task operation using tk_fwd_por is illustrated in Figure 9.[2]

Figure 9. Server Task Operation Using tk_fwd_por

Generally tk_fwd_por is executed by server distribution tasks (tasks for distributing server-accepted processing to other tasks) as shown in Figure 9. Accordingly, a server distribution task that has executed tk_fwd_por must go on to accept the next request regardless of whether the forwarded rendezvous is established or not. The tk_fwd_por message area in this case is used for processing the next request, making it necessary to ensure that changes to the contents of this message area will not affect the previously forwarded rendezvous. For this reason, after tk_fwd_por is executed, it must be possible to modify the contents of the message area indicated in msg passed to tk_fwd_por even before the forwarded rendezvous is established.

In order to fulfill this requirement, an implementation is allowed to use the message area specified with tk_cal_por as a buffer. That is, in the tk_fwd_por processing, it is permissible to copy the call messages specified with tk_fwd_por to the message area indicated in msg when tk_cal_por was called, and for the task calling tk_fwd_por to change the contents of the message area. When a rendezvous is established, the message placed in the tk_cal_por message area is passed to the accepting task, regardless of whether the rendezvous is one that was forwarded from another port.

The following is specified to allow this sort of implementation.

  • If there is a possibility that a rendezvous requested by tk_cal_por may be forwarded, a memory space of at least maxrmsz bytes must be allocated starting from msg (passed to tk_cal_por),regardless of the expected reply message size.

  • The send message size cmsgsz passed to tk_fwd_por must be no larger than maxrmsz of the rendezvous port before forwarding.

  • If a rendezvous is forwarded using tk_fwd_por, maxrmsz of the destination port rendezvous does not become larger than maxrmsz of the port before forwarding. The former is equal to or smaller than the latter.

Rationale for the Specification

The tk_fwd_por specification is designed not to require logging a history of rendezvous forwarding, so as to reduce the number of states that must be kept track of in the system as a whole. Applications that require such a log to be kept can use nested pairs of tk_cal_por and tk_acp_por rather than using tk_fwd_por.

tk_rpl_rdv - Reply Rendezvous

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_rpl_rdv (RNO rdvno , void *msg , INT rmsgsz );

Parameter

RNO rdvno Rendezvous NumberRendezvous number
void* msg Reply MessageAddress of the reply message
INT rmsgsz Reply Message SizeReply message size (in bytes)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_PAR Parameter error (rmsgsz < 0, rmsgsz > maxrmsz, or invalid msg)
E_OBJ Invalid object state (rdvno is invalid)
E_CTX Context error (issued from task-independent portion (implementation-dependent error))

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Returns a reply to the calling task in the rendezvous, ending the rendezvous.

The task issuing this system call (here "Task X") must be engaged in a rendezvous; that is, this system call can be issued only after executing tk_acp_por. In the discussion that follows, the rendezvous calling task is "Task Y", and the rendezvous number passed in a return parameter by tk_acp_por is rdvno. When tk_rpl_rdv is executed in this situation, the rendezvous state between Task X and Task Y is released, and the Task Y state goes from WAITING for rendezvous completion back to READY state.

When a rendezvous is ended by tk_rpl_rdv, accepting Task X can send a reply message to calling Task Y. The contents of the message specified by the accepting task are copied to the memory space specified in msg passed by Task Y to tk_cal_por. The size of the reply message rmsgsz is set in a tk_cal_por return parameter.

Error code E_PAR is returned if rmsgsz is larger than maxrmsz specified with tk_cre_por. When this error is detected, the rendezvous is not ended and the task that called tk_cal_por remains in WAITING state for rendezvous completion.

It is not possible to issue tk_fwd_por and tk_rpl_rdv from a task-independent portion, but it is possible to issue tk_fwd_por or tk_rpl_rdv from dispatch disabled or interrupts disabled state. This capability can be used to perform processing that is inseparable from tk_fwd_por or tk_rpl_rdv. Whether or not error checking is made for issuing of tk_fwd_por or tk_rpl_rdv from a task-independent portion is implementation-dependent.

Additional Notes

If a task calling a rendezvous aborts for some reason before completion of the rendezvous (before tk_rpl_rdv is executed), the accepting task has no direct way of knowing of the abort. In such a case, error code E_OBJ is returned to the rendezvous accepting task when it executes tk_rpl_rdv.

After a rendezvous is established, tasks are in principle detached from the rendezvous port and have no need to reference information about each other. However, since the value of maxrmsz, used when checking the length of the reply message sent using tk_rpl_rdv, is dependent on the rendezvous port, the task in rendezvous must record this information somewhere. One possible implementation would be to put this information in the TCB of the calling task after it goes to WAITING state, or in another area that can be referenced from the TCB, such as a stack area.

Rationale for the Specification

The parameter rdvno is passed to tk_rpl_rdv and tk_fwd_por as information for distinguishing a established rendezvous from another, but the rendezvous port ID (porid) used when establishing a rendezvous is not specified. This is based on the design principle that tasks are no longer related to rendezvous ports after a rendezvous has been established.

Error code E_OBJ rather than E_PAR is returned for an invalid rdvno. This is because rdvno itself is an object indicating the task that called the rendezvous.

tk_ref_por - Reference Port Status

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_ref_por (ID porid , T_RPOR *pk_rpor );

Parameter

ID porid Port IDRendezvous port ID
T_RPOR* pk_rpor Packet to Return Port StatusPointer to the area to return the rendezvous port status

Return Parameter

ER ercd Error CodeError code

pk_rpor Detail:

void* exinf Extended InformationExtended information
ID wtsk Wait Task InformationCall waiting task ID
ID atsk Accept Task InformationAccept waiting task ID
INT maxcmsz Maximum Call Message SizeMaximum call message size (in bytes)
INT maxrmsz Maximum Reply Message SizeMaximum reply message size (in bytes)
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_OK Normal completion
E_ID Invalid ID number (porid is invalid or cannot be used)
E_NOEXS Object does not exist (the rendezvous port specified in porid does not exist)
E_PAR Parameter error (invalid pk_rpor)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

References the status of the rendezvous port specified in porid, passing in return parameters the accept waiting task ID (atsk), the call waiting task ID (wtsk), the maximum message sizes (maxcmsz, maxrmsz), and the extended information (exinf).

wtsk indicates the ID of a task in WAITING state on rendezvous call at the rendezvous port. If there is no task waiting on rendezvous call, wtsk = 0 is returned. atsk indicates the ID of a task in WAITING state on rendezvous acceptance at the rendezvous port. If there is no task waiting for rendezvous acceptance, atsk = 0 is returned.

If there are multiple tasks waiting on rendezvous call or acceptance at this rendezvous port, the ID of the task at the head of the call queue and accept queue is returned.

If the specified rendezvous port does not exist, error code E_NOEXS is returned.

Additional Notes

This system call cannot be used to get information about tasks involved in a currently established rendezvous.

Notes

[1]

Base priority: The task priority before it is automatically raised by the mutex. This is the priority last set by tk_chg_pri (including while the mutex is locked), or if tk_chg_pri has never been issued, the priority that was set when the task was created.

[2]

  • Bold outlines indicate rendezvous ports (rendezvous entries).

  • While it is possible to use tk_cal_por in place of tk_fwd_por, this results in rendezvous nesting. Assuming it is acceptable for requesting Task X to resume execution after the processing of server tasks A to C is completed, use of tk_fwd_por does away with the need for rendezvous nesting and results in more efficient operations.