diff mbox

[2/2] linux-generic: test: ODP_SHM_PROP test

Message ID 1456850094-39712-3-git-send-email-christophe.milard@linaro.org
State Superseded
Headers show

Commit Message

Christophe Milard March 1, 2016, 4:34 p.m. UTC
Adding a platform side test to test sharing memory between ODP and linux.
Also tests that the shared memory device name (under /dev/shm/) is scoped.

Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
---
 platform/linux-generic/m4/configure.m4           |   1 +
 platform/linux-generic/test/Makefile.am          |   4 +-
 platform/linux-generic/test/shmem/.gitignore     |   2 +
 platform/linux-generic/test/shmem/Makefile.am    |  18 +++
 platform/linux-generic/test/shmem/shmem.h        |  21 +++
 platform/linux-generic/test/shmem/shmem_common.h |  23 ++++
 platform/linux-generic/test/shmem/shmem_linux.c  | 156 +++++++++++++++++++++++
 platform/linux-generic/test/shmem/shmem_linux.h  |   9 ++
 platform/linux-generic/test/shmem/shmem_odp.c    |  74 +++++++++++
 platform/linux-generic/test/shmem/shmem_odp.h    |   7 +
 10 files changed, 314 insertions(+), 1 deletion(-)
 create mode 100644 platform/linux-generic/test/shmem/.gitignore
 create mode 100644 platform/linux-generic/test/shmem/Makefile.am
 create mode 100644 platform/linux-generic/test/shmem/shmem.h
 create mode 100644 platform/linux-generic/test/shmem/shmem_common.h
 create mode 100644 platform/linux-generic/test/shmem/shmem_linux.c
 create mode 100644 platform/linux-generic/test/shmem/shmem_linux.h
 create mode 100644 platform/linux-generic/test/shmem/shmem_odp.c
 create mode 100644 platform/linux-generic/test/shmem/shmem_odp.h
diff mbox

Patch

diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index df6dc64..f24e0fb 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -23,4 +23,5 @@  m4_include([platform/linux-generic/m4/odp_pcap.m4])
 
 AC_CONFIG_FILES([platform/linux-generic/Makefile
 		 platform/linux-generic/test/Makefile
+		 platform/linux-generic/test/shmem/Makefile
 		 platform/linux-generic/test/pktio/Makefile])
diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am
index db923b8..c24afe9 100644
--- a/platform/linux-generic/test/Makefile.am
+++ b/platform/linux-generic/test/Makefile.am
@@ -1,11 +1,13 @@ 
 include $(top_srcdir)/test/Makefile.inc
 TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation
 
-ODP_MODULES = pktio
+ODP_MODULES = pktio \
+	      shmem
 
 if test_vald
 TESTS = pktio/pktio_run \
 	pktio/pktio_run_tap \
