added script for Grub2 image creation;
[MuString.git] / tests / ipc_test.c
blob3440ba0664857ffc794d4facd49e127f57a9cb96
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>
12 #include <ipc/ipc.h>
13 #include <ipc/port.h>
14 #include <arch/asm.h>
15 #include <arch/preempt.h>
16 #include <kernel/syscalls.h>
17 #include <mstring/uinterrupt.h>
18 #include <ipc/poll.h>
19 #include <mstring/gc.h>
20 #include <ipc/port.h>
21 #include <ipc/channel.h>
22 #include <test.h>
23 #include <mm/slab.h>
24 #include <mstring/errno.h>
25 #include <mstring/process.h>
26 #include <mstring/usercopy.h>
27 #include <config.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
40 #define TEST_ROUNDS 3
41 #define SERVER_NUM_BLOCKED_PORTS NON_BLOCKED_PORT_ID
43 typedef struct __ipc_test_ctx {
44 test_framework_t *tf;
45 ulong_t server_pid;
46 bool tests_finished;
47 } ipc_test_ctx_t;
49 typedef struct __thread_port {
50 ulong_t port_id,server_pid;
51 ipc_test_ctx_t *tctx;
52 bool finished_tests;
53 long msg_id;
54 long reply_msg_id;
55 int pid;
56 } thread_port_t;
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]= {
71 "1",
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)
91 int i;
92 uint8_t *p=__big_message_pattern;
94 for(i=0;i<BIG_MESSAGE_SIZE;i++) {
95 if( *p != *buf ) {
96 *diff_offset=i;
97 return false;
99 p++;
100 buf++;
102 return true;
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)
114 uint8_t *p;
115 ulong_t len;
116 ulong_t *lengths,chunks;
117 int i;
119 if( msg_id != BIG_MSG_ID ) {
120 p=(uint8_t *)patterns[msg_id];
121 len=strlen(patterns[msg_id])+1;
124 if( msg_id == 0 ) {
125 iovecs->iov_base=p;
126 iovecs->iov_len=len;
127 *numvecs=1;
128 return;
129 } else if( msg_id == BIG_MSG_ID ) {
130 p=__big_message_pattern;
131 len=BIG_MESSAGE_SIZE;
132 lengths=__v_big_7;
133 chunks=7;
134 } else {
136 switch( current_task()->pid % 3 ) {
137 case 0:
138 lengths=__v_2;
139 chunks=2;
140 break;
141 case 1:
142 lengths=__v_6;
143 chunks=6;
144 break;
145 case 2:
146 lengths=__v_4;
147 chunks=4;
148 break;
152 for(i=0;i<chunks;i++) {
153 iovecs->iov_base=p;
154 iovecs->iov_len=lengths[i];
156 iovecs++;
157 len-=lengths[i];
158 p+=lengths[i];
160 /* Process the last chunk. */
161 iovecs->iov_base=p;
162 iovecs->iov_len=len;
163 *numvecs=chunks+1;
166 static void __client_thread(void *ctx)
168 DECLARE_TEST_CONTEXT;
169 int i;
170 int channels[SERVER_NUM_PORTS];
171 int r;
172 iovec_t iovecs[MAX_IOVECS];
173 ulong_t numvecs;
175 tf->printf(CLIENT_THREAD "Opening %d channels.\n",SERVER_NUM_PORTS );
176 for(i=0;i<SERVER_NUM_PORTS;i++) {
177 ulong_t flags;
179 if( i != NON_BLOCKED_PORT_ID ) {
180 flags |= IPC_CHANNEL_FLAG_BLOCKED_MODE;
181 } else {
182 flags = 0;
185 channels[i]=sys_open_channel(tctx->server_pid,i,
186 flags);
187 if( channels[i] != i ) {
188 tf->printf(CLIENT_THREAD "Channel number mismatch: %d instead of %d\n",
189 channels[i],i);
190 tf->failed();
191 goto exit_test;
194 /* Now check if channel's flags macth. */
195 r=sys_control_channel(channels[i],IPC_CHANNEL_CTL_GET_SYNC_MODE,0);
196 if( r >= 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);
201 tf->failed();
203 } else {
204 tf->printf(CLIENT_THREAD"Can't read channel's sync mode: %d\n",r );
207 tf->passed();
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);
212 if( r == -EINVAL ) {
213 tf->passed();
214 } else {
215 tf->failed();
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);
226 if( r < 0 ) {
227 tf->printf(CLIENT_THREAD "Error while sending data over channel N%d : %d\n",
228 channels[i],r);
229 tf->failed();
230 goto exit_test;
231 } else {
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",
236 tf->failed();
238 } else {
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);
241 tf->failed();
245 tf->printf(CLIENT_THREAD "All messages were successfully processed.\n" );
246 tf->passed();
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],
255 iovecs,numvecs,
256 (ulong_t)__big_message_client_buf,BIG_MESSAGE_SIZE);
257 if( r < 0 ) {
258 tf->printf(CLIENT_THREAD "Error while sending a big message over channel N%d : %d\n",
259 channels[BIG_MESSAGE_PORT_ID],r);
260 tf->failed();
261 goto exit_test;
262 } else {
263 kprintf( CLIENT_THREAD "Got big reply: %d bytes.\n",r );
264 if( r == BIG_MESSAGE_SIZE ) {
265 ulong_t offt;
267 if( !__verify_big_message(__big_message_client_buf,&offt) ) {
268 tf->printf(CLIENT_THREAD "Server reply mismatch at offset: %d\n",
269 offt);
270 tf->failed();
271 } else {
272 tf->printf(CLIENT_THREAD "Big message was successfully replied.\n" );
273 tf->passed();
275 } else {
276 tf->printf(CLIENT_THREAD "Server reply has insufficient length: %d instead of %d\n",
277 r,BIG_MESSAGE_SIZE);
278 tf->failed();
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,
290 0,0);
291 if( r < 0 ) {
292 tf->printf(CLIENT_THREAD "Error while sending data over channel N%d : %d\n",
293 channels[NON_BLOCKED_PORT_ID],r);
294 tf->failed();
295 goto exit_test;
298 tf->printf(CLIENT_THREAD "All messages were successfully sent.\n" );
299 tf->passed();
301 goto exit_test;
302 exit_test:
303 sys_exit(0);
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;
313 int i,r;
314 ulong_t msg_id;
315 char client_rcv_buf[MAX_TEST_MESSAGE_SIZE];
316 iovec_t iovecs[MAX_IOVECS];
318 port=tp->port_id;
319 r=sys_open_channel(tp->server_pid,port,IPC_CHANNEL_FLAG_BLOCKED_MODE);
320 if( r < 0 ) {
321 tf->printf(POLL_CLIENT "Can't open a channel to %d:%d ! r=%d\n",
322 tp->server_pid,port,r);
323 tf->abort();
325 channel=r;
327 msg_id=port % TEST_ROUNDS;
328 for(i=0;i<TEST_ROUNDS;i++) {
329 char *snd_type;
330 tf->printf(POLL_CLIENT "Sending message to port %d.\n",port );
332 if( i & 0x1 ) {
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()";
337 } else {
338 /* Sending a message using I/O vector array. */
339 ulong_t numvecs;
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));
346 if( r < 0 ) {
347 tf->printf(POLL_CLIENT "Error occured while sending message: %d via %s\n",
348 r,snd_type);
349 tf->failed();
350 } else {
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");
354 tf->failed();
356 } else {
357 tf->printf(POLL_CLIENT "Reply to my message has insufficient length: %d instead of %d\n",
358 r,strlen(patterns[msg_id])+1);
359 tf->failed();
362 tf->printf(POLL_CLIENT "Message from port %d was successfully replied.\n",
363 port);
364 sleep(HZ/50);
368 /* Special case: test client wake up during port close. */
369 if( port == 0 ) {
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));
374 if( r == -EPIPE ) {
375 tf->printf( POLL_CLIENT "Got -EPIPE. It seems that kernel woke us properly.\n" );
376 tp->finished_tests=true;
377 } else {
378 tf->printf(POLL_CLIENT "Insufficient return value upon wake-up on port closing: %d\n",
380 tf->failed();
382 } else {
383 tp->finished_tests=true;
386 tf->printf(POLL_CLIENT "Exiting (target port: %d)\n",port );
387 sys_exit(0);
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)
396 int i,r,j;
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++) {
404 task_t *task;
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" );
416 tf->abort();
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++) {
423 ulong_t msg_id;
424 thread_port_t *_tt;
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;
431 fds[i].revents=0;
432 fds[i].fd=ports[i];
435 tf->printf( SERVER_THREAD "Polling ports (%d clients left) ...\n",polled_clients );
436 r=sys_ipc_port_poll(fds,NUM_POLL_CLIENTS,NULL);
437 if( r < 0 ) {
438 tf->printf( SERVER_THREAD "Error occured while polling ports: %d\n",r );
439 tf->abort();
441 int jl,nc=r;
443 tf->printf( SERVER_THREAD ">> Events occured: %d\n", r );
444 polled_clients-=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);
451 if( r != 0 ) {
452 tf->printf( SERVER_THREAD "Error during RCV from port N %d. r=%d\n",
453 fds[jl].fd,r);
454 tf->abort();
457 if( !nc ) {
458 tf->printf(SERVER_THREAD"Extra poll events available !\n");
459 tf->abort();
461 nc--;
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",
467 fds[i].fd );
468 tf->abort();
470 } else {
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);
473 tf->abort();
476 /* Good message, so store its details for further reply. */
477 _tt=NULL;
478 for(i=0;i<NUM_POLL_CLIENTS;i++) {
479 if( poller_ports[i].pid == msg_info.sender_pid ) {
480 _tt=&poller_ports[i];
484 if( !_tt ) {
485 tf->printf(SERVER_THREAD"Can't locate poll client: %d\n",
486 msg_info.sender_pid);
487 tf->abort();
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);
493 tf->abort();
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);
499 tf->abort();
501 _tt->msg_id=msg_info.msg_id;
502 _tt->reply_msg_id=msg_id;
506 if( nc ) {
507 tf->printf(SERVER_THREAD"%d not processed events after current poll round !\n",nc);
508 tf->abort();
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",
518 _tt->pid);
519 tf->abort();
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);
524 if( r ) {
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);
527 tf->abort();
529 _tt->msg_id=-1;
531 tf->printf( SERVER_THREAD "All messages were replied. Now let's have some rest (HZ/2) ...\n" );
532 sleep(HZ/2);
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,
541 * or not.
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);
546 if( r != 0 ) {
547 tf->printf( SERVER_THREAD "Error during receiving message for client wake-up. r=%d\n",
549 tf->abort();
552 /* Simulate an accident port shutdown. */
553 r=sys_close_port(0);
554 if( r ) {
555 tf->printf( SERVER_THREAD "Can't close port N 0. r=%d\n",r );
556 tf->abort();
559 /* Let sleep for a while to allow the client to let us know about its state. */
560 sleep(HZ/2);
561 if( poller_ports[0].finished_tests ) {
562 tf->printf( SERVER_THREAD "Clien't was successfully woken up.\n" );
563 tf->passed();
564 } else {
565 tf->printf( SERVER_THREAD "Client wasn't woken up !\n",r );
566 tf->failed();
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" );
582 sys_exit(0);
585 static void __process_events_test(void *ctx)
587 DECLARE_TEST_CONTEXT;
588 int port=sys_create_port(0,0);
589 task_t *task;
590 int r;
591 task_event_ctl_arg te_ctl;
592 task_event_descr_t ev_descr;
593 port_msg_info_t msg_info;
595 if( port < 0 ) {
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");
601 tf->abort();
604 te_ctl.ev_mask=TASK_EVENT_TERMINATION;
605 te_ctl.port=port;
606 r=sys_task_control(task->pid,0,SYS_PR_CTL_ADD_EVENT_LISTENER,
607 (ulong_t)&te_ctl);
608 if( r ) {
609 tf->printf("Can't set event listener: %d\n",r);
610 tf->failed();
613 tf->printf( "Check that no one can set more than one same listeners.\n" );
614 te_ctl.ev_mask=TASK_EVENT_TERMINATION;
615 te_ctl.port=port;
616 r=sys_task_control(task->pid,0,SYS_PR_CTL_ADD_EVENT_LISTENER,
617 (ulong_t)&te_ctl);
618 if( r != -EBUSY ) {
619 tf->printf("How did I manage to set the second listener ? %d\n",r);
620 tf->failed();
621 } else {
622 tf->passed();
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);
628 if( r ) {
629 tf->printf("Error occured while waiting for task's events: %d !\n",
631 tf->failed();
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);
638 tf->failed();
641 tf->printf( "All process event tests passed.\n" );
642 tf->passed();
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 {
654 uint16_t data_base;
655 uint16_t data[MSG_HEADER_DATA_SIZE];
656 } message_header_t;
658 typedef struct __message_part {
659 uint16_t data_base;
660 uint16_t data[MSG_PART_DATA_SIZE];
661 } message_part_t;
663 typedef struct __message_tail {
664 uint16_t data_base;
665 uint16_t data[MSG_TAIL_DATA_SIZE];
666 } message_tail_t;
668 #define FAIL_ON(c,tf) do { \
669 if( (c) ) (tf)->failed(); \
670 } while(0)
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)
685 int i;
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;
693 return 0;
696 static void __prepare_message_data(uint16_t *data,uint16_t base,ulong_t size)
698 while( size ) {
699 *data=base;
700 size--;
701 data++;
702 base++;
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;
712 int r,i;
714 r=__validate_message_data(hdr->data,hdr->data_base,MSG_HEADER_DATA_SIZE);
715 if( r < 0 ) {
716 tf->printf("Message header mismatches at %d\n",-r);
717 return false;
720 hdr++;
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);
724 if( r < 0 ) {
725 tf->printf("Message part %d mismatches at %d\n",i,-r);
726 return false;
730 tail=(message_tail_t *)part;
732 r=__validate_message_data(tail->data,tail->data_base,MSG_TAIL_DATA_SIZE);
733 if( r < 0 ) {
734 tf->printf("Message tail mismatches at %d\n",-r);
735 return false;
737 return true;
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;
748 int i;
750 LOCK_SHARED_DATA();
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);
756 hdr++;
757 part=(message_part_t *)hdr;
758 for(i=0;i<parts;i++,part++) {
759 LOCK_SHARED_DATA();
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;
767 LOCK_SHARED_DATA();
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);
779 iovecs++;
780 msg += sizeof(message_header_t);
782 for(;parts;parts--) {
783 iovecs->iov_base=msg;
784 iovecs->iov_len=sizeof(message_part_t);
786 iovecs++;
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;
810 int r,i;
811 iovec_t snd_iovecs[MAX_IOVECS],rcv_iovecs[MAX_IOVECS];
812 ulong_t channel;
813 ulong_t size;
815 tf->printf(VECTORER_ID "Starting on CPU %d.\n",cpu_id());
817 channel=sys_open_channel(__server_pid,__vectored_port,IPC_BLOCKED_ACCESS);
818 if( channel < 0 ) {
819 tf->printf(VECTORER_ID"Can't open a channel !\n" );
820 tf->abort();
823 for(i=0;i<5*TEST_ROUNDS;i++) {
824 ulong_t parts=(i%6)+1;
825 ulong_t *watchline;
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));
839 if( i & 0x1 ) {
840 r=sys_port_send_iov(channel,snd_iovecs,parts+2,
841 (uintptr_t)__vectored_msg_client_rcv_buf,
842 MAX_MSG_SIZE);
843 tf->printf(VECTORER_ID"Message was sent: r=%d. RCV BUFSIZE=%d\n",r,
844 sizeof(__vectored_msg_client_rcv_buf));
845 if( r < 0 ) {
846 tf->failed();
848 } else {
849 __setup_message_iovecs(__vectored_msg_client_rcv_buf,parts,rcv_iovecs);
850 r=sys_port_send_iov_v(channel,snd_iovecs,parts+2,
851 rcv_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));
854 if( r < 0 ) {
855 tf->failed();
858 tf->printf(VECTORER_ID"Varifying server's reply (%d-parts message).\n",
859 parts);
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);
864 tf->failed();
868 tf->printf(VECTORER_ID "All messages were successfully transmitted.\n");
869 sys_exit(0);
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",
878 tf->failed();
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];
897 ulong_t __parts;
898 unsigned char *p;
899 int i,r,__offset;
900 long *lp;
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) ) {
926 tf->passed();
927 } else {
928 tf->failed();
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) ) {
954 tf->passed();
955 } else {
956 tf->failed();
959 /* 2-parts buffer, 8 pieces of data. */
960 __parts=8;
961 tf->printf(SERVER_THREAD"Transferring %d pieces of data to a 2-part IPC buffer.\n",
962 __parts);
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) ) {
981 tf->passed();
982 } else {
983 tf->failed();
987 * Testing IPC buffers data transfer using non-zero xfer offsets.
989 for(i=0;i<READ_LONGS;i++) {
990 __zbuffer_snd[i]=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);
1001 if( r ) {
1002 tf->printf("Can't create buffers for offset reading !\n");
1003 tf->abort();
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++) {
1009 int j,op;
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);
1023 if( r ) {
1024 tf->printf("\n"SERVER_THREAD"Failed to read data from buffer [1] : %d\n",r);
1025 tf->failed();
1026 } else {
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);
1033 tf->failed();
1036 lp=(long *)rcv_iovecs[0].iov_base;
1037 op=__offsets[i];
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++) {
1041 if( *lp != op ) {
1042 tf->printf("\nMessage mismatch ! 0x%X instead of 0x%X at position %d.\n",
1043 *lp,op,__offsets[i]+j);
1044 tf->failed();
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);
1056 int r,i;
1057 port_msg_info_t msg_info;
1058 message_header_t *hdr;
1059 message_tail_t *tail;
1061 if( port < 0 ) {
1062 tf->printf( "Can't create a port !\n" );
1063 tf->abort();
1066 __vectored_port=port;
1067 if( kernel_thread(__vectored_messages_thread,ctx,NULL) ) {
1068 tf->printf("Can't create the vectored messages tester !\n");
1069 tf->abort();
1072 for(i=0;i<5*TEST_ROUNDS;i++) {
1073 ulong_t parts=(i%6)+1;
1074 ulong_t *watchline;
1075 ulong_t size;
1076 int j;
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",
1084 parts,size);
1085 r=sys_port_receive(port,IPC_BLOCKED_ACCESS,(uintptr_t)__zbuffer_rcv,
1086 sizeof(message_header_t),&msg_info);
1087 if( r ) {
1088 tf->printf(SERVER_THREAD"Error during receive ! %d.\n",r);
1089 tf->failed();
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);
1095 tf->failed();
1098 if( *watchline != WL_PATTERN ) {
1099 tf->printf("[MSG READ] [abc] Watchline mismatch: 0x%X instead of 0x%X !\n",
1100 *watchline,WL_PATTERN);
1101 tf->abort();
1104 hdr=(message_header_t*)__zbuffer_rcv;
1105 r=__validate_message_data(hdr->data,hdr->data_base,MSG_HEADER_DATA_SIZE);
1106 if( r < 0 ) {
1107 tf->printf("First message part mismatch at %d\n",-r);
1108 tf->failed();
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,
1118 size,0);
1119 if( r ) {
1120 tf->printf(SERVER_THREAD"Error during reading the message ! %d.\n",r);
1121 tf->failed();
1124 if( *watchline != WL_PATTERN ) {
1125 tf->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1126 *watchline,WL_PATTERN);
1127 tf->abort();
1130 hdr=(message_header_t*)__zbuffer_rcv;
1131 r=__validate_message_data(hdr->data,hdr->data_base,MSG_HEADER_DATA_SIZE);
1132 if( r < 0 ) {
1133 tf->printf("First message part mismatch at %d\n",-r);
1134 tf->failed();
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));
1146 if( r ) {
1147 tf->printf(SERVER_THREAD"[xx] Error during reading the message ! %d.\n",r);
1148 tf->failed();
1151 if( *watchline != WL_PATTERN ) {
1152 tf->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1153 *watchline,WL_PATTERN);
1154 tf->abort();
1157 part=(message_part_t*)__zbuffer_rcv;
1158 r=__validate_message_data(part->data,part->data_base,MSG_PART_DATA_SIZE);
1159 if( r < 0 ) {
1160 tf->printf("%d-th message part mismatch at %d\n",j+1,-r);
1161 tf->failed();
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));
1172 if( r ) {
1173 tf->printf(SERVER_THREAD"Error during reading message's tail ! %d.\n",r);
1174 tf->failed();
1177 if( *watchline != WL_PATTERN ) {
1178 tf->printf("[MSG READ] Watchline mismatch: 0x%X instead of 0x%X !\n",
1179 *watchline,WL_PATTERN);
1180 tf->abort();
1183 tail=(message_tail_t*)__zbuffer_rcv;
1184 r=__validate_message_data(tail->data,tail->data_base,MSG_TAIL_DATA_SIZE);
1185 if( r < 0 ) {
1186 tf->printf("%message tail mismatch at %d\n",-r);
1187 tf->failed();
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);
1193 if( r ) {
1194 tf->printf(SERVER_THREAD"Error during whole 'READ' message ! %d.\n",r);
1195 tf->failed();
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));
1199 if( r ) {
1200 tf->printf(SERVER_THREAD"[READ MSG] Error during reply to message %d ! r=%d\n",
1201 msg_info.msg_id,r);
1202 tf->abort();
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);
1213 task_t *task;
1214 int r,i;
1215 port_msg_info_t msg_info;
1216 iovec_t snd_iovecs[MAX_IOVECS];
1218 if( port < 0 ) {
1219 tf->printf( "Can't create a port !\n" );
1220 tf->abort();
1223 __vectored_port=port;
1224 if( kernel_thread(__vectored_messages_thread,ctx,&task) ) {
1225 tf->printf("Can't create the vectored messages tester !\n");
1226 tf->abort();
1229 for(i=0;i<5*TEST_ROUNDS;i++) {
1230 ulong_t parts=(i%6)+1;
1231 ulong_t *watchline;
1232 ulong_t size;
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",
1246 msg_info.msg_len);
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);
1253 tf->failed();
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",
1262 parts);
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",
1265 msg_info.msg_id,r);
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");
1271 tf->abort();
1275 #define __NGROUPS 3
1276 #define __NGROUP_TASKS 3
1277 #define __NUM_PRIO_THREADS (__NGROUPS*__NGROUP_TASKS)
1279 int __prio_port;
1281 typedef struct __prio_data {
1282 test_framework_t *tf;
1283 ulong_t priority,runs;
1284 } prio_data_t;
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;
1295 int r,i;
1296 iovec_t snd_iovecs[MAX_IOVECS],rcv_iovecs[MAX_IOVECS];
1297 ulong_t channel;
1298 ulong_t size,prio,parts;
1299 uint8_t *_sbuf,*_rbuf;
1301 channel=sys_open_channel(__server_pid,__prio_port,IPC_BLOCKED_ACCESS);
1302 if( channel < 0 ) {
1303 tf->printf(PRIORER_ID"Can't open a channel !\n" );
1304 tf->abort();
1307 prio=pd->priority;
1308 r=do_scheduler_control(current_task(),SYS_SCHED_CTL_SET_PRIORITY,prio);
1309 if( r ) {
1310 tf->printf(PRIORER_ID"Can't change my priority to %d ! r=%d\n",
1311 prio,r);
1312 tf->abort();
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);
1318 parts=3;
1319 for(i=0;i<TEST_ROUNDS;i++) {
1320 ulong_t *watchline;
1322 if( !cpu_id() ) {
1323 CLEAR_CLIENT_BUFFERS;
1324 _sbuf=__vectored_msg_client_snd_buf;
1325 _rbuf=__vectored_msg_client_rcv_buf;
1326 } else {
1327 memset(__buf114_snd,0,sizeof(__buf114_snd));
1328 memset(__buf114_snd,0,sizeof(__buf114_snd));
1329 _sbuf=__buf114_snd;
1330 _rbuf=__buf114_rcv;
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));
1345 if( i & 0x1 ) {
1346 r=sys_port_send_iov(channel,snd_iovecs,parts+2,
1347 (uintptr_t)_rbuf,
1348 MAX_MSG_SIZE);
1349 tf->printf(PRIORER_ID"Message was sent: r=%d. RCV BUFSIZE=%d\n",r,
1350 MAX_MSG_SIZE);
1351 if( r < 0 ) {
1352 tf->failed();
1354 } else {
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,
1359 MAX_MSG_SIZE);
1360 if( r < 0 ) {
1361 tf->failed();
1364 tf->printf(PRIORER_ID"Verifying server's reply (%d-parts message).\n",
1365 parts);
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);
1370 tf->failed();
1374 sys_exit(0);
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];
1383 } ovf_data_t;
1385 typedef struct __ovf_header {
1386 ulong_t f1,f2;
1387 } ovf_header_t;
1389 static ovf_data_t __master_ovf;
1390 static ovf_header_t __header_ovf={0x99999999AAAAAAAA,
1391 0xBBBBBBBBCCCCCCCC};
1393 #define __CP 0xFE
1394 #define __CP_BUFSIZE 31
1396 static long __ovf_port;
1398 static void __stack_overflow_client(void *ctx)
1400 DECLARE_TEST_CONTEXT;
1401 int r;
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];
1413 long channel;
1414 int i;
1416 channel=sys_open_channel(__server_pid,__vectored_port,IPC_BLOCKED_ACCESS);
1417 if( channel < 0 ) {
1418 tf->printf("[OVF TESTER]: Can't open a channel !\n" );
1419 tf->abort();
1422 tf->printf("[OVF TESTER]: Sending message ...\n" );
1424 *p1=__CP;
1425 *p2=__CP;
1426 *p3=__CP;
1427 *p4=__CP;
1429 *ovf_header=__header_ovf;
1431 s_vec.iov_base=ovf_header;
1432 s_vec.iov_len=sizeof(*ovf_header);
1434 r_vec[0]=s_vec;
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);
1444 tf->failed();
1447 if( *p1 != __CP ) {
1448 kprintf("[!!] P1 mismatch ! %p instead of %p\n",
1449 *p1,__CP);
1450 tf->abort();
1453 if( *p2 != __CP ) {
1454 kprintf("[!!] P2 mismatch ! %p instead of %p\n",
1455 *p2,__CP);
1456 tf->abort();
1459 if( *p3 != __CP ) {
1460 kprintf("[!!] P3 mismatch ! %p instead of %p\n",
1461 *p3,__CP);
1462 tf->abort();
1465 if( *p4 != __CP ) {
1466 kprintf("[!!] P4 mismatch ! %p instead of %p\n",
1467 *p4,__CP);
1468 tf->abort();
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");
1476 tf->printf("OK\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]);
1483 tf->failed();
1486 tf->printf("[OVF TESTER]: Test passed\n");
1487 sys_exit(0);
1490 static void __stack_overflow_test(void *ctx)
1492 DECLARE_TEST_CONTEXT;
1493 int r,i;
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;
1500 iovec_t iov[2];
1501 ovf_header_t header=__header_ovf,i_header;
1502 ovf_data_t o_data;
1504 *p1=__CP;
1505 *p2=__CP;
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);
1512 if( *p1 != __CP ) {
1513 kprintf("[!!] P1 mismatch ! %p instead of %p\n",
1514 *p1,__CP);
1515 tf->abort();
1517 if( *p2 != __CP ) {
1518 kprintf("[!!] P2 mismatch ! %p instead of %p\n",
1519 *p2,__CP);
1520 tf->abort();
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");
1527 tf->abort();
1530 if( kernel_thread(__stack_overflow_client,ctx,NULL) ) {
1531 tf->printf(SERVER_THREAD"Can't create the overflow client !\n");
1532 tf->abort();
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);
1538 if( r < 0 ) {
1539 tf->printf("[OVF TEST]: Error wuring receiving a message ! %d\n",
1541 tf->abort();
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,
1545 msg_info.msg_len);
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));
1549 tf->failed();
1552 if( memcmp(&i_header,&__header_ovf,sizeof(i_header)) ) {
1553 tf->printf("[OVF TEST]: Insufficient message data !\n");
1554 tf->failed();
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,
1572 iov,2);
1573 if( r ) {
1574 tf->printf(SERVER_THREAD"[PRIO PORT] Error during reply to message %d ! r=%d\n",
1575 msg_info.msg_id,r);
1576 tf->abort();
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;
1586 int r;
1587 int i,j,k;
1588 port_msg_info_t msg_info;
1589 iovec_t snd_iovecs[MAX_IOVECS];
1590 const int __PRIO_STEP=4;
1591 int prio,parts;
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 !");
1602 tf->abort();
1605 for(i=0;i<__NUM_PRIO_THREADS;i++) {
1606 prio=PRIO_BASE-__PRIO_STEP*(i/__NGROUP_TASKS);
1607 pdata[i].tf=tf;
1608 pdata[i].priority=prio;
1609 pdata[i].runs=0;
1611 if( kernel_thread(__prio_thread,&pdata[i],&ptasks[i]) ) {
1612 tf->printf("Can't create a prio tester !");
1613 tf->abort();
1617 tf->printf(SERVER_THREAD"[PRIO PORT] Sleeping for a while ...\n");
1618 sleep(HZ/3);
1619 tf->printf(SERVER_THREAD"[PRIO PORT] Got woken up ! Testing ! (start priority=%d)\n",
1620 prio);
1622 /* OK, ready for tests. */
1623 parts=3;
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++) {
1627 ulong_t *watchline;
1628 ulong_t size;
1629 task_t *t;
1630 int idx;
1631 prio_data_t *_pd;
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",
1646 msg_info.msg_len);
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);
1653 tf->failed();
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) {
1659 t=ptasks[idx];
1660 _pd=&pdata[idx];
1661 break;
1665 if( !t ) {
1666 tf->printf(SERVER_THREAD"[PRIO PORT] Can't locate a client with PID=%d\n",
1667 msg_info.sender_pid);
1668 tf->abort();
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);
1675 tf->abort();
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",
1683 i,j,k);
1684 tf->abort();
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",
1696 parts);
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",
1699 msg_info.msg_id,r);
1700 if( r ) {
1701 tf->printf(SERVER_THREAD"[PRIO PORT] Error during reply to message %d ! r=%d\n",
1702 msg_info.msg_id,r);
1703 tf->abort();
1709 genport=ipc_get_port(current_task(),__prio_port);
1710 if( !genport ) {
1711 tf->printf(SERVER_THREAD"Can't resolve port !");
1712 tf->abort();
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);
1718 tf->abort();
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];
1729 int i;
1730 ulong_t flags;
1731 int r;
1732 port_msg_info_t msg_info;
1734 __server_pid=current_task()->pid;
1736 #ifdef CONFIG_SMP
1737 kthread_cpu_autodeploy=true;
1738 #endif
1740 __stack_overflow_test(ctx);
1741 sleep(HZ);
1742 __ipc_buffer_test(ctx);
1743 sleep(HZ);
1744 __process_events_test(ctx);
1745 sleep(HZ);
1746 __message_read_test(ctx);
1747 sleep(HZ);
1748 __prioritized_port_test(ctx);
1749 sleep(HZ);
1750 __vectored_messages_test(ctx);
1751 sleep(HZ);
1753 for( i=0;i<SERVER_NUM_PORTS;i++) {
1754 if( i != NON_BLOCKED_PORT_ID ) {
1755 flags=IPC_BLOCKED_ACCESS;
1756 } else {
1757 flags=0;
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",
1762 ports[i],i);
1763 tf->failed();
1764 goto exit_test;
1768 tctx->server_pid=current_task()->pid;
1769 tf->printf(SERVER_THREAD "%d ports created.\n", SERVER_NUM_PORTS );
1771 goto poll_tests;
1773 if( kernel_thread(__client_thread,ctx,NULL) ) {
1774 tf->printf(SERVER_THREAD "Can't launch client thread.\n",
1775 ports[i],i);
1776 goto abort_test;
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");
1787 if( r ) {
1788 tf->printf(SERVER_THREAD "Insufficient return value during 'sys_port_receive': %d\n",
1790 tf->failed();
1791 goto exit_test;
1792 } else {
1793 if( msg_info.msg_id != 0 ) {
1794 tf->printf(SERVER_THREAD "Insufficient message id: %d instead of 0\n",
1795 msg_info.msg_id);
1796 tf->failed();
1797 } else {
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",
1801 i );
1802 tf->failed();
1803 } else {
1804 tf->printf( SERVER_THREAD "Message N %d was successfuly transmitted.\n",
1805 i );
1806 tf->passed();
1808 } else {
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);
1811 tf->failed();
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);
1818 if( r ) {
1819 tf->printf(SERVER_THREAD "Insufficient return value during 'sys_port_reply': %d\n",
1821 tf->failed();
1822 goto exit_test;
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",
1830 BIG_MESSAGE_SIZE);
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);
1834 if( r ) {
1835 tf->printf(SERVER_THREAD "Insufficient return value during 'sys_port_receive': %d\n",
1837 tf->failed();
1838 goto exit_test;
1839 } else {
1840 kprintf( SERVER_THREAD "Big message received: %d bytes.\n",msg_info.msg_len );
1841 if( msg_info.msg_len == BIG_MESSAGE_SIZE ) {
1842 ulong_t offt;
1844 if( !__verify_big_message(__big_message_server_buf,&offt) ) {
1845 tf->printf( SERVER_THREAD "Big message mismatch at offset: %d\n",
1846 offt);
1847 tf->failed();
1848 } else {
1849 tf->printf( SERVER_THREAD "Big message was successfully transmitted.\n" );
1850 tf->passed();
1852 } else {
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);
1855 tf->failed();
1858 r=sys_port_reply(BIG_MESSAGE_PORT_ID,msg_info.msg_id,
1859 (ulong_t)__big_message_pattern,BIG_MESSAGE_SIZE);
1860 if( r ) {
1861 tf->printf(SERVER_THREAD "Insufficient return value during 'sys_port_reply': %d\n",
1863 tf->failed();
1864 goto exit_test;
1867 /*****************************************************************
1868 * Testing message delivery in non-blocking mode (small messages).
1869 ****************************************************************/
1870 sleep(HZ/2);
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);
1877 if( r ) {
1878 tf->printf(SERVER_THREAD "Insufficient return value during 'sys_port_receive': %d\n",
1880 tf->failed();
1881 goto exit_test;
1882 } else {
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 );
1886 tf->failed();
1887 } else {
1888 tf->printf( SERVER_THREAD "Non-blocking Message N %d successfully received.\n",i );
1889 tf->passed();
1891 } else {
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);
1894 tf->failed();
1899 poll_tests:
1900 /*****************************************************************
1901 * Testing port polling.
1902 ****************************************************************/
1903 tf->printf(SERVER_THREAD "Testing IPC port polling.\n" );
1904 __ipc_poll_test(tctx,ports);
1906 goto exit_test;
1907 abort_test:
1908 tf->abort();
1909 exit_test:
1910 tctx->tests_finished=true;
1911 sys_exit(0);
1914 static void __initialize_big_pattern(void)
1916 int i;
1917 int *p=(int *)__big_message_pattern;
1919 for(i=0;i<BIG_MESSAGE_SIZE/sizeof(int);i++) {
1920 *p++=i;
1924 static bool __ipc_tests_initialize(void **ctx)
1926 ipc_test_ctx_t *tctx=memalloc(sizeof(*tctx));
1928 if( tctx ) {
1929 memset(tctx,0,sizeof(*tctx));
1930 tctx->tests_finished=false;
1931 tctx->server_pid=10000;
1932 *ctx=tctx;
1933 __initialize_big_pattern();
1934 return true;
1936 return false;
1939 void __ipc_tests_run(test_framework_t *f,void *ctx)
1941 ipc_test_ctx_t *tctx=(ipc_test_ctx_t*)ctx;
1943 tctx->tf=f;
1945 if( kernel_thread(__server_thread,tctx,NULL) ) {
1946 f->printf( "Can't create server thread !" );
1947 f->abort();
1948 } else {
1949 f->test_completion_loop(TEST_ID,&tctx->tests_finished);
1953 void __ipc_tests_deinitialize(void *ctx)
1955 memfree(ctx);
1958 testcase_t ipc_testcase={
1959 .id=TEST_ID,
1960 .initialize=__ipc_tests_initialize,
1961 .deinitialize=__ipc_tests_deinitialize,
1962 .run=__ipc_tests_run,
1963 .autodeploy_threads=true,