1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include "vchiq_test.h"
33#ifndef USE_VCHIQ_ARM
34#define USE_VCHIQ_ARM
35#endif
36#include "interface/vchi/vchi.h"
37
38#define NUM_BULK_BUFS 2
39#define BULK_SIZE (1024*256)
40#ifndef PAGE_SIZE
41#define PAGE_SIZE 4096
42#endif
43
44#define INIT_PARAMS(sp_, fourcc_, cb_, userdata_, ver_) \
45 do { \
46 memset((sp_), 0, sizeof(*(sp_))); \
47 (sp_)->fourcc = fourcc_; \
48 (sp_)->callback = cb_; \
49 (sp_)->userdata = userdata_; \
50 (sp_)->version = ver_; \
51 (sp_)->version_min = ver_; \
52 } while (0)
53
54
55static struct test_params g_params = { MSG_CONFIG, 64, 100, 1, 1, 1, 0, 0, 0, 0 };
56static const char *g_servname = "echo";
57
58static VCOS_EVENT_T g_server_reply;
59static VCOS_EVENT_T g_shutdown;
60static VCOS_MUTEX_T g_mutex;
61
62static const char *g_server_error = NULL;
63
64static volatile int g_sync_mode = 0;
65
66static VCOS_EVENT_T func_test_sync;
67static int want_echo = 1;
68static int func_error = 0;
69static int fun2_error = 0;
70static int func_data_test_start = -1;
71static int func_data_test_end = 0x7fffffff;
72static int func_data_test_iter;
73
74char *bulk_bufs[NUM_BULK_BUFS * 2];
75char *bulk_tx_data[NUM_BULK_BUFS];
76char *bulk_rx_data[NUM_BULK_BUFS];
77
78static int ctrl_received = 0;
79static int bulk_tx_sent = 0;
80static int bulk_rx_sent = 0;
81static int bulk_tx_received = 0;
82static int bulk_rx_received = 0;
83
84static char clnt_service1_data[SERVICE1_DATA_SIZE];
85static char clnt_service2_data[SERVICE2_DATA_SIZE];
86
87static VCOS_LOG_CAT_T vchiq_test_log_category;
88
89static int vchiq_test(int argc, char **argv);
90static VCHIQ_STATUS_T vchiq_bulk_test(void);
91static VCHIQ_STATUS_T vchiq_ctrl_test(void);
92static VCHIQ_STATUS_T vchiq_functional_test(void);
93static VCHIQ_STATUS_T vchiq_ping_test(void);
94static VCHIQ_STATUS_T vchiq_signal_test(void);
95
96static VCHIQ_STATUS_T do_functional_test(void);
97static void do_ping_test(VCHIQ_SERVICE_HANDLE_T service, int size, int async, int oneway, int iters);
98static void do_vchi_ping_test(VCHI_SERVICE_HANDLE_T service, int size, int async, int oneway, int iters);
99
100static VCHIQ_STATUS_T func_data_test(VCHIQ_SERVICE_HANDLE_T service, int size, int align, int server_align);
101
102#ifdef VCHIQ_LOCAL
103static void *vchiq_test_server(void *);
104#endif
105
106static VCHIQ_STATUS_T
107clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
108 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata);
109static void
110vchi_clnt_callback(void *callback_param, VCHI_CALLBACK_REASON_T reason,
111 void *handle);
112static VCHIQ_STATUS_T func_clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
113 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata);
114static VCHIQ_STATUS_T fun2_clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
115 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata);
116static int mem_check(const void *expected, const void *actual, int size);
117static void usage(void);
118static void check_timer(void);
119static char *buf_align(char *buf, int align_size, int align);
120
121#ifdef ANDROID
122
123static int g_timeout_ms = 0;
124static pid_t main_process_pid;
125static void kill_timeout_handler(int cause, siginfo_t *how, void *ucontext);
126static int setup_auto_kill(int timeout_ms);
127
128#endif
129
130#ifdef __linux__
131
132#include <fcntl.h>
133#include <sys/ioctl.h>
134#include "interface/vmcs_host/vc_cma.h"
135
136static void reserve_test(int reserve, int delay)
137{
138 int fd = open("/dev/vc-cma", O_RDWR);
139 int rc = -1;
140 if (fd >= 0)
141 {
142 rc = ioctl(fd, VC_CMA_IOC_RESERVE, reserve);
143 if (rc == 0)
144 {
145 printf("Sleeping for %d seconds...\n", delay);
146 sleep(delay);
147 }
148 else
149 printf("* failed to ioctl /dev/vc-cma - rc %d\n", rc);
150 close(fd);
151 }
152 else
153 printf("* failed to open /dev/vc-cma - rc %d\n", fd);
154}
155
156#endif
157
158static int vchiq_test(int argc, char **argv)
159{
160 VCHIQ_STATUS_T status;
161 int run_bulk_test = 0;
162 int run_ctrl_test = 0;
163 int run_functional_test = 0;
164 int run_ping_test = 0;
165 int run_signal_test = 0;
166 int verbose = 0;
167 int argn;
168
169 argn = 1;
170 while ((argn < argc) && (argv[argn][0] == '-'))
171 {
172 const char *arg = argv[argn++];
173 if (strcmp(arg, "-s") == 0)
174 {
175 g_servname = argv[argn++];
176 if (!g_servname || (strlen(g_servname) != 4))
177 {
178 usage();
179 }
180 }
181 else if (strcasecmp(arg, "-a") == 0)
182 {
183 g_params.align_size = (strcmp(arg, "-A") == 0) ? 4096 : 32;
184 g_params.client_align = atoi(argv[argn++]);
185 g_params.server_align = atoi(argv[argn++]);
186 }
187 else if (strcmp(arg, "-b") == 0)
188 {
189 run_bulk_test = 1;
190 g_params.blocksize = atoi(argv[argn++]);
191 }
192 else if (strcmp(arg, "-c") == 0)
193 {
194 run_ctrl_test = 1;
195 g_params.blocksize = atoi(argv[argn++]);
196 }
197 else if (strcmp(arg, "-e") == 0)
198 {
199 want_echo = 0;
200 }
201 else if (strcmp(arg, "-f") == 0)
202 {
203 run_functional_test = 1;
204 }
205 else if (strcmp(arg, "-h") == 0)
206 {
207 usage();
208 }
209 else if (strcmp(arg, "-i") == 0)
210 {
211 run_signal_test = 1;
212 }
213 else if (strcmp(arg, "-m") == 0)
214 {
215 g_params.client_message_quota = atoi(argv[argn++]);
216 }
217 else if (strcmp(arg, "-M") == 0)
218 {
219 g_params.server_message_quota = atoi(argv[argn++]);
220 }
221 else if (strcmp(arg, "-p") == 0)
222 {
223 run_ping_test = 1;
224 g_params.iters = 1000;
225 }
226 else if (strcmp(arg, "-q") == 0)
227 {
228 /* coverity[missing_lock : FALSE] - g_server_reply is not used for mutual exclusion */
229 g_params.verify = 0;
230 }
231#ifdef __linux__
232 else if (strcmp(arg, "-r") == 0)
233 {
234 int reserve, delay;
235 if (argn+1 < argc)
236 {
237 reserve = atoi(argv[argn++]);
238 delay = atoi(argv[argn++]);
239 reserve_test(reserve, delay);
240 exit(0);
241 }
242 else
243 {
244 printf("not enough arguments (-r reserve delay)\n");
245 exit(-1);
246 }
247 }
248#endif
249#ifdef ANDROID
250 else if (strcmp(arg, "-K") == 0)
251 {
252 if (argn < argc)
253 g_timeout_ms = atoi(argv[argn++]);
254 else
255 {
256 printf("not enough arguments (-K timeout)\n");
257 exit(-1);
258 }
259 }
260#endif
261 else if (strcmp(arg, "-t") == 0)
262 {
263 check_timer();
264 exit(0);
265 }
266 else if (strcmp(arg, "-v") == 0)
267 {
268 verbose = 1;
269 }
270 else if (strcmp(arg, "-S") == 0)
271 {
272 func_data_test_start = atoi(argv[argn++]);
273 }
274 else if (strcmp(arg, "-E") == 0)
275 {
276 func_data_test_end = atoi(argv[argn++]);
277 }
278 else
279 {
280 printf("* unknown option '%s'\n", arg);
281 usage();
282 }
283 }
284
285 if ((run_ctrl_test + run_bulk_test + run_functional_test + run_ping_test + run_signal_test) != 1)
286 usage();
287
288 if (argn < argc)
289 {
290 g_params.iters = atoi(argv[argn++]);
291 if (argn != argc)
292 {
293 usage();
294 }
295 }
296
297 vcos_log_set_level(VCOS_LOG_CATEGORY, verbose ? VCOS_LOG_TRACE : VCOS_LOG_INFO);
298 vcos_log_register("vchiq_test", VCOS_LOG_CATEGORY);
299
300#ifdef VCHIQ_LOCAL
301 {
302 static VCOS_THREAD_T server_task;
303 void *pointer = NULL;
304 int stack_size = 4096;
305
306#if VCOS_CAN_SET_STACK_ADDR
307 pointer = malloc(stack_size);
308 vcos_demand(pointer);
309#endif
310 vcos_thread_create_classic(&server_task, "vchiq_test server", vchiq_test_server, (void *)0, pointer, stack_size,
311 10 | VCOS_AFFINITY_CPU1, 20, VCOS_START);
312 }
313#endif
314
315 vcos_event_create(&g_server_reply, "g_server_reply");
316 vcos_event_create(&g_shutdown, "g_shutdown");
317 vcos_mutex_create(&g_mutex, "g_mutex");
318
319
320 status = VCHIQ_ERROR;
321
322 if (run_bulk_test)
323 status = vchiq_bulk_test();
324 else if (run_ctrl_test)
325 status = vchiq_ctrl_test();
326 else if (run_functional_test)
327 status = vchiq_functional_test();
328 else if (run_ping_test)
329 status = vchiq_ping_test();
330 else if (run_signal_test)
331 status = vchiq_signal_test();
332
333 return (status == VCHIQ_SUCCESS) ? 0 : -1;
334}
335
336static VCHIQ_STATUS_T
337vchiq_bulk_test(void)
338{
339 VCHIQ_INSTANCE_T vchiq_instance;
340 VCHIQ_SERVICE_HANDLE_T vchiq_service;
341 VCHIQ_SERVICE_PARAMS_T service_params;
342 VCHIQ_ELEMENT_T elements[4];
343 VCHIQ_ELEMENT_T *element;
344 int num_bulk_bufs = NUM_BULK_BUFS;
345 uint32_t start, end;
346 int i;
347
348 g_params.blocksize *= 1024;
349
350 for (i = 0; i < (NUM_BULK_BUFS * 2); i++)
351 {
352 bulk_bufs[i] = malloc(g_params.blocksize + BULK_ALIGN_SIZE - 1);
353 if (!bulk_bufs[i])
354 {
355 printf("* out of memory\n");
356 while (i > 0)
357 {
358 free(bulk_bufs[--i]);
359 }
360 return VCHIQ_ERROR;
361 }
362 }
363
364 for (i = 0; i < NUM_BULK_BUFS; i++)
365 {
366 int j;
367 bulk_tx_data[i] = buf_align(bulk_bufs[i*2 + 0], g_params.align_size, g_params.client_align);
368 bulk_rx_data[i] = buf_align(bulk_bufs[i*2 + 1], g_params.align_size, g_params.client_align);
369 for (j = 0; j < g_params.blocksize; j+=4)
370 {
371 *(unsigned int *)(bulk_tx_data[i] + j) = ((0x80 | i) << 24) + j;
372 }
373 memset(bulk_rx_data[i], 0xff, g_params.blocksize);
374 }
375
376#ifdef ANDROID
377 if (g_timeout_ms)
378 {
379 setup_auto_kill(g_timeout_ms);
380 }
381#endif
382
383 if (vchiq_initialise(&vchiq_instance) != VCHIQ_SUCCESS)
384 {
385 printf("* failed to open vchiq instance\n");
386 return VCHIQ_ERROR;
387 }
388
389 vchiq_connect(vchiq_instance);
390
391 memset(&service_params, 0, sizeof(service_params));
392
393 service_params.version = service_params.version_min = VCHIQ_TEST_VER;
394 service_params.fourcc = VCHIQ_MAKE_FOURCC(g_servname[0], g_servname[1], g_servname[2], g_servname[3]);
395 service_params.callback = clnt_callback;
396 service_params.userdata = "clnt userdata";
397
398 if (vchiq_open_service(vchiq_instance, &service_params, &vchiq_service) != VCHIQ_SUCCESS)
399 {
400 printf("* failed to open service - already in use?\n");
401 return VCHIQ_ERROR;
402 }
403
404 printf("Bulk test - service:%s, block size:%d, iters:%d\n", g_servname, g_params.blocksize, g_params.iters);
405
406 /* coverity[missing_lock : FALSE] - g_server_reply is not used for mutual exclusion */
407 g_params.echo = want_echo;
408 element = elements;
409 element->data = &g_params;
410 element->size = sizeof(g_params);
411 element++;
412
413 vchiq_queue_message(vchiq_service, elements, element - elements);
414
415 vcos_event_wait(&g_server_reply);
416
417 if (g_server_error)
418 {
419 printf("* server error: %s\n", g_server_error);
420 return VCHIQ_ERROR;
421 }
422
423 if ( num_bulk_bufs > g_params.iters )
424 num_bulk_bufs = g_params.iters;
425
426 start = vcos_getmicrosecs();
427
428 vcos_mutex_lock(&g_mutex);
429
430 for (i = 0; i < num_bulk_bufs; i++)
431 {
432 vchiq_queue_bulk_transmit(vchiq_service, bulk_tx_data[i], g_params.blocksize, (void *)i);
433
434 vcos_log_trace("vchiq_test: queued bulk tx %d", i);
435 bulk_tx_sent++;
436
437 if (g_params.echo)
438 {
439 vchiq_queue_bulk_receive(vchiq_service, bulk_rx_data[i], g_params.blocksize, (void *)i);
440
441 vcos_log_trace("vchiq_test: queued bulk rx %d", i);
442 bulk_rx_sent++;
443 }
444 }
445
446 vcos_mutex_unlock(&g_mutex);
447
448 vcos_log_trace("Sent all messages");
449
450 vcos_log_trace("vchiq_test: waiting for shutdown");
451
452 vcos_event_wait(&g_shutdown);
453
454 end = vcos_getmicrosecs();
455
456 for (i = 0; i < (NUM_BULK_BUFS * 2); i++)
457 {
458 free(bulk_bufs[i]);
459 }
460
461 vchiq_remove_service(vchiq_service);
462
463 vcos_log_trace("vchiq_test: shutting down");
464
465 vchiq_shutdown(vchiq_instance);
466
467 printf("Elapsed time: %dus per iteration\n", (end - start) / g_params.iters);
468
469 return VCHIQ_SUCCESS;
470}
471
472static VCHIQ_STATUS_T
473vchiq_ctrl_test(void)
474{
475 VCHIQ_INSTANCE_T vchiq_instance;
476 VCHIQ_SERVICE_HANDLE_T vchiq_service;
477 VCHIQ_SERVICE_PARAMS_T service_params;
478 uint32_t start, end;
479 int i;
480
481 ctrl_received = 0;
482 if (g_params.blocksize < 4)
483 g_params.blocksize = 4;
484
485 for (i = 0; i < NUM_BULK_BUFS; i++)
486 {
487 int j;
488 bulk_tx_data[i] = malloc(g_params.blocksize);
489 if (!bulk_tx_data[i])
490 {
491 printf("* out of memory\n");
492 return VCHIQ_ERROR;
493 }
494 *(int *)bulk_tx_data[i] = MSG_ECHO;
495 for (j = 4; j < g_params.blocksize; j+=4)
496 {
497 *(unsigned int *)(bulk_tx_data[i] + j) = ((0x80 | i) << 24) + j;
498 }
499 }
500
501#ifdef ANDROID
502 if (g_timeout_ms)
503 {
504 setup_auto_kill(g_timeout_ms);
505 }
506#endif
507
508 if (vchiq_initialise(&vchiq_instance) != VCHIQ_SUCCESS)
509 {
510 printf("* failed to open vchiq instance\n");
511 return VCHIQ_ERROR;
512 }
513
514 vchiq_connect(vchiq_instance);
515
516 memset(&service_params, 0, sizeof(service_params));
517
518 service_params.fourcc = VCHIQ_MAKE_FOURCC(g_servname[0], g_servname[1], g_servname[2], g_servname[3]);
519 service_params.callback = clnt_callback;
520 service_params.userdata = "clnt userdata";
521 service_params.version = VCHIQ_TEST_VER;
522 service_params.version_min = VCHIQ_TEST_VER;
523
524 if (vchiq_open_service(vchiq_instance, &service_params, &vchiq_service) != VCHIQ_SUCCESS)
525 {
526 printf("* failed to open service - already in use?\n");
527 return VCHIQ_ERROR;
528 }
529
530 printf("Ctrl test - service:%s, block size:%d, iters:%d\n", g_servname, g_params.blocksize, g_params.iters);
531
532 start = vcos_getmicrosecs();
533
534 for (i = 0; i < g_params.iters; i++)
535 {
536 VCHIQ_ELEMENT_T element;
537 element.data = bulk_tx_data[i % NUM_BULK_BUFS];
538 element.size = g_params.blocksize;
539
540 if (vchiq_queue_message(vchiq_service, &element, 1) != VCHIQ_SUCCESS)
541 {
542 printf("* failed to send a message\n");
543 goto error_exit;
544 }
545 if (g_server_error)
546 {
547 printf("* error - %s\n", g_server_error);
548 goto error_exit;
549 }
550 }
551
552 vcos_log_trace("Sent all messages");
553
554 if (g_params.echo)
555 {
556 vcos_log_trace("vchiq_test: waiting for shutdown");
557
558 vcos_event_wait(&g_shutdown);
559 }
560
561 if (g_server_error)
562 {
563 printf("* error - %s\n", g_server_error);
564 goto error_exit;
565 }
566
567 end = vcos_getmicrosecs();
568
569 vchiq_remove_service(vchiq_service);
570
571 vcos_log_trace("vchiq_test: shutting down");
572
573 vchiq_shutdown(vchiq_instance);
574
575 printf("Elapsed time: %dus per iteration\n", (end - start) / g_params.iters);
576
577 return VCHIQ_SUCCESS;
578
579error_exit:
580 vchiq_remove_service(vchiq_service);
581 vchiq_shutdown(vchiq_instance);
582 return VCHIQ_ERROR;
583}
584
585static VCHIQ_STATUS_T
586vchiq_functional_test(void)
587{
588 int i;
589 printf("Functional test - iters:%d\n", g_params.iters);
590 for (i = 0; i < g_params.iters; i++)
591 {
592 printf("======== iteration %d ========\n", i+1);
593
594 if (do_functional_test() != VCHIQ_SUCCESS)
595 return VCHIQ_ERROR;
596 }
597 return VCHIQ_SUCCESS;
598}
599
600static VCHIQ_STATUS_T
601vchiq_ping_test(void)
602{
603 /* Measure message round trip time for various sizes*/
604 VCHIQ_INSTANCE_T vchiq_instance;
605 VCHIQ_SERVICE_HANDLE_T vchiq_service;
606 VCHI_SERVICE_HANDLE_T vchi_service;
607 SERVICE_CREATION_T service_params;
608 VCHIQ_SERVICE_PARAMS_T vchiq_service_params;
609 int fourcc;
610
611 static int sizes[] = { 0, 1024, 2048, VCHIQ_MAX_MSG_SIZE };
612 unsigned int i;
613
614 fourcc = VCHIQ_MAKE_FOURCC(g_servname[0], g_servname[1], g_servname[2], g_servname[3]);
615
616 printf("Ping test - service:%s, iters:%d, version %d\n", g_servname, g_params.iters, VCHIQ_TEST_VER);
617
618#ifdef ANDROID
619 if (g_timeout_ms)
620 {
621 setup_auto_kill(g_timeout_ms);
622 }
623#endif
624
625 if (vchiq_initialise(&vchiq_instance) != VCHIQ_SUCCESS)
626 {
627 printf("* failed to open vchiq instance\n");
628 return VCHIQ_ERROR;
629 }
630
631 vchiq_connect(vchiq_instance);
632
633 memset(&service_params, 0, sizeof(service_params));
634 service_params.version.version = service_params.version.version_min = VCHIQ_TEST_VER;
635 service_params.service_id = fourcc;
636 service_params.callback = vchi_clnt_callback;
637 service_params.callback_param = &vchi_service;
638
639 if (vchi_service_open((VCHI_INSTANCE_T)vchiq_instance, &service_params, &vchi_service) != VCHIQ_SUCCESS)
640 {
641 printf("* failed to open service - already in use?\n");
642 return VCHIQ_ERROR;
643 }
644
645 for (i = 0; i < sizeof(sizes)/sizeof(sizes[0]); i++)
646 {
647 const int iter_count = g_params.iters;
648 do_vchi_ping_test(vchi_service, sizes[i], 0, 0, iter_count);
649 do_vchi_ping_test(vchi_service, sizes[i], 0, 0, iter_count);
650 do_vchi_ping_test(vchi_service, sizes[i], 1, 0, iter_count);
651 do_vchi_ping_test(vchi_service, sizes[i], 2, 0, iter_count);
652 do_vchi_ping_test(vchi_service, sizes[i], 10, 0, iter_count);
653 do_vchi_ping_test(vchi_service, sizes[i], 0, 1, iter_count);
654 do_vchi_ping_test(vchi_service, sizes[i], 0, 2, iter_count);
655 do_vchi_ping_test(vchi_service, sizes[i], 0, 10, iter_count);
656 do_vchi_ping_test(vchi_service, sizes[i], 10, 10, iter_count);
657 do_vchi_ping_test(vchi_service, sizes[i], 100, 0, iter_count/10);
658 do_vchi_ping_test(vchi_service, sizes[i], 0, 100, iter_count/10);
659 do_vchi_ping_test(vchi_service, sizes[i], 100, 100, iter_count/10);
660 do_vchi_ping_test(vchi_service, sizes[i], 200, 0, iter_count/10);
661 do_vchi_ping_test(vchi_service, sizes[i], 0, 200, iter_count/10);
662 do_vchi_ping_test(vchi_service, sizes[i], 200, 200, iter_count/10);
663 do_vchi_ping_test(vchi_service, sizes[i], 400, 0, iter_count/20);
664 do_vchi_ping_test(vchi_service, sizes[i], 0, 400, iter_count/20);
665 do_vchi_ping_test(vchi_service, sizes[i], 400, 400, iter_count/20);
666 do_vchi_ping_test(vchi_service, sizes[i], 1000, 0, iter_count/50);
667 do_vchi_ping_test(vchi_service, sizes[i], 0, 1000, iter_count/50);
668 do_vchi_ping_test(vchi_service, sizes[i], 1000, 1000, iter_count/50);
669 }
670
671 vchi_service_close(vchi_service);
672
673 INIT_PARAMS(&vchiq_service_params, fourcc, clnt_callback, "clnt userdata", VCHIQ_TEST_VER);
674 if (vchiq_open_service(vchiq_instance, &vchiq_service_params, &vchiq_service) != VCHIQ_SUCCESS)
675 {
676 printf("* failed to open service - already in use?\n");
677 return VCHIQ_ERROR;
678 }
679
680 for (i = 0; i < sizeof(sizes)/sizeof(sizes[0]); i++)
681 {
682 const int iter_count = g_params.iters;
683 do_ping_test(vchiq_service, sizes[i], 0, 0, iter_count);
684 do_ping_test(vchiq_service, sizes[i], 0, 0, iter_count);
685 do_ping_test(vchiq_service, sizes[i], 1, 0, iter_count);
686 do_ping_test(vchiq_service, sizes[i], 2, 0, iter_count);
687 do_ping_test(vchiq_service, sizes[i], 10, 0, iter_count);
688 do_ping_test(vchiq_service, sizes[i], 0, 1, iter_count);
689 do_ping_test(vchiq_service, sizes[i], 0, 2, iter_count);
690 do_ping_test(vchiq_service, sizes[i], 0, 10, iter_count);
691 do_ping_test(vchiq_service, sizes[i], 10, 10, iter_count);
692 do_ping_test(vchiq_service, sizes[i], 100, 0, iter_count/10);
693 do_ping_test(vchiq_service, sizes[i], 0, 100, iter_count/10);
694 do_ping_test(vchiq_service, sizes[i], 100, 100, iter_count/10);
695 do_ping_test(vchiq_service, sizes[i], 200, 0, iter_count/10);
696 do_ping_test(vchiq_service, sizes[i], 0, 200, iter_count/10);
697 do_ping_test(vchiq_service, sizes[i], 200, 200, iter_count/10);
698 do_ping_test(vchiq_service, sizes[i], 400, 0, iter_count/20);
699 do_ping_test(vchiq_service, sizes[i], 0, 400, iter_count/20);
700 do_ping_test(vchiq_service, sizes[i], 400, 400, iter_count/20);
701 do_ping_test(vchiq_service, sizes[i], 1000, 0, iter_count/50);
702 do_ping_test(vchiq_service, sizes[i], 0, 1000, iter_count/50);
703 do_ping_test(vchiq_service, sizes[i], 1000, 1000, iter_count/50);
704 }
705
706 vchiq_close_service(vchiq_service);
707
708 return VCHIQ_SUCCESS;
709}
710
711static VCHIQ_STATUS_T
712vchiq_signal_test(void)
713{
714 /* Measure message round trip time for various sizes*/
715 VCHIQ_INSTANCE_T vchiq_instance;
716 VCHIQ_SERVICE_HANDLE_T vchiq_service;
717 VCHIQ_SERVICE_PARAMS_T vchiq_service_params;
718 int fourcc;
719
720 static int sizes[] = { 0, 1024, 2048, VCHIQ_MAX_MSG_SIZE };
721
722 fourcc = VCHIQ_MAKE_FOURCC(g_servname[0], g_servname[1], g_servname[2], g_servname[3]);
723
724 printf("signal test - service:%s, iters:%d, version %d\n", g_servname, g_params.iters, VCHIQ_TEST_VER);
725
726#ifdef ANDROID
727 if (g_timeout_ms)
728 {
729 setup_auto_kill(g_timeout_ms);
730 }
731#endif
732
733 if (vchiq_initialise(&vchiq_instance) != VCHIQ_SUCCESS)
734 {
735 printf("* failed to open vchiq instance\n");
736 return VCHIQ_ERROR;
737 }
738
739 vchiq_connect(vchiq_instance);
740
741 INIT_PARAMS(&vchiq_service_params, fourcc, clnt_callback, "clnt userdata", VCHIQ_TEST_VER);
742 if (vchiq_open_service(vchiq_instance, &vchiq_service_params, &vchiq_service) != VCHIQ_SUCCESS)
743 {
744 printf("* failed to open service - already in use?\n");
745 return VCHIQ_ERROR;
746 }
747
748 vchiq_bulk_transmit(vchiq_service, &sizes, 16, 0, VCHIQ_BULK_MODE_BLOCKING);
749
750 vchiq_close_service(vchiq_service);
751
752 return VCHIQ_SUCCESS;
753}
754
755static VCHIQ_STATUS_T
756do_functional_test(void)
757{
758 VCHIQ_ELEMENT_T elements[4];
759 VCHIQ_INSTANCE_T instance;
760 VCHIQ_SERVICE_HANDLE_T service, service2, service3;
761 VCHIQ_SERVICE_PARAMS_T service_params;
762 VCHIQ_CONFIG_T config;
763 unsigned int size, i;
764
765 vcos_event_create(&func_test_sync, "test_sync");
766
767#ifdef ANDROID
768 if (g_timeout_ms)
769 {
770 setup_auto_kill(g_timeout_ms);
771 }
772#endif
773
774 if (func_data_test_start != -1)
775 goto bulk_tests_only;
776
777 EXPECT(vchiq_initialise(&instance), VCHIQ_SUCCESS);
778 EXPECT(vchiq_get_config(instance, sizeof(config) - 1, &config), VCHIQ_SUCCESS); // too small, but allowed for backwards compatibility
779 EXPECT(vchiq_get_config(instance, sizeof(config) + 1, &config), VCHIQ_ERROR); // too large
780 EXPECT(vchiq_get_config(instance, sizeof(config), &config), VCHIQ_SUCCESS); // just right
781 EXPECT(config.max_msg_size, VCHIQ_MAX_MSG_SIZE);
782
783 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void *)1, VCHIQ_TEST_VER);
784 EXPECT(vchiq_add_service(instance, &service_params, &service), VCHIQ_SUCCESS);
785
786 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void *)2, VCHIQ_TEST_VER);
787 EXPECT(vchiq_add_service(instance, &service_params, &service2), VCHIQ_SUCCESS);
788
789 INIT_PARAMS(&service_params, FUNC_FOURCC, clnt_callback, (void *)3, VCHIQ_TEST_VER);
790 EXPECT(vchiq_add_service(instance, &service_params, &service3), VCHIQ_ERROR); // callback doesn't match
791
792 EXPECT(vchiq_set_service_option(service, VCHIQ_SERVICE_OPTION_AUTOCLOSE, 0), VCHIQ_SUCCESS);
793 EXPECT(vchiq_set_service_option(service, VCHIQ_SERVICE_OPTION_AUTOCLOSE, 1), VCHIQ_SUCCESS);
794 EXPECT(vchiq_set_service_option(service, 42, 1), VCHIQ_ERROR); // invalid option
795 EXPECT(vchiq_remove_service(service), VCHIQ_SUCCESS);
796 EXPECT(vchiq_remove_service(service), VCHIQ_ERROR); // service already removed
797 EXPECT(vchiq_remove_service(service2), VCHIQ_SUCCESS);
798 EXPECT(vchiq_queue_message(service, NULL, 0), VCHIQ_ERROR); // service not valid
799 EXPECT(vchiq_set_service_option(service, VCHIQ_SERVICE_OPTION_AUTOCLOSE, 0), VCHIQ_ERROR); // service not valid
800
801 INIT_PARAMS(&service_params, FUNC_FOURCC, clnt_callback, (void *)3, VCHIQ_TEST_VER);
802 EXPECT(vchiq_add_service(instance, &service_params, &service3), VCHIQ_SUCCESS);
803
804 EXPECT(vchiq_queue_message(service, NULL, 0), VCHIQ_ERROR); // service not open
805 EXPECT(vchiq_queue_bulk_transmit(service, clnt_service1_data, sizeof(clnt_service1_data), (void *)1), VCHIQ_ERROR); // service not open
806 EXPECT(vchiq_queue_bulk_receive(service2, clnt_service2_data, sizeof(clnt_service2_data), (void *)2), VCHIQ_ERROR); // service not open
807 EXPECT(vchiq_queue_bulk_receive(service, 0, sizeof(clnt_service1_data), (void *)1), VCHIQ_ERROR); // invalid buffer
808 EXPECT(vchiq_shutdown(instance), VCHIQ_SUCCESS);
809 EXPECT(vchiq_initialise(&instance), VCHIQ_SUCCESS);
810 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void*)1, 0);
811 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_ERROR); // not connected
812 EXPECT(vchiq_connect(instance), VCHIQ_SUCCESS);
813 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_ERROR); // wrong version number
814 memset(&service_params, 0, sizeof(service_params));
815 service_params.fourcc = FUNC_FOURCC;
816 service_params.callback = func_clnt_callback;
817 service_params.userdata = (void*)1;
818 service_params.version = 1;
819 service_params.version_min = 1;
820 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_ERROR); // Still the wrong version number
821 service_params.version = VCHIQ_TEST_VER + 1;
822 service_params.version_min = VCHIQ_TEST_VER + 1;
823 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_ERROR); // Still the wrong version number
824 service_params.version = VCHIQ_TEST_VER;
825 service_params.version_min = VCHIQ_TEST_VER;
826 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_SUCCESS); // That's better
827
828 INIT_PARAMS(&service_params, VCHIQ_MAKE_FOURCC('n','o','n','e'), func_clnt_callback, (void*)2, VCHIQ_TEST_VER);
829 EXPECT(vchiq_open_service(instance, &service_params, &service2), VCHIQ_ERROR); // no listener
830 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void*)2, VCHIQ_TEST_VER);
831 EXPECT(vchiq_open_service(instance, &service_params, &service2), VCHIQ_SUCCESS);
832 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void*)3, VCHIQ_TEST_VER);
833 EXPECT(vchiq_open_service(instance, &service_params, &service3), VCHIQ_ERROR); // no more listeners
834 EXPECT(vchiq_remove_service(service2), VCHIQ_SUCCESS);
835 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, (void*)2, VCHIQ_TEST_VER);
836 EXPECT(vchiq_open_service(instance, &service_params, &service2), VCHIQ_SUCCESS);
837
838 elements[0].data = "a";
839 elements[0].size = 1;
840 elements[1].data = "bcdef";
841 elements[1].size = 5;
842 elements[2].data = "ghijklmnopq";
843 elements[2].size = 11;
844 elements[3].data = "rstuvwxyz";
845 elements[3].size = 9;
846 EXPECT(vchiq_queue_message(service, elements, 4), VCHIQ_SUCCESS);
847
848 EXPECT(vchiq_queue_bulk_transmit(service2, clnt_service2_data, sizeof(clnt_service2_data), (void *)0x2001), VCHIQ_SUCCESS);
849 for (i = 0; i < sizeof(clnt_service1_data); i++)
850 {
851 clnt_service1_data[i] = (char)i;
852 }
853 EXPECT(vchiq_queue_bulk_transmit(service, clnt_service1_data, sizeof(clnt_service1_data), (void*)0x1001), VCHIQ_SUCCESS);
854
855 vcos_event_wait(&func_test_sync);
856 EXPECT(func_error, 0);
857 EXPECT(vchiq_remove_service(service), VCHIQ_SUCCESS);
858 vcos_event_wait(&func_test_sync);
859
860 EXPECT(vchiq_shutdown(instance), VCHIQ_SUCCESS);
861
862 vcos_event_wait(&func_test_sync);
863 EXPECT(func_error, 0);
864
865 INIT_PARAMS(&service_params, FUNC_FOURCC, func_clnt_callback, NULL, VCHIQ_TEST_VER);
866 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_ERROR); /* Instance not initialised */
867 EXPECT(vchiq_add_service(instance, &service_params, &service), VCHIQ_ERROR); /* Instance not initialised */
868 EXPECT(vchiq_connect(instance), VCHIQ_ERROR); /* Instance not initialised */
869
870bulk_tests_only:
871 /* Now test the bulk data transfers */
872 EXPECT(vchiq_initialise(&instance), VCHIQ_SUCCESS);
873 EXPECT(vchiq_connect(instance), VCHIQ_SUCCESS);
874
875 func_data_test_iter = 0;
876
877 INIT_PARAMS(&service_params, FUN2_FOURCC, fun2_clnt_callback, NULL, VCHIQ_TEST_VER);
878 EXPECT(vchiq_open_service(instance, &service_params, &service), VCHIQ_SUCCESS);
879
880 if (func_data_test_end < func_data_test_start)
881 goto skip_bulk_tests;
882
883 printf("Testing bulk transfer for alignment.\n");
884 for (size = 1; size < 64; size++)
885 {
886 int align, srvr_align;
887 for (srvr_align = 32; srvr_align; srvr_align >>= 1)
888 {
889 for (align = 32; align; align >>= 1)
890 {
891 EXPECT(func_data_test(service, size, align & 31, srvr_align & 31), VCHIQ_SUCCESS);
892 }
893 }
894 }
895
896 printf("Testing bulk transfer at PAGE_SIZE.\n");
897 for (size = 1; size < 64; size++)
898 {
899 int align, srvr_align;
900 for (srvr_align = 32; srvr_align; srvr_align >>= 1)
901 {
902 for (align = 32; align; align >>= 1)
903 {
904 EXPECT(func_data_test(service, size, PAGE_SIZE - align, srvr_align & 31), VCHIQ_SUCCESS);
905 }
906 }
907 }
908
909 for (size = 64; size < FUN2_MAX_DATA_SIZE; size<<=1)
910 {
911 static const int aligns[] = { 0, 1, 31 };
912
913 for (i = 0; i < vcos_countof(aligns); i++)
914 {
915 int srvr_align = aligns[i];
916 unsigned int j;
917 for (j = 0; j < vcos_countof(aligns); j++)
918 {
919 int k;
920 int align = aligns[j];
921 for (k = 0; k <= 8; k++)
922 {
923 EXPECT(func_data_test(service, size, align, srvr_align + k), VCHIQ_SUCCESS);
924 }
925 }
926 }
927 }
928
929skip_bulk_tests:
930
931 EXPECT(vchiq_shutdown(instance), VCHIQ_SUCCESS);
932
933 vcos_event_delete(&func_test_sync);
934
935 return VCHIQ_SUCCESS;
936
937error_exit:
938 return VCHIQ_ERROR;
939}
940
941static void
942do_ping_test(VCHIQ_SERVICE_HANDLE_T service, int size, int async, int oneway, int iters)
943{
944 uint32_t start, end;
945 char *ping_buf = malloc(size + sizeof(struct test_params));
946 struct test_params *params = (struct test_params *)ping_buf;
947 VCHIQ_ELEMENT_T element;
948 int i;
949
950 element.data = ping_buf;
951
952 /* Set up the quotas for messages */
953 *params = g_params;
954 params->magic = MSG_CONFIG;
955 params->blocksize = 0;
956 element.size = sizeof(*params);
957 vchiq_queue_message(service, &element, 1);
958 vcos_event_wait(&g_server_reply);
959 vchiq_set_service_option(service, VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, params->client_message_quota);
960
961 /* Allow enough room for the type header */
962 element.size = (size < 4) ? 4 : size;
963
964 bulk_tx_received = -1;
965
966 start = vcos_getmicrosecs();
967 for (i = 0; i < iters; i++)
968 {
969 int j;
970 for (j = 0; j < vcos_max(async, oneway); j++)
971 {
972 if (j < async)
973 {
974 params->magic = MSG_ASYNC;
975 vchiq_queue_message(service, &element, 1);
976 }
977 if (j < oneway)
978 {
979 params->magic = MSG_ONEWAY;
980 vchiq_queue_message(service, &element, 1);
981 }
982 }
983 params->magic = MSG_SYNC;
984 vchiq_queue_message(service, &element, 1);
985 vcos_event_wait(&g_server_reply);
986 }
987 end = vcos_getmicrosecs();
988
989 printf("ping (size %d, %d async, %d oneway) -> %fus\n", size, async, oneway, ((float)(end - start))/iters);
990
991 vcos_sleep(20);
992
993 if ((async == 0) && (oneway == 0))
994 {
995 *params = g_params;
996 params->magic = MSG_CONFIG;
997 params->blocksize = size ? size : 8;
998 params->iters = iters;
999 params->verify = 0;
1000 params->echo = 0;
1001
1002 element.size = sizeof(*params);
1003 vchiq_queue_message(service, &element, 1);
1004 vcos_event_wait(&g_server_reply);
1005
1006 vcos_sleep(30);
1007
1008 start = vcos_getmicrosecs();
1009 for (i = 0; i < iters; i++)
1010 {
1011 vchiq_queue_bulk_transmit(service, ping_buf, params->blocksize, 0);
1012 vcos_event_wait(&g_server_reply);
1013 }
1014 end = vcos_getmicrosecs();
1015
1016 printf("bulk (size %d, async) -> %fus\n", size, ((float)(end - start))/iters);
1017
1018 vcos_sleep(40);
1019 }
1020
1021 if (oneway == 0)
1022 {
1023 *params = g_params;
1024 params->magic = MSG_CONFIG;
1025 params->blocksize = size ? size : 8;
1026 params->iters = iters * (async + 1);
1027 params->verify = 0;
1028 params->echo = 0;
1029
1030 element.size = sizeof(*params);
1031 vchiq_queue_message(service, &element, 1);
1032 vcos_event_wait(&g_server_reply);
1033
1034 vcos_sleep(50);
1035
1036 start = vcos_getmicrosecs();
1037 for (i = 0; i < iters; i++)
1038 {
1039 int j;
1040 for (j = 0; j < async; j++)
1041 vchiq_bulk_transmit(service, ping_buf, params->blocksize, 0, VCHIQ_BULK_MODE_NOCALLBACK);
1042 vchiq_bulk_transmit(service, ping_buf, params->blocksize, 0, VCHIQ_BULK_MODE_BLOCKING);
1043 }
1044 end = vcos_getmicrosecs();
1045
1046 printf("bulk (size %d, %d async) -> %fus\n", size, async, ((float)(end - start))/iters);
1047
1048 vcos_sleep(60);
1049 }
1050
1051 free(ping_buf);
1052
1053 bulk_tx_received = 0;
1054}
1055
1056static void
1057do_vchi_ping_test(VCHI_SERVICE_HANDLE_T service, int size, int async, int oneway, int iters)
1058{
1059 uint32_t start, end;
1060 uint32_t actual;
1061 char *ping_buf = malloc(size + sizeof(struct test_params));
1062 char pong_buf[100];
1063 struct test_params *params = (struct test_params *)ping_buf;
1064 int msg_size;
1065 int i;
1066
1067 /* Set up the quotas for messages */
1068 *params = g_params;
1069 params->magic = MSG_CONFIG;
1070 params->blocksize = 0;
1071 vchi_msg_queue(service, params, sizeof(*params), VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1072 vcos_event_wait(&g_server_reply);
1073 vchiq_set_service_option((VCHIQ_SERVICE_HANDLE_T)service, VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, params->client_message_quota);
1074
1075 /* Allow enough room for the type header */
1076 msg_size = (size < 4) ? 4 : size;
1077
1078 bulk_tx_received = -1;
1079
1080 if ((oneway == 0) && (async == 0))
1081 {
1082 params->magic = MSG_SYNC;
1083
1084 g_sync_mode = 1;
1085
1086 start = vcos_getmicrosecs();
1087 for (i = 0; i < iters; i++)
1088 {
1089 vchi_msg_queue(service, ping_buf, msg_size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1090 vchi_msg_dequeue(service, pong_buf, sizeof(pong_buf), &actual, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
1091 }
1092 end = vcos_getmicrosecs();
1093
1094 printf("vchi ping (size %d) -> %fus\n", size, ((float)(end - start))/iters);
1095
1096 vcos_sleep(10);
1097
1098 g_sync_mode = 0;
1099 }
1100
1101 while (vchi_msg_dequeue(service, pong_buf, sizeof(pong_buf), &actual, VCHI_FLAGS_NONE) != -1)
1102 {
1103 printf("* Unexpected message found in queue - size %d\n", actual);
1104 }
1105
1106 start = vcos_getmicrosecs();
1107 for (i = 0; i < iters; i++)
1108 {
1109 int j;
1110 for (j = 0; j < vcos_max(async, oneway); j++)
1111 {
1112 if (j < async)
1113 {
1114 params->magic = MSG_ASYNC;
1115 vchi_msg_queue(service, ping_buf, msg_size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1116 }
1117 if (j < oneway)
1118 {
1119 params->magic = MSG_ONEWAY;
1120 vchi_msg_queue(service, ping_buf, msg_size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1121 }
1122 }
1123 params->magic = MSG_SYNC;
1124 vchi_msg_queue(service, ping_buf, msg_size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1125 vcos_event_wait(&g_server_reply);
1126 }
1127 end = vcos_getmicrosecs();
1128
1129 printf("vchi ping (size %d, %d async, %d oneway) -> %fus\n", size, async, oneway, ((float)(end - start))/iters);
1130
1131 vcos_sleep(20);
1132
1133 if ((async == 0) && (oneway == 0))
1134 {
1135 *params = g_params;
1136 params->magic = MSG_CONFIG;
1137 params->blocksize = size ? size : 8;
1138 params->iters = iters;
1139 params->verify = 0;
1140 params->echo = 0;
1141
1142 vchi_msg_queue(service, params, sizeof(*params), VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1143 vcos_event_wait(&g_server_reply);
1144
1145 vcos_sleep(30);
1146
1147 start = vcos_getmicrosecs();
1148 for (i = 0; i < iters; i++)
1149 {
1150 vchi_bulk_queue_transmit(service, ping_buf, params->blocksize,
1151 VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1152 vcos_event_wait(&g_server_reply);
1153 }
1154 end = vcos_getmicrosecs();
1155
1156 printf("vchi bulk (size %d, %d async, %d oneway) -> %fus\n", size, async, oneway, ((float)(end - start))/iters);
1157
1158 vcos_sleep(40);
1159 }
1160
1161 if (oneway == 0)
1162 {
1163 *params = g_params;
1164 params->magic = MSG_CONFIG;
1165 params->blocksize = size ? size : 8;
1166 params->iters = iters * (async + 1);
1167 params->verify = 0;
1168 params->echo = 0;
1169
1170 vchi_msg_queue(service, params, sizeof(*params), VCHI_FLAGS_BLOCK_UNTIL_QUEUED, 0);
1171 vcos_event_wait(&g_server_reply);
1172
1173 vcos_sleep(50);
1174
1175 start = vcos_getmicrosecs();
1176 for (i = 0; i < iters; i++)
1177 {
1178 int j;
1179 for (j = 0; j < async; j++)
1180 vchi_bulk_queue_transmit(service, ping_buf, params->blocksize, VCHI_FLAGS_NONE, 0);
1181 vchi_bulk_queue_transmit(service, ping_buf, params->blocksize, VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, 0);
1182 }
1183 end = vcos_getmicrosecs();
1184
1185 printf("vchi bulk (size %d, %d oneway) -> %fus\n", size, oneway, ((float)(end - start))/iters);
1186
1187 vcos_sleep(60);
1188 }
1189
1190 free(ping_buf);
1191
1192 bulk_tx_received = 0;
1193}
1194
1195static VCHIQ_STATUS_T
1196func_data_test(VCHIQ_SERVICE_HANDLE_T service, int datalen, int align, int server_align)
1197{
1198 enum { PROLOGUE_SIZE = 32, EPILOGUE_SIZE = 32 };
1199 static uint8_t databuf[PAGE_SIZE + PROLOGUE_SIZE + FUN2_MAX_DATA_SIZE + EPILOGUE_SIZE];
1200 static uint8_t databuf2[PAGE_SIZE + PROLOGUE_SIZE + FUN2_MAX_DATA_SIZE + EPILOGUE_SIZE];
1201 uint8_t *data, *data2, *prologue, *epilogue;
1202 VCHIQ_ELEMENT_T element;
1203 int params[4] = { datalen, server_align, align, func_data_test_iter };
1204 int success = 1, i;
1205
1206 if (!vcos_verify(datalen < FUN2_MAX_DATA_SIZE))
1207 return VCHIQ_ERROR;
1208
1209 if ((func_data_test_iter < func_data_test_start) || (func_data_test_iter > func_data_test_end))
1210 goto skip_iter;
1211
1212 element.size = sizeof(params);
1213 element.data = &params;
1214 EXPECT(vchiq_queue_message(service, &element, 1), VCHIQ_SUCCESS);
1215
1216 memset(databuf, 0xff, sizeof(databuf));
1217 data = (uint8_t *)((uintptr_t)databuf & ~(PAGE_SIZE - 1)) + align;
1218 data = (uint8_t *)((((intptr_t)databuf + PROLOGUE_SIZE) & ~(FUN2_MAX_ALIGN - 1)) + align - PROLOGUE_SIZE);
1219 if (data < databuf)
1220 data += PAGE_SIZE;
1221 data += PROLOGUE_SIZE;
1222
1223 EXPECT(vchiq_queue_bulk_receive(service, data, datalen, NULL), VCHIQ_SUCCESS);
1224
1225 data2 = (uint8_t *)(((uintptr_t)databuf2 + PROLOGUE_SIZE) & ~(PAGE_SIZE - 1)) + align - PROLOGUE_SIZE;
1226 if (data2 < databuf2)
1227 data2 += PAGE_SIZE;
1228 prologue = data2;
1229 data2 += PROLOGUE_SIZE;
1230 epilogue = data2 + datalen;
1231
1232 memset(prologue, 0xff, PROLOGUE_SIZE);
1233 memset(epilogue, 0xff, EPILOGUE_SIZE);
1234
1235 for (i = 0; i < (datalen - 1); i++)
1236 {
1237 data2[i] = (uint8_t)(((i & 0x1f) == 0) ? (i >> 5) : i);
1238 }
1239 data2[i] = '\0';
1240
1241 /* Attempt to pull the boundaries into the cache */
1242 prologue = data - PROLOGUE_SIZE;
1243 epilogue = data + datalen;
1244 prologue[PROLOGUE_SIZE - 1] = 0xfe;
1245 epilogue[0] = 0xfe;
1246
1247 EXPECT(vchiq_queue_bulk_transmit(service, data2, datalen, NULL), VCHIQ_SUCCESS);
1248 vcos_event_wait(&func_test_sync); /* Wait for the receive to complete */
1249
1250 for (i = 0; i < PROLOGUE_SIZE; i++)
1251 {
1252 if (prologue[i] != (uint8_t)((i == PROLOGUE_SIZE - 1) ? '\xfe' : '\xff'))
1253 {
1254 vcos_log_error("%d: Prologue corrupted at %x (datalen %x, align %x, server_align %x) -> %02x", func_data_test_iter, i, datalen, align, server_align, prologue[i]);
1255 VCOS_BKPT;
1256 success = 0;
1257 break;
1258 }
1259 }
1260 for (i = 0; i < EPILOGUE_SIZE; i++)
1261 {
1262 if (epilogue[i] != (uint8_t)((i == 0) ? '\xfe' : '\xff'))
1263 {
1264 vcos_log_error("%d: Epilogue corrupted at %x (datalen %x, align %x, server_align %x) -> %02x", func_data_test_iter, i, datalen, align, server_align, epilogue[i]);
1265 VCOS_BKPT;
1266 success = 0;
1267 break;
1268 }
1269 }
1270
1271 if (success)
1272 {
1273 int diffs = 0;
1274 for (i = 0; i < datalen; i++)
1275 {
1276 int diff = (i == datalen - 1) ?
1277 (data[i] != 0) :
1278 ((i & 0x1f) == 0) ?
1279 (data[i] != (uint8_t)(i >> 5)) :
1280 (data[i] != (uint8_t)i);
1281
1282 if (diff)
1283 diffs++;
1284 else if (diffs)
1285 {
1286 vcos_log_error("%d: Data corrupted at %x-%x (datalen %x, align %x, server_align %x) -> %02x", func_data_test_iter, i - diffs, i - 1, datalen, align, server_align, data[i-1]);
1287 VCOS_BKPT;
1288 success = 0;
1289 diffs = 0;
1290 }
1291 }
1292 if (diffs)
1293 {
1294 vcos_log_error("%d: Data corrupted at %x-%x (datalen %x, align %x, server_align %x) -> %02x", func_data_test_iter, i - diffs, i - 1, datalen, align, server_align, data[i-1]);
1295 VCOS_BKPT;
1296 success = 0;
1297 }
1298 }
1299
1300skip_iter:
1301 if (success)
1302 {
1303 func_data_test_iter++;
1304 return VCHIQ_SUCCESS;
1305 }
1306
1307error_exit:
1308 return VCHIQ_ERROR;
1309}
1310
1311
1312#ifdef VCHIQ_LOCAL
1313
1314static void *vchiq_test_server(void *param)
1315{
1316 VCHIQ_INSTANCE_T instance;
1317
1318 vcos_demand(vchiq_initialise(&instance) == VCHIQ_SUCCESS);
1319 vchiq_test_start_services(instance);
1320 vchiq_connect(instance);
1321 printf("test server started\n");
1322 return 0;
1323}
1324
1325#endif
1326
1327static VCHIQ_STATUS_T
1328clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
1329 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata)
1330{
1331 int data;
1332 vcos_mutex_lock(&g_mutex);
1333 if (reason == VCHIQ_MESSAGE_AVAILABLE)
1334 {
1335 /*
1336 * Store the header size as it is going to be released
1337 * and the size may be overwritten by the release.
1338 */
1339 size_t header_size = header->size;
1340
1341 if (header_size <= 1)
1342 vchiq_release_message(service, header);
1343 else
1344 /* Responses of length 0 are not sync points */
1345 if ((header_size >= 4) && (memcpy(&data, header->data, sizeof(data)), data == MSG_ECHO))
1346 {
1347 /* This is a complete echoed packet */
1348 if (g_params.verify && (mem_check(header->data, bulk_tx_data[ctrl_received % NUM_BULK_BUFS], g_params.blocksize) != 0))
1349 g_server_error = "corrupt data";
1350 else
1351 ctrl_received++;
1352 if (g_server_error || (ctrl_received == g_params.iters))
1353 vcos_event_signal(&g_shutdown);
1354 vchiq_release_message(service, header);
1355 }
1356 else if (header_size != 0)
1357 g_server_error = header->data;
1358
1359 if ((header_size != 0) || g_server_error)
1360 vcos_event_signal(&g_server_reply);
1361 }
1362 else if (reason == VCHIQ_BULK_TRANSMIT_DONE)
1363 {
1364 int i = (int)bulk_userdata;
1365 vcos_log_trace(" BULK_TRANSMIT_DONE(%d)", i);
1366 if (bulk_tx_received < 0)
1367 vcos_event_signal(&g_server_reply);
1368 else
1369 {
1370 vcos_assert(i == bulk_tx_received);
1371 bulk_tx_received++;
1372 if (bulk_tx_sent < g_params.iters)
1373 {
1374 vchiq_queue_bulk_transmit(service, bulk_tx_data[i % NUM_BULK_BUFS], g_params.blocksize, (void *)bulk_tx_sent);
1375 bulk_tx_sent++;
1376 }
1377 }
1378 }
1379 else if (reason == VCHIQ_BULK_RECEIVE_DONE)
1380 {
1381 int i = (int)bulk_userdata;
1382 vcos_log_trace(" BULK_RECEIVE_DONE(%d): data '%s'", i, bulk_rx_data[i % NUM_BULK_BUFS]);
1383 vcos_assert(i == bulk_rx_received);
1384 if (g_params.verify && (mem_check(bulk_tx_data[i % NUM_BULK_BUFS], bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize) != 0))
1385 {
1386 vcos_log_error("* Data corruption - %d: %x, %x, %x", i, (unsigned int)bulk_tx_data[i % NUM_BULK_BUFS], (unsigned int)bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize);
1387 VCOS_BKPT;
1388 }
1389 bulk_rx_received++;
1390 if (bulk_rx_sent < g_params.iters)
1391 {
1392 if (g_params.verify)
1393 memset(bulk_rx_data[i % NUM_BULK_BUFS], 0xff, g_params.blocksize);
1394 vchiq_queue_bulk_receive(service, bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize, (void *)bulk_rx_sent);
1395 bulk_rx_sent++;
1396 }
1397 }
1398 else if (reason == VCHIQ_BULK_TRANSMIT_ABORTED)
1399 {
1400 int i = (int)bulk_userdata;
1401 vcos_log_info(" BULK_TRANSMIT_ABORTED(%d)", i);
1402 }
1403 else if (reason == VCHIQ_BULK_RECEIVE_ABORTED)
1404 {
1405 int i = (int)bulk_userdata;
1406 vcos_log_info(" BULK_RECEIVE_ABORTED(%d)", i);
1407 }
1408 if ((bulk_tx_received == g_params.iters) &&
1409 ((g_params.echo == 0) || (bulk_rx_received == g_params.iters)))
1410 vcos_event_signal(&g_shutdown);
1411 vcos_mutex_unlock(&g_mutex);
1412 return VCHIQ_SUCCESS;
1413}
1414
1415static void
1416vchi_clnt_callback(void *callback_param,
1417 VCHI_CALLBACK_REASON_T reason,
1418 void *handle)
1419{
1420 VCHI_SERVICE_HANDLE_T service = *(VCHI_SERVICE_HANDLE_T *)callback_param;
1421 vcos_mutex_lock(&g_mutex);
1422 if (reason == VCHI_CALLBACK_MSG_AVAILABLE)
1423 {
1424 if (!g_sync_mode)
1425 {
1426 static char pong_buf[100];
1427 uint32_t actual;
1428 while (vchi_msg_dequeue(service, pong_buf, sizeof(pong_buf), &actual, VCHI_FLAGS_NONE) == 0)
1429 {
1430 if (actual > 1)
1431 g_server_error = pong_buf;
1432 if (actual != 0)
1433 {
1434 /* Responses of length 0 are not sync points */
1435 vcos_event_signal(&g_server_reply);
1436 break;
1437 }
1438 }
1439 }
1440 }
1441 else if (reason == VCHI_CALLBACK_BULK_SENT)
1442 {
1443 int i = (int)handle;
1444 vcos_log_trace(" BULK_TRANSMIT_DONE(%d)", i);
1445 if (bulk_tx_received < 0)
1446 vcos_event_signal(&g_server_reply);
1447 else
1448 {
1449 vcos_assert(i == bulk_tx_received);
1450 bulk_tx_received++;
1451 if (bulk_tx_sent < g_params.iters)
1452 {
1453 vchi_bulk_queue_transmit(service, bulk_tx_data[i % NUM_BULK_BUFS],
1454 g_params.blocksize,
1455 VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
1456 (void *)bulk_tx_sent);
1457 bulk_tx_sent++;
1458 }
1459 }
1460 }
1461 else if (reason == VCHI_CALLBACK_BULK_RECEIVED)
1462 {
1463 int i = (int)handle;
1464 vcos_log_trace(" BULK_RECEIVE_DONE(%d): data '%s'", i, bulk_rx_data[i % NUM_BULK_BUFS]);
1465 vcos_assert(i == bulk_rx_received);
1466 if (g_params.verify && (mem_check(bulk_tx_data[i % NUM_BULK_BUFS], bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize) != 0))
1467 {
1468 vcos_log_error("* Data corruption - %x, %x, %x", (unsigned int)bulk_tx_data[i % NUM_BULK_BUFS], (unsigned int)bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize);
1469 VCOS_BKPT;
1470 }
1471 bulk_rx_received++;
1472 if (bulk_rx_sent < g_params.iters)
1473 {
1474 if (g_params.verify)
1475 memset(bulk_rx_data[i % NUM_BULK_BUFS], 0xff, g_params.blocksize);
1476 vchi_bulk_queue_receive(service, bulk_rx_data[i % NUM_BULK_BUFS], g_params.blocksize,
1477 VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
1478 (void *)bulk_rx_sent);
1479 bulk_rx_sent++;
1480 }
1481 }
1482 else if (reason == VCHI_CALLBACK_BULK_TRANSMIT_ABORTED)
1483 {
1484 int i = (int)handle;
1485 vcos_log_info(" BULK_TRANSMIT_ABORTED(%d)", i);
1486 }
1487 else if (reason == VCHI_CALLBACK_BULK_RECEIVE_ABORTED)
1488 {
1489 int i = (int)handle;
1490 vcos_log_info(" BULK_RECEIVE_ABORTED(%d)", i);
1491 }
1492 if ((bulk_tx_received == g_params.iters) && (bulk_rx_received == g_params.iters))
1493 vcos_event_signal(&g_shutdown);
1494 vcos_mutex_unlock(&g_mutex);
1495}
1496
1497static VCHIQ_STATUS_T
1498func_clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
1499 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata)
1500{
1501 static int callback_count = 0, bulk_count = 0;
1502 int callback_index = 0, bulk_index = 0;
1503
1504 if (reason < VCHIQ_BULK_TRANSMIT_DONE)
1505 {
1506 callback_count++;
1507
1508 START_CALLBACK(VCHIQ_SERVICE_CLOSED, 2)
1509 END_CALLBACK(VCHIQ_SUCCESS)
1510
1511 START_CALLBACK(VCHIQ_MESSAGE_AVAILABLE, 1)
1512 EXPECT(bulk_userdata, NULL);
1513 EXPECT(header->size, 26);
1514 EXPECT(mem_check(header->data, "abcdefghijklmnopqrstuvwxyz", 26), 0);
1515 vchiq_release_message(service, header);
1516 END_CALLBACK(VCHIQ_SUCCESS)
1517
1518 START_CALLBACK(VCHIQ_MESSAGE_AVAILABLE, 1)
1519 EXPECT(bulk_userdata, NULL);
1520 EXPECT(header->size, 0);
1521 vchiq_release_message(service, header);
1522 EXPECT(vchiq_queue_bulk_receive(service, clnt_service2_data, sizeof(clnt_service2_data), (void*)0x1004), VCHIQ_SUCCESS);
1523 vcos_event_signal(&func_test_sync);
1524 END_CALLBACK(VCHIQ_SUCCESS)
1525
1526 START_CALLBACK(VCHIQ_SERVICE_CLOSED, 1)
1527 vcos_event_signal(&func_test_sync);
1528 END_CALLBACK(VCHIQ_SUCCESS)
1529
1530 START_CALLBACK(VCHIQ_SERVICE_CLOSED, 2)
1531 vcos_event_signal(&func_test_sync);
1532 callback_count = 0;
1533 bulk_count = 0;
1534 END_CALLBACK(VCHIQ_SUCCESS)
1535 }
1536 else
1537 {
1538 bulk_count++;
1539
1540 START_BULK_CALLBACK(VCHIQ_BULK_TRANSMIT_DONE, 1, 0x1001)
1541 memset(clnt_service2_data, 0xff, sizeof(clnt_service2_data));
1542 EXPECT(vchiq_queue_bulk_receive(service, clnt_service2_data, sizeof(clnt_service2_data), (void*)0x1002), VCHIQ_SUCCESS);
1543 END_CALLBACK(VCHIQ_SUCCESS)
1544
1545 START_BULK_CALLBACK(VCHIQ_BULK_RECEIVE_ABORTED, 1, 0x1002)
1546 EXPECT(vchiq_queue_bulk_receive(service, clnt_service2_data, sizeof(clnt_service2_data), (void*)0x1003), VCHIQ_SUCCESS);
1547 END_CALLBACK(VCHIQ_SUCCESS)
1548
1549 START_BULK_CALLBACK(VCHIQ_BULK_RECEIVE_DONE, 1, 0x1003)
1550 (void)(mem_check(clnt_service1_data, clnt_service2_data, sizeof(clnt_service1_data)), 0);
1551 (void)(mem_check(clnt_service1_data, clnt_service2_data + sizeof(clnt_service1_data), sizeof(clnt_service1_data)), 0);
1552 END_CALLBACK(VCHIQ_SUCCESS)
1553
1554 START_BULK_CALLBACK(VCHIQ_BULK_RECEIVE_ABORTED, 1, 0x1004)
1555 END_CALLBACK(VCHIQ_SUCCESS)
1556
1557 START_BULK_CALLBACK(VCHIQ_BULK_TRANSMIT_ABORTED, 2, 0x2001)
1558 END_CALLBACK(VCHIQ_SUCCESS)
1559 }
1560
1561error_exit:
1562 callback_count = 0;
1563 bulk_count = 0;
1564
1565 func_error = 1;
1566 vcos_event_signal(&func_test_sync);
1567
1568 return VCHIQ_ERROR;
1569}
1570
1571static VCHIQ_STATUS_T
1572fun2_clnt_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
1573 VCHIQ_SERVICE_HANDLE_T service, void *bulk_userdata)
1574{
1575 vcos_unused(header);
1576 vcos_unused(service);
1577 vcos_unused(bulk_userdata);
1578
1579 switch (reason)
1580 {
1581 case VCHIQ_SERVICE_OPENED:
1582 case VCHIQ_SERVICE_CLOSED:
1583 case VCHIQ_BULK_TRANSMIT_DONE:
1584 break;
1585 case VCHIQ_BULK_RECEIVE_DONE:
1586 vcos_event_signal(&func_test_sync);
1587 break;
1588 default:
1589 fun2_error = 1;
1590 vcos_event_signal(&func_test_sync);
1591 break;
1592 }
1593
1594 return VCHIQ_SUCCESS;
1595}
1596
1597static int mem_check(const void *expected, const void *actual, int size)
1598{
1599 if (memcmp(expected, actual, size) != 0)
1600 {
1601 int i;
1602 for (i = 0; i < size; i++)
1603 {
1604 int ce = ((const char *)expected)[i];
1605 int ca = ((const char *)actual)[i];
1606 if (ca != ce)
1607 printf("%08x,%x: %02x <-> %02x\n", i + (unsigned int)actual, i, ce, ca);
1608 }
1609 printf("mem_check failed - buffer %x, size %d\n", (unsigned int)actual, size);
1610 return 1;
1611 }
1612 return 0;
1613}
1614
1615static void usage(void)
1616{
1617 printf("Usage: vchiq_test [<options>] <mode> <iters>\n");
1618 printf(" where <options> is any of:\n");
1619 printf(" -a <c> <s> set the client and server bulk alignment (modulo 32)\n");
1620 printf(" -A <c> <s> set the client and server bulk alignment (modulo 4096)\n");
1621 printf(" -e disable echoing in the main bulk transfer mode\n");
1622 printf(" -k <n> skip the first <n> func data tests\n");
1623 printf(" -m <n> set the client message quota to <n>\n");
1624 printf(" -M <n> set the server message quota to <n>\n");
1625 printf(" -q disable data verification\n");
1626 printf(" -s ???? service (any 4 characters)\n");
1627 printf(" -v enable more verbose output\n");
1628 printf(" -r <b> <s> reserve <b> bytes for <s> seconds\n");
1629 printf(" -K <t> send a SIGKILL after <t> ms\n");
1630 printf(" and <mode> is one of:\n");
1631 printf(" -c <size> control test (size in bytes)\n");
1632 printf(" -b <size> bulk test (size in kilobytes)\n");
1633 printf(" -f functional test\n");
1634 printf(" -p ping test\n");
1635 printf(" -t check the timer\n");
1636 printf(" and <iters> is the number of test iterations\n");
1637 exit(1);
1638}
1639
1640static void check_timer(void)
1641{
1642 uint32_t start = vcos_getmicrosecs();
1643 uint32_t sleep_time = 1000;
1644
1645 printf("0\n");
1646
1647 while (1)
1648 {
1649 uint32_t now;
1650 vcos_sleep(sleep_time);
1651 now = vcos_getmicrosecs();
1652 printf("%d - sleep %d\n", now - start, sleep_time);
1653 }
1654}
1655
1656static char *buf_align(char *buf, int align_size, int align)
1657{
1658 char *aligned = buf - ((intptr_t)buf & (align_size - 1)) + align;
1659 if (aligned < buf)
1660 aligned += align_size;
1661 return aligned;
1662}
1663
1664#ifdef ANDROID
1665
1666static void kill_timeout_handler(int cause, siginfo_t *how, void *ucontext)
1667{
1668 printf("Sending signal SIGKILL\n");
1669 kill(main_process_pid, SIGKILL);
1670}
1671
1672static int setup_auto_kill(int timeout_ms)
1673{
1674 long timeout;
1675 struct timeval interval;
1676
1677 if (timeout_ms <= 0)
1678 {
1679 return -1;
1680 }
1681 timeout = 1000 * timeout_ms;
1682
1683 /* install a signal handler for the alarm */
1684 struct sigaction sa;
1685 memset(&sa, 0, sizeof(struct sigaction));
1686 sa.sa_sigaction = kill_timeout_handler;
1687 sigemptyset(&sa.sa_mask);
1688 sa.sa_flags = SA_SIGINFO;
1689 if (sigaction(SIGALRM, &sa, 0))
1690 {
1691 perror("sigaction");
1692 exit(1);
1693 }
1694
1695 /* when to expire */
1696 interval.tv_sec = timeout / 1000000;
1697 interval.tv_usec = timeout % 1000000;
1698
1699 struct itimerval alarm_spec = {
1700 .it_interval = {0,0},
1701 .it_value = interval
1702 };
1703
1704 int rc = setitimer(ITIMER_REAL, &alarm_spec, NULL);
1705 if (rc < 0)
1706 {
1707 perror("setitimer failed");
1708 exit(1);
1709 }
1710
1711 return 0;
1712}
1713
1714
1715
1716#endif
1717
1718#ifdef VCOS_APPLICATION_INITIALIZE
1719
1720static VCOS_THREAD_T Task_0;
1721
1722void *main_task(void *param)
1723{
1724 vchiq_test(rtos_argc, rtos_argv);
1725
1726 VCOS_BKPT;
1727
1728 return NULL;
1729}
1730
1731#include "vcfw/logging/logging.h"
1732
1733void VCOS_APPLICATION_INITIALIZE(void *first_available_memory)
1734{
1735 const int stack_size = 64*1024;
1736 void *pointer = NULL;
1737 VCOS_STATUS_T status;
1738
1739 logging_init();
1740 logging_level(LOGGING_VCOS);
1741 vcos_init();
1742
1743 /* Create task 0. */
1744#if VCOS_CAN_SET_STACK_ADDR
1745 pointer = malloc(stack_size);
1746 vcos_demand(pointer);
1747#endif
1748 status = vcos_thread_create_classic( &Task_0, "TASK 0", main_task, (void *)0, pointer, stack_size,
1749 10 | VCOS_AFFINITY_DEFAULT, 20, VCOS_START );
1750 vcos_demand(status == VCOS_SUCCESS);
1751}
1752
1753#else
1754
1755int main(int argc, char **argv)
1756{
1757#ifdef ANDROID
1758 main_process_pid = getpid();
1759#endif
1760
1761 vcos_init();
1762 vcos_use_android_log = 0;
1763 return vchiq_test(argc, argv);
1764}
1765
1766#endif
1767