diff mbox

[API-NEXT,12/14] test: linux-gen: api: shmem: test sharing memory between ODP instances

Message ID 1475836517-60484-13-git-send-email-christophe.milard@linaro.org
State Superseded
Headers show

Commit Message

Christophe Milard Oct. 7, 2016, 10:35 a.m. UTC
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
diff mbox

Patch

diff --git a/test/linux-generic/validation/api/shmem/.gitignore b/test/linux-generic/validation/api/shmem/.gitignore
index 7627079..74195f5 100644
--- a/test/linux-generic/validation/api/shmem/.gitignore
+++ b/test/linux-generic/validation/api/shmem/.gitignore
@@ -1,2 +1,3 @@ 
 shmem_linux
-shmem_odp
+shmem_odp1
+shmem_odp2
diff --git a/test/linux-generic/validation/api/shmem/Makefile.am b/test/linux-generic/validation/api/shmem/Makefile.am
index 341747f..b0ae627 100644
--- a/test/linux-generic/validation/api/shmem/Makefile.am
+++ b/test/linux-generic/validation/api/shmem/Makefile.am
@@ -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
diff --git a/test/linux-generic/validation/api/shmem/shmem_linux.c b/test/linux-generic/validation/api/shmem/shmem_linux.c
index 7e2ff04..7cb405a 100644
--- a/test/linux-generic/validation/api/shmem/shmem_linux.c
+++ b/test/linux-generic/validation/api/shmem/shmem_linux.c
@@ -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);
 }
diff --git a/test/linux-generic/validation/api/shmem/shmem_odp.c b/test/linux-generic/validation/api/shmem/shmem_odp1.c
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
index a1f750f..3869c2e 100644
--- a/test/linux-generic/validation/api/shmem/shmem_odp.c
+++ b/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);
 
diff --git a/test/linux-generic/validation/api/shmem/shmem_odp.h b/test/linux-generic/validation/api/shmem/shmem_odp1.h
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
diff --git a/test/linux-generic/validation/api/shmem/shmem_odp2.c b/test/linux-generic/validation/api/shmem/shmem_odp2.c
new file mode 100644
index 0000000..398a7ce
--- /dev/null
+++ b/test/linux-generic/validation/api/shmem/shmem_odp2.c
@@ -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;
+}
diff --git a/test/linux-generic/validation/api/shmem/shmem_odp2.h b/test/linux-generic/validation/api/shmem/shmem_odp2.h
new file mode 100644
index 0000000..a8db909
--- /dev/null
+++ b/test/linux-generic/validation/api/shmem/shmem_odp2.h
@@ -0,0 +1,7 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+int main(int argc, char *argv[]);