1 #include <mstring/kernel.h>
2 #include <mstring/kprintf.h>
3 #include <mstring/smp.h>
4 #include <arch/scheduler.h>
5 #include <arch/types.h>
6 #include <mstring/task.h>
7 #include <mstring/scheduler.h>
8 #include <mstring/swks.h>
9 #include <mstring/string.h>
10 #include <arch/preempt.h>
11 #include <sync/spinlock.h>
15 #include <arch/preempt.h>
16 #include <kernel/syscalls.h>
17 #include <mstring/uinterrupt.h>
19 #include <mstring/gc.h>
21 #include <ipc/channel.h>
24 #include <mstring/errno.h>
25 #include <mstring/process.h>
26 #include <mstring/usercopy.h>
29 #define TEST_ID "IPC subsystem test"
30 #define SERVER_THREAD "[SERVER THREAD] "
31 #define CLIENT_THREAD "[CLIENT THREAD] "
33 #define DECLARE_TEST_CONTEXT ipc_test_ctx_t *tctx=(ipc_test_ctx_t*)ctx; \
34 test_framework_t *tf=tctx->tf
36 #define SERVER_NUM_PORTS 10
37 #define NON_BLOCKED_PORT_ID (SERVER_NUM_PORTS-1)
38 #define BIG_MESSAGE_PORT_ID 5
41 #define SERVER_NUM_BLOCKED_PORTS NON_BLOCKED_PORT_ID
43 typedef struct __ipc_test_ctx
{
49 typedef struct __thread_port
{
50 ulong_t port_id
,server_pid
;
58 #define MAX_TEST_MESSAGE_SIZE 512
59 static char __c_rcv_buf
[CONFIG_NRCPUS
][MAX_TEST_MESSAGE_SIZE
];
61 #define __client_rcv_buf (char *)&__c_rcv_buf[cpu_id()][0]
63 static char __server_rcv_buf
[MAX_TEST_MESSAGE_SIZE
];
65 #define BIG_MESSAGE_SIZE (1500*1024)
66 static uint8_t __big_message_pattern
[BIG_MESSAGE_SIZE
+sizeof(int)];
67 static uint8_t __big_message_server_buf
[BIG_MESSAGE_SIZE
+sizeof(int)];
68 static uint8_t __big_message_client_buf
[BIG_MESSAGE_SIZE
+sizeof(int)];
70 static char *patterns
[TEST_ROUNDS
]= {
72 "1111111111111111111111111111112222222222222222222222222222222222222222222222222",
73 "55555555555555555555555555555555555555555555555555555555555555555555555555555555"
74 "55555555555555555555555555555555555555555555555555555555555555555555555555555555"
75 "55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555",
78 #define BIG_MSG_ID TEST_ROUNDS
79 static SPINLOCK_DEFINE(__shared_data_lock
);
81 #define LOCK_SHARED_DATA() spinlock_lock(&__shared_data_lock)
82 #define UNLOCK_SHARED_DATA() spinlock_unlock(&__shared_data_lock)
84 static bool __verify_message(ulong_t id
,char *msg
)
86 return !memcmp(patterns
[id
],msg
,strlen(patterns
[id
])+1);
89 static bool __verify_big_message(uint8_t *buf
,ulong_t
*diff_offset
)
92 uint8_t *p
=__big_message_pattern
;
94 for(i
=0;i
<BIG_MESSAGE_SIZE
;i
++) {
105 static ulong_t __v_2
[]={10,57};
106 static ulong_t __v_6
[]={8,8,4,10,10,30};
107 static ulong_t __v_4
[]={2,10,10,39};
109 static ulong_t __v_big_7
[]={1156,32500,79000,217299,
110 376415,121783,573200};
112 void __setup_iovectors(ulong_t msg_id
,iovec_t
*iovecs
,ulong_t
*numvecs
)
116 ulong_t
*lengths
,chunks
;
119 if( msg_id
!= BIG_MSG_ID
) {
120 p
=(uint8_t *)patterns
[msg_id
];
121 len
=strlen(patterns
[msg_id
])+1;
129 } else if( msg_id
== BIG_MSG_ID
) {
130 p
=__big_message_pattern
;
131 len
=BIG_MESSAGE_SIZE
;
136 switch( current_task()->pid
% 3 ) {
152 for(i
=0;i
<chunks
;i
++) {
154 iovecs
->iov_len
=lengths
[i
];
160 /* Process the last chunk. */
166 static void __client_thread(void *ctx
)
168 DECLARE_TEST_CONTEXT
;
170 int channels
[SERVER_NUM_PORTS
];
172 iovec_t iovecs
[MAX_IOVECS
];
175 tf
->printf(CLIENT_THREAD
"Opening %d channels.\n",SERVER_NUM_PORTS
);
176 for(i
=0;i
<SERVER_NUM_PORTS
;i
++) {
179 if( i
!= NON_BLOCKED_PORT_ID
) {
180 flags
|= IPC_CHANNEL_FLAG_BLOCKED_MODE
;
185 channels
[i
]=sys_open_channel(tctx
->server_pid
,i
,
187 if( channels
[i
] != i
) {
188 tf
->printf(CLIENT_THREAD
"Channel number mismatch: %d instead of %d\n",
194 /* Now check if channel's flags macth. */
195 r
=sys_control_channel(channels
[i
],IPC_CHANNEL_CTL_GET_SYNC_MODE
,0);
197 int shouldbe
=(i
!= NON_BLOCKED_PORT_ID
) ? 1 : 0;
198 if( r
!= shouldbe
) {
199 tf
->printf(CLIENT_THREAD
"Synchronous mode flag mismatch for channel %d ! %d:%d\n",
200 channels
[i
],r
,shouldbe
);
204 tf
->printf(CLIENT_THREAD
"Can't read channel's sync mode: %d\n",r
);
209 tf
->printf(CLIENT_THREAD
"Trying to open a channel to insufficient port number.\n" );
210 r
=sys_open_channel(tctx
->server_pid
,SERVER_NUM_PORTS
,
211 IPC_CHANNEL_FLAG_BLOCKED_MODE
);
218 /****************************************************************
219 * Sending messages in blocking mode.
220 ****************************************************************/
221 tf
->printf(CLIENT_THREAD
"Sending messages in blocking mode.\n" );
222 for(i
=0;i
<TEST_ROUNDS
;i
++) {
223 r
=sys_port_send(channels
[i
],
224 (ulong_t
)patterns
[i
],strlen(patterns
[i
])+1,
225 (ulong_t
)__client_rcv_buf
,MAX_TEST_MESSAGE_SIZE
);
227 tf
->printf(CLIENT_THREAD
"Error while sending data over channel N%d : %d\n",
232 if( r
== strlen(patterns
[i
])+1 ) {
233 if( !__verify_message(i
,__client_rcv_buf
) ) {
234 tf
->printf(CLIENT_THREAD
"Reply to message N%d mismatch.\n",
239 tf
->printf(CLIENT_THREAD
"Reply to message N%d has insufficient length: %d instead of %d\n",
240 i
,r
,strlen(patterns
[i
])+1);
245 tf
->printf(CLIENT_THREAD
"All messages were successfully processed.\n" );
248 /****************************************************************
249 * Sending a big message in blocking mode.
250 ****************************************************************/
251 tf
->printf(CLIENT_THREAD
"Sending a big message in blocking mode via I/O vectors.\n" );
252 __setup_iovectors(BIG_MSG_ID
,iovecs
,&numvecs
);
254 r
=sys_port_send_iov(channels
[BIG_MESSAGE_PORT_ID
],
256 (ulong_t
)__big_message_client_buf
,BIG_MESSAGE_SIZE
);
258 tf
->printf(CLIENT_THREAD
"Error while sending a big message over channel N%d : %d\n",
259 channels
[BIG_MESSAGE_PORT_ID
],r
);
263 kprintf( CLIENT_THREAD
"Got big reply: %d bytes.\n",r
);
264 if( r
== BIG_MESSAGE_SIZE
) {
267 if( !__verify_big_message(__big_message_client_buf
,&offt
) ) {
268 tf
->printf(CLIENT_THREAD
"Server reply mismatch at offset: %d\n",
272 tf
->printf(CLIENT_THREAD
"Big message was successfully replied.\n" );
276 tf
->printf(CLIENT_THREAD
"Server reply has insufficient length: %d instead of %d\n",
282 /****************************************************************
283 * Sending messages in non-blocking mode.
284 ****************************************************************/
285 tf
->printf(CLIENT_THREAD
"Sending messages in non-blocking mode (using channel N%d).\n",
286 channels
[NON_BLOCKED_PORT_ID
]);
287 for( i
=0; i
<TEST_ROUNDS
;i
++ ) {
288 r
=sys_port_send(channels
[NON_BLOCKED_PORT_ID
],
289 (ulong_t
)patterns
[i
],strlen(patterns
[i
])+1,
292 tf
->printf(CLIENT_THREAD
"Error while sending data over channel N%d : %d\n",
293 channels
[NON_BLOCKED_PORT_ID
],r
);
298 tf
->printf(CLIENT_THREAD
"All messages were successfully sent.\n" );
306 #define POLL_CLIENT "[POLL CLIENT] "
307 static void __poll_client(void *d
)
309 thread_port_t
*tp
=(thread_port_t
*)d
;
310 ipc_test_ctx_t
*tctx
=tp
->tctx
;
311 test_framework_t
*tf
=tctx
->tf
;
312 ulong_t channel
,port
;
315 char client_rcv_buf
[MAX_TEST_MESSAGE_SIZE
];
316 iovec_t iovecs
[MAX_IOVECS
];
319 r
=sys_open_channel(tp
->server_pid
,port
,IPC_CHANNEL_FLAG_BLOCKED_MODE
);
321 tf
->printf(POLL_CLIENT
"Can't open a channel to %d:%d ! r=%d\n",
322 tp
->server_pid
,port
,r
);
327 msg_id
=port
% TEST_ROUNDS
;
328 for(i
=0;i
<TEST_ROUNDS
;i
++) {
330 tf
->printf(POLL_CLIENT
"Sending message to port %d.\n",port
);
333 r
=sys_port_send(channel
,
334 (ulong_t
)patterns
[msg_id
],strlen(patterns
[msg_id
])+1,
335 (ulong_t
)client_rcv_buf
,sizeof(client_rcv_buf
));
336 snd_type
="sys_port_send()";
338 /* Sending a message using I/O vector array. */
341 snd_type
="sys_port_send_iov()";
342 __setup_iovectors(msg_id
,iovecs
,&numvecs
);
343 r
=sys_port_send_iov(channel
,iovecs
,numvecs
,
344 (ulong_t
)client_rcv_buf
,sizeof(client_rcv_buf
));
347 tf
->printf(POLL_CLIENT
"Error occured while sending message: %d via %s\n",
351 if( r
== strlen(patterns
[msg_id
])+1 ) {
352 if( !__verify_message(msg_id
,client_rcv_buf
) ) {
353 tf
->printf(POLL_CLIENT
"Reply to my message mismatches !\n");
357 tf
->printf(POLL_CLIENT
"Reply to my message has insufficient length: %d instead of %d\n",
358 r
,strlen(patterns
[msg_id
])+1);
362 tf
->printf(POLL_CLIENT
"Message from port %d was successfully replied.\n",
368 /* Special case: test client wake up during port close. */
370 tf
->printf(POLL_CLIENT
"Testing correct client wake-up on port closing...\n" );
371 r
=sys_port_send(channel
,
372 (ulong_t
)patterns
[msg_id
],strlen(patterns
[msg_id
])+1,
373 (ulong_t
)client_rcv_buf
,sizeof(client_rcv_buf
));
375 tf
->printf( POLL_CLIENT
"Got -EPIPE. It seems that kernel woke us properly.\n" );
376 tp
->finished_tests
=true;
378 tf
->printf(POLL_CLIENT
"Insufficient return value upon wake-up on port closing: %d\n",
383 tp
->finished_tests
=true;
386 tf
->printf(POLL_CLIENT
"Exiting (target port: %d)\n",port
);
390 #define NUM_POLL_CLIENTS SERVER_NUM_BLOCKED_PORTS
392 thread_port_t poller_ports
[NUM_POLL_CLIENTS
];
394 static void __ipc_poll_test(ipc_test_ctx_t
*tctx
,int *ports
)
397 pollfd_t fds
[NUM_POLL_CLIENTS
];
398 test_framework_t
*tf
=tctx
->tf
;
399 ulong_t polled_clients
;
400 port_msg_info_t msg_info
;
401 char server_rcv_buf
[MAX_TEST_MESSAGE_SIZE
];
403 for(i
=0;i
<NUM_POLL_CLIENTS
;i
++) {
406 memset(&poller_ports
[i
],0,sizeof(poller_ports
[i
]));
408 poller_ports
[i
].port_id
=ports
[i
];
409 poller_ports
[i
].tctx
=tctx
;
410 poller_ports
[i
].server_pid
=current_task()->pid
;
411 poller_ports
[i
].finished_tests
=false;
412 poller_ports
[i
].msg_id
=-1;
414 if( kernel_thread(__poll_client
,&poller_ports
[i
],&task
) ) {
415 tf
->printf( "Can't create a client thread for testing IPC poll !\n" );
418 poller_ports
[i
].pid
=task
->pid
;
421 tf
->printf(SERVER_THREAD
"Client threads created. Ready for polling ports.\n");
422 for(j
=0;j
<TEST_ROUNDS
;j
++) {
426 polled_clients
=NUM_POLL_CLIENTS
;
428 while(polled_clients
) {
429 for(i
=0;i
<NUM_POLL_CLIENTS
;i
++) {
430 fds
[i
].events
=POLLIN
| POLLRDNORM
;
435 tf
->printf( SERVER_THREAD
"Polling ports (%d clients left) ...\n",polled_clients
);
436 r
=sys_ipc_port_poll(fds
,NUM_POLL_CLIENTS
,NULL
);
438 tf
->printf( SERVER_THREAD
"Error occured while polling ports: %d\n",r
);
443 tf
->printf( SERVER_THREAD
">> Events occured: %d\n", r
);
446 for(jl
=0;jl
<NUM_POLL_CLIENTS
;jl
++) {
447 if( fds
[jl
].revents
) {
448 r
=sys_port_receive(fds
[jl
].fd
,0,(ulong_t
)server_rcv_buf
,
449 sizeof(server_rcv_buf
),&msg_info
);
452 tf
->printf( SERVER_THREAD
"Error during RCV from port N %d. r=%d\n",
458 tf
->printf(SERVER_THREAD
"Extra poll events available !\n");
463 msg_id
=fds
[jl
].fd
% TEST_ROUNDS
;
464 if( msg_info
.msg_len
== strlen(patterns
[msg_id
])+1 ) {
465 if( !__verify_message(msg_id
,server_rcv_buf
) ) {
466 tf
->printf( SERVER_THREAD
"Poll: Message N %d mismatch.\n",
471 tf
->printf(SERVER_THREAD
"Message N%d has insufficient length: %d instead of %d\n",
472 fds
[i
].fd
,msg_info
.msg_len
,strlen(patterns
[msg_id
])+1);
476 /* Good message, so store its details for further reply. */
478 for(i
=0;i
<NUM_POLL_CLIENTS
;i
++) {
479 if( poller_ports
[i
].pid
== msg_info
.sender_pid
) {
480 _tt
=&poller_ports
[i
];
485 tf
->printf(SERVER_THREAD
"Can't locate poll client: %d\n",
486 msg_info
.sender_pid
);
490 if( fds
[jl
].fd
!= _tt
->port_id
) {
491 tf
->printf(SERVER_THREAD
"Insufficient poll client's (%d) port: %d instead of %d !\n",
492 jl
,fds
[jl
].fd
,_tt
->port_id
);
496 if( _tt
->msg_id
!= -1 ) {
497 tf
->printf(SERVER_THREAD
"Another message for client %d ! (%d)\n",
498 msg_info
.sender_pid
,_tt
->msg_id
);
501 _tt
->msg_id
=msg_info
.msg_id
;
502 _tt
->reply_msg_id
=msg_id
;
507 tf
->printf(SERVER_THREAD
"%d not processed events after current poll round !\n",nc
);
511 tf
->printf( SERVER_THREAD
"All clients sent their messages. Replying to them ...\n" );
513 for(i
=0;i
<NUM_POLL_CLIENTS
;i
++) {
514 _tt
=&poller_ports
[i
];
516 if( _tt
->msg_id
== -1 ) {
517 tf
->printf(SERVER_THREAD
"Not processed poll client found! %d\n",
521 r
=sys_port_reply(_tt
->port_id
,_tt
->msg_id
,
522 (ulong_t
)patterns
[_tt
->reply_msg_id
],
523 strlen(patterns
[_tt
->reply_msg_id
])+1);
525 tf
->printf(SERVER_THREAD
"Error occured during replying message %d via port %d. r=%d\n",
526 _tt
->msg_id
,_tt
->port_id
,r
);
531 tf
->printf( SERVER_THREAD
"All messages were replied. Now let's have some rest (HZ/2) ...\n" );
535 /*****************************************************************
536 * Testing client wake-up on port closing.
537 ****************************************************************/
538 /* By now poll client that communicates with port N0 is still running
539 * and waiting for us to reply it.
540 * But we will just close the port to check if it is still sleeping,
543 tf
->printf(SERVER_THREAD
"Testing client wake-up during port closing.\n" );
544 r
=sys_port_receive(0,0,(ulong_t
)server_rcv_buf
,
545 sizeof(server_rcv_buf
),&msg_info
);
547 tf
->printf( SERVER_THREAD
"Error during receiving message for client wake-up. r=%d\n",
552 /* Simulate an accident port shutdown. */
555 tf
->printf( SERVER_THREAD
"Can't close port N 0. r=%d\n",r
);
559 /* Let sleep for a while to allow the client to let us know about its state. */
561 if( poller_ports
[0].finished_tests
) {
562 tf
->printf( SERVER_THREAD
"Clien't was successfully woken up.\n" );
565 tf
->printf( SERVER_THREAD
"Client wasn't woken up !\n",r
);
568 tf
->printf( SERVER_THREAD
"All poll tests finished.\n" );
571 static void __notifier_thread(void *ctx
)
573 DECLARE_TEST_CONTEXT
;
574 uint64_t target_tick
=system_ticks
+ 200;
576 tf
->printf( "[Notifier] Starting.\n" );
578 while(system_ticks
< target_tick
) {
581 tf
->printf( "[Notifier] Exiting.\n" );
585 static void __process_events_test(void *ctx
)
587 DECLARE_TEST_CONTEXT
;
588 int port
=sys_create_port(0,0);
591 task_event_ctl_arg te_ctl
;
592 task_event_descr_t ev_descr
;
593 port_msg_info_t msg_info
;
596 tf
->printf( "Can't create a port !\n" );
599 if( kernel_thread(__notifier_thread
,ctx
,&task
) ) {
600 tf
->printf("Can't create the Notifier !\n");
604 te_ctl
.ev_mask
=TASK_EVENT_TERMINATION
;
606 r
=sys_task_control(task
->pid
,0,SYS_PR_CTL_ADD_EVENT_LISTENER
,
609 tf
->printf("Can't set event listener: %d\n",r
);
613 tf
->printf( "Check that no one can set more than one same listeners.\n" );
614 te_ctl
.ev_mask
=TASK_EVENT_TERMINATION
;
616 r
=sys_task_control(task
->pid
,0,SYS_PR_CTL_ADD_EVENT_LISTENER
,
619 tf
->printf("How did I manage to set the second listener ? %d\n",r
);
625 memset(&ev_descr
,0,sizeof(ev_descr
));
626 r
=sys_port_receive(port
,IPC_BLOCKED_ACCESS
,(ulong_t
)&ev_descr
,
627 sizeof(ev_descr
),&msg_info
);
629 tf
->printf("Error occured while waiting for task's events: %d !\n",
634 if( ev_descr
.pid
!= task
->pid
|| ev_descr
.tid
!= task
->tid
||
635 !(ev_descr
.ev_mask
& te_ctl
.ev_mask
) ) {
636 tf
->printf( "Improper notification message received: PID: %d, TID: %d, EVENT: 0x%X\n",
637 ev_descr
.pid
,ev_descr
.tid
,ev_descr
.ev_mask
);
641 tf
->printf( "All process event tests passed.\n" );
644 sys_close_port(port
);
647 #define VECTORER_ID "[VECTORER] "
649 #define MSG_HEADER_DATA_SIZE 715 // 715
650 #define MSG_PART_DATA_SIZE 3419 // 3419
651 #define MSG_TAIL_DATA_SIZE 17918 //17918
653 typedef struct __message_header
{
655 uint16_t data
[MSG_HEADER_DATA_SIZE
];
658 typedef struct __message_part
{
660 uint16_t data
[MSG_PART_DATA_SIZE
];
663 typedef struct __message_tail
{
665 uint16_t data
[MSG_TAIL_DATA_SIZE
];
668 #define FAIL_ON(c,tf) do { \
669 if( (c) ) (tf)->failed(); \
672 #define MAX_MSG_PARTS 6
673 #define MAX_MSG_SIZE (sizeof(message_header_t) + MAX_MSG_PARTS*sizeof(message_part_t) + sizeof(message_tail_t))
675 static uint8_t __vmsg_client_snd_buf
[CONFIG_NRCPUS
][MAX_MSG_SIZE
];
676 static uint8_t __vmsg_client_rcv_buf
[CONFIG_NRCPUS
][MAX_MSG_SIZE
];
677 static uint8_t __vectored_msg_server_snd_buf
[MAX_MSG_SIZE
];
678 static uint8_t __vectored_msg_server_rcv_buf
[MAX_MSG_SIZE
];
680 #define __vectored_msg_client_snd_buf (uint8_t*)&__vmsg_client_snd_buf[cpu_id()][0]
681 #define __vectored_msg_client_rcv_buf (uint8_t*)&__vmsg_client_rcv_buf[cpu_id()][0]
683 static int __validate_message_data(uint16_t *data
,uint16_t base
,ulong_t size
)
687 for(i
=0;i
<size
;i
++,data
++,base
++) {
688 if( *data
!= base
) {
689 kprintf( "M: %d instead of %d at %d\n", *data
,base
,i
);
690 return i
? -i
: -100000000;
696 static void __prepare_message_data(uint16_t *data
,uint16_t base
,ulong_t size
)
706 static bool __validate_vectored_message(uint8_t *msg
,int parts
,
707 test_framework_t
*tf
)
709 message_header_t
*hdr
=(message_header_t
*)msg
;
710 message_part_t
*part
;
711 message_tail_t
*tail
;
714 r
=__validate_message_data(hdr
->data
,hdr
->data_base
,MSG_HEADER_DATA_SIZE
);
716 tf
->printf("Message header mismatches at %d\n",-r
);
721 part
=(message_part_t
*)hdr
;
722 for(i
=0;i
<parts
;i
++,part
++) {
723 r
=__validate_message_data(part
->data
,part
->data_base
,MSG_PART_DATA_SIZE
);
725 tf
->printf("Message part %d mismatches at %d\n",i
,-r
);
730 tail
=(message_tail_t
*)part
;
732 r
=__validate_message_data(tail
->data
,tail
->data_base
,MSG_TAIL_DATA_SIZE
);
734 tf
->printf("Message tail mismatches at %d\n",-r
);
740 static uint16_t __data_base
=210;
741 #define DATA_BASE_STEP 75
743 static void __prepare_vectored_message(uint8_t *buf
,int parts
)
745 message_header_t
*hdr
=(message_header_t
*)buf
;
746 message_part_t
*part
;
747 message_tail_t
*tail
;
751 hdr
->data_base
=__data_base
;
752 __data_base
+= DATA_BASE_STEP
;
753 UNLOCK_SHARED_DATA();
754 __prepare_message_data(hdr
->data
,hdr
->data_base
,MSG_HEADER_DATA_SIZE
);
757 part
=(message_part_t
*)hdr
;
758 for(i
=0;i
<parts
;i
++,part
++) {
760 part
->data_base
=__data_base
;
761 __data_base
+= DATA_BASE_STEP
;
762 UNLOCK_SHARED_DATA();
763 __prepare_message_data(part
->data
,part
->data_base
,MSG_PART_DATA_SIZE
);
766 tail
=(message_tail_t
*)part
;
768 tail
->data_base
=__data_base
;
769 __data_base
+= DATA_BASE_STEP
;
770 UNLOCK_SHARED_DATA();
771 __prepare_message_data(tail
->data
,tail
->data_base
,MSG_TAIL_DATA_SIZE
);
774 static void __setup_message_iovecs(uint8_t *msg
,int parts
,iovec_t
*iovecs
)
776 iovecs
->iov_base
=msg
;
777 iovecs
->iov_len
=sizeof(message_header_t
);
780 msg
+= sizeof(message_header_t
);
782 for(;parts
;parts
--) {
783 iovecs
->iov_base
=msg
;
784 iovecs
->iov_len
=sizeof(message_part_t
);
787 msg
+= sizeof(message_part_t
);
790 iovecs
->iov_base
=msg
;
791 iovecs
->iov_len
=sizeof(message_tail_t
);
794 #define CLEAR_CLIENT_BUFFERS \
795 memset(__vectored_msg_client_snd_buf,0,MAX_MSG_SIZE); \
796 memset(__vectored_msg_client_rcv_buf,0,MAX_MSG_SIZE)
798 #define CLEAR_SERVER_BUFFERS \
799 memset(__vectored_msg_server_snd_buf,0,sizeof(__vectored_msg_server_snd_buf)); \
800 memset(__vectored_msg_server_rcv_buf,0,sizeof(__vectored_msg_server_rcv_buf))
802 static ulong_t __server_pid
,__vectored_port
;
804 #define MESSAGE_SIZE(n) (sizeof(message_header_t)+((n)*sizeof(message_part_t))+sizeof(message_tail_t))
805 #define WL_PATTERN 0x00AA11BB22CC33DD
807 static void __vectored_messages_thread(void *ctx
)
809 DECLARE_TEST_CONTEXT
;
811 iovec_t snd_iovecs
[MAX_IOVECS
],rcv_iovecs
[MAX_IOVECS
];
815 tf
->printf(VECTORER_ID
"Starting on CPU %d.\n",cpu_id());
817 channel
=sys_open_channel(__server_pid
,__vectored_port
,IPC_BLOCKED_ACCESS
);
819 tf
->printf(VECTORER_ID
"Can't open a channel !\n" );
823 for(i
=0;i
<5*TEST_ROUNDS
;i
++) {
824 ulong_t parts
=(i
%6)+1;
827 CLEAR_CLIENT_BUFFERS
;
828 __prepare_vectored_message(__vectored_msg_client_snd_buf
,parts
);
829 __setup_message_iovecs(__vectored_msg_client_snd_buf
,parts
,snd_iovecs
);
831 /* Setup memory watchline. */
832 size
=MESSAGE_SIZE(parts
);
833 watchline
=(ulong_t
*)(__vectored_msg_client_rcv_buf
+size
);
834 *watchline
=WL_PATTERN
;
836 tf
->printf(VECTORER_ID
"Sending a message consisting of %d parts via %s. SIZE=%d\n",
837 parts
, (i
& 0x1) ? "'sys_port_send_iov()'" : "'sys_port_send_iov_v()'",
838 MESSAGE_SIZE(parts
));
840 r
=sys_port_send_iov(channel
,snd_iovecs
,parts
+2,
841 (uintptr_t)__vectored_msg_client_rcv_buf
,
843 tf
->printf(VECTORER_ID
"Message was sent: r=%d. RCV BUFSIZE=%d\n",r
,
844 sizeof(__vectored_msg_client_rcv_buf
));
849 __setup_message_iovecs(__vectored_msg_client_rcv_buf
,parts
,rcv_iovecs
);
850 r
=sys_port_send_iov_v(channel
,snd_iovecs
,parts
+2,
852 tf
->printf(VECTORER_ID
"Message was sent: r=%d. RCV BUFSIZE=%d\n",r
,
853 sizeof(__vectored_msg_client_rcv_buf
));
858 tf
->printf(VECTORER_ID
"Varifying server's reply (%d-parts message).\n",
860 FAIL_ON(!__validate_vectored_message(__vectored_msg_client_rcv_buf
,parts
,tf
),tf
);
861 if( *watchline
!= WL_PATTERN
) {
862 tf
->printf(VECTORER_ID
"Watchline pattern mismatch ! 0x%X instead of 0x%X\n",
863 *watchline
,WL_PATTERN
);
868 tf
->printf(VECTORER_ID
"All messages were successfully transmitted.\n");
872 static void __validate_retval(int r
,int expected
,
873 test_framework_t
*tf
)
875 if( r
!= expected
) {
876 tf
->printf(SERVER_THREAD
"Insufficient return value: %d\n",
882 #define READ_LONGS 15500
883 static page_idx_t __buf_pages
[512];
884 static long __bufzone
[32];
885 static long __zbuffer_snd
[READ_LONGS
];
886 static long __zbuffer_rcv
[READ_LONGS
];
888 #define MIDDLE_PARTS(t) ((t)-2)
890 #define NUM_OFFSETS 20
892 static void __ipc_buffer_test(void *ctx
)
894 DECLARE_TEST_CONTEXT
;
895 iovec_t snd_iovecs
[MAX_IOVECS
],rcv_iovecs
[MAX_IOVECS
];
896 ipc_buffer_t bufs
[MAX_IOVECS
];
901 int __offsets
[NUM_OFFSETS
]={315,10,715,1129,2390,3578,4096,4912,
902 5791,6379,7490,8111,8757,9300,10319,10999,
903 10999,11715,12514,13845};
905 tf
->printf(SERVER_THREAD
"Testing IPC buffers functionality.\n");
907 /* 1-part buffer, 3-parts message. */
908 tf
->printf(SERVER_THREAD
"Transferring 6 pieces of data to a 1-part IPC buffer.\n");
909 CLEAR_SERVER_BUFFERS
;
910 __prepare_vectored_message(__vectored_msg_server_snd_buf
,4);
912 rcv_iovecs
[0].iov_base
=__vectored_msg_server_rcv_buf
;
913 rcv_iovecs
[0].iov_len
=4*sizeof(message_part_t
)+sizeof(message_tail_t
)+sizeof(message_header_t
);
915 snd_iovecs
[0].iov_base
=__vectored_msg_server_snd_buf
;
916 snd_iovecs
[0].iov_len
=sizeof(message_header_t
);
917 snd_iovecs
[1].iov_base
=snd_iovecs
[0].iov_base
+snd_iovecs
[0].iov_len
;
918 snd_iovecs
[1].iov_len
=4*sizeof(message_part_t
);
919 snd_iovecs
[2].iov_base
=snd_iovecs
[1].iov_base
+snd_iovecs
[1].iov_len
;
920 snd_iovecs
[2].iov_len
=sizeof(message_tail_t
);
922 ipc_setup_buffer_pages(rcv_iovecs
,1,__buf_pages
,bufs
, false);
924 ipc_transfer_buffer_data_iov(bufs
,1,snd_iovecs
,6,0,true);
925 if( __validate_vectored_message(__vectored_msg_server_rcv_buf
,4,tf
) ) {
931 /* 1-part buffer, 8-parts message. */
932 tf
->printf(SERVER_THREAD
"Transferring 8 pieces of data to a 1-part IPC buffer.\n");
933 CLEAR_SERVER_BUFFERS
;
934 __prepare_vectored_message(__vectored_msg_server_snd_buf
,6);
936 rcv_iovecs
[0].iov_base
=__vectored_msg_server_rcv_buf
;
937 rcv_iovecs
[0].iov_len
=6*sizeof(message_part_t
)+sizeof(message_tail_t
)+sizeof(message_header_t
);
939 snd_iovecs
[0].iov_base
=__vectored_msg_server_snd_buf
;
940 snd_iovecs
[0].iov_len
=sizeof(message_header_t
);
941 snd_iovecs
[1].iov_base
=snd_iovecs
[0].iov_base
+snd_iovecs
[0].iov_len
;
942 snd_iovecs
[1].iov_len
=6*sizeof(message_part_t
);
943 snd_iovecs
[2].iov_base
=snd_iovecs
[1].iov_base
+snd_iovecs
[1].iov_len
;
944 snd_iovecs
[2].iov_len
=sizeof(message_tail_t
);
946 tf
->printf(SERVER_THREAD
"Setting up buffer pages ... " );
947 ipc_setup_buffer_pages(rcv_iovecs
,1,__buf_pages
,bufs
, false);
948 tf
->printf(" Done !\n" );
950 tf
->printf(SERVER_THREAD
"Transferring data to the buffers ... " );
951 ipc_transfer_buffer_data_iov(bufs
,1,snd_iovecs
,8,0,true);
952 tf
->printf(" Done !" );
953 if( __validate_vectored_message(__vectored_msg_server_rcv_buf
,6,tf
) ) {
959 /* 2-parts buffer, 8 pieces of data. */
961 tf
->printf(SERVER_THREAD
"Transferring %d pieces of data to a 2-part IPC buffer.\n",
963 CLEAR_SERVER_BUFFERS
;
964 __prepare_vectored_message(__vectored_msg_server_snd_buf
,MIDDLE_PARTS(__parts
));
965 __setup_message_iovecs(__vectored_msg_server_snd_buf
,MIDDLE_PARTS(__parts
),snd_iovecs
);
967 rcv_iovecs
[0].iov_base
=__vectored_msg_server_rcv_buf
;
968 rcv_iovecs
[0].iov_len
=sizeof(message_header_t
);
969 rcv_iovecs
[1].iov_base
=rcv_iovecs
[0].iov_base
+rcv_iovecs
[0].iov_len
;
970 rcv_iovecs
[1].iov_len
=6*sizeof(message_part_t
)+sizeof(message_tail_t
);
972 tf
->printf("Setting up buffer pages ... " );
973 ipc_setup_buffer_pages(rcv_iovecs
,2,__buf_pages
,bufs
, false);
974 tf
->printf("Done !\n" );
976 tf
->printf("Transferring data to the buffer (PATTERN=0x%X) ... ",
977 *(ulong_t
*)snd_iovecs
[1].iov_base
);
978 ipc_transfer_buffer_data_iov(bufs
,2,snd_iovecs
,__parts
,0,true);
979 tf
->printf("Done !\n" );
980 if( __validate_vectored_message(__vectored_msg_server_rcv_buf
,MIDDLE_PARTS(__parts
),tf
) ) {
987 * Testing IPC buffers data transfer using non-zero xfer offsets.
989 for(i
=0;i
<READ_LONGS
;i
++) {
993 snd_iovecs
[0].iov_base
=__zbuffer_snd
;
994 snd_iovecs
[0].iov_len
=715*sizeof(long);
995 snd_iovecs
[1].iov_base
=snd_iovecs
[0].iov_base
+snd_iovecs
[0].iov_len
;
996 snd_iovecs
[1].iov_len
=9300*sizeof(long);
997 snd_iovecs
[2].iov_base
=snd_iovecs
[1].iov_base
+snd_iovecs
[1].iov_len
;
998 snd_iovecs
[2].iov_len
=sizeof(__zbuffer_snd
)- snd_iovecs
[0].iov_len
- snd_iovecs
[1].iov_len
;
1000 r
=ipc_setup_buffer_pages(snd_iovecs
,3,__buf_pages
,bufs
, true);
1002 tf
->printf("Can't create buffers for offset reading !\n");
1006 tf
->printf("Size of pattern for IPC buffers read tests is %d bytes.\n",
1007 sizeof(__zbuffer_snd
));
1008 for(i
=0;i
<NUM_OFFSETS
;i
++) {
1010 __offset
=__offsets
[i
]*sizeof(long);
1012 rcv_iovecs
[0].iov_base
=__zbuffer_rcv
;
1013 rcv_iovecs
[0].iov_len
=sizeof(__zbuffer_snd
)-__offset
;
1014 memset(__zbuffer_rcv
,0,sizeof(__zbuffer_rcv
));
1016 p
=(unsigned char *)rcv_iovecs
[0].iov_base
+rcv_iovecs
[0].iov_len
;
1017 *(ulong_t
*)p
=WL_PATTERN
;
1019 tf
->printf("Reading from buffer at offset %d (%d words of data) ... ",
1020 __offset
,(sizeof(__zbuffer_snd
)-__offset
)/sizeof(long));
1021 r
=ipc_transfer_buffer_data_iov(bufs
,3,rcv_iovecs
,1,__offset
,false);
1024 tf
->printf("\n"SERVER_THREAD
"Failed to read data from buffer [1] : %d\n",r
);
1027 tf
->printf("Done.\n");
1030 if( *(ulong_t
*)p
!= WL_PATTERN
) {
1031 tf
->printf(SERVER_THREAD
"[1] Watchline mismatch ! 0x%X instead of 0x%X !\n",
1032 *(ulong_t
*)p
,WL_PATTERN
);
1036 lp
=(long *)rcv_iovecs
[0].iov_base
;
1038 tf
->printf(" Verifying buffer (%d) words of data, start pattern= %d ... ",
1039 rcv_iovecs
[0].iov_len
/sizeof(long),op
);
1040 for(j
=0;j
<rcv_iovecs
[0].iov_len
/sizeof(long);j
++,lp
++,op
++) {
1042 tf
->printf("\nMessage mismatch ! 0x%X instead of 0x%X at position %d.\n",
1043 *lp
,op
,__offsets
[i
]+j
);
1047 tf
->printf(" OK.\n");
1049 tf
->printf(SERVER_THREAD
"All IPC buffers functionality tests finished.\n");
1052 static void __message_read_test(void *ctx
)
1054 DECLARE_TEST_CONTEXT
;
1055 int port
=sys_create_port(IPC_BLOCKED_ACCESS
,0);
1057 port_msg_info_t msg_info
;
1058 message_header_t
*hdr
;
1059 message_tail_t
*tail
;
1062 tf
->printf( "Can't create a port !\n" );
1066 __vectored_port
=port
;
1067 if( kernel_thread(__vectored_messages_thread
,ctx
,NULL
) ) {
1068 tf
->printf("Can't create the vectored messages tester !\n");
1072 for(i
=0;i
<5*TEST_ROUNDS
;i
++) {
1073 ulong_t parts
=(i
%6)+1;
1078 memset(__zbuffer_rcv
,0,sizeof(__zbuffer_rcv
));
1079 size
=sizeof(message_header_t
);
1080 watchline
=(ulong_t
*)((char *)__zbuffer_rcv
+size
);
1081 *watchline
=WL_PATTERN
;
1083 tf
->printf(SERVER_THREAD
"RCV a message that has %d parts. SIZE=%d, NULL RCV buffer\n",
1085 r
=sys_port_receive(port
,IPC_BLOCKED_ACCESS
,(uintptr_t)__zbuffer_rcv
,
1086 sizeof(message_header_t
),&msg_info
);
1088 tf
->printf(SERVER_THREAD
"Error during receive ! %d.\n",r
);
1092 if( msg_info
.msg_len
!= MESSAGE_SIZE(parts
) ) {
1093 tf
->printf(SERVER_THREAD
"Bad message size ! %d instead of %d bytes.\n",
1094 msg_info
.msg_len
,size
);
1098 if( *watchline
!= WL_PATTERN
) {
1099 tf
->printf("[MSG READ] [abc] Watchline mismatch: 0x%X instead of 0x%X !\n",
1100 *watchline
,WL_PATTERN
);
1104 hdr
=(message_header_t
*)__zbuffer_rcv
;
1105 r
=__validate_message_data(hdr
->data
,hdr
->data_base
,MSG_HEADER_DATA_SIZE
);
1107 tf
->printf("First message part mismatch at %d\n",-r
);
1111 /* Now read the message partially. */
1112 memset(__zbuffer_rcv
,0,sizeof(__zbuffer_rcv
));
1113 size
=sizeof(message_header_t
);
1114 watchline
=(ulong_t
*)((char *)__zbuffer_rcv
+size
);
1115 *watchline
=WL_PATTERN
;
1117 r
=sys_port_msg_read(port
,msg_info
.msg_id
,(uintptr_t)__zbuffer_rcv
,
1120 tf
->printf(SERVER_THREAD
"Error during reading the message ! %d.\n",r
);
1124 if( *watchline
!= WL_PATTERN
) {
1125 tf
->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1126 *watchline
,WL_PATTERN
);
1130 hdr
=(message_header_t
*)__zbuffer_rcv
;
1131 r
=__validate_message_data(hdr
->data
,hdr
->data_base
,MSG_HEADER_DATA_SIZE
);
1133 tf
->printf("First message part mismatch at %d\n",-r
);
1137 for(j
=0;j
<parts
;j
++) {
1138 memset(__zbuffer_rcv
,0,sizeof(__zbuffer_rcv
));
1139 message_part_t
*part
;
1140 size
=sizeof(message_part_t
);
1141 watchline
=(ulong_t
*)((char *)__zbuffer_rcv
+size
);
1142 *watchline
=WL_PATTERN
;
1144 r
=sys_port_msg_read(port
,msg_info
.msg_id
,(uintptr_t)__zbuffer_rcv
,
1145 size
,sizeof(message_header_t
)+j
*sizeof(message_part_t
));
1147 tf
->printf(SERVER_THREAD
"[xx] Error during reading the message ! %d.\n",r
);
1151 if( *watchline
!= WL_PATTERN
) {
1152 tf
->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1153 *watchline
,WL_PATTERN
);
1157 part
=(message_part_t
*)__zbuffer_rcv
;
1158 r
=__validate_message_data(part
->data
,part
->data_base
,MSG_PART_DATA_SIZE
);
1160 tf
->printf("%d-th message part mismatch at %d\n",j
+1,-r
);
1165 memset(__zbuffer_rcv
,0,sizeof(__zbuffer_rcv
));
1166 size
=sizeof(message_tail_t
);
1167 watchline
=(ulong_t
*)((char *)__zbuffer_rcv
+size
);
1168 *watchline
=WL_PATTERN
;
1170 r
=sys_port_msg_read(port
,msg_info
.msg_id
,(uintptr_t)__zbuffer_rcv
,
1171 size
,sizeof(message_header_t
)+parts
*sizeof(message_part_t
));
1173 tf
->printf(SERVER_THREAD
"Error during reading message's tail ! %d.\n",r
);
1177 if( *watchline
!= WL_PATTERN
) {
1178 tf
->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1179 *watchline
,WL_PATTERN
);
1183 tail
=(message_tail_t
*)__zbuffer_rcv
;
1184 r
=__validate_message_data(tail
->data
,tail
->data_base
,MSG_TAIL_DATA_SIZE
);
1186 tf
->printf("%message tail mismatch at %d\n",-r
);
1190 /* Now read message as one part. */
1191 r
=sys_port_msg_read(port
,msg_info
.msg_id
,(uintptr_t)__zbuffer_rcv
,
1192 MESSAGE_SIZE(parts
),0);
1194 tf
->printf(SERVER_THREAD
"Error during whole 'READ' message ! %d.\n",r
);
1197 FAIL_ON(!__validate_vectored_message((uint8_t *)__zbuffer_rcv
,parts
,tf
),tf
);
1198 r
=sys_port_reply(port
,msg_info
.msg_id
,(uintptr_t)__zbuffer_rcv
,MESSAGE_SIZE(parts
));
1200 tf
->printf(SERVER_THREAD
"[READ MSG] Error during reply to message %d ! r=%d\n",
1204 tf
->printf("Message header, tail and %d its parts validated.\n",parts
);
1206 sys_close_port(port
);
1209 static void __vectored_messages_test(void *ctx
)
1211 DECLARE_TEST_CONTEXT
;
1212 int port
=sys_create_port(IPC_BLOCKED_ACCESS
,0);
1215 port_msg_info_t msg_info
;
1216 iovec_t snd_iovecs
[MAX_IOVECS
];
1219 tf
->printf( "Can't create a port !\n" );
1223 __vectored_port
=port
;
1224 if( kernel_thread(__vectored_messages_thread
,ctx
,&task
) ) {
1225 tf
->printf("Can't create the vectored messages tester !\n");
1229 for(i
=0;i
<5*TEST_ROUNDS
;i
++) {
1230 ulong_t parts
=(i
%6)+1;
1234 CLEAR_SERVER_BUFFERS
;
1236 /* Setup memory watchline. */
1237 size
=MESSAGE_SIZE(parts
);
1238 watchline
=(ulong_t
*)(__vectored_msg_server_rcv_buf
+size
);
1239 *watchline
=WL_PATTERN
;
1241 tf
->printf(SERVER_THREAD
"Receiving a message that has %d middle parts. SIZE=%d\n",
1242 parts
,MESSAGE_SIZE(parts
));
1243 r
=sys_port_receive(port
,IPC_BLOCKED_ACCESS
,(ulong_t
)__vectored_msg_server_rcv_buf
,
1244 sizeof(__vectored_msg_server_rcv_buf
),&msg_info
);
1245 tf
->printf(SERVER_THREAD
"Vectored message received. MESSAGE SIZE=%d\n",
1247 __validate_retval(r
,0,tf
);
1248 FAIL_ON(!__validate_vectored_message(__vectored_msg_server_rcv_buf
,parts
,tf
),tf
);
1250 if( *watchline
!= WL_PATTERN
) {
1251 tf
->printf(SERVER_THREAD
"Watchline pattern mismatch ! 0x%X instead of 0x%X\n",
1252 *watchline
,WL_PATTERN
);
1256 /* Reply to the client using a vectored message. */
1257 CLEAR_SERVER_BUFFERS
;
1258 __prepare_vectored_message(__vectored_msg_server_snd_buf
,parts
);
1259 __setup_message_iovecs(__vectored_msg_server_snd_buf
,parts
,snd_iovecs
);
1261 tf
->printf(SERVER_THREAD
"Replying by a message that consists of %d parts.\n",
1263 r
=sys_port_reply_iov(port
,msg_info
.msg_id
,snd_iovecs
,parts
+2);
1264 tf
->printf(SERVER_THREAD
"Message %d was replied (%d)\n",
1267 tf
->printf(SERVER_THREAD
"All messages were successfully transmitted.\n");
1269 if( sys_close_port(port
) ) {
1270 tf
->printf(SERVER_THREAD
"Can't close the port used for vectored messages tests !\n");
1276 #define __NGROUP_TASKS 3
1277 #define __NUM_PRIO_THREADS (__NGROUPS*__NGROUP_TASKS)
1281 typedef struct __prio_data
{
1282 test_framework_t
*tf
;
1283 ulong_t priority
,runs
;
1286 #define PRIORER_ID "[PRIO CLIENT]"
1288 static uint8_t __buf114_snd
[MAX_MSG_SIZE
];
1289 static uint8_t __buf114_rcv
[MAX_MSG_SIZE
];
1291 static void __prio_thread(void *data
)
1293 prio_data_t
*pd
=(prio_data_t
*)data
;
1294 test_framework_t
*tf
=pd
->tf
;
1296 iovec_t snd_iovecs
[MAX_IOVECS
],rcv_iovecs
[MAX_IOVECS
];
1298 ulong_t size
,prio
,parts
;
1299 uint8_t *_sbuf
,*_rbuf
;
1301 channel
=sys_open_channel(__server_pid
,__prio_port
,IPC_BLOCKED_ACCESS
);
1303 tf
->printf(PRIORER_ID
"Can't open a channel !\n" );
1308 r
=do_scheduler_control(current_task(),SYS_SCHED_CTL_SET_PRIORITY
,prio
);
1310 tf
->printf(PRIORER_ID
"Can't change my priority to %d ! r=%d\n",
1314 tf
->printf(PRIORER_ID
"[CPU %d:%d] Successfully changed priority to %d. [%d]\n",
1315 cpu_id(),current_task()->pid
,prio
,
1316 current_task()->static_priority
);
1319 for(i
=0;i
<TEST_ROUNDS
;i
++) {
1323 CLEAR_CLIENT_BUFFERS
;
1324 _sbuf
=__vectored_msg_client_snd_buf
;
1325 _rbuf
=__vectored_msg_client_rcv_buf
;
1327 memset(__buf114_snd
,0,sizeof(__buf114_snd
));
1328 memset(__buf114_snd
,0,sizeof(__buf114_snd
));
1333 __prepare_vectored_message(_sbuf
,parts
);
1334 __setup_message_iovecs(_sbuf
,parts
,snd_iovecs
);
1336 /* Setup memory watchline. */
1337 size
=MESSAGE_SIZE(parts
);
1338 watchline
=(ulong_t
*)(_sbuf
+size
);
1339 *watchline
=WL_PATTERN
;
1341 tf
->printf(PRIORER_ID
"[CPU %d:%d] Sending a message of %d parts via %s. SIZE=%d\n",
1342 cpu_id(),current_task()->pid
,
1343 parts
, (i
& 0x1) ? "'sys_port_send_iov()'" : "'sys_port_send_iov_v()'",
1344 MESSAGE_SIZE(parts
));
1346 r
=sys_port_send_iov(channel
,snd_iovecs
,parts
+2,
1349 tf
->printf(PRIORER_ID
"Message was sent: r=%d. RCV BUFSIZE=%d\n",r
,
1355 __setup_message_iovecs(_rbuf
,parts
,rcv_iovecs
);
1356 r
=sys_port_send_iov_v(channel
,snd_iovecs
,parts
+2,
1357 rcv_iovecs
,parts
+2);
1358 tf
->printf(PRIORER_ID
"Message was sent: r=%d. RCV BUFSIZE=%d\n",r
,
1364 tf
->printf(PRIORER_ID
"Verifying server's reply (%d-parts message).\n",
1366 FAIL_ON(!__validate_vectored_message(_rbuf
,parts
,tf
),tf
);
1367 if( *watchline
!= WL_PATTERN
) {
1368 tf
->printf(VECTORER_ID
"Watchline pattern mismatch ! 0x%X instead of 0x%X\n",
1369 *watchline
,WL_PATTERN
);
1377 static prio_data_t pdata
[__NUM_PRIO_THREADS
];
1378 static task_t
*ptasks
[__NUM_PRIO_THREADS
];
1380 #define __OVF_DATA_SIZE 137
1381 typedef struct __ovf_data
{
1382 unsigned char data
[__OVF_DATA_SIZE
];
1385 typedef struct __ovf_header
{
1389 static ovf_data_t __master_ovf
;
1390 static ovf_header_t __header_ovf
={0x99999999AAAAAAAA,
1391 0xBBBBBBBBCCCCCCCC};
1394 #define __CP_BUFSIZE 31
1396 static long __ovf_port
;
1398 static void __stack_overflow_client(void *ctx
)
1400 DECLARE_TEST_CONTEXT
;
1402 unsigned char d
[sizeof(ovf_header_t
)+2];
1403 unsigned char *p1
=&d
[0];
1404 ovf_header_t
*ovf_header
=(ovf_header_t
*)&d
[1];
1405 unsigned char *p2
=&d
[sizeof(d
)-1];
1407 unsigned char e
[sizeof(ovf_data_t
)+2];
1408 unsigned char *p3
=&e
[0];
1409 ovf_data_t
*ovf_data
=(ovf_data_t
*)&e
[1];
1410 unsigned char *p4
=&e
[sizeof(e
)-1];
1412 iovec_t s_vec
,r_vec
[2];
1416 channel
=sys_open_channel(__server_pid
,__vectored_port
,IPC_BLOCKED_ACCESS
);
1418 tf
->printf("[OVF TESTER]: Can't open a channel !\n" );
1422 tf
->printf("[OVF TESTER]: Sending message ...\n" );
1429 *ovf_header
=__header_ovf
;
1431 s_vec
.iov_base
=ovf_header
;
1432 s_vec
.iov_len
=sizeof(*ovf_header
);
1435 r_vec
[1].iov_base
=ovf_data
;
1436 r_vec
[1].iov_len
=sizeof(*ovf_data
);
1438 r
=sys_port_send_iov_v(channel
,&s_vec
,1,r_vec
,2);
1439 tf
->printf("[OVF TESTER]: Got a response: %d bytes\n",
1441 if( r
< 0 || r
!= (r_vec
[0].iov_len
+ r_vec
[1].iov_len
) ) {
1442 tf
->printf("[OVF TESTER]: Message had to be %d bytes length.\n",
1443 r_vec
[0].iov_len
+ r_vec
[1].iov_len
);
1448 kprintf("[!!] P1 mismatch ! %p instead of %p\n",
1454 kprintf("[!!] P2 mismatch ! %p instead of %p\n",
1460 kprintf("[!!] P3 mismatch ! %p instead of %p\n",
1466 kprintf("[!!] P4 mismatch ! %p instead of %p\n",
1471 tf
->printf("[OVF TESTER]: Verifying header ...\n");
1472 if( ovf_header
->f1
!= WL_PATTERN
||
1473 ovf_header
->f2
!= WL_PATTERN
*2 ) {
1474 tf
->printf("[OVF TESTER]: Insufficient header !\n");
1478 tf
->printf("[OVF TESTER]: Verifying the message ...\n");
1479 for(i
=0;i
<__OVF_DATA_SIZE
;i
++) {
1480 if( ovf_data
->data
[i
] != 0x15 ) {
1481 tf
->printf("[OVF TESTER]: Bad data at %d position: 0x%X\n",
1482 i
,ovf_data
->data
[i
]);
1486 tf
->printf("[OVF TESTER]: Test passed\n");
1490 static void __stack_overflow_test(void *ctx
)
1492 DECLARE_TEST_CONTEXT
;
1494 unsigned char d
[__CP_BUFSIZE
+2];
1495 unsigned char *p1
=&d
[0];
1496 unsigned char *dst
=&d
[1];
1497 unsigned char *p2
=&d
[sizeof(d
)-1];
1498 int to_copy
=p2
-p1
-1;
1499 port_msg_info_t msg_info
;
1501 ovf_header_t header
=__header_ovf
,i_header
;
1506 kprintf("p1=%p\n",p1
);
1507 kprintf("d=[%p,size=%d], last address=%p\n",
1508 &d
[1],to_copy
,(ulong_t
)&d
[1]+to_copy
-1);
1509 kprintf("p2=%p\n",p2
);
1510 copy_to_user(dst
,&__master_ovf
,to_copy
);
1513 kprintf("[!!] P1 mismatch ! %p instead of %p\n",
1518 kprintf("[!!] P2 mismatch ! %p instead of %p\n",
1523 kprintf( "** Raw usercopy tests finished !\n" );
1524 __ovf_port
=sys_create_port(IPC_BLOCKED_ACCESS
,0);
1525 if( __ovf_port
< 0 ) {
1526 tf
->printf(SERVER_THREAD
"Can't create a port for stack overflow tests !\n");
1530 if( kernel_thread(__stack_overflow_client
,ctx
,NULL
) ) {
1531 tf
->printf(SERVER_THREAD
"Can't create the overflow client !\n");
1535 tf
->printf("[OVF TEST]: Waiting for incoming messages ...\n");
1536 r
=sys_port_receive(__ovf_port
,IPC_BLOCKED_ACCESS
,(ulong_t
)&i_header
,
1537 sizeof(i_header
),&msg_info
);
1539 tf
->printf("[OVF TEST]: Error wuring receiving a message ! %d\n",
1543 tf
->printf("[OVF TEST]: Got a message %d from %d of %d bytes length!\n",
1544 msg_info
.msg_id
,msg_info
.sender_pid
,
1546 if( msg_info
.msg_len
!= sizeof(i_header
) ) {
1547 tf
->printf("[OVF TEST]: Insufficient message size: %d instead of %d\n",
1548 msg_info
.msg_len
,sizeof(i_header
));
1552 if( memcmp(&i_header
,&__header_ovf
,sizeof(i_header
)) ) {
1553 tf
->printf("[OVF TEST]: Insufficient message data !\n");
1557 tf
->printf("[OVF TEST]: Replying by a 2-part message.\n");
1558 for(i
=0;i
<__OVF_DATA_SIZE
;i
++) {
1559 o_data
.data
[i
]=0x15;
1562 header
.f1
=WL_PATTERN
;
1563 header
.f2
=WL_PATTERN
*2;
1565 iov
[0].iov_base
=&header
;
1566 iov
[0].iov_len
=sizeof(header
);
1568 iov
[1].iov_base
=&o_data
;
1569 iov
[1].iov_len
=sizeof(o_data
)+10;
1571 r
=sys_port_reply_iov(__ovf_port
,msg_info
.msg_id
,
1574 tf
->printf(SERVER_THREAD
"[PRIO PORT] Error during reply to message %d ! r=%d\n",
1579 tf
->printf("[OVF TEST]: All tests finished.\n");
1580 sys_close_port(__ovf_port
);
1583 static void __prioritized_port_test(void *ctx
)
1585 DECLARE_TEST_CONTEXT
;
1588 port_msg_info_t msg_info
;
1589 iovec_t snd_iovecs
[MAX_IOVECS
];
1590 const int __PRIO_STEP
=4;
1592 static int PRIO_BASE
=64;
1593 struct __ipc_gen_port
*genport
;
1595 /* Only one task from the most prioritized group can initially be
1596 * in the port's message queue. This will give us a better test conditions.
1598 __prio_port
=sys_create_port(IPC_BLOCKED_ACCESS
,
1599 __NUM_PRIO_THREADS
-(__NGROUP_TASKS
-1));
1600 if( __prio_port
< 0 ) {
1601 tf
->printf("Can't create prioritized port !");
1605 for(i
=0;i
<__NUM_PRIO_THREADS
;i
++) {
1606 prio
=PRIO_BASE
-__PRIO_STEP
*(i
/__NGROUP_TASKS
);
1608 pdata
[i
].priority
=prio
;
1611 if( kernel_thread(__prio_thread
,&pdata
[i
],&ptasks
[i
]) ) {
1612 tf
->printf("Can't create a prio tester !");
1617 tf
->printf(SERVER_THREAD
"[PRIO PORT] Sleeping for a while ...\n");
1619 tf
->printf(SERVER_THREAD
"[PRIO PORT] Got woken up ! Testing ! (start priority=%d)\n",
1622 /* OK, ready for tests. */
1624 for(k
=0;k
<__NGROUPS
;k
++,prio
+=__PRIO_STEP
) {
1625 for(j
=0;j
<__NGROUP_TASKS
;j
++) {
1626 for(i
=0;i
<TEST_ROUNDS
;i
++) {
1633 CLEAR_SERVER_BUFFERS
;
1635 /* Setup memory watchline. */
1636 size
=MESSAGE_SIZE(parts
);
1637 watchline
=(ulong_t
*)(__vectored_msg_server_rcv_buf
+size
);
1638 *watchline
=WL_PATTERN
;
1640 tf
->printf(SERVER_THREAD
"[PRIO PORT] Receiving a message that has %d middle parts. SIZE=%d\n",
1641 parts
,MESSAGE_SIZE(parts
));
1642 msg_info
.msg_id
= 666;
1643 r
=sys_port_receive(__prio_port
,IPC_BLOCKED_ACCESS
,(ulong_t
)__vectored_msg_server_rcv_buf
,
1644 sizeof(__vectored_msg_server_rcv_buf
),&msg_info
);
1645 tf
->printf(SERVER_THREAD
"[PRIO PORT]Vectored message received. MESSAGE SIZE=%d\n",
1647 __validate_retval(r
,0,tf
);
1648 FAIL_ON(!__validate_vectored_message(__vectored_msg_server_rcv_buf
,parts
,tf
),tf
);
1650 if( *watchline
!= WL_PATTERN
) {
1651 tf
->printf(SERVER_THREAD
"[PRIO PORT] Watchline pattern mismatch ! 0x%X instead of 0x%X\n",
1652 *watchline
,WL_PATTERN
);
1656 /* Make sure client has a proper priority. */
1657 for(t
=NULL
,idx
=0;idx
<__NUM_PRIO_THREADS
;idx
++) {
1658 if(ptasks
[idx
]->pid
== msg_info
.sender_pid
) {
1666 tf
->printf(SERVER_THREAD
"[PRIO PORT] Can't locate a client with PID=%d\n",
1667 msg_info
.sender_pid
);
1671 /* Make sure kernel provided us with sender's TID and UID properly. */
1672 if( msg_info
.sender_tid
!= t
->tid
|| msg_info
.sender_uid
!= t
->uid
) {
1673 tf
->printf(SERVER_THREAD
"[PRIO PORT] Wrong sender info ! TID (%d:%d), UID (%d:%d)\n",
1674 t
->tid
,msg_info
.sender_tid
,t
->uid
,msg_info
.sender_uid
);
1678 /* OK, now compare priority */
1679 if( t
->static_priority
!= prio
) {
1680 tf
->printf(SERVER_THREAD
"[PRIO PORT]: Priority mismatch ! %d instead of %d\n",
1681 t
->static_priority
,prio
);
1682 tf
->printf(" CURRENT ITERATION: round=%d,task=%d,group=%d\n",
1687 tf
->printf(SERVER_THREAD
"[PRIO PORT] Good client: MSG ID=%d, PRIO=%d\n",
1688 msg_info
.msg_id
,t
->static_priority
);
1690 /* Reply to the client using a vectored message. */
1691 CLEAR_SERVER_BUFFERS
;
1692 __prepare_vectored_message(__vectored_msg_server_snd_buf
,parts
);
1693 __setup_message_iovecs(__vectored_msg_server_snd_buf
,parts
,snd_iovecs
);
1695 tf
->printf(SERVER_THREAD
"[PRIO PORT]Replying by a message that consists of %d parts.\n",
1697 r
=sys_port_reply_iov(__prio_port
,msg_info
.msg_id
,snd_iovecs
,parts
+2);
1698 tf
->printf(SERVER_THREAD
"[PRIO PORT]Message %d was replied (%d)\n",
1701 tf
->printf(SERVER_THREAD
"[PRIO PORT] Error during reply to message %d ! r=%d\n",
1709 genport
=ipc_get_port(current_task(),__prio_port
);
1711 tf
->printf(SERVER_THREAD
"Can't resolve port !");
1715 if( genport
->avail_messages
|| genport
->total_messages
) {
1716 tf
->printf(SERVER_THREAD
"Error ! Port state is insufficient! Avail: %d, Total: %d\n",
1717 genport
->avail_messages
,genport
->total_messages
);
1721 tf
->printf(SERVER_THREAD
"All priority-related tests finished.\n");
1722 sys_close_port(__prio_port
);
1725 static void __server_thread(void *ctx
)
1727 DECLARE_TEST_CONTEXT
;
1728 int ports
[SERVER_NUM_PORTS
];
1732 port_msg_info_t msg_info
;
1734 __server_pid
=current_task()->pid
;
1737 kthread_cpu_autodeploy
=true;
1740 __stack_overflow_test(ctx
);
1742 __ipc_buffer_test(ctx
);
1744 __process_events_test(ctx
);
1746 __message_read_test(ctx
);
1748 __prioritized_port_test(ctx
);
1750 __vectored_messages_test(ctx
);
1753 for( i
=0;i
<SERVER_NUM_PORTS
;i
++) {
1754 if( i
!= NON_BLOCKED_PORT_ID
) {
1755 flags
=IPC_BLOCKED_ACCESS
;
1759 ports
[i
]=sys_create_port(flags
,0);
1760 if( ports
[i
] != i
) {
1761 tf
->printf(SERVER_THREAD
"IPC port number mismatch: %d instead of %d\n",
1768 tctx
->server_pid
=current_task()->pid
;
1769 tf
->printf(SERVER_THREAD
"%d ports created.\n", SERVER_NUM_PORTS
);
1773 if( kernel_thread(__client_thread
,ctx
,NULL
) ) {
1774 tf
->printf(SERVER_THREAD
"Can't launch client thread.\n",
1779 /********************************************************
1780 * Testing message delivery in blocking mode.
1781 ********************************************************/
1782 tf
->printf(SERVER_THREAD
"Testing message delivery in blocking mode.\n" );
1783 for(i
=0;i
<TEST_ROUNDS
;i
++) {
1784 r
=sys_port_receive(i
,IPC_BLOCKED_ACCESS
,(ulong_t
)__server_rcv_buf
,
1785 sizeof(__server_rcv_buf
),&msg_info
);
1786 tf
->printf(SERVER_THREAD
"Got a message !\n");
1788 tf
->printf(SERVER_THREAD
"Insufficient return value during 'sys_port_receive': %d\n",
1793 if( msg_info
.msg_id
!= 0 ) {
1794 tf
->printf(SERVER_THREAD
"Insufficient message id: %d instead of 0\n",
1798 if( msg_info
.msg_len
== strlen(patterns
[i
])+1 ) {
1799 if( !__verify_message(i
,__server_rcv_buf
) ) {
1800 tf
->printf( SERVER_THREAD
"Message N %d mismatch.\n",
1804 tf
->printf( SERVER_THREAD
"Message N %d was successfuly transmitted.\n",
1809 tf
->printf(SERVER_THREAD
"Message N%d has insufficient length: %d instead of %d\n",
1810 i
,msg_info
.msg_len
,strlen(patterns
[i
])+1);
1815 tf
->printf(SERVER_THREAD
"Replying to %d with %d bytes of data\n",
1816 i
,strlen(patterns
[i
])+1);
1817 r
=sys_port_reply(i
,0,(ulong_t
)patterns
[i
],strlen(patterns
[i
])+1);
1819 tf
->printf(SERVER_THREAD
"Insufficient return value during 'sys_port_reply': %d\n",
1826 /****************************************************************
1827 * Testing delivery of big messages in blocking mode.
1828 ****************************************************************/
1829 tf
->printf(SERVER_THREAD
"Testing delivery of a big message (%d bytes).\n",
1831 r
=sys_port_receive(BIG_MESSAGE_PORT_ID
,IPC_BLOCKED_ACCESS
,
1832 (ulong_t
)__big_message_server_buf
,
1833 BIG_MESSAGE_SIZE
,&msg_info
);
1835 tf
->printf(SERVER_THREAD
"Insufficient return value during 'sys_port_receive': %d\n",
1840 kprintf( SERVER_THREAD
"Big message received: %d bytes.\n",msg_info
.msg_len
);
1841 if( msg_info
.msg_len
== BIG_MESSAGE_SIZE
) {
1844 if( !__verify_big_message(__big_message_server_buf
,&offt
) ) {
1845 tf
->printf( SERVER_THREAD
"Big message mismatch at offset: %d\n",
1849 tf
->printf( SERVER_THREAD
"Big message was successfully transmitted.\n" );
1853 tf
->printf(SERVER_THREAD
"Message N%d has insufficient length: %d instead of %d\n",
1854 msg_info
.msg_id
,msg_info
.msg_len
,BIG_MESSAGE_SIZE
);
1858 r
=sys_port_reply(BIG_MESSAGE_PORT_ID
,msg_info
.msg_id
,
1859 (ulong_t
)__big_message_pattern
,BIG_MESSAGE_SIZE
);
1861 tf
->printf(SERVER_THREAD
"Insufficient return value during 'sys_port_reply': %d\n",
1867 /*****************************************************************
1868 * Testing message delivery in non-blocking mode (small messages).
1869 ****************************************************************/
1871 tf
->printf(SERVER_THREAD
"Testing message delivery in non-blocking mode.\n" );
1873 for(i
=0;i
<TEST_ROUNDS
;i
++) {
1874 r
=sys_port_receive(NON_BLOCKED_PORT_ID
,IPC_BLOCKED_ACCESS
,
1875 (ulong_t
)__server_rcv_buf
,
1876 sizeof(__server_rcv_buf
),&msg_info
);
1878 tf
->printf(SERVER_THREAD
"Insufficient return value during 'sys_port_receive': %d\n",
1883 if( msg_info
.msg_len
== strlen(patterns
[i
])+1 ) {
1884 if( !__verify_message(i
,__server_rcv_buf
) ) {
1885 tf
->printf( SERVER_THREAD
"Message N %d mismatch.\n",i
);
1888 tf
->printf( SERVER_THREAD
"Non-blocking Message N %d successfully received.\n",i
);
1892 tf
->printf(SERVER_THREAD
"Message N%d has insufficient length: %d instead of %d\n",
1893 i
,msg_info
.msg_len
,strlen(patterns
[i
])+1);
1900 /*****************************************************************
1901 * Testing port polling.
1902 ****************************************************************/
1903 tf
->printf(SERVER_THREAD
"Testing IPC port polling.\n" );
1904 __ipc_poll_test(tctx
,ports
);
1910 tctx
->tests_finished
=true;
1914 static void __initialize_big_pattern(void)
1917 int *p
=(int *)__big_message_pattern
;
1919 for(i
=0;i
<BIG_MESSAGE_SIZE
/sizeof(int);i
++) {
1924 static bool __ipc_tests_initialize(void **ctx
)
1926 ipc_test_ctx_t
*tctx
=memalloc(sizeof(*tctx
));
1929 memset(tctx
,0,sizeof(*tctx
));
1930 tctx
->tests_finished
=false;
1931 tctx
->server_pid
=10000;
1933 __initialize_big_pattern();
1939 void __ipc_tests_run(test_framework_t
*f
,void *ctx
)
1941 ipc_test_ctx_t
*tctx
=(ipc_test_ctx_t
*)ctx
;
1945 if( kernel_thread(__server_thread
,tctx
,NULL
) ) {
1946 f
->printf( "Can't create server thread !" );
1949 f
->test_completion_loop(TEST_ID
,&tctx
->tests_finished
);
1953 void __ipc_tests_deinitialize(void *ctx
)
1958 testcase_t ipc_testcase
={
1960 .initialize
=__ipc_tests_initialize
,
1961 .deinitialize
=__ipc_tests_deinitialize
,
1962 .run
=__ipc_tests_run
,
1963 .autodeploy_threads
=true,