+	shmem/shmem_linux \
 	${top_builddir}/test/validation/atomic/atomic_main$(EXEEXT) \
 	${top_builddir}/test/validation/barrier/barrier_main$(EXEEXT) \
 	${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \
diff --git a/platform/linux-generic/test/shmem/.gitignore b/platform/linux-generic/test/shmem/.gitignore
new file mode 100644
index 0000000..7627079
--- /dev/null
+++ b/platform/linux-generic/test/shmem/.gitignore
@@ -0,0 +1,2 @@ 
+shmem_linux
+shmem_odp
diff --git a/platform/linux-generic/test/shmem/Makefile.am b/platform/linux-generic/test/shmem/Makefile.am
new file mode 100644
index 0000000..ffec6ee
--- /dev/null
+++ b/platform/linux-generic/test/shmem/Makefile.am
@@ -0,0 +1,18 @@ 
+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_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) \
+		   $(INCCUNIT_COMMON) \
+		   $(INCODP)
+shmem_odp_LDFLAGS = $(AM_LDFLAGS)
+shmem_odp_LDADD = $(LIBCUNIT_COMMON) $(LIBODP)
diff --git a/platform/linux-generic/test/shmem/shmem.h b/platform/linux-generic/test/shmem/shmem.h
new file mode 100644
index 0000000..2368a2e
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem.h
@@ -0,0 +1,21 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _ODP_LINUX_TEST_SHMEM_H_
+#define _ODP_LINUX_TEST_SHMEM_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void shmem_test_odp_shm_proc(void);
+
+/* test arrays: */
+extern odp_testinfo_t shmem_linux_suite[];
+
+/* test registry: */
+extern odp_suiteinfo_t shmem_linux_suites[];
+
+#endif
diff --git a/platform/linux-generic/test/shmem/shmem_common.h b/platform/linux-generic/test/shmem/shmem_common.h
new file mode 100644
index 0000000..16227ec
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem_common.h
@@ -0,0 +1,23 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _COMMON_TEST_SHMEM_H_
+#define _COMMON_TEST_SHMEM_H_
+
+#define ODP_SHM_NAME "odp_linux_shared_mem"
+#define FIFO_NAME_FMT "/tmp/shmem_test_fifo-%d"
+#define ALIGN_SIZE  (128)
+#define TEST_SHARE_FOO (0xf0f0f0f0)
+#define TEST_SHARE_BAR (0xf0f0f0f)
+#define TEST_FAILURE 'F'
+#define TEST_SUCCESS 'S'
+
+typedef struct {
+	uint32_t foo;
+	uint32_t bar;
+} test_shared_linux_data_t;
+
+#endif
diff --git a/platform/linux-generic/test/shmem/shmem_linux.c b/platform/linux-generic/test/shmem/shmem_linux.c
new file mode 100644
index 0000000..516bbe4
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem_linux.c
@@ -0,0 +1,156 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/* 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
+ * is indeed shared.
+ * we want:
+ * -the odp test to run using C UNIT
+ * -the main process to return the correct return code.
+ *  (for the autotools test harness)
+ *
+ * To achieve this, the flow of operations is as follows:
+ *
+ *   linux process (main, non odp)	|	ODP process
+ *   (shmem_linux.c)			|	(shmem_odp.c)
+ *					|
+ *   main()				|
+ *   forks odp process			|  allocate shmem
+ *   wait for named pipe creation	|  populate shmem
+ *					|  create named pipe
+ *   read shared memory			|  wait for test report in fifo
+ *   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
+ *   terminate with same status as child|
+ *					|
+ *				       \|/
+ *				      time
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <libgen.h>
+#include <linux/limits.h>
+#include "shmem_linux.h"
+#include "shmem_common.h"
+
+#define ODP_APP_NAME "shmem_odp" /* name of the odp program, in this dir */
+#define DEVNAME_FMT "odp-%d-%s"  /* shm device format: odp-<pid>-<name>  */
+
+void test_success(char *fifo_name, int fd, pid_t odp_app)
+{
+	int status;
+	int nb_char;
+	char result = TEST_SUCCESS;
+	/* write "Success" to the FIFO */
+	nb_char = write(fd, &result, sizeof(char));
+	close(fd);
+	/* wait for the odp app to terminate */
+	waitpid(odp_app, &status, 0);
+	/* if the write failed, report an error anyway */
+	if (nb_char != 1)
+		status = 1;
+	unlink(fifo_name);
+	exit(status);	/* the status reported by the odp side is returned */
+}
+
+void test_failure(char *fifo_name, int fd, pid_t odp_app)
+{
+	int status;
+	char result;
+
+	int nb_char __attribute__((unused)); /*ignored: we fail anyway */
+
+	result = TEST_FAILURE;
+	/* write "Success" to the FIFO */
+	nb_char = write(fd, &result, sizeof(char));
+	close(fd);
+	/* wait for the odp app to terminate */
+	waitpid(odp_app, &status, 0);
+	unlink(fifo_name);
+	exit(1); /* error */
+}
+
+int main(int argc __attribute__((unused)), char *argv[])
+{
+	char prg_name[PATH_MAX];
+	char odp_name[PATH_MAX];
+	int nb_sec = 0;
+	int size;
+	pid_t odp_app;
+	char *odp_params = NULL;
+	char fifo_name[PATH_MAX];  /* fifo for linux->odp feedback */
+	int fifo_fd;
+	char shm_devname[PATH_MAX];/* shared mem device name, under /dev/shm */
+	int shm_fd;
+	test_shared_linux_data_t *addr;
+
+	/* odp app is in the same directory as this file: */
+	strncpy(prg_name, argv[0], PATH_MAX);
+	sprintf(odp_name, "%s/%s", dirname(prg_name), ODP_APP_NAME);
+
+	/* start the ODP application: */
+	odp_app = fork();
+	if (odp_app < 0)  /* error */
+		exit(1);
+
+	if (odp_app == 0) /* child */
+		execv(odp_name, &odp_params);
+
+	/* 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);
+	while (access(fifo_name, W_OK) != 0) {
+		sleep(1);
+		if  (nb_sec++ == 30)
+			exit(1);
+	}
+	fifo_fd = open(fifo_name, O_WRONLY);
+	printf("pipe found\n");
+
+	/* the linux named pipe has now been found, meaning that the
+	 * 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);
+
+	/* O_CREAT flag not given => failure if shm_devname does not already
+	 * exist */
+	shm_fd = shm_open(shm_devname, O_RDONLY,
+			  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+	if (shm_fd == -1)
+		test_failure(fifo_name, shm_fd, odp_app);
+
+	/* we know that the linux generic ODP actually allocates the required
+	 * size + alignment and aligns the returned address after.
+	 * we must do the same here: */
+	size = sizeof(test_shared_linux_data_t) + ALIGN_SIZE;
+	addr = mmap(NULL, size, PROT_READ, MAP_SHARED, shm_fd, 0);
+	if (addr == MAP_FAILED)
+		test_failure(fifo_name, shm_fd, odp_app);
+
+	/* perform manual alignment */
+	addr = (test_shared_linux_data_t *)((((unsigned long int)addr +
+				 ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE);
+
+	/* 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);
+}
diff --git a/platform/linux-generic/test/shmem/shmem_linux.h b/platform/linux-generic/test/shmem/shmem_linux.h
new file mode 100644
index 0000000..a07a775
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem_linux.h
@@ -0,0 +1,9 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+void test_success(char *fifo_name, int fd, pid_t odp_app);
+void test_failure(char *fifo_name, int fd, pid_t odp_app);
+int main(int argc, char *argv[]);
diff --git a/platform/linux-generic/test/shmem/shmem_odp.c b/platform/linux-generic/test/shmem/shmem_odp.c
new file mode 100644
index 0000000..df584e6
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem_odp.c
@@ -0,0 +1,74 @@ 
+/* Copyright (c) 2014, 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 <odp_cunit_common.h>
+#include "shmem_odp.h"
+#include "shmem_common.h"
+
+#define TEST_SHARE_FOO (0xf0f0f0f0)
+#define TEST_SHARE_BAR (0xf0f0f0f)
+
+void shmem_test_odp_shm_proc(void)
+{
+	char fifo_name[PATH_MAX];
+	int fd;
+	odp_shm_t shm;
+	test_shared_data_t *test_shared_data;
+	char test_result;
+
+	shm = odp_shm_reserve(ODP_SHM_NAME,
+			      sizeof(test_shared_data_t),
+			      ALIGN_SIZE, ODP_SHM_PROC);
+	CU_ASSERT_FATAL(ODP_SHM_INVALID != shm);
+	test_shared_data = odp_shm_addr(shm);
+	CU_ASSERT_FATAL(NULL != test_shared_data);
+	test_shared_data->foo = TEST_SHARE_FOO;
+	test_shared_data->bar = TEST_SHARE_BAR;
+
+	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 */
+	sprintf(fifo_name, FIFO_NAME_FMT, getpid());
+	CU_ASSERT_FATAL(mkfifo(fifo_name, 0666) == 0);
+
+	/* read from the fifo: the linux process result: */
+	fd = open(fifo_name, O_RDONLY);
+	CU_ASSERT_FATAL(fd >= 0);
+
+	CU_ASSERT(read(fd, &test_result, sizeof(char)) == 1);
+	CU_ASSERT_FATAL(test_result == TEST_SUCCESS);
+
+	CU_ASSERT(odp_shm_free(shm) == 0);
+}
+
+odp_testinfo_t shmem_suite[] = {
+	ODP_TEST_INFO(shmem_test_odp_shm_proc),
+	ODP_TEST_INFO_NULL,
+};
+
+odp_suiteinfo_t shmem_suites[] = {
+	{"Shared Memory", NULL, NULL, shmem_suite},
+	ODP_SUITE_INFO_NULL,
+};
+
+int main(void)
+{
+	int ret = odp_cunit_register(shmem_suites);
+
+	if (ret == 0)
+		ret = odp_cunit_run();
+
+	return ret;
+}
diff --git a/platform/linux-generic/test/shmem/shmem_odp.h b/platform/linux-generic/test/shmem/shmem_odp.h
new file mode 100644
index 0000000..6fed569
--- /dev/null
+++ b/platform/linux-generic/test/shmem/shmem_odp.h
@@ -0,0 +1,7 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+void shmem_test_odp_shm_proc(void);