@@ -1,2 +1,3 @@
shmem_linux
-shmem_odp
+shmem_odp1
+shmem_odp2
@@ -2,19 +2,27 @@ include ../Makefile.inc
#the main test program is shmem_linux, which, in turn, starts a shmem_odp:
test_PROGRAMS = shmem_linux$(EXEEXT)
-test_extra_PROGRAMS = shmem_odp$(EXEEXT)
+test_extra_PROGRAMS = shmem_odp1$(EXEEXT) shmem_odp2$(EXEEXT)
test_extradir = $(testdir)
#shmem_linux is stand alone, pure linux (no ODP):
dist_shmem_linux_SOURCES = shmem_linux.c
shmem_linux_LDFLAGS = $(AM_LDFLAGS) -lrt
-#shmem_odp is the odp part:
-dist_shmem_odp_SOURCES = shmem_odp.c
-shmem_odp_CFLAGS = $(AM_CFLAGS) \
+#shmem_odp1 and shmem_odp2 are the 2 ODP processes:
+dist_shmem_odp1_SOURCES = shmem_odp1.c
+shmem_odp1_CFLAGS = $(AM_CFLAGS) \
$(INCCUNIT_COMMON) \
$(INCODP)
-shmem_odp_LDFLAGS = $(AM_LDFLAGS)
-shmem_odp_LDADD = $(LIBCUNIT_COMMON) $(LIBODP)
+shmem_odp1_LDFLAGS = $(AM_LDFLAGS)
+shmem_odp1_LDADD = $(LIBCUNIT_COMMON) $(LIBODP)
-noinst_HEADERS = shmem_common.h shmem_linux.h shmem_odp.h
+dist_shmem_odp2_SOURCES = shmem_odp2.c
+shmem_odp2_CFLAGS = $(AM_CFLAGS) \
+ $(INCCUNIT_COMMON) \
+ $(INCODP)
+shmem_odp2_LDFLAGS = $(AM_LDFLAGS)
+shmem_odp2_LDADD = $(LIBCUNIT_COMMON) $(LIBODP)
+
+
+noinst_HEADERS = shmem_common.h shmem_linux.h shmem_odp1.h shmem_odp2.h
@@ -5,8 +5,10 @@
*/
/* this test makes sure that odp shared memory created with the ODP_SHM_PROC
- * flag is visible under linux. It therefore checks both that the device
- * name under /dev/shm is correct, and also checks that the memory contents
+ * flag is visible under linux, and checks that memory created with the
+ * ODP_SHM_EXPORT flag is visible by other ODP instances.
+ * It therefore checks both that the link
+ * name under /tmp is correct, and also checks that the memory contents
* is indeed shared.
* we want:
* -the odp test to run using C UNIT
@@ -15,18 +17,47 @@
*
* To achieve this, the flow of operations is as follows:
*
- * linux process (main, non odp) | ODP process
- * (shmem_linux.c) | (shmem_odp.c)
+ * linux process (main, non odp) |
+ * (shmem_linux.c) |
+ * |
+ * |
* |
* main() |
- * forks odp process | allocate shmem
- * wait for named pipe creation | populate shmem
+ * forks odp_app1 process |
+ * wait for named pipe creation |
+ * |
+ * | ODP_APP1 process
+ * | (shmem_odp1.c)
+ * |
+ * | allocate shmem
+ * | populate shmem
* | create named pipe
- * read shared memory | wait for test report in fifo
+ * | wait for test report in fifo...
+ * read shared memory |
* check if memory contents is OK |
- * if OK, write "S" in fifo, else "F" | report success or failure to C-Unit
- * wait for child terminaison & status| terminate with usual F/S status
+ * If not OK, write "F" in fifo and |
+ * exit with failure code. | -------------------
+ * |
+ * forks odp app2 process | ODP APP2 process
+ * wait for child terminaison & status| (shmem_odp2.c)
+ * | lookup ODP_APP1 shared memory,
+ * | check if memory contents is OK
+ * | Exit(0) on success, exit(1) on fail
+ * If child failed, write "F" in fifo |
+ * exit with failure code. | -------------------
+ * |
+ * OK, write "S" in fifo, |
+ * wait for child terminaison & status|
* terminate with same status as child|
+ * | ODP APP1 process
+ * | (shmem_odp1.c)
+ * |
+ * | ...(continued)
+ * | read S(success) or F(fail) from fifo
+ * | report success or failure to C-Unit
+ * | Exit(0) on success, exit(1) on fail
+ * wait for child terminaison & status |
+ * terminate with same status as child |
* |
* \|/
* time
@@ -48,7 +79,8 @@
#include "shmem_linux.h"
#include "shmem_common.h"
-#define ODP_APP_NAME "shmem_odp" /* name of the odp program, in this dir */
+#define ODP_APP1_NAME "shmem_odp1" /* name of the odp1 program, in this dir */
+#define ODP_APP2_NAME "shmem_odp2" /* name of the odp2 program, in this dir */
#define DEVNAME_FMT "/tmp/odp-%d-shm-%s" /* shm link: odp-<pid>-shm-<name> */
#define MAX_FIFO_WAIT 30 /* Max time waiting for the fifo (sec) */
@@ -60,7 +92,7 @@ void test_success(char *fifo_name, int fd, pid_t odp_app)
/* write "Success" to the FIFO */
nb_char = write(fd, &result, sizeof(char));
close(fd);
- /* wait for the odp app to terminate */
+ /* wait for the odp app1 to terminate */
waitpid(odp_app, &status, 0);
/* if the write failed, report an error anyway */
if (nb_char != 1)
@@ -77,10 +109,10 @@ void test_failure(char *fifo_name, int fd, pid_t odp_app)
int nb_char __attribute__((unused)); /*ignored: we fail anyway */
result = TEST_FAILURE;
- /* write "Success" to the FIFO */
+ /* write "Failure" to the FIFO */
nb_char = write(fd, &result, sizeof(char));
close(fd);
- /* wait for the odp app to terminate */
+ /* wait for the odp app1 to terminate */
waitpid(odp_app, &status, 0);
unlink(fifo_name);
exit(1); /* error */
@@ -89,33 +121,40 @@ void test_failure(char *fifo_name, int fd, pid_t odp_app)
int main(int argc __attribute__((unused)), char *argv[])
{
char prg_name[PATH_MAX];
- char odp_name[PATH_MAX];
+ char odp_name1[PATH_MAX];
+ char odp_name2[PATH_MAX];
int nb_sec;
int size;
- pid_t odp_app;
- char *odp_params = NULL;
+ pid_t odp_app1;
+ pid_t odp_app2;
+ char *odp_params1 = NULL;
+ char *odp_params2[3];
+ char pid1[10];
char fifo_name[PATH_MAX]; /* fifo for linux->odp feedback */
int fifo_fd = -1;
- char shm_devname[PATH_MAX];/* shared mem device name, under /dev/shm */
+ char shm_filename[PATH_MAX];/* shared mem device name, under /dev/shm */
int shm_fd;
test_shared_linux_data_t *addr;
+ int app2_status;
- /* odp app is in the same directory as this file: */
+ /* odp_app1 is in the same directory as this file: */
strncpy(prg_name, argv[0], PATH_MAX - 1);
- sprintf(odp_name, "%s/%s", dirname(prg_name), ODP_APP_NAME);
+ sprintf(odp_name1, "%s/%s", dirname(prg_name), ODP_APP1_NAME);
/* start the ODP application: */
- odp_app = fork();
- if (odp_app < 0) /* error */
+ odp_app1 = fork();
+ if (odp_app1 < 0) /* error */
exit(1);
- if (odp_app == 0) /* child */
- execv(odp_name, &odp_params);
+ if (odp_app1 == 0) { /* child */
+ execv(odp_name1, &odp_params1); /* no return unless error */
+ fprintf(stderr, "execv failed: %s\n", strerror(errno));
+ }
/* wait max 30 sec for the fifo to be created by the ODP side.
* Just die if time expire as there is no fifo to communicate
* through... */
- sprintf(fifo_name, FIFO_NAME_FMT, odp_app);
+ sprintf(fifo_name, FIFO_NAME_FMT, odp_app1);
for (nb_sec = 0; nb_sec < MAX_FIFO_WAIT; nb_sec++) {
fifo_fd = open(fifo_name, O_WRONLY);
if (fifo_fd >= 0)
@@ -130,14 +169,14 @@ int main(int argc __attribute__((unused)), char *argv[])
* ODP application is up and running, and has allocated shmem.
* check to see if linux can see the created shared memory: */
- sprintf(shm_devname, DEVNAME_FMT, odp_app, ODP_SHM_NAME);
+ sprintf(shm_filename, DEVNAME_FMT, odp_app1, ODP_SHM_NAME);
- /* O_CREAT flag not given => failure if shm_devname does not already
+ /* O_CREAT flag not given => failure if shm_filename does not already
* exist */
- shm_fd = open(shm_devname, O_RDONLY,
+ shm_fd = open(shm_filename, O_RDONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (shm_fd == -1)
- test_failure(fifo_name, shm_fd, odp_app);
+ test_failure(fifo_name, fifo_fd, odp_app1); /* no return */
/* linux ODP guarantees page size alignement. Larger alignment may
* fail as 2 different processes will have fully unrelated
@@ -145,12 +184,41 @@ int main(int argc __attribute__((unused)), char *argv[])
*/
size = sizeof(test_shared_linux_data_t);
addr = mmap(NULL, size, PROT_READ, MAP_SHARED, shm_fd, 0);
- if (addr == MAP_FAILED)
- test_failure(fifo_name, shm_fd, odp_app);
+ if (addr == MAP_FAILED) {
+ printf("shmem_linux: map failed!\n");
+ test_failure(fifo_name, fifo_fd, odp_app1);
+ }
/* check that we see what the ODP application wrote in the memory */
- if ((addr->foo == TEST_SHARE_FOO) && (addr->bar == TEST_SHARE_BAR))
- test_success(fifo_name, fifo_fd, odp_app);
- else
- test_failure(fifo_name, fifo_fd, odp_app);
+ if ((addr->foo != TEST_SHARE_FOO) || (addr->bar != TEST_SHARE_BAR))
+ test_failure(fifo_name, fifo_fd, odp_app1); /* no return */
+
+ /* odp_app2 is in the same directory as this file: */
+ strncpy(prg_name, argv[0], PATH_MAX - 1);
+ sprintf(odp_name2, "%s/%s", dirname(prg_name), ODP_APP2_NAME);
+
+ /* start the second ODP application with pid of ODP_APP1 as parameter:*/
+ sprintf(pid1, "%d", odp_app1);
+ odp_params2[0] = odp_name2;
+ odp_params2[1] = pid1;
+ odp_params2[2] = NULL;
+ odp_app2 = fork();
+ if (odp_app2 < 0) /* error */
+ exit(1);
+
+ if (odp_app2 == 0) { /* child */
+ execv(odp_name2, odp_params2); /* no return unless error */
+ fprintf(stderr, "execv failed: %s\n", strerror(errno));
+ }
+
+ /* wait for the second ODP application to terminate:
+ * status is OK if that second ODP application could see the
+ * memory shared by the first one. */
+ waitpid(odp_app2, &app2_status, 0);
+
+ if (app2_status)
+ test_failure(fifo_name, fifo_fd, odp_app1); /* no return */
+
+ /* everything looked good: */
+ test_success(fifo_name, fifo_fd, odp_app1);
}
similarity index 81%
rename from test/linux-generic/validation/api/shmem/shmem_odp.c
rename to test/linux-generic/validation/api/shmem/shmem_odp1.c
@@ -13,7 +13,7 @@
#include <fcntl.h>
#include <odp_cunit_common.h>
-#include "shmem_odp.h"
+#include "shmem_odp1.h"
#include "shmem_common.h"
#define TEST_SHARE_FOO (0xf0f0f0f0)
@@ -27,9 +27,10 @@ void shmem_test_odp_shm_proc(void)
test_shared_data_t *test_shared_data;
char test_result;
+ /* reminder: ODP_SHM_PROC => export to linux, ODP_SHM_EXPORT=>to odp */
shm = odp_shm_reserve(ODP_SHM_NAME,
sizeof(test_shared_data_t),
- ALIGN_SIZE, ODP_SHM_PROC);
+ ALIGN_SIZE, ODP_SHM_PROC | ODP_SHM_EXPORT);
CU_ASSERT_FATAL(ODP_SHM_INVALID != shm);
test_shared_data = odp_shm_addr(shm);
CU_ASSERT_FATAL(NULL != test_shared_data);
@@ -39,15 +40,18 @@ void shmem_test_odp_shm_proc(void)
odp_mb_full();
/* open the fifo: this will indicate to linux process that it can
- * start the shmem lookup and check if it sees the data */
+ * start the shmem lookups and check if it sees the data */
sprintf(fifo_name, FIFO_NAME_FMT, getpid());
CU_ASSERT_FATAL(mkfifo(fifo_name, 0666) == 0);
/* read from the fifo: the linux process result: */
+ printf("shmem_odp1: opening fifo: %s\n", fifo_name);
fd = open(fifo_name, O_RDONLY);
CU_ASSERT_FATAL(fd >= 0);
+ printf("shmem_odp1: reading fifo: %s\n", fifo_name);
CU_ASSERT(read(fd, &test_result, sizeof(char)) == 1);
+ printf("shmem_odp1: closing fifo: %s\n", fifo_name);
close(fd);
CU_ASSERT_FATAL(test_result == TEST_SUCCESS);
similarity index 100%
rename from test/linux-generic/validation/api/shmem/shmem_odp.h
rename to test/linux-generic/validation/api/shmem/shmem_odp1.h
new file mode 100644
@@ -0,0 +1,95 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp.h>
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <odp_cunit_common.h>
+#include "shmem_odp2.h"
+#include "shmem_common.h"
+
+#define TEST_SHARE_FOO (0xf0f0f0f0)
+#define TEST_SHARE_BAR (0xf0f0f0f)
+
+/* The C unit test harness is run by ODP1 app which will be told the return
+ * staus of this process. See top of shmem_linux.c for chart flow of events
+ */
+int main(int argc, char *argv[])
+{
+ odp_instance_t odp1;
+ odp_instance_t odp2;
+ odp_shm_t shm;
+ test_shared_data_t *test_shared_data;
+
+ /* odp init: */
+ if (0 != odp_init_global(&odp2, NULL, NULL)) {
+ fprintf(stderr, "error: odp_init_global() failed.\n");
+ return 1;
+ }
+ if (0 != odp_init_local(odp2, ODP_THREAD_CONTROL)) {
+ fprintf(stderr, "error: odp_init_local() failed.\n");
+ return 1;
+ }
+
+ /* test: map ODP1 memory and check its contents:
+ * The pid of the ODP instantiation process sharing its memory
+ * is given as first arg. In linux-generic ODP, this pid is actually
+ * the ODP instance */
+ if (argc != 2) {
+ fprintf(stderr, "One single parameter expected, %d found.\n",
+ argc);
+ return 1;
+ }
+ odp1 = (odp_instance_t)atoi(argv[1]);
+
+ printf("shmem_odp2: trying to grab %s from pid %d\n",
+ ODP_SHM_NAME, (int)odp1);
+ shm = odp_shm_reserve_exported(ODP_SHM_NAME, odp1, ODP_SHM_NAME, 0, 0);
+ if (shm == ODP_SHM_INVALID) {
+ fprintf(stderr, "error: odp_shm_lookup_external failed.\n");
+ return 1;
+ }
+
+ test_shared_data = odp_shm_addr(shm);
+ if (test_shared_data == NULL) {
+ fprintf(stderr, "error: odp_shm_addr failed.\n");
+ return 1;
+ }
+
+ if (test_shared_data->foo != TEST_SHARE_FOO) {
+ fprintf(stderr, "error: Invalid data TEST_SHARE_FOO.\n");
+ return 1;
+ }
+
+ if (test_shared_data->bar != TEST_SHARE_BAR) {
+ fprintf(stderr, "error: Invalid data TEST_SHARE_BAR.\n");
+ return 1;
+ }
+
+ if (odp_shm_free(shm) != 0) {
+ fprintf(stderr, "error: odp_shm_free() failed.\n");
+ return 1;
+ }
+
+ /* odp term: */
+ if (0 != odp_term_local()) {
+ fprintf(stderr, "error: odp_term_local() failed.\n");
+ return 1;
+ }
+
+ if (0 != odp_term_global(odp2)) {
+ fprintf(stderr, "error: odp_term_global() failed.\n");
+ return 1;
+ }
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,7 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+int main(int argc, char *argv[]);
The platform tests odp/test/linux-generic/validation/api/shmem are updated to both test ODP<->linux process memory sharing, but also test ODP to ODP (different instances) memory sharing. shmem_linux is the main test process, and shmem_linux.c contains (at file top) a chart flow of the test procedure. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> --- test/linux-generic/validation/api/shmem/.gitignore | 3 +- .../linux-generic/validation/api/shmem/Makefile.am | 22 ++-- .../validation/api/shmem/shmem_linux.c | 136 +++++++++++++++------ .../api/shmem/{shmem_odp.c => shmem_odp1.c} | 10 +- .../api/shmem/{shmem_odp.h => shmem_odp1.h} | 0 .../validation/api/shmem/shmem_odp2.c | 95 ++++++++++++++ .../validation/api/shmem/shmem_odp2.h | 7 ++ 7 files changed, 228 insertions(+), 45 deletions(-) rename test/linux-generic/validation/api/shmem/{shmem_odp.c => shmem_odp1.c} (81%) rename test/linux-generic/validation/api/shmem/{shmem_odp.h => shmem_odp1.h} (100%) create mode 100644 test/linux-generic/validation/api/shmem/shmem_odp2.c create mode 100644 test/linux-generic/validation/api/shmem/shmem_odp2.h -- 2.7.4