]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/ipc3x_dev/ti/syslink/samples/hlos/rpmsg-rpc-stress/usr/tests_rpc_stress.c
98dbd332db3e402ae36191a654d81d86f7839018
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / samples / hlos / rpmsg-rpc-stress / usr / tests_rpc_stress.c
1 /*
2  * Copyright (c) 2013-2015, 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_FXNCOMPUTE,
78     FXN_IDX_FXNFAULT,
79     FXN_IDX_MAX
80 };
82 #define NUM_ITERATIONS               20
84 static int test_status = 0;
85 static bool runTest = true;
86 static int testFunc = FXN_IDX_FXNTRIPLE;
88 int exec_cmd(int fd, char *msg, size_t len, char *reply_msg, int *reply_len)
89 {
90     int ret = 0;
92     ret = write(fd, msg, len);
93     if (ret < 0) {
94         perror("Can't write to rpc_example instance");
95         return -1;
96     }
98     /* Now, await normal function result from rpc_example service:
99      * Note: len should be max length of response expected.
100      */
101     ret = read(fd, reply_msg, len);
102     if (ret < 0) {
103         perror("Can't read from rpc_example instance");
104         return -1;
105     }
106     else {
107         *reply_len = ret;
108     }
109     return 0;
112 int send_cmd(int fd, char *msg, int len)
114     int ret = 0;
116     ret = write(fd, msg, len);
117     if (ret < 0) {
118          perror("Can't write to rpc_example instance\n");
119          return -1;
120     }
122     return(0);
125 int recv_cmd(int fd, int len, char *reply_msg, int *reply_len)
127     int ret = 0;
129     /* Now, await normal function result from rpc_example service: */
130     // Note: len should be max length of response expected.
131     ret = read(fd, reply_msg, len);
132     if (ret < 0) {
133          perror("Can't read from rpc_example instance\n");
134          return -1;
135     }
136     else {
137           *reply_len = ret;
138     }
139     return(0);
142 typedef struct test_exec_args {
143     int fd;
144     int start_num;
145     int test_num;
146     sem_t * sem;
147     int thread_num;
148     int func_idx;
149     int sub_test;
150 } test_exec_args;
152 static pthread_t * clientThreads = NULL;
153 static sem_t * clientSems = NULL;
154 static char **clientPackets = NULL;
155 static bool *readMsg = NULL;
156 static int *fds;
158 void *sharedmemalloc_lib = NULL;
159 int (*sharedmem_alloc)(int size, shm_buf *buf);
160 int (*sharedmem_free)(shm_buf *buf);
162 int deinit_sharedmem_funcs(void)
164     int ret = 0;
166     if (sharedmemalloc_lib)
167         dlclose(sharedmemalloc_lib);
168     sharedmemalloc_lib = NULL;
170     return ret;
173 int init_sharedmem_funcs()
175     int ret = 0;
177     if (sharedmemalloc_lib == NULL) {
178         sharedmemalloc_lib = dlopen("libsharedmemallocator.so",
179                                     RTLD_NOW | RTLD_GLOBAL);
180         if (sharedmemalloc_lib == NULL) {
181             perror("init_sharedmem_funcs: Error opening shared lib");
182             ret = -1;
183         }
184         else {
185             sharedmem_alloc = dlsym(sharedmemalloc_lib, "SHM_alloc");
186             if (sharedmem_alloc == NULL) {
187                 perror("init_sharedmem_funcs: Error getting shared lib sym");
188                 ret = -1;
189             }
190             else {
191                 sharedmem_free = dlsym(sharedmemalloc_lib, "SHM_release");
192                 if (sharedmem_free == NULL) {
193                     perror("init_sharedmem_funcs: Error getting shared lib sym");
194                     ret = -1;
195                 }
196             }
197         }
198     }
199     if (ret < 0) {
200         deinit_sharedmem_funcs();
201     }
202     return ret;
205 void * test_exec_call(void * arg)
207     int               i;
208     int               packet_len;
209     int               reply_len;
210     char              packet_buf[512] = {0};
211     char              return_buf[512] = {0};
212     test_exec_args    *args = (test_exec_args *) arg;
213     int               fd = args->fd;
214     struct rppc_function *function;
215     struct rppc_function_return *returned;
216     shm_buf           buf, buf2;
217     void              *ptr = NULL, *ptr2 = NULL;
219     for (i = args->start_num; i < args->start_num + NUM_ITERATIONS; i++) {
220         function = (struct rppc_function *)packet_buf;
221         function->fxn_id = args->func_idx;
222         switch (function->fxn_id) {
223             case FXN_IDX_FXNTRIPLE:
224                 function->num_params = 1;
225                 function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
226                 function->params[0].size = sizeof(int);
227                 function->params[0].data = i;
228                 function->num_translations = 0;
229                 break;
230             case FXN_IDX_FXNADD:
231                 function->num_params = 2;
232                 function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
233                 function->params[0].size = sizeof(int);
234                 function->params[0].data = i;
235                 function->params[1].type = RPPC_PARAM_TYPE_ATOMIC;
236                 function->params[1].size = sizeof(int);
237                 function->params[1].data = i+1;
238                 function->num_translations = 0;
239                 break;
240             case FXN_IDX_FXNADD3:
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                 break;
257             case FXN_IDX_FXNADDX:
258                 if ((*sharedmem_alloc)(sizeof(fxn_addx_args), &buf) < 0) {
259                     test_status = -1;
260                 }
261                 else if ((*sharedmem_alloc)(sizeof(int) * 3, &buf2) < 0) {
262                     test_status = -1;
263                 }
264                 else {
265                     ptr = (fxn_addx_args *)(buf.vir_addr);
266                     ptr2 = (int *)(buf2.vir_addr);
267                     ((fxn_addx_args *)ptr)->num = 3;
268                     ((fxn_addx_args *)ptr)->array = ptr2;
269                     ((int *)ptr2)[0] = i;
270                     ((int *)ptr2)[1] = i+1;
271                     ((int *)ptr2)[2] = i+2;
272                     function->num_params = 1;
273                     function->params[0].type = RPPC_PARAM_TYPE_PTR;
274                     function->params[0].size = sizeof(fxn_addx_args);
275                     function->params[0].data = (size_t)ptr;
276                     function->params[0].base = (size_t)ptr;
277                     function->num_translations = 1;
278                     function->translations[0].index = 0;
279                     function->translations[0].offset = (int)&(((fxn_addx_args *)ptr)->array) - (int)ptr;
280                     function->translations[0].base = (size_t)(((fxn_addx_args *)ptr)->array);
281                 }
282                 break;
283             case FXN_IDX_FXNFAULT:
284                 function->num_params = 1;
285                 function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
286                 function->params[0].size = sizeof(int);
287                 function->params[0].data = args->sub_test;
288                 function->num_translations = 0;
289                 break;
290         }
292         if (test_status == -1)
293             break;
295         returned = (struct rppc_function_return *)return_buf;
297         /* Exec command: */
298         packet_len = sizeof(struct rppc_function) +\
299                      (function->num_translations * \
300                       sizeof(struct rppc_param_translation));
301         if (args->test_num == 1)  {
302             if (exec_cmd(fd, (char *)packet_buf, packet_len,
303                          (char *)return_buf, &reply_len)) {
304                 test_status = -1;
305                 break;
306             }
307         }
308         else if (args->test_num == 2 || args->test_num == 3) {
309             if (send_cmd(fd, (char *)packet_buf, packet_len)) {
310                 test_status = -1;
311                 break;
312             }
313             sem_wait(&clientSems[args->thread_num]);
314             memcpy(return_buf, clientPackets[args->thread_num], 512);
315             readMsg[args->thread_num] = true;
316         }
317         switch (function->fxn_id) {
318             case FXN_IDX_FXNTRIPLE:
319                 if (i * 3 != returned->status) {
320                     printf ("rpc_stress: "
321                             "called fxnTriple(%d), result = %d, expected %d\n",
322                             function->params[0].data, returned->status, i * 3);
323                     test_status = -1;
324                 }
325                 else {
326                     printf ("rpc_stress: called fxnTriple(%d), result = %d\n",
327                             function->params[0].data, returned->status);
328                 }
329                 break;
330             case FXN_IDX_FXNADD:
331                 if (i + (i+1) != returned->status) {
332                     printf ("rpc_stress: "
333                             "called fxnAdd(%d,%d), result = %d, expected %d\n",
334                             function->params[0].data, function->params[1].data,
335                             returned->status, i + (i+1));
336                     test_status = -1;
337                 }
338                 else {
339                     printf ("rpc_stress: called fxnAdd(%d,%d), result = %d\n",
340                             function->params[0].data, function->params[1].data,
341                             returned->status);
342                 }
343                 break;
344             case FXN_IDX_FXNADD3:
345                 if (i + (i+1) + (i+2) != returned->status) {
346                     printf ("rpc_stress: "
347                             "called fxnAdd3(%d,%d,%d), result = %d, expected %d\n",
348                             ((fxn_add3_args *)ptr)->a,
349                             ((fxn_add3_args *)ptr)->b,
350                             ((fxn_add3_args *)ptr)->c, returned->status,
351                             i + (i+1) + (i+2));
352                     test_status = -1;
353                 }
354                 else {
355                     printf ("rpc_stress: called fxnAdd3(%d,%d,%d), result = %d\n",
356                             ((fxn_add3_args *)ptr)->a,
357                             ((fxn_add3_args *)ptr)->b,
358                             ((fxn_add3_args *)ptr)->c, returned->status);
359                 }
360                 (*sharedmem_free)(&buf);
361                 break;
362             case FXN_IDX_FXNADDX:
363                 if (i + (i+1) + (i+2) != returned->status) {
364                     printf ("rpc_stress: "
365                             "called fxnAddX(%d,%d,%d), result = %d, expected %d\n",
366                             ((int *)ptr2)[0], ((int *)ptr2)[1],
367                             ((int *)ptr2)[2], returned->status,
368                             i + (i+1) + (i+2));
369                     test_status = -1;
370                 }
371                 else {
372                     /* Check that reverse address translation is working */
373                     if (((fxn_addx_args *)ptr)->array != ptr2) {
374                         printf("rpc_stress: reverse addr translation failed, "
375                                "addr = 0x%x expected 0x%x\n",
376                                (int)(((fxn_addx_args *)ptr)->array), (int)ptr2);
377                         test_status = -1;
378                     }
379                     printf ("rpc_stress: called fxnAddX(%d,%d,%d), result = %d\n",
380                             ((int *)ptr2)[0], ((int *)ptr2)[1],
381                             ((int *)ptr2)[2], returned->status);
382                 }
383                 (*sharedmem_free)(&buf);
384                 (*sharedmem_free)(&buf2);
385                 break;
386         }
387         if (test_status == -1) {
388             break;
389         }
390     }
392     return NULL;
395 void * test_select_thread (void * arg)
397     int fd = 0;
398     int reply_len;
399     char return_buf[512] = {0};
400     struct rppc_function_return *rtn_packet =
401                                (struct rppc_function_return *)return_buf;
402     int n, i;
403     fd_set rfd;
404     int max_fd = -1;
406     while (runTest) {
407         FD_ZERO(&rfd);
408         for (i = 0; i < (int)arg; i++) {
409             FD_SET(fds[i], &rfd);
410             max_fd = max(max_fd, fds[i]);
411         }
412         n = select(1 + max_fd, &rfd, NULL, NULL, NULL);
413         switch (n) {
414             case -1:
415                 perror("select");
416                 return NULL;
417             default:
418                 for (i = 0; i < (int)arg; i++) {
419                     if (FD_ISSET(fds[i], &rfd)) {
420                         fd = fds[i];
421                         break;
422                     }
423                 }
424                 break;
425         }
426         if (recv_cmd(fd, 512, (char *)rtn_packet, &reply_len)) {
427             test_status = -1;
428             printf("test_select_thread: recv_cmd failed!");
429             break;
430         }
432         if (runTest == false)
433             break;
435         /* Decode reply: */
436         while (readMsg[i] == false) {
437             sleep(1);
438         }
439         memcpy(clientPackets[i], rtn_packet, 512);
440         readMsg[i] = false;
441         sem_post(&clientSems[i]);
442     }
443     return NULL;
446 void * test_read_thread (void * arg)
448     int    fd = (int)arg;
449     int    reply_len;
450     char   return_buf[512] = {0};
451     struct rppc_function_return *rtn_packet =
452                                (struct rppc_function_return *)return_buf;
453     int    packet_id = 0;
455     while (runTest) {
456         if (recv_cmd(fd, 512, (char *)rtn_packet, &reply_len)) {
457             test_status = -1;
458             printf("test_read_tread: recv_cmd failed!");
459             break;
460         }
462         if (runTest == false)
463             break;
465         /* Decode reply: */
466         switch (testFunc) {
467             case FXN_IDX_FXNTRIPLE:
468                 packet_id = ((rtn_packet->status / 3) - 1) / NUM_ITERATIONS;
469                 break;
470             case FXN_IDX_FXNADD:
471                 packet_id = (((rtn_packet->status - 1) / 2) - 1) / NUM_ITERATIONS;
472                 break;
473             case FXN_IDX_FXNADD3:
474                 packet_id = (((rtn_packet->status - 3) / 3) - 1) / NUM_ITERATIONS;
475                 break;
476             case FXN_IDX_FXNADDX:
477                 packet_id = (((rtn_packet->status - 3) / 3) - 1) / NUM_ITERATIONS;
478                 break;
479         }
480         while (readMsg[packet_id] == false) {
481             sleep(1);
482         }
483         memcpy(clientPackets[packet_id], rtn_packet, 512);
484         readMsg[packet_id] = false;
485         sem_post(&clientSems[packet_id]);
486     }
487     return NULL;
490 int test_rpc_stress_select(int core_id, int num_comps, int func_idx)
492     int ret = 0;
493     int i = 0, j = 0;
494     struct rppc_create_instance connreq;
495     struct rppc_function *function;
496     pthread_t select_thread;
497     int               packet_len;
498     char              packet_buf[512] = {0};
499     test_exec_args args[num_comps];
500     char serviceMgrName[20];
501     char serviceMgrPath[20];
503     snprintf (serviceMgrName, _POSIX_PATH_MAX, "rpc_example_%d", core_id);
504     snprintf (serviceMgrPath, _POSIX_PATH_MAX, "/dev/%s", serviceMgrName);
506     fds = malloc (sizeof(int) * num_comps);
507     if (!fds) {
508         return -1;
509     }
510     for (i = 0; i < num_comps; i++) {
511         fds[i] = open(serviceMgrPath, O_RDWR);
512         if (fds[i] < 0) {
513             perror("Can't open rpc_example device");
514             break;
515         }
516         strcpy(connreq.name, serviceMgrName);
518         /* Create an rpc_example server instance, and rebind its address to this
519         * file descriptor.
520         */
521         ret = ioctl(fds[i], RPPC_IOC_CREATE, &connreq);
522         if (ret < 0) {
523             perror("Can't connect to rpc_example instance");
524             close(fds[i]);
525             break;
526         }
527         printf("rpc_sample: Connected to %s\n", connreq.name);
528     }
529     if (i != num_comps) {
530         /* cleanup */
531         for (j = 0; j < i; j++) {
532             ret = close(fds[j]);
533             if (ret < 0) {
534                 perror("Can't close rpc_example fd ??");
535             }
536         }
537         free(fds);
538         return -1;
539     }
541     clientSems = malloc(sizeof(sem_t) * num_comps);
542     if (!clientSems) {
543         free(clientThreads);
544         for (i = 0; i < num_comps; i++) {
545             ret = close(fds[i]);
546             if (ret < 0) {
547                 perror("Can't close rpc_example fd ??");
548             }
549         }
550         return -1;
551     }
553     readMsg = malloc(sizeof(bool) * num_comps);
554     if (!readMsg) {
555         free(clientSems);
556         free(clientThreads);
557         for (i = 0; i < num_comps; i++) {
558             ret = close(fds[i]);
559             if (ret < 0) {
560                 perror("Can't close rpc_example fd ??");
561             }
562         }
563         return -1;
564     }
566     clientPackets = malloc(sizeof(char *) * num_comps);
567     if (!clientPackets) {
568         free(readMsg);
569         free(clientSems);
570         free(clientThreads);
571         for (i = 0; i < num_comps; i++) {
572             ret = close(fds[i]);
573             if (ret < 0) {
574                 perror("Can't close rpc_example fd ??");
575             }
576         }
577         return -1;
578     }
580     for (i = 0; i < num_comps; i++) {
581         clientPackets[i] = malloc(512 * sizeof(char));
582         if (!clientPackets[i]) {
583             for (j = 0; j < i; j++) {
584                 free(clientPackets[j]);
585             }
586             free(clientPackets);
587             free(readMsg);
588             free(clientSems);
589             free(clientThreads);
590             for (i = 0; i < num_comps; i++) {
591                 ret = close(fds[i]);
592                 if (ret < 0) {
593                     perror("Can't close rpc_example fd ??");
594                 }
595             }
596             return -1;
597         }
598     }
600     ret = pthread_create(&select_thread, NULL, test_select_thread,
601                          (void *)num_comps);
602     if (ret < 0) {
603         perror("Can't create thread");
604         ret = -1;
605     }
607     clientThreads = malloc(sizeof(pthread_t) * num_comps);
608     if (!clientThreads) {
609         for (i = 0; i < num_comps; i++) {
610             ret = close(fds[i]);
611             if (ret < 0) {
612                 perror("Can't close rpc_example fd ??");
613             }
614         }
615         free(fds);
616         return -1;
617     }
619     for ( i = 0; i < num_comps; i++) {
620         ret = sem_init(&clientSems[i], 0, 0);
621         args[i].fd = fds[i];
622         args[i].start_num = 1;
623         args[i].test_num = 3;
624         args[i].sem = &clientSems[i];
625         args[i].thread_num = i;
626         args[i].func_idx = func_idx;
627         readMsg[i] = true;
628         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
629                              (void *)&args[i]);
630         if (ret < 0) {
631             perror("Can't create thread");
632             ret = -1;
633             break;
634         }
635         printf("Created thread %d\n", i);
636     }
638     for (j = 0; j < i; j++) {
639         printf("Join thread %d\n", j);
640         pthread_join(clientThreads[j], NULL);
641     }
643     free(clientThreads);
645     function = (struct rppc_function *)packet_buf;
646     function->fxn_id = FXN_IDX_FXNTRIPLE;
647     function->num_params = 1;
648     function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
649     function->params[0].size = sizeof(int);
650     function->params[0].data = i;
651     function->num_translations = 0;
653     /* Exec command: */
654     packet_len = sizeof(struct rppc_function) +\
655                  (function->num_translations *\
656                   sizeof(struct rppc_param_translation));
658     runTest = false;
659     if (send_cmd(fds[0], (char *)packet_buf, packet_len)) {
660         test_status = -1;
661     }
663     pthread_join(select_thread, NULL);
665     for (i = 0; i < num_comps; i++) {
666         free(clientPackets[i]);
667     }
668     free(clientPackets);
669     free(readMsg);
670     free(clientSems);
672     for (i = 0; i < num_comps; i++) {
673         /* Terminate connection and destroy rpc_example instance */
674         ret = close(fds[i]);
675         if (ret < 0) {
676             perror("Can't close rpc_example fd ??");
677             ret = -1;
678         }
679         printf("rpc_sample: Closed connection to %s!\n", connreq.name);
680     }
682     free(fds);
683     return ret;
686 int test_rpc_stress_multi_threads(int core_id, int num_threads, int func_idx)
688     int ret = 0;
689     int i = 0, j = 0;
690     int fd;
691     int packet_len;
692     char packet_buf[512] = {0};
693     pthread_t read_thread;
694     struct rppc_create_instance connreq;
695     struct rppc_function *function;
696     test_exec_args args[num_threads];
697     char serviceMgrName[20];
698     char serviceMgrPath[20];
700     snprintf (serviceMgrName, _POSIX_PATH_MAX, "rpc_example_%d", core_id);
701     snprintf (serviceMgrPath, _POSIX_PATH_MAX, "/dev/%s", serviceMgrName);
703     /* Connect to the rpc_example ServiceMgr on the specified core: */
704     fd = open(serviceMgrPath, O_RDWR);
705     if (fd < 0) {
706         perror("Can't open rpc_example device");
707         return -1;
708     }
709     strcpy(connreq.name, serviceMgrName);
711     /* Create an rpc_example server instance, and rebind its address to this
712     * file descriptor.
713     */
714     ret = ioctl(fd, RPPC_IOC_CREATE, &connreq);
715     if (ret < 0) {
716         perror("Can't connect to rpc_example instance");
717         close(fd);
718         return -1;
719     }
720     printf("rpc_sample: Connected to %s\n", connreq.name);
722     clientThreads = malloc(sizeof(pthread_t) * num_threads);
723     if (!clientThreads) {
724         ret = close(fd);
725         return -1;
726     }
727     clientSems = malloc(sizeof(sem_t) * num_threads);
728     if (!clientSems) {
729         free(clientThreads);
730         ret = close(fd);
731         return -1;
732     }
734     readMsg = malloc(sizeof(bool) * num_threads);
735     if (!readMsg) {
736         free(clientSems);
737         free(clientThreads);
738         ret = close(fd);
739         return -1;
740     }
742     clientPackets = malloc(sizeof(char *) * num_threads);
743     if (!clientPackets) {
744         free(readMsg);
745         free(clientSems);
746         free(clientThreads);
747         ret = close(fd);
748         return -1;
749     }
751     for (i = 0; i < num_threads; i++) {
752         clientPackets[i] = malloc(512 * sizeof(char));
753         if (!clientPackets[i]) {
754             for (j = 0; j < i; j++) {
755                 free(clientPackets[j]);
756             }
757             free(clientPackets);
758             free(readMsg);
759             free(clientSems);
760             free(clientThreads);
761             close(fd);
762             return -1;
763         }
764     }
766     ret = pthread_create(&read_thread, NULL, test_read_thread, (void *)fd);
767     if (ret < 0) {
768         perror("Can't create thread");
769         for (i = 0; i < num_threads; i++) {
770             free(clientPackets[i]);
771         }
772         free(clientPackets);
773         free(readMsg);
774         free(clientSems);
775         free(clientThreads);
776         close(fd);
777         return -1;
778     }
780     for ( i = 0; i < num_threads; i++) {
781         ret = sem_init(&clientSems[i], 0, 0);
782         args[i].fd = fd;
783         args[i].start_num = (i * NUM_ITERATIONS) + 1;
784         args[i].test_num = 2;
785         args[i].sem = &clientSems[i];
786         args[i].thread_num = i;
787         args[i].func_idx = func_idx;
788         readMsg[i] = true;
789         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
790                              (void *)&args[i]);
791         if (ret < 0) {
792             perror("Can't create thread");
793             ret = -1;
794             break;
795         }
796         printf("Created thread %d\n", i);
797     }
799     for (j = 0; j < i; j++) {
800         printf("Join thread %d\n", j);
801         pthread_join(clientThreads[j], NULL);
802         sem_destroy(&clientSems[j]);
803     }
805     function = (struct rppc_function *)packet_buf;
806     function->fxn_id = FXN_IDX_FXNTRIPLE;
807     function->num_params = 1;
808     function->params[0].type = RPPC_PARAM_TYPE_ATOMIC;
809     function->params[0].size = sizeof(int);
810     function->params[0].data = i;
811     function->num_translations = 0;
813     /* Exec command: */
814     packet_len = sizeof(struct rppc_function) +\
815                  (function->num_translations *\
816                   sizeof(struct rppc_param_translation));
818     runTest = false;
819     if (send_cmd(fd, (char *)packet_buf, packet_len)) {
820         test_status = -1;
821     }
823     pthread_join(read_thread, NULL);
825     for (i = 0; i < num_threads; i++) {
826         free(clientPackets[i]);
827     }
828     free(clientPackets);
829     free(readMsg);
830     free(clientSems);
831     free(clientThreads);
833     /* Terminate connection and destroy rpc_example instance */
834     ret = close(fd);
835     if (ret < 0) {
836         perror("Can't close rpc_example fd ??");
837         ret = -1;
838     }
839     printf("rpc_sample: Closed connection to %s!\n", connreq.name);
841     return ret;
844 int test_rpc_stress_multi_srvmgr(int core_id, int num_comps, int func_idx)
846     int ret = 0;
847     int i = 0, j = 0;
848     int fd[num_comps];
849     struct rppc_create_instance connreq;
850     test_exec_args args[num_comps];
851     char serviceMgrName[20];
852     char serviceMgrPath[20];
854     snprintf (serviceMgrName, _POSIX_PATH_MAX, "rpc_example_%d", core_id);
855     snprintf (serviceMgrPath, _POSIX_PATH_MAX, "/dev/%s", serviceMgrName);
857     for (i = 0; i < num_comps; i++) {
858         /* Connect to the rpc_example ServiceMgr on the specified core: */
859         fd[i] = open(serviceMgrPath, O_RDWR);
860         if (fd[i] < 0) {
861             perror("Can't open rpc_example device");
862             ret = -1;
863             break;
864         }
865         strcpy(connreq.name, serviceMgrName);
867         /* Create an rpc_example server instance, and rebind its address to this
868         * file descriptor.
869         */
870         ret = ioctl(fd[i], RPPC_IOC_CREATE, &connreq);
871         if (ret < 0) {
872             perror("Can't connect to rpc_example instance");
873             close(fd[i]);
874             break;
875         }
876         printf("rpc_sample: Connected to %s\n", connreq.name);
877     }
878     if (i != num_comps) {
879         /* cleanup */
880         for (j = 0; j < i; j++) {
881             ret = close(fd[j]);
882             if (ret < 0) {
883                 perror("Can't close rpc_example fd ??");
884             }
885         }
886         return -1;
887     }
889     clientThreads = malloc(sizeof(pthread_t) * num_comps);
890     if (!clientThreads) {
891         for (i = 0; i < num_comps; i++) {
892             ret = close(fd[i]);
893             if (ret < 0) {
894                 perror("Can't close rpc_example fd ??");
895             }
896         }
897         return -1;
898     }
900     for ( i = 0; i < num_comps; i++) {
901         args[i].fd = fd[i];
902         args[i].start_num = 1;
903         args[i].test_num = 1;
904         args[i].sem = NULL;
905         args[i].thread_num = i;
906         args[i].func_idx = func_idx;
907         ret = pthread_create(&clientThreads[i], NULL, test_exec_call,
908                              (void *)&args[i]);
909         if (ret < 0) {
910             perror("Can't create thread");
911             ret = -1;
912             break;
913         }
914         printf("Created thread %d\n", i);
915     }
917     for (j = 0; j < i; j++) {
918         printf("Join thread %d\n", j);
919         pthread_join(clientThreads[j], NULL);
920     }
922     free(clientThreads);
924     for (i = 0; i < num_comps; i++) {
925         /* Terminate connection and destroy rpc_example instance */
926         ret = close(fd[i]);
927         if (ret < 0) {
928             perror("Can't close rpc_example fd ??");
929             ret = -1;
930         }
931         printf("rpc_sample: Closed connection to %s!\n", connreq.name);
932     }
934     return ret;
937 int test_errors(int core_id, int num_comps, int sub_test)
939     int ret = 0;
940     int i = 0, j = 0;
941     int fd;
942     struct rppc_create_instance connreq;
943     test_exec_args args;
944     char serviceMgrName[20];
945     char serviceMgrPath[20];
947     snprintf (serviceMgrName, _POSIX_PATH_MAX, "rpc_example_%d", core_id);
948     snprintf (serviceMgrPath, _POSIX_PATH_MAX, "/dev/%s", serviceMgrName);
950     /* Connect to the rpc_example ServiceMgr on the specified core: */
951     fd = open(serviceMgrPath, O_RDWR);
952     if (fd < 0) {
953         perror("Can't open rpc_example device");
954         ret = -1;
955         return -1;
956     }
957     strcpy(connreq.name, serviceMgrName);
959     /* Create an rpc_example server instance, and rebind its address to this
960     * file descriptor.
961     */
962     ret = ioctl(fd, RPPC_IOC_CREATE, &connreq);
963     if (ret < 0) {
964         perror("Can't connect to rpc_example instance");
965         close(fd);
966         return -1;
967     }
968     printf("rpc_sample: Connected to %s\n", connreq.name);
970     clientThreads = malloc(sizeof(pthread_t));
971     if (!clientThreads) {
972         ret = close(fd);
973         if (ret < 0) {
974             perror("Can't close rpc_example fd ??");
975         }
976         return -1;
977     }
979     args.fd = fd;
980     args.start_num = 1;
981     args.test_num = 1;
982     args.sem = NULL;
983     args.thread_num = i;
984     args.func_idx = FXN_IDX_FXNFAULT;
985     args.sub_test = sub_test;
986     ret = pthread_create(&clientThreads[0], NULL, test_exec_call,
987                          (void *)&args);
988     if (ret < 0) {
989         perror("Can't create thread");
990         ret = close(fd);
991         if (ret < 0) {
992             perror("Can't close rpc_example fd ??");
993         }
994         return -1;
995     }
996     printf("Created thread %d\n", i);
998     printf("Join thread %d\n", j);
999     pthread_join(clientThreads[0], NULL);
1001     free(clientThreads);
1003     /* Terminate connection and destroy rpc_example instance */
1004     ret = close(fd);
1005     if (ret < 0) {
1006         perror("Can't close rpc_example fd ??");
1007         ret = -1;
1008     }
1009     printf("rpc_sample: Closed connection to %s!\n", connreq.name);
1011     return ret;
1014 int main(int argc, char *argv[])
1016     int ret = 0;
1017     int test_id = -1;
1018     int core_id = 0;
1019     int num_comps = 1;
1020     int num_threads = 1;
1021     int func_idx = 1;
1022     int sub_test = 0;
1023     int c;
1025     while (1)
1026     {
1027         c = getopt (argc, argv, "t:c:x:l:f:s:");
1028         if (c == -1)
1029             break;
1031         switch (c)
1032         {
1033         case 't':
1034             test_id = atoi(optarg);
1035             break;
1036         case 'c':
1037             core_id = atoi(optarg);
1038             break;
1039         case 'x':
1040             num_comps = atoi(optarg);
1041             break;
1042         case 'l':
1043             num_threads = atoi(optarg);
1044             break;
1045         case 'f':
1046             func_idx = atoi(optarg);
1047             break;
1048         case 's':
1049             sub_test = atoi(optarg);
1050             break;
1051         default:
1052             printf ("Unrecognized argument\n");
1053         }
1054     }
1056     if (test_id < 0 || test_id > 4) {
1057         printf("Invalid test id\n");
1058         return 1;
1059     }
1061     if (func_idx < FXN_IDX_FXNTRIPLE || func_idx >= FXN_IDX_MAX) {
1062         printf("Invalid function index\n");
1063         return 1;
1064     }
1065     testFunc = func_idx;
1067     if (func_idx == FXN_IDX_FXNADD3 || func_idx == FXN_IDX_FXNADDX) {
1068         if (init_sharedmem_funcs() < 0) {
1069             printf("failure: shmemallocator library must be present for this test function\n");
1070             return 1;
1071         }
1072     }
1074     switch (test_id) {
1075         case 1:
1076             /* multiple threads each with an RPMSG-RPC ServiceMgr instance */
1077             if (core_id < 0 || core_id > 4) {
1078                 printf("Invalid core id\n");
1079                 return 1;
1080             }
1081             if (num_comps < 0) {
1082                 printf("Invalid num comps id\n");
1083                 return 1;
1084             }
1085             ret = test_rpc_stress_multi_srvmgr(core_id, num_comps, func_idx);
1086             break;
1087         case 2:
1088             /* Multiple threads, 1 RPMSG-RPC ServiceMgr instances */
1089             if (core_id < 0 || core_id > 4) {
1090                 printf("Invalid core id\n");
1091                 return 1;
1092             }
1093             if (num_threads < 0) {
1094                 printf("Invalid num threads\n");
1095                 return 1;
1096             }
1097             ret = test_rpc_stress_multi_threads(core_id, num_threads, func_idx);
1098             break;
1099         case 3:
1100             /* 1 thread using multiple RPMSG-RPC ServiceMgr instances */
1101             if (core_id < 0 || core_id > 4) {
1102                 printf("Invalid core id\n");
1103                 return 1;
1104             }
1105             if (num_comps < 0) {
1106                 printf("Invalid num comps id\n");
1107                 return 1;
1108             }
1109             ret = test_rpc_stress_select(core_id, num_comps, func_idx);
1110             break;
1111         case 4:
1112             /* MMU fault test */
1113             if (core_id < 0 || core_id > 4) {
1114                 printf("Invalid core id\n");
1115                 return 1;
1116             }
1117             if (num_comps < 0) {
1118                 printf("Invalid num comps id\n");
1119                 return 1;
1120             }
1121             ret = test_errors(core_id, num_comps, sub_test);
1122             break;
1123         default:
1124             break;
1125     }
1127     if (ret < 0 || test_status < 0) {
1128         printf ("TEST STATUS: FAILED.\n");
1129     }
1130     else {
1131         printf ("TEST STATUS: PASSED.\n");
1132     }
1133     return 0;