Merge remote-tracking branch 'angela/13_eng_dev-ramsey-3.00.a' into dev-3.00
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / samples / hlos / rpmsg-rpc-stress / usr / tests_rpc_stress.c
1 /*
2  * Copyright (c) 2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  * tests_rpc_stress.c
34  *
35  * Stress tests for rpmsg-rpc.
36  *
37  */
39 #include <sys/select.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <pthread.h>
49 #include <time.h>
50 #include <stdbool.h>
51 #include <semaphore.h>
52 #include <dlfcn.h>
54 #include "ti/ipc/rpmsg_rpc.h"
55 #include "ti/shmemallocator/SharedMemoryAllocatorUsr.h"
58 typedef struct {
59     int a;
60     int b;
61     int c;
62 } fxn_add3_args;
64 typedef struct {
65     int num;
66     int *array;
67 } fxn_addx_args;
69 /* Note: Set bit 31 to indicate static function indicies:
70  * This function order will be hardcoded on BIOS side, hence preconfigured:
71  */
72 enum {
73     FXN_IDX_FXNTRIPLE = 1,
74     FXN_IDX_FXNADD,
75     FXN_IDX_FXNADD3,
76     FXN_IDX_FXNADDX,
77     FXN_IDX_MAX
78 };
80 #define NUM_ITERATIONS               20
82 static int test_status = 0;
83 static bool runTest = true;
84 static int testFunc = FXN_IDX_FXNTRIPLE;
86 int exec_cmd(int fd, char *msg, size_t len, char *reply_msg, int *reply_len)
87 {
88     int ret = 0;
90     ret = write(fd, msg, len);
91     if (ret < 0) {
92         perror("Can't write to rpc_example instance");
93         return -1;
94     }
96     /* Now, await normal function result from rpc_example service:
97      * Note: len should be max length of response expected.
98      */
99     ret = read(fd, reply_msg, len);
100     if (ret < 0) {
101         perror("Can't read from rpc_example instance");
102         return -1;
103     }
104     else {
105         *reply_len = ret;
106     }
107     return 0;
110 int send_cmd(int fd, char *msg, int len)
112     int ret = 0;
114     ret = write(fd, msg, len);
115     if (ret < 0) {
116          perror("Can't write to rpc_example instance\n");
117          return -1;
118     }
120     return(0);
123 int recv_cmd(int fd, int len, char *reply_msg, int *reply_len)
125     int ret = 0;
127     /* Now, await normal function result from rpc_example service: */
128     // Note: len should be max length of response expected.
129     ret = read(fd, reply_msg, len);
130     if (ret < 0) {
131          perror("Can't read from rpc_example instance\n");
132          return -1;
133     }
134     else {
135           *reply_len = ret;
136     }
137     return(0);
140 typedef struct test_exec_args {
141     int fd;
142     int start_num;
143     int test_num;
144     sem_t * sem;
145     int thread_num;
146     int func_idx;
147 } test_exec_args;
149 static pthread_t * clientThreads = NULL;
150 static sem_t * clientSems = NULL;
151 static char **clientPackets = NULL;
152 static bool *readMsg = NULL;
153 static int *fds;
155 void *sharedmemalloc_lib = NULL;
156 int (*sharedmem_alloc)(int size, shm_buf *buf);
157 int (*sharedmem_free)(shm_buf *buf);
159 int deinit_sharedmem_funcs(void)
161     int ret = 0;
163     if (sharedmemalloc_lib)
164         dlclose(sharedmemalloc_lib);
165     sharedmemalloc_lib = NULL;
167     return ret;
170 int init_sharedmem_funcs()
172     int ret = 0;
174     if (sharedmemalloc_lib == NULL) {
175         sharedmemalloc_lib = dlopen("libsharedmemallocator.so",
176                                     RTLD_NOW | RTLD_GLOBAL);
177         if (sharedmemalloc_lib == NULL) {
178             perror("init_sharedmem_funcs: Error opening shared lib");
179             ret = -1;
180         }
181         else {
182             sharedmem_alloc = dlsym(sharedmemalloc_lib, "SHM_alloc");
183             if (sharedmem_alloc == NULL) {
184                 perror("init_sharedmem_funcs: Error getting shared lib sym");
185                 ret = -1;
186             }
187             else {
188                 sharedmem_free = dlsym(sharedmemalloc_lib, "SHM_release");
189                 if (sharedmem_free == NULL) {
190                     perror("init_sharedmem_funcs: Error getting shared lib sym");
191                     ret = -1;
192                 }
193             }
194         }
195     }
196     if (ret < 0) {
197         deinit_sharedmem_funcs();
198     }
199     return ret;
202 void * test_exec_call(void * arg)
204     int               i;
205     int               packet_len;
206     int               reply_len;
207     char              packet_buf[512] = {0};
208     char              return_buf[512] = {0};
209     test_exec_args    *args = (test_exec_args *) arg;
210     int               fd = args->fd;
211     struct rppc_function *function;
212     struct rppc_function_return *returned;
213     shm_buf           buf, buf2;
214     void              *ptr = NULL, *ptr2 = NULL;
216     for (i = args->start_num; i < args->start_num + NUM_ITERATIONS; i++) {
217         function = (struct rppc_function *)packet_buf;
218         function->fxn_id = args->func_idx;
219         switch (function->fxn_id) {
220             case FXN_IDX_FXNTRIPLE:
221                 function->num_params = 1;
222                 function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
223                 function->params[0].size = sizeof(int);
224                 function->params[0].data = i;
225                 function->num_translations = 0;
226                 break;
227             case FXN_IDX_FXNADD:
228                 function->num_params = 2;
229                 function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
230                 function->params[0].size = sizeof(int);
231                 function->params[0].data = i;
232                 function->params[1].type = RPPC_PARAM_TYPE_ATOMIC;
233                 function->params[1].size = sizeof(int);
234                 function->params[1].data = i+1;
235                 function->num_translations = 0;
236                 break;
237             case FXN_IDX_FXNADD3:
238                 if (init_sharedmem_funcs() < 0)
239                     test_status = -1;
240                 else {
241                     if ((*sharedmem_alloc)(sizeof(fxn_add3_args), &buf) < 0) {
242                         test_status = -1;
243                     }
244                     else {
245                         ptr = (fxn_add3_args *)(buf.vir_addr);
246                         ((fxn_add3_args *)ptr)->a = i;
247                         ((fxn_add3_args *)ptr)->b = i+1;
248                         ((fxn_add3_args *)ptr)->c = i+2;
249                         function->num_params = 1;
250                         function->params[0].type = RPPC_PARAM_TYPE_PTR;
251                         function->params[0].size = sizeof(fxn_add3_args);
252                         function->params[0].data = (size_t)ptr;
253                         function->params[0].base = (size_t)ptr;
254                         function->num_translations = 0;
255                     }
256                 }
257                 break;
258             case FXN_IDX_FXNADDX:
259                 if (init_sharedmem_funcs() < 0)
260                     test_status = -1;
261                 else {
262                     if ((*sharedmem_alloc)(sizeof(fxn_addx_args), &buf) < 0) {
263                         test_status = -1;
264                     }
265                     else if ((*sharedmem_alloc)(sizeof(int) * 3, &buf2) < 0) {
266                         test_status = -1;
267                     }
268                     else {
269                         ptr = (fxn_addx_args *)(buf.vir_addr);
270                         ptr2 = (int *)(buf2.vir_addr);
271                         ((fxn_addx_args *)ptr)->num = 3;
272                         ((fxn_addx_args *)ptr)->array = ptr2;
273                         ((int *)ptr2)[0] = i;
274                         ((int *)ptr2)[1] = i+1;
275                         ((int *)ptr2)[2] = i+2;
276                         function->num_params = 1;
277                         function->params[0].type = RPPC_PARAM_TYPE_PTR;
278                         function->params[0].size = sizeof(fxn_addx_args);
279                         function->params[0].data = (size_t)ptr;
280                         function->params[0].base = (size_t)ptr;
281                         function->num_translations = 1;
282                         function->translations[0].index = 0;
283                         function->translations[0].offset = (int)&(((fxn_addx_args *)ptr)->array) - (int)ptr;
284                         function->translations[0].base = ((fxn_addx_args *)ptr)->array;
285                     }
286                 }
287                 break;
288         }
290         if (test_status == -1)
291             break;
293         returned = (struct rppc_function_return *)return_buf;
295         /* Exec command: */
296         packet_len = sizeof(struct rppc_function) +\
297                      (function->num_translations * \
298                       sizeof(struct rppc_param_translation));
299         if (args->test_num == 1)  {
300             if (exec_cmd(fd, (char *)packet_buf, packet_len,
301                          (char *)return_buf, &reply_len)) {
302                 test_status = -1;
303                 break;
304             }
305         }
306         else if (args->test_num == 2 || args->test_num == 3) {
307             if (send_cmd(fd, (char *)packet_buf, packet_len)) {
308                 test_status = -1;
309                 break;
310             }
311             sem_wait(&clientSems[args->thread_num]);
312             memcpy(return_buf, clientPackets[args->thread_num], 512);
313             readMsg[args->thread_num] = true;
314         }
315         switch (function->fxn_id) {
316             case FXN_IDX_FXNTRIPLE:
317                 if (i * 3 != returned->status) {
318                     printf ("rpc_stress: "
319                             "called fxnTriple(%d), result = %d, expected %d\n",
320                             function->params[0].data, returned->status, i * 3);
321                     test_status = -1;
322                 }
323                 else {
324                     printf ("rpc_stress: called fxnTriple(%d), result = %d\n",
325                             function->params[0].data, returned->status);
326                 }
327                 break;
328             case FXN_IDX_FXNADD:
329                 if (i + (i+1) != returned->status) {
330                     printf ("rpc_stress: "
331                             "called fxnAdd(%d,%d), result = %d, expected %d\n",
332                             function->params[0].data, function->params[1].data,
333                             returned->status, i + (i+1));
334                     test_status = -1;
335                 }
336                 else {
337                     printf ("rpc_stress: called fxnAdd(%d,%d), result = %d\n",
338                             function->params[0].data, function->params[1].data,
339                             returned->status);
340                 }
341                 break;
342             case FXN_IDX_FXNADD3:
343                 if (i + (i+1) + (i+2) != returned->status) {
344                     printf ("rpc_stress: "
345                             "called fxnAdd3(%d,%d,%d), result = %d, expected %d\n",
346                             ((fxn_add3_args *)ptr)->a,
347                             ((fxn_add3_args *)ptr)->b,
348                             ((fxn_add3_args *)ptr)->c, returned->status,
349                             i + (i+1) + (i+2));
350                     test_status = -1;
351                 }
352                 else {
353                     printf ("rpc_stress: called fxnAdd3(%d,%d,%d), result = %d\n",
354                             ((fxn_add3_args *)ptr)->a,
355                             ((fxn_add3_args *)ptr)->b,
356                             ((fxn_add3_args *)ptr)->c, returned->status);
357                 }
358                 (*sharedmem_free)(&buf);
359                 break;
360             case FXN_IDX_FXNADDX:
361                 if (i + (i+1) + (i+2) != returned->status) {
362                     printf ("rpc_stress: "
363                             "called fxnAddX(%d,%d,%d), result = %d, expected %d\n",
364                             ((int *)ptr2)[0], ((int *)ptr2)[1],
365                             ((int *)ptr2)[2], returned->status,
366                             i + (i+1) + (i+2));
367                     test_status = -1;
368                 }
369                 else {
370                     /* Check that reverse address translation is working */
371                     if (((fxn_addx_args *)ptr)->array != ptr2) {
372                         printf("rpc_stress: reverse addr translation failed, "
373                                "addr = 0x%x expected 0x%x\n",
374                                ((fxn_addx_args *)ptr)->array, ptr2);
375                         test_status = -1;
376                     }
377                     printf ("rpc_stress: called fxnAddX(%d,%d,%d), result = %d\n",
378                             ((int *)ptr2)[0], ((int *)ptr2)[1],
379                             ((int *)ptr2)[2], returned->status);
380                 }
381                 (*sharedmem_free)(&buf);
382                 (*sharedmem_free)(&buf2);
383                 break;
384         }
385         if (test_status == -1) {
386             break;
387         }
388     }
390     return NULL;
393 void * test_select_thread (void * arg)
395     int fd;
396     int reply_len;
397     char return_buf[512] = {0};
398     struct rppc_function_return *rtn_packet =
399                                (struct rppc_function_return *)return_buf;
400     int n, i;
401     fd_set rfd;
402     int max_fd = -1;
404     while (runTest) {
405         FD_ZERO(&rfd);
406         for (i = 0; i < (int)arg; i++) {
407             FD_SET(fds[i], &rfd);
408             max_fd = max(max_fd, fds[i]);
409         }
410         n = select(1 + max_fd, &rfd, NULL, NULL, NULL);
411         switch (n) {
412             case -1:
413                 perror("select");
414                 return NULL;
415             default:
416                 for (i = 0; i < (int)arg; i++) {
417                     if (FD_ISSET(fds[i], &rfd)) {
418                         fd = fds[i];
419                         break;
420                     }
421                 }
422                 break;
423         }
424         if (recv_cmd(fd, 512, (char *)rtn_packet, &reply_len)) {
425             test_status = -1;
426             printf("test_select_thread: recv_cmd failed!");
427             break;
428         }
430         if (runTest == false)
431             break;
433         /* Decode reply: */
434         while (readMsg[i] == false) {
435             sleep(1);
436         }
437         memcpy(clientPackets[i], rtn_packet, 512);
438         readMsg[i] = false;
439         sem_post(&clientSems[i]);
440     }
441     return NULL;
444 void * test_read_thread (void * arg)
446     int fd = (int)arg;
447     int reply_len;
448     char  return_buf[512] = {0};
449     struct rppc_function_return *rtn_packet =
450                                (struct rppc_function_return *)return_buf;
451     int               packet_id;
453     while (runTest) {
454         if (recv_cmd(fd, 512, (char *)rtn_packet, &reply_len)) {
455             test_status = -1;
456             printf("test_read_tread: recv_cmd failed!");
457             break;
458         }
460         if (runTest == false)
461             break;
463         /* Decode reply: */
464         switch (testFunc) {
465             case FXN_IDX_FXNTRIPLE:
466                 packet_id = ((rtn_packet->status / 3) - 1) / NUM_ITERATIONS;
467                 break;
468             case FXN_IDX_FXNADD:
469                 packet_id = (((rtn_packet->status - 1) / 2) - 1) / NUM_ITERATIONS;
470                 break;
471             case FXN_IDX_FXNADD3:
472                 packet_id = (((rtn_packet->status - 3) / 3) - 1) / NUM_ITERATIONS;
473                 break;
474             case FXN_IDX_FXNADDX:
475                 packet_id = (((rtn_packet->status - 3) / 3) - 1) / NUM_ITERATIONS;
476                 break;
477         }
478         while (readMsg[packet_id] == false) {
479             sleep(1);
480         }
481         memcpy(clientPackets[packet_id], rtn_packet, 512);
482         readMsg[packet_id] = false;
483         sem_post(&clientSems[packet_id]);
484     }
485     return NULL;
488 int test_rpc_stress_select(int core_id, int num_comps, int func_idx)
490     int ret = 0;
491     int i = 0, j = 0;
492     struct rppc_create_instance connreq;
493     struct rppc_function *function;
494     pthread_t select_thread;
495     int               packet_len;
496     char              packet_buf[512] = {0};
497     test_exec_args args[num_comps];
499     fds = malloc (sizeof(int) * num_comps);
500     if (!fds) {
501         return -1;
502     }
503     for (i = 0; i < num_comps; i++) {
504         /* Connect to the rpc_example ServiceMgr on the specified core: */
505         if (core_id == 0) {
506             fds[i] = open("/dev/rpmsg-omx0", O_RDWR);
507             if (fds[i] < 0) {
508                 perror("Can't open OMX device");
509                 ret = -1;
510                 break;
511             }
512             strcpy(connreq.name, "rpmsg-omx0");
513         }
514         else if (core_id == 1) {
515             fds[i] = open("/dev/rpc_example", O_RDWR);
516             if (fds[i] < 0) {
517                 perror("Can't open rpc_example device");
518                 break;
519             }
520             strcpy(connreq.name, "rpc_example");
521         }
522         else if (core_id == 2) {
523             fds[i] = open("/dev/rpmsg-omx2", O_RDWR);
524             if (fds[i] < 0) {
525                 perror("Can't open OMX device");
526                 break;
527             }
528             strcpy(connreq.name, "rpmsg-omx2");
529         }
530         /* Create an rpc_example server instance, and rebind its address to this
531         * file descriptor.
532         */
533         ret = ioctl(fds[i], RPPC_IOC_CREATE, &connreq);
534         if (ret < 0) {
535             perror("Can't connect to rpc_example instance");
536             close(fds[i]);
537             break;
538         }
539         printf("rpc_sample: Connected to %s\n", connreq.name);
540     }
541     if (i != num_comps) {
542         /* cleanup */
543         for (j = 0; j < i; j++) {
544             ret = close(fds[j]);
545             if (ret < 0) {
546                 perror("Can't close rpc_example fd ??");
547             }
548         }
549         free(fds);
550         return -1;
551     }
553     clientSems = malloc(sizeof(sem_t) * num_comps);
554     if (!clientSems) {
555         free(clientThreads);
556         for (i = 0; i < num_comps; i++) {
557             ret = close(fds[i]);
558             if (ret < 0) {
559                 perror("Can't close rpc_example fd ??");
560             }
561         }
562         return -1;
563     }
565     readMsg = malloc(sizeof(bool) * num_comps);
566     if (!readMsg) {
567         free(clientSems);
568         free(clientThreads);
569         for (i = 0; i < num_comps; i++) {
570             ret = close(fds[i]);
571             if (ret < 0) {
572                 perror("Can't close rpc_example fd ??");
573             }
574         }
575         return -1;
576     }
578     clientPackets = malloc(sizeof(char *) * num_comps);
579     if (!clientPackets) {
580         free(readMsg);
581         free(clientSems);
582         free(clientThreads);
583         for (i = 0; i < num_comps; i++) {
584             ret = close(fds[i]);
585             if (ret < 0) {
586                 perror("Can't close rpc_example fd ??");
587             }
588         }
589         return -1;
590     }
592     for (i = 0; i < num_comps; i++) {
593         clientPackets[i] = malloc(512 * sizeof(char));
594         if (!clientPackets[i]) {
595             for (j = 0; j < i; j++) {
596                 free(clientPackets[j]);
597             }
598             free(clientPackets);
599             free(readMsg);
600             free(clientSems);
601             free(clientThreads);
602             for (i = 0; i < num_comps; i++) {
603                 ret = close(fds[i]);
604                 if (ret < 0) {
605                     perror("Can't close rpc_example fd ??");
606                 }
607             }
608             return -1;
609         }
610     }
612     ret = pthread_create(&select_thread, NULL, test_select_thread,
613                          (void *)num_comps);
614     if (ret < 0) {
615         perror("Can't create thread");
616         ret = -1;
617     }
619     clientThreads = malloc(sizeof(pthread_t) * num_comps);
620     if (!clientThreads) {
621         for (i = 0; i < num_comps; i++) {
622             ret = close(fds[i]);
623             if (ret < 0) {
624                 perror("Can't close rpc_example fd ??");
625             }
626         }
627         free(fds);
628         return -1;
629     }
631     for ( i = 0; i < num_comps; i++) {
632         ret = sem_init(&clientSems[i], 0, 0);
633         args[i].fd = fds[i];
634         args[i].start_num = 1;
635         args[i].test_num = 3;
636         args[i].sem = &clientSems[i];
637         args[i].thread_num = i;
638         args[i].func_idx = func_idx;
639         readMsg[i] = true;
640         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
641                              (void *)&args[i]);
642         if (ret < 0) {
643             perror("Can't create thread");
644             ret = -1;
645             break;
646         }
647         printf("Created thread %d\n", i);
648     }
650     for (j = 0; j < i; j++) {
651         printf("Join thread %d\n", j);
652         pthread_join(clientThreads[j], NULL);
653     }
655     free(clientThreads);
657     function = (struct rppc_function *)packet_buf;
658     function->fxn_id = FXN_IDX_FXNTRIPLE;
659     function->num_params = 1;
660     function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
661     function->params[0].size = sizeof(int);
662     function->params[0].data = i;
663     function->num_translations = 0;
665     /* Exec command: */
666     packet_len = sizeof(struct rppc_function) +\
667                  (function->num_translations *\
668                   sizeof(struct rppc_param_translation));
670     runTest = false;
671     if (send_cmd(fds[0], (char *)packet_buf, packet_len)) {
672         test_status = -1;
673     }
675     pthread_join(select_thread, NULL);
677     for (i = 0; i < num_comps; i++) {
678         free(clientPackets[i]);
679     }
680     free(clientPackets);
681     free(readMsg);
682     free(clientSems);
684     for (i = 0; i < num_comps; i++) {
685         /* Terminate connection and destroy rpc_example instance */
686         ret = close(fds[i]);
687         if (ret < 0) {
688             perror("Can't close rpc_example fd ??");
689             ret = -1;
690         }
691         printf("rpc_sample: Closed connection to %s!\n", connreq.name);
692     }
694     free(fds);
695     return ret;
698 int test_rpc_stress_multi_threads(int core_id, int num_threads, int func_idx)
700     int ret = 0;
701     int i = 0, j = 0;
702     int fd;
703     int packet_len;
704     char packet_buf[512] = {0};
705     pthread_t read_thread;
706     struct rppc_create_instance connreq;
707     struct rppc_function *function;
708     test_exec_args args[num_threads];
710     /* Connect to the rpc_example ServiceMgr on the specified core: */
711     if (core_id == 0) {
712         fd = open("/dev/rpmsg-omx0", O_RDWR);
713         if (fd < 0) {
714             perror("Can't open OMX device");
715             return -1;
716         }
717             strcpy(connreq.name, "rpmsg-omx0");
719     }
720     else if (core_id == 1) {
721         fd = open("/dev/rpc_example", O_RDWR);
722         if (fd < 0) {
723             perror("Can't open rpc_example device");
724             return -1;
725         }
726             strcpy(connreq.name, "rpc_example");
727     }
728     else if (core_id == 2) {
729         fd = open("/dev/rpmsg-omx2", O_RDWR);
730         if (fd < 0) {
731             perror("Can't open OMX device");
732             return -1;
733         }
734             strcpy(connreq.name, "rpmsg-omx2");
735     }
736     /* Create an rpc_example server instance, and rebind its address to this
737     * file descriptor.
738     */
739     ret = ioctl(fd, RPPC_IOC_CREATE, &connreq);
740     if (ret < 0) {
741         perror("Can't connect to rpc_example instance");
742         close(fd);
743         return -1;
744     }
745     printf("rpc_sample: Connected to %s\n", connreq.name);
747     clientThreads = malloc(sizeof(pthread_t) * num_threads);
748     if (!clientThreads) {
749         ret = close(fd);
750         return -1;
751     }
752     clientSems = malloc(sizeof(sem_t) * num_threads);
753     if (!clientSems) {
754         free(clientThreads);
755         ret = close(fd);
756         return -1;
757     }
759     readMsg = malloc(sizeof(bool) * num_threads);
760     if (!readMsg) {
761         free(clientSems);
762         free(clientThreads);
763         ret = close(fd);
764         return -1;
765     }
767     clientPackets = malloc(sizeof(char *) * num_threads);
768     if (!clientPackets) {
769         free(readMsg);
770         free(clientSems);
771         free(clientThreads);
772         ret = close(fd);
773         return -1;
774     }
776     for (i = 0; i < num_threads; i++) {
777         clientPackets[i] = malloc(512 * sizeof(char));
778         if (!clientPackets[i]) {
779             for (j = 0; j < i; j++) {
780                 free(clientPackets[j]);
781             }
782             free(clientPackets);
783             free(readMsg);
784             free(clientSems);
785             free(clientThreads);
786             close(fd);
787             return -1;
788         }
789     }
791     ret = pthread_create(&read_thread, NULL, test_read_thread, (void *)fd);
792     if (ret < 0) {
793         perror("Can't create thread");
794         for (i = 0; i < num_threads; i++) {
795             free(clientPackets[i]);
796         }
797         free(clientPackets);
798         free(readMsg);
799         free(clientSems);
800         free(clientThreads);
801         close(fd);
802         return -1;
803     }
805     for ( i = 0; i < num_threads; i++) {
806         ret = sem_init(&clientSems[i], 0, 0);
807         args[i].fd = fd;
808         args[i].start_num = (i * NUM_ITERATIONS) + 1;
809         args[i].test_num = 2;
810         args[i].sem = &clientSems[i];
811         args[i].thread_num = i;
812         args[i].func_idx = func_idx;
813         readMsg[i] = true;
814         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
815                              (void *)&args[i]);
816         if (ret < 0) {
817             perror("Can't create thread");
818             ret = -1;
819             break;
820         }
821         printf("Created thread %d\n", i);
822     }
824     for (j = 0; j < i; j++) {
825         printf("Join thread %d\n", j);
826         pthread_join(clientThreads[j], NULL);
827         sem_destroy(&clientSems[j]);
828     }
830     function = (struct rppc_function *)packet_buf;
831     function->fxn_id = FXN_IDX_FXNTRIPLE;
832     function->num_params = 1;
833     function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
834     function->params[0].size = sizeof(int);
835     function->params[0].data = i;
836     function->num_translations = 0;
838     /* Exec command: */
839     packet_len = sizeof(struct rppc_function) +\
840                  (function->num_translations *\
841                   sizeof(struct rppc_param_translation));
843     runTest = false;
844     if (send_cmd(fd, (char *)packet_buf, packet_len)) {
845         test_status = -1;
846     }
848     pthread_join(read_thread, NULL);
850     for (i = 0; i < num_threads; i++) {
851         free(clientPackets[i]);
852     }
853     free(clientPackets);
854     free(readMsg);
855     free(clientSems);
856     free(clientThreads);
858     /* Terminate connection and destroy rpc_example instance */
859     ret = close(fd);
860     if (ret < 0) {
861         perror("Can't close rpc_example fd ??");
862         ret = -1;
863     }
864     printf("rpc_sample: Closed connection to %s!\n", connreq.name);
866     return ret;
869 int test_rpc_stress_multi_srvmgr(int core_id, int num_comps, int func_idx)
871     int ret = 0;
872     int i = 0, j = 0;
873     int fd[num_comps];
874     struct rppc_create_instance connreq;
875     test_exec_args args[num_comps];
877     for (i = 0; i < num_comps; i++) {
878         /* Connect to the rpc_example ServiceMgr on the specified core: */
879         if (core_id == 0) {
880             fd[i] = open("/dev/rpmsg-omx0", O_RDWR);
881             if (fd[i] < 0) {
882                 perror("Can't open OMX device");
883                 ret = -1;
884                 break;
885             }
886             strcpy(connreq.name, "rpmsg-omx0");
887         }
888         else if (core_id == 1) {
889             fd[i] = open("/dev/rpc_example", O_RDWR);
890             if (fd[i] < 0) {
891                 perror("Can't open rpc_example device");
892                 ret = -1;
893                 break;
894             }
895             strcpy(connreq.name, "rpc_example");
896         }
897         else if (core_id == 2) {
898             fd[i] = open("/dev/rpmsg-omx2", O_RDWR);
899             if (fd[i] < 0) {
900                 perror("Can't open OMX device");
901                 ret = -1;
902                 break;
903             }
904             strcpy(connreq.name, "rpmsg-omx2");
905         }
906         /* Create an rpc_example server instance, and rebind its address to this
907         * file descriptor.
908         */
909         ret = ioctl(fd[i], RPPC_IOC_CREATE, &connreq);
910         if (ret < 0) {
911             perror("Can't connect to rpc_example instance");
912             close(fd[i]);
913             break;
914         }
915         printf("rpc_sample: Connected to %s\n", connreq.name);
916     }
917     if (i != num_comps) {
918         /* cleanup */
919         for (j = 0; j < i; j++) {
920             ret = close(fd[j]);
921             if (ret < 0) {
922                 perror("Can't close rpc_example fd ??");
923             }
924         }
925         return -1;
926     }
928     clientThreads = malloc(sizeof(pthread_t) * num_comps);
929     if (!clientThreads) {
930         for (i = 0; i < num_comps; i++) {
931             ret = close(fd[i]);
932             if (ret < 0) {
933                 perror("Can't close rpc_example fd ??");
934             }
935         }
936         return -1;
937     }
939     for ( i = 0; i < num_comps; i++) {
940         args[i].fd = fd[i];
941         args[i].start_num = 1;
942         args[i].test_num = 1;
943         args[i].sem = NULL;
944         args[i].thread_num = i;
945         args[i].func_idx = func_idx;
946         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
947                              (void *)&args[i]);
948         if (ret < 0) {
949             perror("Can't create thread");
950             ret = -1;
951             break;
952         }
953         printf("Created thread %d\n", i);
954     }
956     for (j = 0; j < i; j++) {
957         printf("Join thread %d\n", j);
958         pthread_join(clientThreads[j], NULL);
959     }
961     free(clientThreads);
963     for (i = 0; i < num_comps; i++) {
964         /* Terminate connection and destroy rpc_example instance */
965         ret = close(fd[i]);
966         if (ret < 0) {
967             perror("Can't close rpc_example fd ??");
968             ret = -1;
969         }
970         printf("rpc_sample: Closed connection to %s!\n", connreq.name);
971     }
973     return ret;
976 int main(int argc, char *argv[])
978     int ret;
979     int test_id = -1;
980     int core_id = 0;
981     int num_comps = 1;
982     int num_threads = 1;
983     int func_idx = 1;
984     int c;
986     while (1)
987     {
988         c = getopt (argc, argv, "t:c:x:l:f:");
989         if (c == -1)
990             break;
992         switch (c)
993         {
994         case 't':
995             test_id = atoi(optarg);
996             break;
997         case 'c':
998             core_id = atoi(optarg);
999             break;
1000         case 'x':
1001             num_comps = atoi(optarg);
1002             break;
1003         case 'l':
1004             num_threads = atoi(optarg);
1005             break;
1006         case 'f':
1007             func_idx = atoi(optarg);
1008             break;
1009         default:
1010             printf ("Unrecognized argument\n");
1011         }
1012     }
1014     if (test_id < 0 || test_id > 3) {
1015         printf("Invalid test id\n");
1016         return 1;
1017     }
1019     if (func_idx < FXN_IDX_FXNTRIPLE || func_idx >= FXN_IDX_MAX) {
1020         printf("Invalid function index\n");
1021         return 1;
1022     }
1023     testFunc = func_idx;
1025     switch (test_id) {
1026         case 1:
1027             /* multiple threads each with an RPMSG-RPC ServiceMgr instance */
1028             if (core_id < 0 || core_id > 2) {
1029                 printf("Invalid core id\n");
1030                 return 1;
1031             }
1032             if (num_comps < 0) {
1033                 printf("Invalid num comps id\n");
1034                 return 1;
1035             }
1036             ret = test_rpc_stress_multi_srvmgr(core_id, num_comps, func_idx);
1037             break;
1038         case 2:
1039             /* Multiple threads, 1 RPMSG-RPC ServiceMgr instances */
1040             if (core_id < 0 || core_id > 2) {
1041                 printf("Invalid core id\n");
1042                 return 1;
1043             }
1044             if (num_threads < 0) {
1045                 printf("Invalid num threads\n");
1046                 return 1;
1047             }
1048             ret = test_rpc_stress_multi_threads(core_id, num_threads, func_idx);
1049             break;
1050         case 3:
1051             /* 1 thread using multiple RPMSG-RPC ServiceMgr instances */
1052             if (core_id < 0 || core_id > 2) {
1053                 printf("Invalid core id\n");
1054                 return 1;
1055             }
1056             if (num_comps < 0) {
1057                 printf("Invalid num comps id\n");
1058                 return 1;
1059             }
1060             ret = test_rpc_stress_select(core_id, num_comps, func_idx);
1061             break;
1062         default:
1063             break;
1064     }
1066     if (ret < 0 || test_status < 0) {
1067         printf ("TEST STATUS: FAILED.\n");
1068     }
1069     else {
1070         printf ("TEST STATUS: PASSED.\n");
1071     }
1072     return 0;