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;
110 }
112 int send_cmd(int fd, char *msg, int len)
113 {
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);
123 }
125 int recv_cmd(int fd, int len, char *reply_msg, int *reply_len)
126 {
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);
140 }
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)
163 {
164 int ret = 0;
166 if (sharedmemalloc_lib)
167 dlclose(sharedmemalloc_lib);
168 sharedmemalloc_lib = NULL;
170 return ret;
171 }
173 int init_sharedmem_funcs()
174 {
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;
203 }
205 void * test_exec_call(void * arg)
206 {
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;
393 }
395 void * test_select_thread (void * arg)
396 {
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;
444 }
446 void * test_read_thread (void * arg)
447 {
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;
488 }
490 int test_rpc_stress_select(int core_id, int num_comps, int func_idx)
491 {
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;
684 }
686 int test_rpc_stress_multi_threads(int core_id, int num_threads, int func_idx)
687 {
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;
842 }
844 int test_rpc_stress_multi_srvmgr(int core_id, int num_comps, int func_idx)
845 {
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;
935 }
937 int test_errors(int core_id, int num_comps, int sub_test)
938 {
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;
1012 }
1014 int main(int argc, char *argv[])
1015 {
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;
1134 }