Randeveport
Randev Synchronization between tasks
Rendezvous is a type of function for synchronization and communication between tasks.
It supports the request for processing from one task to another and the return of processing results from the requested task to the requested task as a series of steps (Figure 1).
The objects that allow these tasks to synchronize (wait for each other) are called Rendezvous Ports.
A typical example of using rendezvous is the client/server model of inter-task communication. In Figure 1, taskCL
corresponds to the client and taskSV
corresponds to the server. The system calls used by each are tk_cal_por
on the client side and tk_acp_por
and tk_rpl_rdv
on the server side. The client calls the server (call
), the server accepts the call by the client (accept
), and returns the result to the client (reply
) when the server process is complete.
Listing 1 shows an actual programming example of Figure 1.
【Listing 1: Rendezvous Use Cases】
#include <basic.h> #include <tk/tkernel.h> #include <tm/tmonitor.h> ID porid; #define ACP_PTN (0xFFFFFFFF) /* Receptionist Selection Criteria */ #define CAL_PTN (0x00000001) /* caller selection condition */ #define MSGSZ 16 /* Message Size. */ void taskSV( INT stacd, void *exinf ) { RNO rdvno; while(1){ // tk_dly_tsk( 100 ); /* Processing required prior to the issuance of a rendezvous */ tk_acp_por( porid, ACP_PTN, &rdvno, NULL, TMO_FEVR ); /* reception desk */ /* The process requested by the client */ tk_rpl_rdv( rdvno, NULL, 0 ); /* reply */ /* Processing required after the end of the rendezvous */ } tk_ext_tsk(); } void taskCL( INT stacd, void *exinf ) { while(1){ /* Processing required before issuing a rendezvous call */ tk_cal_por( porid, CAL_PTN, NULL, 0, TMO_FEVR ); /* call out */ /* Processing required after the end of the rendezvous */ } tk_ext_tsk(); } EXPORT INT usermain( void ) { T_CPOR cpor = { NULL, TA_TFIFO, 0, 0 }; T_CTSK ctskSV = { NULL, TA_HLNG|TA_RNG0, taskSV, 2, 4*1024 }; T_CTSK ctskCL = { NULL, TA_HLNG|TA_RNG0, taskCL, 3, 4*1024 }; ID tskidSV, tskidCL; tk_chg_pri(TSK_SELF, 1); porid = tk_cre_por( &cpor ); tskidSV = tk_cre_tsk( &ctskSV ); tk_sta_tsk( tskidSV, 0 ); tskidCL = tk_cre_tsk( &ctskCL ); tk_sta_tsk( tskidCL, 0 ); tk_slp_tsk(TMO_FEVR); return 1; }
By the way, in Listing 1, the rendezvous is established when taskCL
requests processing while taskSV
is waiting in the rendezvous port. Figure 2 shows the change in both task states at this time.
On the other hand, if you enable tk_dly_tsk(100)
on line 15, which is commented out in Listing 1, then taskCL
will be executed before taskSV
waits for acceptance in the rendezvous port. request. The changes in both task states at this time are shown in Figure 3.
When rendezvousing, either the server or the client can start the rendezvous first, and there is no difference in behavior after the rendezvous is established.
Passing messages by rendezvous
When a rendezvous is established, the task that called the rendezvous passes the call message from the task that received it to the task that received it.
Specifically, cmsgsz
bytes under msg
specified in tk_cal_por
by the caller task are copied to an area under msg
specified in tk_acp_por
by the receiving task.
This is shown in Figure 4.
Randev’s reply to the results
Now, if you just want to synchronize, you can do it with the semaphores and event flags we’ve been talking about, or you can use mailboxes and message buffers to synchronize and send messages at the same time.
The equivalent of a rendezvous can be achieved by combining these synchronization and communication functions, but with rendezvous, the server side can send a reply message to the client side. The client task waits for a response message to be sent after the server process is complete, so there is no need to prepare a separate area for response messages, making it easier to write applications.
Figure 5 shows the situation when a response message is sent at the end of a rendezvous.
Listing 2 shows an example of a program that actually passes messages.
To give you a clearer picture of the processing flow, we have added a simple server process in List 2 (*1).
(*1) The numeric value passed from taskCL as a message at the time of the rendezvous call is converted to a hexadecimal string by taskSV
, and the converted result (string) is sent to taskCL
as a reply message at the end of the rendezvous.
【Listing 2: Example use of rendezvous with message passing】
#include <basic.h> #include <tk/tkernel.h> #include <tm/tmonitor.h> ID porid; #define ACP_PTN (0xFFFFFFFF) /* Receptionist Selection Criteria */ #define CAL_PTN (0x00000001) /* caller selection condition */ #define MSGSZ 16 /* >= "0x12345678\n" */ IMPORT INT hex2str( char *buf, UW val ); void taskSV( INT stacd, void *exinf ) { RNO rdvno; char msg[MSGSZ]; INT sz; while(1){ // tk_dly_tsk( 100 ); /* Processing required prior to the issuance of a rendezvous */ tk_acp_por( porid, ACP_PTN, &rdvno, msg, TMO_FEVR ); /* reception desk */ /* The process requested by the client */ sz = hex2str( msg, *(UW*)msg ); tk_rpl_rdv( rdvno, msg, sz ); /* reply */ /* Processing required after the end of the rendezvous */ } tk_ext_tsk(); } void taskCL( INT stacd, void *exinf ) { UW msg[MSGSZ/sizeof(UW)+1]; UW i = 0; while(1){ /* Processing required before issuing a rendezvous call */ msg[0] = i++; /* Create a call message */ tk_cal_por( porid, CAL_PTN, msg, sizeof(UW), TMO_FEVR ); /* call out */ /* Processing required after the end of the rendezvous */ tm_putstring( (UB*)msg ); /* Outputting Conversion Results */ } tk_ext_tsk(); } EXPORT INT usermain( void ) { T_CPOR cpor = { NULL, TA_TFIFO, sizeof(UW), MSGSZ }; T_CTSK ctskSV = { NULL, TA_HLNG|TA_RNG0, taskSV, 2, 4*1024 }; T_CTSK ctskCL = { NULL, TA_HLNG|TA_RNG0, taskCL, 3, 4*1024 }; ID tskidSV, tskidCL; tk_chg_pri(TSK_SELF, 1); porid = tk_cre_por( &cpor ); tskidSV = tk_cre_tsk( &ctskSV ); tk_sta_tsk( tskidSV, 0 ); tskidCL = tk_cre_tsk( &ctskCL ); tk_sta_tsk( tskidCL, 0 ); tk_slp_tsk(TMO_FEVR); return 1; } /* Convert numbers to hexadecimal strings */ IMPORT INT hex2str( char *buf, UW val ) { INT len; INT i; /* Skip 0's in the upper digits. */ for( i = sizeof(UW)*2 - 1; i > 0; i-- ){ if( (val >> 4*i) != 0 ){ break; } } /* Convert to hexadecimal number (string) */ *(buf+0) = '0'; *(buf+1) = 'x'; len = 2; do{ *(buf+len) = (val >> 4*i) & 0x0F; *(buf+len) += (*(buf+len) < 10)? '0':'A'-10; len++; }while( i-- > 0 ); *(buf+len++) = '\n'; *(buf+len++) = '\0'; return len; }
Summary
In this article, we have explained the basic functions of rendezvous. In addition, there are functions to select a task to be rendezvoused by specifying a bit pattern (*2) between the caller and the receptionist and to forward a process that has been accepted to another rendezvous port.
T-Kernel provides a variety of synchronization and communication functions as explained in the previous series. Efficient program development is possible by appropriately combining these functions in application development. So please use T-Kernel with a good understanding of each function.
(*2) The ACP_PTN
(receptionist selection condition) and CAL_PTN
(caller selection condition) in the list have this bit pattern. A rendezvous is established if the logical product of the bit patterns of the receptionist and caller is non-zero.
“もっと見る” カテゴリーなし
Mbed TLS overview and features
In this article, I'd like to discuss Mbed TLS, which I've touched on a few times in the past, Transport …
What is an “IoT device development platform”?
I started using Mbed because I wanted a microcontroller board that could connect natively to the Internet. At that time, …
Mbed OS overview and features
In this article, I would like to write about one of the components of Arm Mbed, and probably the most …