This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, api-next has been updated
via b5781eeee0fa56710ea865e67f47ad9b3656b955 (commit)
via b8693f93ee8aa586af5f39111195506d9a826c8a (commit)
via 783ca69b2f6e1ce1d7e2b2e2774d4d475a12cf10 (commit)
from ecf6f8e63c7da7ad020dd3179481d98b86e676f9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b5781eeee0fa56710ea865e67f47ad9b3656b955
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Tue Nov 29 15:45:49 2016 +0100
test: drvshm: removing invalid test
The test trying to free a unallocated address is now erroneous since
ODP is using ishm too: unknown drvshm addresses may well be valid ODP
addresses, in which case the test frees someone else memory!
The test is simply suppressed.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Petri Savolainen <petri.savolainen(a)nokia.com>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/test/common_plat/validation/drv/drvshmem/drvshmem.c b/test/common_plat/validation/drv/drvshmem/drvshmem.c
index 559c55d..0247a03 100644
--- a/test/common_plat/validation/drv/drvshmem/drvshmem.c
+++ b/test/common_plat/validation/drv/drvshmem/drvshmem.c
@@ -135,8 +135,6 @@ void drvshmem_test_basic(void)
shared_test_data->foo = TEST_SHARE_FOO;
shared_test_data->bar = TEST_SHARE_BAR;
- CU_ASSERT(odpdrv_shm_free_by_address((char *)shared_test_data - 1) < 0);
-
thrdarg.numthrds = odp_cpumask_default_worker(&unused, 0);
if (thrdarg.numthrds > MAX_WORKERS)
commit b8693f93ee8aa586af5f39111195506d9a826c8a
Merge: ecf6f8e 783ca69
Author: Maxim Uvarov <maxim.uvarov(a)linaro.org>
Date: Wed Nov 30 16:51:57 2016 +0300
Merge branch 'master' into api-next
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
-----------------------------------------------------------------------
Summary of changes:
test/common_plat/validation/drv/drvshmem/drvshmem.c | 2 --
test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via 783ca69b2f6e1ce1d7e2b2e2774d4d475a12cf10 (commit)
from e819c669f474bba418c5897b6cdcf945da25c75e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 783ca69b2f6e1ce1d7e2b2e2774d4d475a12cf10
Author: Maxim Uvarov <maxim.uvarov(a)linaro.org>
Date: Fri Nov 25 17:06:02 2016 +0300
test: linux-gen: fix termination in mmap_vlan_ins
exit variable has to be volatile to be visible from thread. Without
that background process is not killed with default optimization level.
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
index 0682d2d..b91eb53 100644
--- a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
+++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
@@ -19,7 +19,7 @@
#define MAX_PKT_BURST 32
#define MAX_WORKERS 1
-static int exit_thr;
+static volatile int exit_thr;
static int g_ret;
struct {
-----------------------------------------------------------------------
Summary of changes:
test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, api-next has been updated
via ecf6f8e63c7da7ad020dd3179481d98b86e676f9 (commit)
via e819c669f474bba418c5897b6cdcf945da25c75e (commit)
via 21ddf9b672ed6dd4254d4df1b1a414cb73306833 (commit)
via dd4fce83fe3168e7cc1ca9ae8ecbea0da2665de2 (commit)
via 020c91ca5367e971cbfc493c5b92f65ec72a43e7 (commit)
via 90ac2ecbf8aec6d4f876d161b3844c199527c33e (commit)
via 9b29422bde38980e66c8474546727433ce5c2995 (commit)
via 01fc389137187cabd79a9e87319cd6c462cc6015 (commit)
via ab57009c2ddcc6ddeb0c180ce8800ebbf723ac8f (commit)
via 9c8ab9126181e5457f5711075b97ca9ec9a20fc8 (commit)
via 9ad380fa0a113b90e26518b7d659213f05264841 (commit)
via b3b97530679ed0fe6f975986270a3fa7d4c59a72 (commit)
via 99117760f8bed0d8351c35a2c037e288d5a9280a (commit)
via a560c609e78716421e782aa388805937d177ef0e (commit)
via 524987a32f9873e59ce265ffba6e831e756a2441 (commit)
via ab966018496e7ebb0d1532d6c5c119b9db7d56fa (commit)
from ef13af84fb6e8649679b06585bec9dead71cfbe5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ecf6f8e63c7da7ad020dd3179481d98b86e676f9
Merge: ef13af8 e819c66
Author: Maxim Uvarov <maxim.uvarov(a)linaro.org>
Date: Tue Nov 29 19:33:09 2016 +0300
Merge branch 'master' into api-next
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
-----------------------------------------------------------------------
Summary of changes:
.travis.yml | 42 +++++++--
CHANGELOG | 122 ++++++++++++++++++++++++++
configure.ac | 2 +-
platform/linux-generic/odp_packet_io.c | 6 +-
platform/linux-generic/odp_traffic_mngr.c | 3 +
test/common_plat/performance/odp_pktio_perf.c | 3 +
test/linux-generic/mmap_vlan_ins/Makefile.am | 2 +-
7 files changed, 171 insertions(+), 9 deletions(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via e819c669f474bba418c5897b6cdcf945da25c75e (commit)
from 21ddf9b672ed6dd4254d4df1b1a414cb73306833 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit e819c669f474bba418c5897b6cdcf945da25c75e
Author: Mike Holmes <mike.holmes(a)linaro.org>
Date: Fri Nov 18 13:34:22 2016 -0500
travis.yml: add coverity support
Enables static analysis when pushing to a branch coverity_scan on github
See https://scan.coverity.com/travis_ci
Signed-off-by: Mike Holmes <mike.holmes(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/.travis.yml b/.travis.yml
index 1092cd0..adf3307 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,17 @@
# Copyright (c) 2016, Linaro Limited
# All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
+#
+# Please update xxxx for your coverity token and notification email if required
+# pushing to github/master will run make check
+# pushing to github/coverity_scan will also launch a static analysis
+# See https://scan.coverity.com/travis_ci
-
+env:
+ global:
+ # COVERITY_SCAN_TOKEN
+ # ** specific to your project **
+ - secure: "xxxx"
language: c
compiler: clang
@@ -47,3 +56,12 @@ script:
- ./configure
- make doxygen-doc
- make distcheck
+
+addons:
+ coverity_scan:
+ project:
+ name: "$TRAVIS_REPO_SLUG"
+ notification_email: xxxx
+ build_command_prepend: "./bootstrap && ./configure --enable-test-cpp --enable-test-vald --enable-test-helper --enable-test-perf --enable-user-guides --enable-test-perf-proc --enable-test-example"
+ build_command: "make"
+ branch_pattern: coverity_scan
-----------------------------------------------------------------------
Summary of changes:
.travis.yml | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via 21ddf9b672ed6dd4254d4df1b1a414cb73306833 (commit)
via dd4fce83fe3168e7cc1ca9ae8ecbea0da2665de2 (commit)
from 020c91ca5367e971cbfc493c5b92f65ec72a43e7 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 21ddf9b672ed6dd4254d4df1b1a414cb73306833
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Fri Nov 25 18:14:36 2016 +0100
performance: odp_pktio_perf: adding missing term functions
Both term function were missing for the ODP main process.
Added here.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/test/common_plat/performance/odp_pktio_perf.c b/test/common_plat/performance/odp_pktio_perf.c
index 483f067..6db02e0 100644
--- a/test/common_plat/performance/odp_pktio_perf.c
+++ b/test/common_plat/performance/odp_pktio_perf.c
@@ -1077,5 +1077,8 @@ int main(int argc, char **argv)
test_term();
}
+ odp_term_local();
+ odp_term_global(instance);
+
return ret;
}
commit dd4fce83fe3168e7cc1ca9ae8ecbea0da2665de2
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Fri Nov 25 18:14:35 2016 +0100
linux-gen: packet_io: handling term_global while in CLOSE_PENDING
If odp_pktio_term_global() is called while a pktio in in state
PKTIO_STATE_CLOSE_PENDING, a new close() is attempted on a already
closed pktio, resulting as an abort. This patch fixes this.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index 0b9939b..3524ff8 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -1054,7 +1054,7 @@ void odp_pktio_print(odp_pktio_t hdl)
int odp_pktio_term_global(void)
{
- int ret;
+ int ret = 0;
int i;
int pktio_if;
@@ -1073,7 +1073,9 @@ int odp_pktio_term_global(void)
ODP_ABORT("unable to stop pktio %s\n",
pktio_entry->s.name);
}
- ret = _pktio_close(pktio_entry);
+
+ if (pktio_entry->s.state != PKTIO_STATE_CLOSE_PENDING)
+ ret = _pktio_close(pktio_entry);
if (ret)
ODP_ABORT("unable to close pktio %s\n",
pktio_entry->s.name);
-----------------------------------------------------------------------
Summary of changes:
platform/linux-generic/odp_packet_io.c | 6 ++++--
test/common_plat/performance/odp_pktio_perf.c | 3 +++
2 files changed, 7 insertions(+), 2 deletions(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, api-next has been updated
via ef13af84fb6e8649679b06585bec9dead71cfbe5 (commit)
via bf4660cc53039e11f11c3bcf5f8c536a23844f52 (commit)
via beaf855847ba00fe180629b4fad1b93b59ca1f0f (commit)
from 32d6c59d28b39dbe1835f19f3ec0d422091ad5b0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ef13af84fb6e8649679b06585bec9dead71cfbe5
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Tue Nov 8 10:49:30 2016 +0100
doc: shm: defining behaviour when blocks have same name
Defining the reserve and lookup behaviour when multiple blocks are reserved
using the same name.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/doc/users-guide/users-guide.adoc b/doc/users-guide/users-guide.adoc
index 078dd7c..9a427fa 100755
--- a/doc/users-guide/users-guide.adoc
+++ b/doc/users-guide/users-guide.adoc
@@ -594,7 +594,9 @@ resource.
Blocks of shared memory can be created using the `odp_shm_reserve()` API
call. The call expects a shared memory block name, a block size, an alignment
requirement, and optional flags as parameters. It returns a `odp_shm_t`
-handle. The size and alignment requirement are given in bytes.
+handle. The size and alignment requirement are given in bytes. The provided
+name does not have to be unique, i.e. a given name can be used multiple times,
+when reserving different blocks.
.creating a block of shared memory
[source,c]
@@ -670,7 +672,9 @@ block is to use the `odp_shm_lookup()` API function call.
This nevertheless requires the calling ODP thread to provide the name of the
shared memory block:
`odp_shm_lookup()` will return `ODP_SHM_INVALID` if no shared memory block
-with the provided name is known by ODP.
+with the provided name is known by ODP. When multiple blocks were reserved
+using the same name, the lookup function will return the handle of any
+of these blocks.
.retrieving a block handle and address from another ODP task
[source,c]
commit bf4660cc53039e11f11c3bcf5f8c536a23844f52
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Tue Nov 8 10:49:29 2016 +0100
test: api: shm: test using the same block name multiple times
Make sure that many memory blocks can be created with the name.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/test/common_plat/validation/api/shmem/shmem.c b/test/common_plat/validation/api/shmem/shmem.c
index 6ea92d9..0e757a7 100644
--- a/test/common_plat/validation/api/shmem/shmem.c
+++ b/test/common_plat/validation/api/shmem/shmem.c
@@ -111,6 +111,7 @@ void shmem_test_basic(void)
{
pthrd_arg thrdarg;
odp_shm_t shm;
+ odp_shm_t shm2;
shared_test_data_t *shared_test_data;
odp_cpumask_t unused;
@@ -120,7 +121,15 @@ void shmem_test_basic(void)
CU_ASSERT(odp_shm_to_u64(shm) !=
odp_shm_to_u64(ODP_SHM_INVALID));
+ /* also check that another reserve with same name is accepted: */
+ shm2 = odp_shm_reserve(MEM_NAME,
+ sizeof(shared_test_data_t), ALIGN_SIZE, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm2);
+ CU_ASSERT(odp_shm_to_u64(shm2) !=
+ odp_shm_to_u64(ODP_SHM_INVALID));
+
CU_ASSERT(0 == odp_shm_free(shm));
+ CU_ASSERT(0 == odp_shm_free(shm2));
CU_ASSERT(ODP_SHM_INVALID == odp_shm_lookup(MEM_NAME));
shm = odp_shm_reserve(MEM_NAME,
commit beaf855847ba00fe180629b4fad1b93b59ca1f0f
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Tue Nov 8 10:49:28 2016 +0100
linux-gen: _ishm: accept multiple usage of same block name
This is following the request that using the same name
for multiple memory blocks should be allowed on north API.
The change made here will affect any _ishm users (i.e. both north
and south API), which is probably better for consistency.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index 7d9c213..449e357 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -777,14 +777,6 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
page_sz = odp_sys_page_size();
page_hp_size = odp_sys_huge_page_size();
- /* check if name already exists */
- if (name && (find_block_by_name(name) >= 0)) {
- /* Found a block with the same name */
- odp_spinlock_unlock(&ishm_tbl->lock);
- ODP_ERR("name \"%s\" already used.\n", name);
- return -1;
- }
-
/* grab a new entry: */
for (new_index = 0; new_index < ISHM_MAX_NB_BLOCKS; new_index++) {
if (ishm_tbl->block[new_index].len == 0) {
-----------------------------------------------------------------------
Summary of changes:
doc/users-guide/users-guide.adoc | 8 ++++++--
platform/linux-generic/_ishm.c | 8 --------
test/common_plat/validation/api/shmem/shmem.c | 9 +++++++++
3 files changed, 15 insertions(+), 10 deletions(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, monarch_lts has been updated
via 6dac46d9c8dd8cc1f27638215704effcf6269baf (commit)
from 01fc389137187cabd79a9e87319cd6c462cc6015 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6dac46d9c8dd8cc1f27638215704effcf6269baf
Author: Nicolas Morey-Chaisemartin <nmorey(a)kalray.eu>
Date: Fri Nov 18 11:18:32 2016 +0100
git_hash: handle git worktree
In git worktrees .git is a file and not a directory.
This patches replaces [ -d .git ] test by [ -e .git ]
so it works in both cases
Signed-off-by: Nicolas Morey-Chaisemartin <nmorey(a)kalray.eu>
Reviewed-by: Mike Holmes <mike.holmes(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/scripts/git_hash.sh b/scripts/git_hash.sh
index 336eb01..d0095d5 100755
--- a/scripts/git_hash.sh
+++ b/scripts/git_hash.sh
@@ -6,7 +6,7 @@ if [ -z ${1} ]; then
fi
ROOTDIR=${1}
-if [ -d ${ROOTDIR}/.git ]; then
+if [ -e ${ROOTDIR}/.git ]; then
hash=$(git --git-dir=${ROOTDIR}/.git describe --match 'v[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'\
| tr -d "\n")
if [[ $(git --git-dir=${ROOTDIR}/.git diff --shortstat 2> /dev/null \
@@ -19,7 +19,7 @@ if [ -d ${ROOTDIR}/.git ]; then
sed -i "s|-|.git|" ${ROOTDIR}/.scmversion
sed -i "s|-|.|g" ${ROOTDIR}/.scmversion
sed -i "s|^v||g" ${ROOTDIR}/.scmversion
-elif [ ! -d ${ROOTDIR}/.git -a ! -f ${ROOTDIR}/.scmversion ]; then
+elif [ ! -e ${ROOTDIR}/.git -a ! -f ${ROOTDIR}/.scmversion ]; then
echo -n "File ROOTDIR/.scmversion not found, "
echo "and not inside a git repository"
echo "Bailing out! Not recoverable!"
-----------------------------------------------------------------------
Summary of changes:
scripts/git_hash.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, api-next has been updated
via 32d6c59d28b39dbe1835f19f3ec0d422091ad5b0 (commit)
via 05c128e2550c2deaaab57f043c2bdac295aa0089 (commit)
via b31642f889d6d3b8a3d4ef7abb2efd46722df577 (commit)
via 1caad5bab2e9d74ab7001ee5efe5c3d15f9fda0d (commit)
via 9a4a9bfbbad489077ed35a20b564ef650417fb84 (commit)
via 7b5ba54f3d71ceaca21b988964df4cf8d29b1f02 (commit)
via fb432fef933e276b674a29a24d3ebb9e5c91abbc (commit)
via 02c58efd7bd80ca0d7656e867c0ea70d39e17169 (commit)
via a3013bbd8d534b856693873e46fa95cefa824756 (commit)
via f452a9e04b0da3e71f86d8bb02370b7f86ec0098 (commit)
via 3665147240b4df0b322629f47ca0cd10ed97082d (commit)
via 6794ac225910c56d93fa3cf464644b633ee35f32 (commit)
via 04537e7c3942664fe61fe9adaeb95b6afcb6e36c (commit)
via cc8303560e95a12790103364240e2581cf3213bb (commit)
via ac4ba826d777262b1f25944a4ceb840469ad0bd0 (commit)
from ab531245e61a6a3f4a36dbebba4bb42f2ee65ae9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 32d6c59d28b39dbe1835f19f3ec0d422091ad5b0
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:33 2016 +0100
doc: updating docs for the shm interface extension
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/doc/users-guide/users-guide.adoc b/doc/users-guide/users-guide.adoc
index 62f5833..078dd7c 100755
--- a/doc/users-guide/users-guide.adoc
+++ b/doc/users-guide/users-guide.adoc
@@ -649,13 +649,19 @@ mapping the shared memory block. There is no fragmentation.
By default ODP threads are assumed to behave as cache coherent systems:
Any change performed on a shared memory block is guaranteed to eventually
become visible to other ODP threads sharing this memory block.
-(this behaviour may be altered by flags to `odp_shm_reserve()` in the future).
Nevertheless, there is no implicit memory barrier associated with any action
on shared memories: *When* a change performed by an ODP thread becomes visible
to another ODP thread is not known: An application using shared memory
blocks has to use some memory barrier provided by ODP to guarantee shared data
validity between ODP threads.
+The virtual address at which a given memory block is mapped in different ODP
+threads may differ from ODP thread to ODP thread, if ODP threads have separate
+virtual spaces (for instance if ODP threads are implemented as processes).
+However, the ODP_SHM_SINGLE_VA flag can be used at `odp_shm_reserve()` time
+to guarantee address uniqueness in all ODP threads, regardless of their
+implementation or creation time.
+
=== Lookup by name
As mentioned, shared memory handles can be sent from ODP threads to ODP
threads using any IPC mechanism, and then the block address retrieved.
@@ -698,9 +704,49 @@ if (odp_shm_free(shm) != 0) {
}
----
+=== sharing memory with the external world
+ODP provides ways of sharing memory with entities located outside
+ODP instances:
+
+Sharing a block of memory with an external (non ODP) thread is achieved
+by setting the ODP_SHM_PROC flag at `odp_shm_reserve()` time.
+How the memory block is retrieved on the Operating System side is
+implementation and Operating System dependent.
+
+Sharing a block of memory with an external ODP instance (running
+on the same Operating System) is achieved
+by setting the ODP_SHM_EXPORT flag at `odp_shm_reserve()` time.
+A block of memory created with this flag in an ODP instance A, can be "mapped"
+into a remote ODP instance B (on the same OS) by using the
+`odp_shm_import()`, on ODP instance B:
+
+.sharing memory between ODP instances: instance A
+[source,c]
+----
+odp_shm_t shmA;
+shmA = odp_shm_reserve("memoryA", size, 0, ODP_SHM_EXPORT);
+----
+
+.sharing memory between ODP instances: instance B
+[source,c]
+----
+odp_shm_t shmB;
+odp_instance_t odpA;
+
+/* get ODP A instance handle by some OS method */
+odpA = ...
+
+/* get the shared memory exported by A:
+shmB = odp_shm_import("memoryA", odpA, "memoryB", 0, 0);
+----
+
+Note that the handles shmA and shmB are scoped by each ODP instance
+(you can not use them outside the ODP instance they belong to).
+Also note that both ODP instances have to call `odp_shm_free()` when done.
+
=== Memory creation flags
The last argument to odp_shm_reserve() is a set of ORed flags.
-Two flags are supported:
+The following flags are supported:
==== ODP_SHM_PROC
When this flag is given, the allocated shared memory will become visible
@@ -710,6 +756,12 @@ will be able to access the memory using native (non ODP) OS calls such as
Each ODP implementation should provide a description on exactly how
this mapping should be done on that specific platform.
+==== ODP_SHM_EXPORT
+When this flag is given, the allocated shared memory will become visible
+to other ODP instances running on the same OS.
+Other ODP instances willing to see this exported memory should use the
+`odp_shm_import()` ODP function.
+
==== ODP_SHM_SW_ONLY
This flag tells ODP that the shared memory will be used by the ODP application
software only: no HW (such as DMA, or other accelerator) will ever
@@ -719,6 +771,18 @@ implementation), except for `odp_shm_lookup()` and `odp_shm_free()`.
ODP implementations may use this flag as a hint for performance optimization,
or may as well ignore this flag.
+==== ODP_SHM_SINGLE_VA
+This flag is used to guarantee the uniqueness of the address at which
+the shared memory is mapped: without this flag, a given memory block may be
+mapped at different virtual addresses (assuming the target have virtual
+addresses) by different ODP threads. This means that the value returned by
+`odp_shm_addr()` would be different in different threads, in this case.
+Setting this flag guarantees that all ODP threads sharing this memory
+block will see it at the same address (`odp_shm_addr()` would return the
+same value on all ODP threads, for a given memory block, in this case)
+Note that ODP implementations may have restrictions of the amount of memory
+which can be allocated with this flag.
+
== Queues
Queues are the fundamental event sequencing mechanism provided by ODP and all
ODP applications make use of them either explicitly or implicitly. Queues are
commit 05c128e2550c2deaaab57f043c2bdac295aa0089
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:32 2016 +0100
linux_gen: _ishm: decreasing the number of error messages when no huge pages
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index b00f8f1..7d9c213 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -439,8 +439,12 @@ static int create_file(int block_index, huge_flag_t huge, uint64_t len,
fd = open(filename, oflag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
- ODP_ERR("open failed for %s: %s.\n",
- filename, strerror(errno));
+ if (huge == HUGE)
+ ODP_DBG("open failed for %s: %s.\n",
+ filename, strerror(errno));
+ else
+ ODP_ERR("open failed for %s: %s.\n",
+ filename, strerror(errno));
return -1;
}
@@ -762,6 +766,7 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
void *addr = NULL; /* mapping address */
int new_proc_entry;
struct stat statbuf;
+ static int huge_error_printed; /* to avoid millions of error...*/
odp_spinlock_lock(&ishm_tbl->lock);
@@ -836,11 +841,16 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
len = (size + (page_hp_size - 1)) & (-page_hp_size);
addr = do_map(new_index, len, hp_align, flags, HUGE, &fd);
- if (addr == NULL)
- ODP_DBG("No huge pages, fall back to normal pages, "
- "check: /proc/sys/vm/nr_hugepages.\n");
- else
+ if (addr == NULL) {
+ if (!huge_error_printed) {
+ ODP_ERR("No huge pages, fall back to normal "
+ "pages. "
+ "check: /proc/sys/vm/nr_hugepages.\n");
+ huge_error_printed = 1;
+ }
+ } else {
new_block->huge = HUGE;
+ }
}
/* Try normal pages if huge pages failed */
commit b31642f889d6d3b8a3d4ef7abb2efd46722df577
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:31 2016 +0100
linux-gen: _ishm: cleaning remaining block at odp_term_global
Remaining (forgotten, not freed) blocks are gathered and related files
cleaned when odp_term_global() is called. An error message is also issued
so the application writters get to know about these blocks
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index 7c373dc..b00f8f1 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -1505,12 +1505,25 @@ int _odp_ishm_term_local(void)
int _odp_ishm_term_global(void)
{
int ret = 0;
+ int index;
+ ishm_block_t *block;
if ((getpid() != odp_global_data.main_pid) ||
(syscall(SYS_gettid) != getpid()))
ODP_ERR("odp_term_global() must be performed by the main "
"ODP process!\n.");
+ /* cleanup possibly non freed memory (and complain a bit): */
+ for (index = 0; index < ISHM_MAX_NB_BLOCKS; index++) {
+ block = &ishm_tbl->block[index];
+ if (block->len != 0) {
+ ODP_ERR("block '%s' (file %s) was never freed "
+ "(cleaning up...).\n",
+ block->name, block->filename);
+ delete_file(block);
+ }
+ }
+
/* perform the last thread terminate which was postponed: */
ret = do_odp_ishm_term_local();
commit 1caad5bab2e9d74ab7001ee5efe5c3d15f9fda0d
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:30 2016 +0100
test: linux-gen: api: shmem: test sharing memory between ODP instances
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(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
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 9ab0e2b..39473f3 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
@@ -49,7 +80,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-%" PRIu64 "-shm-%s" /* odp-<pid>-shm-<name> */
#define MAX_FIFO_WAIT 30 /* Max time waiting for the fifo (sec) */
@@ -117,7 +149,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)
@@ -134,10 +166,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 */
@@ -146,36 +178,43 @@ 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;
- uint64_t size;
- pid_t odp_app;
- char *odp_params = NULL;
+ int size;
+ 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.*/
+ char shm_filename[PATH_MAX];/* shared mem device name, under /dev/shm */
uint64_t len;
uint32_t flags;
uint32_t align;
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)
@@ -191,17 +230,17 @@ int main(int argc __attribute__((unused)), char *argv[])
* check to see if linux can see the created shared memory: */
/* read the shared memory attributes (includes the shm filename): */
- if (read_shmem_attribues(odp_app, ODP_SHM_NAME,
- shm_devname, &len, &flags, &align) != 0)
- test_failure(fifo_name, fifo_fd, odp_app);
+ if (read_shmem_attribues(odp_app1, ODP_SHM_NAME,
+ shm_filename, &len, &flags, &align) != 0)
+ test_failure(fifo_name, fifo_fd, odp_app1);
/* open the shm filename (which is either on /tmp or on hugetlbfs)
* O_CREAT flag not given => failure if shm_devname 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, fifo_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
@@ -210,12 +249,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, fifo_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%
copy from test/linux-generic/validation/api/shmem/shmem_odp.h
copy 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..e39dc76
--- /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_import(ODP_SHM_NAME, odp1, ODP_SHM_NAME);
+ 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_odp.h b/test/linux-generic/validation/api/shmem/shmem_odp2.h
similarity index 76%
rename from test/linux-generic/validation/api/shmem/shmem_odp.h
rename to test/linux-generic/validation/api/shmem/shmem_odp2.h
index 614bbf8..a8db909 100644
--- a/test/linux-generic/validation/api/shmem/shmem_odp.h
+++ b/test/linux-generic/validation/api/shmem/shmem_odp2.h
@@ -4,4 +4,4 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-void shmem_test_odp_shm_proc(void);
+int main(int argc, char *argv[]);
commit 9a4a9bfbbad489077ed35a20b564ef650417fb84
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:29 2016 +0100
linux-gen: shm: add flag and function to share memory between ODP instances
Implemented by calling the related functions from _ishm.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/odp_shared_memory.c b/platform/linux-generic/odp_shared_memory.c
index 2377f16..d2bb74c 100644
--- a/platform/linux-generic/odp_shared_memory.c
+++ b/platform/linux-generic/odp_shared_memory.c
@@ -24,6 +24,21 @@ static inline odp_shm_t to_handle(uint32_t index)
return _odp_cast_scalar(odp_shm_t, index + 1);
}
+static uint32_t get_ishm_flags(uint32_t flags)
+{
+ uint32_t f = 0; /* internal ishm flags */
+
+ /* set internal ishm flags according to API flags:
+ * note that both ODP_SHM_PROC and ODP_SHM_EXPORT maps to
+ * _ODP_ISHM_LINK as in the linux-gen implementation there is
+ * no difference between exporting to another ODP instance or
+ * another linux process */
+ f |= (flags & (ODP_SHM_PROC | ODP_SHM_EXPORT)) ? _ODP_ISHM_EXPORT : 0;
+ f |= (flags & ODP_SHM_SINGLE_VA) ? _ODP_ISHM_SINGLE_VA : 0;
+
+ return f;
+}
+
int odp_shm_capability(odp_shm_capability_t *capa)
{
memset(capa, 0, sizeof(odp_shm_capability_t));
@@ -41,9 +56,7 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align,
int block_index;
int flgs = 0; /* internal ishm flags */
- /* set internal ishm flags according to API flags: */
- flgs |= (flags & ODP_SHM_PROC) ? _ODP_ISHM_EXPORT : 0;
- flgs |= (flags & ODP_SHM_SINGLE_VA) ? _ODP_ISHM_SINGLE_VA : 0;
+ flgs = get_ishm_flags(flags);
/* all mem reserved through this interface is requested to be locked: */
flgs |= (flags & _ODP_ISHM_LOCK);
@@ -55,6 +68,18 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align,
return ODP_SHM_INVALID;
}
+odp_shm_t odp_shm_import(const char *remote_name,
+ odp_instance_t odp_inst,
+ const char *local_name)
+{
+ int ret;
+
+ ret = _odp_ishm_find_exported(remote_name, (pid_t)odp_inst,
+ local_name);
+
+ return to_handle(ret);
+}
+
int odp_shm_free(odp_shm_t shm)
{
return _odp_ishm_free_by_index(from_handle(shm));
commit 7b5ba54f3d71ceaca21b988964df4cf8d29b1f02
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:28 2016 +0100
linux-gen: _ishm: adding function to map memory from other ODP
functionality to export and map memory between ODP instance is added:
This includes:
- a bit of simplification in _odp_ishm_reserve() for externaly provided
file descriptors.
- a new function, _odp_ishm_find_exported() to map memory from
other ODP instances (On same OS)
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index eb94306..7c373dc 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -152,6 +152,7 @@ typedef struct ishm_fragment {
* will allocate both a block and a fragment.
* Blocks contain only global data common to all processes.
*/
+typedef enum {UNKNOWN, HUGE, NORMAL, EXTERNAL} huge_flag_t;
typedef struct ishm_block {
char name[ISHM_NAME_MAXLEN]; /* name for the ishm block (if any) */
char filename[ISHM_FILENAME_MAXLEN]; /* name of the .../odp-* file */
@@ -162,7 +163,7 @@ typedef struct ishm_block {
void *start; /* only valid if _ODP_ISHM_SINGLE_VA is set*/
uint64_t len; /* length. multiple of page size. 0 if free*/
ishm_fragment_t *fragment; /* used when _ODP_ISHM_SINGLE_VA is used */
- int huge; /* true if this segment is mapped using huge pages */
+ huge_flag_t huge; /* page type: external means unknown here. */
uint64_t seq; /* sequence number, incremented on alloc and free */
uint64_t refcnt;/* number of linux processes mapping this block */
} ishm_block_t;
@@ -400,7 +401,7 @@ static void free_fragment(ishm_fragment_t *fragmnt)
* or /mnt/huge/odp-<pid>-<sequence_or_name> (for huge pages)
* Return the new file descriptor, or -1 on error.
*/
-static int create_file(int block_index, int huge, uint64_t len,
+static int create_file(int block_index, huge_flag_t huge, uint64_t len,
uint32_t flags, uint32_t align)
{
char *name;
@@ -419,10 +420,11 @@ static int create_file(int block_index, int huge, uint64_t len,
ishm_tbl->dev_seq++);
/* huge dir must be known to create files there!: */
- if (huge && !odp_global_data.hugepage_info.default_huge_page_dir)
+ if ((huge == HUGE) &&
+ (!odp_global_data.hugepage_info.default_huge_page_dir))
return -1;
- if (huge)
+ if (huge == HUGE)
snprintf(filename, ISHM_FILENAME_MAXLEN,
ISHM_FILENAME_FORMAT,
odp_global_data.hugepage_info.default_huge_page_dir,
@@ -502,7 +504,7 @@ static void delete_file(ishm_block_t *block)
* Mutex must be assured by the caller.
*/
static void *do_map(int block_index, uint64_t len, uint32_t align,
- uint32_t flags, int huge, int *fd)
+ uint32_t flags, huge_flag_t huge, int *fd)
{
ishm_block_t *new_block; /* entry in the main block table */
void *addr = NULL;
@@ -552,8 +554,6 @@ static void *do_map(int block_index, uint64_t len, uint32_t align,
return NULL;
}
- new_block->huge = huge;
-
return mapped_addr;
}
@@ -756,27 +756,21 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
int new_index; /* index in the main block table*/
ishm_block_t *new_block; /* entry in the main block table*/
uint64_t page_sz; /* normal page size. usually 4K*/
- uint64_t alloc_size; /* includes extra for alignement*/
uint64_t page_hp_size; /* huge page size */
- uint64_t alloc_hp_size; /* includes extra for alignement*/
uint32_t hp_align;
uint64_t len; /* mapped length */
void *addr = NULL; /* mapping address */
int new_proc_entry;
-
- page_sz = odp_sys_page_size();
+ struct stat statbuf;
odp_spinlock_lock(&ishm_tbl->lock);
/* update this process view... */
procsync();
- /* roundup to page size */
- alloc_size = (size + (page_sz - 1)) & (-page_sz);
-
+ /* Get system page sizes: page_hp_size is 0 if no huge page available*/
+ page_sz = odp_sys_page_size();
page_hp_size = odp_sys_huge_page_size();
- /* roundup to page size */
- alloc_hp_size = (size + (page_hp_size - 1)) & (-page_hp_size);
/* check if name already exists */
if (name && (find_block_by_name(name) >= 0)) {
@@ -809,8 +803,24 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
else
new_block->name[0] = 0;
- /* Try first huge pages when possible and needed: */
- if (page_hp_size && (alloc_size > page_sz)) {
+ /* If a file descriptor is provided, get the real size and map: */
+ if (fd >= 0) {
+ fstat(fd, &statbuf);
+ len = statbuf.st_size;
+ /* note that the huge page flag is meningless here as huge
+ * page is determined by the provided file descriptor: */
+ addr = do_map(new_index, len, align, flags, EXTERNAL, &fd);
+ if (addr == NULL) {
+ close(fd);
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ ODP_ERR("_ishm_reserve failed.\n");
+ return -1;
+ }
+ new_block->huge = EXTERNAL;
+ }
+
+ /* Otherwise, Try first huge pages when possible and needed: */
+ if ((fd < 0) && page_hp_size && (size > page_sz)) {
/* at least, alignment in VA should match page size, but user
* can request more: If the user requirement exceeds the page
* size then we have to make sure the block will be mapped at
@@ -821,18 +831,20 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
hp_align = odp_sys_huge_page_size();
else
flags |= _ODP_ISHM_SINGLE_VA;
- len = alloc_hp_size;
- addr = do_map(new_index, len, hp_align, flags, 1, &fd);
+
+ /* roundup to page size */
+ len = (size + (page_hp_size - 1)) & (-page_hp_size);
+ addr = do_map(new_index, len, hp_align, flags, HUGE, &fd);
if (addr == NULL)
ODP_DBG("No huge pages, fall back to normal pages, "
"check: /proc/sys/vm/nr_hugepages.\n");
else
- new_block->huge = 1;
+ new_block->huge = HUGE;
}
- /* try normal pages if huge pages failed */
- if (addr == NULL) {
+ /* Try normal pages if huge pages failed */
+ if (fd < 0) {
/* at least, alignment in VA should match page size, but user
* can request more: If the user requirement exceeds the page
* size then we have to make sure the block will be mapped at
@@ -843,13 +855,14 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
else
flags |= _ODP_ISHM_SINGLE_VA;
- len = alloc_size;
- addr = do_map(new_index, len, align, flags, 0, &fd);
- new_block->huge = 0;
+ /* roundup to page size */
+ len = (size + (page_sz - 1)) & (-page_sz);
+ addr = do_map(new_index, len, align, flags, NORMAL, &fd);
+ new_block->huge = NORMAL;
}
/* if neither huge pages or normal pages works, we cannot proceed: */
- if ((addr == NULL) || (len == 0)) {
+ if ((fd < 0) || (addr == NULL) || (len == 0)) {
if ((new_block->filename[0]) && (fd >= 0))
close(fd);
odp_spinlock_unlock(&ishm_tbl->lock);
@@ -883,6 +896,83 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
}
/*
+ * Try to map an memory block mapped by another ODP instance into the
+ * current ODP instance.
+ * returns 0 on success.
+ */
+int _odp_ishm_find_exported(const char *remote_name, pid_t external_odp_pid,
+ const char *local_name)
+{
+ char export_filename[ISHM_FILENAME_MAXLEN];
+ char blockname[ISHM_FILENAME_MAXLEN];
+ char filename[ISHM_FILENAME_MAXLEN];
+ FILE *export_file;
+ uint64_t len;
+ uint32_t flags;
+ uint32_t align;
+ int fd;
+ int ret;
+
+ /* try to read the block description file: */
+ snprintf(export_filename, ISHM_FILENAME_MAXLEN,
+ ISHM_EXPTNAME_FORMAT,
+ external_odp_pid,
+ remote_name);
+
+ export_file = fopen(export_filename, "r");
+
+ if (export_file == NULL) {
+ ODP_ERR("Error opening %s.\n", export_filename);
+ return -1;
+ }
+
+ if (fscanf(export_file, EXPORT_FILE_LINE1_FMT " ") != 0)
+ goto error_exp_file;
+
+ if (fscanf(export_file, EXPORT_FILE_LINE2_FMT " ", blockname) != 1)
+ goto error_exp_file;
+
+ if (fscanf(export_file, EXPORT_FILE_LINE3_FMT " ", filename) != 1)
+ goto error_exp_file;
+
+ if (fscanf(export_file, EXPORT_FILE_LINE4_FMT " ", &len) != 1)
+ goto error_exp_file;
+
+ if (fscanf(export_file, EXPORT_FILE_LINE5_FMT " ", &flags) != 1)
+ goto error_exp_file;
+
+ if (fscanf(export_file, EXPORT_FILE_LINE6_FMT " ", &align) != 1)
+ goto error_exp_file;
+
+ fclose(export_file);
+
+ /* now open the filename given in the description file: */
+ fd = open(filename, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd == -1) {
+ ODP_ERR("open failed for %s: %s.\n",
+ filename, strerror(errno));
+ return -1;
+ }
+
+ /* clear the _ODP_ISHM_EXPORT flag so we don't export that again*/
+ flags &= ~(uint32_t)_ODP_ISHM_EXPORT;
+
+ /* reserve the memory, providing the opened file descriptor: */
+ ret = _odp_ishm_reserve(local_name, 0, fd, align, flags, 0);
+ if (ret < 0) {
+ close(fd);
+ return ret;
+ }
+
+ return ret;
+
+error_exp_file:
+ fclose(export_file);
+ ODP_ERR("Error reading %s.\n", export_filename);
+ return -1;
+}
+
+/*
* Free and unmap internal shared memory:
* The file descriptor is closed and the .../odp-* file deleted,
* unless fd was externally provided at reserve() time.
@@ -1189,7 +1279,7 @@ int _odp_ishm_info(int block_index, _odp_ishm_info_t *info)
info->name = ishm_tbl->block[block_index].name;
info->addr = ishm_proctable->entry[proc_index].start;
info->size = ishm_tbl->block[block_index].user_len;
- info->page_size = ishm_tbl->block[block_index].huge ?
+ info->page_size = (ishm_tbl->block[block_index].huge == HUGE) ?
odp_sys_huge_page_size() : odp_sys_page_size();
info->flags = ishm_tbl->block[block_index].flags;
info->user_flags = ishm_tbl->block[block_index].user_flags;
@@ -1483,7 +1573,19 @@ int _odp_ishm_status(const char *title)
flags[1] = (ishm_tbl->block[i].flags & _ODP_ISHM_LOCK) ?
'L' : '.';
flags[2] = 0;
- huge = (ishm_tbl->block[i].huge) ? 'H' : '.';
+ switch (ishm_tbl->block[i].huge) {
+ case HUGE:
+ huge = 'H';
+ break;
+ case NORMAL:
+ huge = 'N';
+ break;
+ case EXTERNAL:
+ huge = 'E';
+ break;
+ default:
+ huge = '?';
+ }
proc_index = procfind_block(i);
ODP_DBG("%-3d: name:%-.24s file:%-.24s"
" flags:%s,%c len:0x%-08lx"
diff --git a/platform/linux-generic/include/_ishm_internal.h b/platform/linux-generic/include/_ishm_internal.h
index f5de26e..c7c3307 100644
--- a/platform/linux-generic/include/_ishm_internal.h
+++ b/platform/linux-generic/include/_ishm_internal.h
@@ -11,6 +11,8 @@
extern "C" {
#endif
+#include <sys/types.h>
+
/* flags available at ishm_reserve: */
#define _ODP_ISHM_SINGLE_VA 1
#define _ODP_ISHM_LOCK 2
@@ -36,6 +38,9 @@ int _odp_ishm_free_by_address(void *addr);
void *_odp_ishm_lookup_by_index(int block_index);
int _odp_ishm_lookup_by_name(const char *name);
int _odp_ishm_lookup_by_address(void *addr);
+int _odp_ishm_find_exported(const char *remote_name,
+ pid_t external_odp_pid,
+ const char *local_name);
void *_odp_ishm_address(int block_index);
int _odp_ishm_info(int block_index, _odp_ishm_info_t *info);
int _odp_ishm_status(const char *title);
commit fb432fef933e276b674a29a24d3ebb9e5c91abbc
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:27 2016 +0100
test: api: shmem: new proper tests for shm API
The shmem "sunnydays" tests for the north interface API are replaced with
proper tests, testing memory allocation at different time (before and
after ODP thread creation, i.e. the tests make sure shmem behaves
the same regardless of fork time). The tests also include stress testing
trying to provoque race conditions. The new shmem tests do not assume
pthreads any longer and are runnable in process mode.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/test/common_plat/validation/api/shmem/shmem.c b/test/common_plat/validation/api/shmem/shmem.c
index cbff673..6ea92d9 100644
--- a/test/common_plat/validation/api/shmem/shmem.c
+++ b/test/common_plat/validation/api/shmem/shmem.c
@@ -7,82 +7,703 @@
#include <odp_api.h>
#include <odp_cunit_common.h>
#include "shmem.h"
+#include <stdlib.h>
-#define ALIGE_SIZE (128)
-#define TESTNAME "cunit_test_shared_data"
+#define ALIGN_SIZE (128)
+#define MEM_NAME "test_shmem"
+#define NAME_LEN (sizeof(MEM_NAME) + 20)
#define TEST_SHARE_FOO (0xf0f0f0f0)
#define TEST_SHARE_BAR (0xf0f0f0f)
+#define SMALL_MEM 10
+#define MEDIUM_MEM 4096
+#define BIG_MEM 65536
+#define STRESS_SIZE 32 /* power of 2 and <=256 */
+#define STRESS_RANDOM_SZ 5
+#define STRESS_ITERATION 5000
-static odp_barrier_t test_barrier;
+typedef enum {
+ STRESS_FREE, /* entry is free and can be allocated */
+ STRESS_BUSY, /* entry is being processed: don't touch */
+ STRESS_ALLOC /* entry is allocated and can be freed */
+} stress_state_t;
-static int run_shm_thread(void *arg ODP_UNUSED)
+typedef struct {
+ stress_state_t state;
+ odp_shm_t shm;
+ char name[NAME_LEN];
+ void *address;
+ uint32_t flags;
+ uint32_t size;
+ uint64_t align;
+ uint8_t data_val;
+} stress_data_t;
+
+typedef struct {
+ odp_barrier_t test_barrier1;
+ odp_barrier_t test_barrier2;
+ odp_barrier_t test_barrier3;
+ odp_barrier_t test_barrier4;
+ uint32_t foo;
+ uint32_t bar;
+ odp_atomic_u32_t index;
+ uint32_t nb_threads;
+ odp_shm_t shm[MAX_WORKERS];
+ void *address[MAX_WORKERS];
+ char name[MAX_WORKERS][NAME_LEN];
+ odp_spinlock_t stress_lock;
+ stress_data_t stress[STRESS_SIZE];
+} shared_test_data_t;
+
+/* memory stuff expected to fit in a single page */
+typedef struct {
+ int data[SMALL_MEM];
+} shared_test_data_small_t;
+
+/* memory stuff expected to fit in a huge page */
+typedef struct {
+ int data[MEDIUM_MEM];
+} shared_test_data_medium_t;
+
+/* memory stuff expected to fit in many huge pages */
+typedef struct {
+ int data[BIG_MEM];
+} shared_test_data_big_t;
+
+/*
+ * thread part for the shmem_test_basic test
+ */
+static int run_test_basic_thread(void *arg ODP_UNUSED)
{
odp_shm_info_t info;
odp_shm_t shm;
- test_shared_data_t *test_shared_data;
+ shared_test_data_t *shared_test_data;
int thr;
- odp_barrier_wait(&test_barrier);
thr = odp_thread_id();
printf("Thread %i starts\n", thr);
- shm = odp_shm_lookup(TESTNAME);
+ shm = odp_shm_lookup(MEM_NAME);
CU_ASSERT(ODP_SHM_INVALID != shm);
- test_shared_data = odp_shm_addr(shm);
- CU_ASSERT(TEST_SHARE_FOO == test_shared_data->foo);
- CU_ASSERT(TEST_SHARE_BAR == test_shared_data->bar);
+ shared_test_data = odp_shm_addr(shm);
+ CU_ASSERT(NULL != shared_test_data);
+
+ odp_barrier_wait(&shared_test_data->test_barrier1);
+ odp_shm_print_all();
+ CU_ASSERT(TEST_SHARE_FOO == shared_test_data->foo);
+ CU_ASSERT(TEST_SHARE_BAR == shared_test_data->bar);
CU_ASSERT(0 == odp_shm_info(shm, &info));
- CU_ASSERT(0 == strcmp(TESTNAME, info.name));
+ CU_ASSERT(0 == strcmp(MEM_NAME, info.name));
CU_ASSERT(0 == info.flags);
- CU_ASSERT(test_shared_data == info.addr);
- CU_ASSERT(sizeof(test_shared_data_t) <= info.size);
-#ifdef MAP_HUGETLB
- CU_ASSERT(odp_sys_huge_page_size() == info.page_size);
-#else
- CU_ASSERT(odp_sys_page_size() == info.page_size);
-#endif
+ CU_ASSERT(shared_test_data == info.addr);
+ CU_ASSERT(sizeof(shared_test_data_t) <= info.size);
+ CU_ASSERT((info.page_size == odp_sys_huge_page_size()) ||
+ (info.page_size == odp_sys_page_size()))
odp_shm_print_all();
fflush(stdout);
return CU_get_number_of_failures();
}
-void shmem_test_odp_shm_sunnyday(void)
+/*
+ * test basic things: shmem creation, info, share, and free
+ */
+void shmem_test_basic(void)
{
pthrd_arg thrdarg;
odp_shm_t shm;
- test_shared_data_t *test_shared_data;
+ shared_test_data_t *shared_test_data;
odp_cpumask_t unused;
- shm = odp_shm_reserve(TESTNAME,
- sizeof(test_shared_data_t), ALIGE_SIZE, 0);
+ shm = odp_shm_reserve(MEM_NAME,
+ sizeof(shared_test_data_t), ALIGN_SIZE, 0);
CU_ASSERT(ODP_SHM_INVALID != shm);
- CU_ASSERT(odp_shm_to_u64(shm) != odp_shm_to_u64(ODP_SHM_INVALID));
+ CU_ASSERT(odp_shm_to_u64(shm) !=
+ odp_shm_to_u64(ODP_SHM_INVALID));
CU_ASSERT(0 == odp_shm_free(shm));
- CU_ASSERT(ODP_SHM_INVALID == odp_shm_lookup(TESTNAME));
+ CU_ASSERT(ODP_SHM_INVALID == odp_shm_lookup(MEM_NAME));
- shm = odp_shm_reserve(TESTNAME,
- sizeof(test_shared_data_t), ALIGE_SIZE, 0);
+ shm = odp_shm_reserve(MEM_NAME,
+ sizeof(shared_test_data_t), ALIGN_SIZE, 0);
CU_ASSERT(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;
+ shared_test_data = odp_shm_addr(shm);
+ CU_ASSERT_FATAL(NULL != shared_test_data);
+ shared_test_data->foo = TEST_SHARE_FOO;
+ shared_test_data->bar = TEST_SHARE_BAR;
thrdarg.numthrds = odp_cpumask_default_worker(&unused, 0);
if (thrdarg.numthrds > MAX_WORKERS)
thrdarg.numthrds = MAX_WORKERS;
- odp_barrier_init(&test_barrier, thrdarg.numthrds);
- odp_cunit_thread_create(run_shm_thread, &thrdarg);
+ odp_barrier_init(&shared_test_data->test_barrier1, thrdarg.numthrds);
+ odp_cunit_thread_create(run_test_basic_thread, &thrdarg);
CU_ASSERT(odp_cunit_thread_exit(&thrdarg) >= 0);
+
+ CU_ASSERT(0 == odp_shm_free(shm));
+}
+
+/*
+ * thread part for the shmem_test_reserve_after_fork
+ */
+static int run_test_reserve_after_fork(void *arg ODP_UNUSED)
+{
+ odp_shm_t shm;
+ shared_test_data_t *glob_data;
+ int thr;
+ int thr_index;
+ int size;
+ shared_test_data_small_t *pattern_small;
+ shared_test_data_medium_t *pattern_medium;
+ shared_test_data_big_t *pattern_big;
+ int i;
+
+ thr = odp_thread_id();
+ printf("Thread %i starts\n", thr);
+
+ shm = odp_shm_lookup(MEM_NAME);
+ glob_data = odp_shm_addr(shm);
+
+ /*
+ * odp_thread_id are not guaranteed to be consecutive, so we create
+ * a consecutive ID
+ */
+ thr_index = odp_atomic_fetch_inc_u32(&glob_data->index);
+
+ /* allocate some memory (of different sizes) and fill with pattern */
+ snprintf(glob_data->name[thr_index], NAME_LEN, "%s-%09d",
+ MEM_NAME, thr_index);
+ switch (thr_index % 3) {
+ case 0:
+ size = sizeof(shared_test_data_small_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size, 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_small = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_small);
+ for (i = 0; i < SMALL_MEM; i++)
+ pattern_small->data[i] = i;
+ break;
+ case 1:
+ size = sizeof(shared_test_data_medium_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size, 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_medium = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_medium);
+ for (i = 0; i < MEDIUM_MEM; i++)
+ pattern_medium->data[i] = (i << 2);
+ break;
+ case 2:
+ size = sizeof(shared_test_data_big_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size, 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_big = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_big);
+ for (i = 0; i < BIG_MEM; i++)
+ pattern_big->data[i] = (i >> 2);
+ break;
+ }
+
+ /* print block address */
+ printf("In thread: Block index: %d mapped at %lx\n",
+ thr_index, (long int)odp_shm_addr(shm));
+
+ odp_barrier_wait(&glob_data->test_barrier1);
+ odp_barrier_wait(&glob_data->test_barrier2);
+
+ fflush(stdout);
+ return CU_get_number_of_failures();
+}
+
+/*
+ * test sharing memory reserved after odp_thread creation (e.g. fork()):
+ */
+void shmem_test_reserve_after_fork(void)
+{
+ pthrd_arg thrdarg;
+ odp_shm_t shm;
+ odp_shm_t thr_shm;
+ shared_test_data_t *glob_data;
+ odp_cpumask_t unused;
+ int thr_index;
+ int i;
+ void *address;
+ shared_test_data_small_t *pattern_small;
+ shared_test_data_medium_t *pattern_medium;
+ shared_test_data_big_t *pattern_big;
+
+ shm = odp_shm_reserve(MEM_NAME, sizeof(shared_test_data_t), 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(glob_data);
+
+ thrdarg.numthrds = odp_cpumask_default_worker(&unused, 0);
+ if (thrdarg.numthrds > MAX_WORKERS)
+ thrdarg.numthrds = MAX_WORKERS;
+
+ odp_barrier_init(&glob_data->test_barrier1, thrdarg.numthrds + 1);
+ odp_barrier_init(&glob_data->test_barrier2, thrdarg.numthrds + 1);
+ odp_atomic_store_u32(&glob_data->index, 0);
+
+ odp_cunit_thread_create(run_test_reserve_after_fork, &thrdarg);
+
+ /* wait until all threads have made their shm_reserve: */
+ odp_barrier_wait(&glob_data->test_barrier1);
+
+ /* perform a lookup of all memories: */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ thr_shm = odp_shm_lookup(glob_data->name[thr_index]);
+ CU_ASSERT(thr_shm == glob_data->shm[thr_index]);
+ }
+
+ /* check that the patterns are correct: */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ switch (thr_index % 3) {
+ case 0:
+ pattern_small =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_small);
+ for (i = 0; i < SMALL_MEM; i++)
+ CU_ASSERT(pattern_small->data[i] == i);
+ break;
+ case 1:
+ pattern_medium =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_medium);
+ for (i = 0; i < MEDIUM_MEM; i++)
+ CU_ASSERT(pattern_medium->data[i] == (i << 2));
+ break;
+ case 2:
+ pattern_big =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_big);
+ for (i = 0; i < BIG_MEM; i++)
+ CU_ASSERT(pattern_big->data[i] == (i >> 2));
+ break;
+ }
+ }
+
+ /*
+ * print the mapping address of the blocks
+ */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ address = odp_shm_addr(glob_data->shm[thr_index]);
+ printf("In main Block index: %d mapped at %lx\n",
+ thr_index, (long int)address);
+ }
+
+ /* unblock the threads and let them terminate (no free is done): */
+ odp_barrier_wait(&glob_data->test_barrier2);
+
+ /* at the same time, (race),free of all memories: */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ thr_shm = glob_data->shm[thr_index];
+ CU_ASSERT(odp_shm_free(thr_shm) == 0);
+ }
+
+ /* wait for all thread endings: */
+ CU_ASSERT(odp_cunit_thread_exit(&thrdarg) >= 0);
+
+ /* just glob_data should remain: */
+
+ CU_ASSERT(0 == odp_shm_free(shm));
+}
+
+/*
+ * thread part for the shmem_test_singleva_after_fork
+ */
+static int run_test_singleva_after_fork(void *arg ODP_UNUSED)
+{
+ odp_shm_t shm;
+ shared_test_data_t *glob_data;
+ int thr;
+ int thr_index;
+ int size;
+ shared_test_data_small_t *pattern_small;
+ shared_test_data_medium_t *pattern_medium;
+ shared_test_data_big_t *pattern_big;
+ uint32_t i;
+ int ret;
+
+ thr = odp_thread_id();
+ printf("Thread %i starts\n", thr);
+
+ shm = odp_shm_lookup(MEM_NAME);
+ glob_data = odp_shm_addr(shm);
+
+ /*
+ * odp_thread_id are not guaranteed to be consecutive, so we create
+ * a consecutive ID
+ */
+ thr_index = odp_atomic_fetch_inc_u32(&glob_data->index);
+
+ /* allocate some memory (of different sizes) and fill with pattern */
+ snprintf(glob_data->name[thr_index], NAME_LEN, "%s-%09d",
+ MEM_NAME, thr_index);
+ switch (thr_index % 3) {
+ case 0:
+ size = sizeof(shared_test_data_small_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size,
+ 0, ODP_SHM_SINGLE_VA);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_small = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_small);
+ glob_data->address[thr_index] = (void *)pattern_small;
+ for (i = 0; i < SMALL_MEM; i++)
+ pattern_small->data[i] = i;
+ break;
+ case 1:
+ size = sizeof(shared_test_data_medium_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size,
+ 0, ODP_SHM_SINGLE_VA);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_medium = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_medium);
+ glob_data->address[thr_index] = (void *)pattern_medium;
+ for (i = 0; i < MEDIUM_MEM; i++)
+ pattern_medium->data[i] = (i << 2);
+ break;
+ case 2:
+ size = sizeof(shared_test_data_big_t);
+ shm = odp_shm_reserve(glob_data->name[thr_index], size,
+ 0, ODP_SHM_SINGLE_VA);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data->shm[thr_index] = shm;
+ pattern_big = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(pattern_big);
+ glob_data->address[thr_index] = (void *)pattern_big;
+ for (i = 0; i < BIG_MEM; i++)
+ pattern_big->data[i] = (i >> 2);
+ break;
+ }
+
+ /* print block address */
+ printf("In thread: Block index: %d mapped at %lx\n",
+ thr_index, (long int)odp_shm_addr(shm));
+
+ odp_barrier_wait(&glob_data->test_barrier1);
+ odp_barrier_wait(&glob_data->test_barrier2);
+
+ /* map each-other block, checking common address: */
+ for (i = 0; i < glob_data->nb_threads; i++) {
+ shm = odp_shm_lookup(glob_data->name[i]);
+ CU_ASSERT(shm == glob_data->shm[i]);
+ CU_ASSERT(odp_shm_addr(shm) == glob_data->address[i]);
+ }
+
+ /* wait for main control task and free the allocated block */
+ odp_barrier_wait(&glob_data->test_barrier3);
+ odp_barrier_wait(&glob_data->test_barrier4);
+ ret = odp_shm_free(glob_data->shm[thr_index]);
+ CU_ASSERT(ret == 0);
+
+ fflush(stdout);
+ return CU_get_number_of_failures();
+}
+
+/*
+ * test sharing memory reserved after odp_thread creation (e.g. fork()):
+ * with single VA flag.
+ */
+void shmem_test_singleva_after_fork(void)
+{
+ pthrd_arg thrdarg;
+ odp_shm_t shm;
+ odp_shm_t thr_shm;
+ shared_test_data_t *glob_data;
+ odp_cpumask_t unused;
+ int thr_index;
+ int i;
+ void *address;
+ shared_test_data_small_t *pattern_small;
+ shared_test_data_medium_t *pattern_medium;
+ shared_test_data_big_t *pattern_big;
+
+ shm = odp_shm_reserve(MEM_NAME, sizeof(shared_test_data_t),
+ 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != shm);
+ glob_data = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(glob_data);
+
+ thrdarg.numthrds = odp_cpumask_default_worker(&unused, 0);
+ if (thrdarg.numthrds > MAX_WORKERS)
+ thrdarg.numthrds = MAX_WORKERS;
+
+ glob_data->nb_threads = thrdarg.numthrds;
+ odp_barrier_init(&glob_data->test_barrier1, thrdarg.numthrds + 1);
+ odp_barrier_init(&glob_data->test_barrier2, thrdarg.numthrds + 1);
+ odp_barrier_init(&glob_data->test_barrier3, thrdarg.numthrds + 1);
+ odp_barrier_init(&glob_data->test_barrier4, thrdarg.numthrds + 1);
+ odp_atomic_store_u32(&glob_data->index, 0);
+
+ odp_cunit_thread_create(run_test_singleva_after_fork, &thrdarg);
+
+ /* wait until all threads have made their shm_reserve: */
+ odp_barrier_wait(&glob_data->test_barrier1);
+
+ /* perform a lookup of all memories: */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ thr_shm = odp_shm_lookup(glob_data->name[thr_index]);
+ CU_ASSERT(thr_shm == glob_data->shm[thr_index]);
+ }
+
+ /* check that the patterns are correct: */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ switch (thr_index % 3) {
+ case 0:
+ pattern_small =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_small);
+ for (i = 0; i < SMALL_MEM; i++)
+ CU_ASSERT(pattern_small->data[i] == i);
+ break;
+ case 1:
+ pattern_medium =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_medium);
+ for (i = 0; i < MEDIUM_MEM; i++)
+ CU_ASSERT(pattern_medium->data[i] == (i << 2));
+ break;
+ case 2:
+ pattern_big =
+ odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT_PTR_NOT_NULL(pattern_big);
+ for (i = 0; i < BIG_MEM; i++)
+ CU_ASSERT(pattern_big->data[i] == (i >> 2));
+ break;
+ }
+ }
+
+ /*
+ * check that the mapping address is common to all (SINGLE_VA):
+ */
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
+ address = odp_shm_addr(glob_data->shm[thr_index]);
+ CU_ASSERT(glob_data->address[thr_index] == address);
+ }
+
+ /* unblock the threads and let them map each-other blocks: */
+ odp_barrier_wait(&glob_data->test_barrier2);
+
+ /* then check mem status */
+ odp_barrier_wait(&glob_data->test_barrier3);
+
+ /* unblock the threads and let them free all thread blocks: */
+ odp_barrier_wait(&glob_data->test_barrier4);
+
+ /* wait for all thread endings: */
+ CU_ASSERT(odp_cunit_thread_exit(&thrdarg) >= 0);
+
+ /* just glob_data should remain: */
+
+ CU_ASSERT(0 == odp_shm_free(shm));
+}
+
+/*
+ * thread part for the shmem_test_stress
+ */
+static int run_test_stress(void *arg ODP_UNUSED)
+{
+ odp_shm_t shm;
+ uint8_t *address;
+ shared_test_data_t *glob_data;
+ uint8_t random_bytes[STRESS_RANDOM_SZ];
+ uint32_t index;
+ uint32_t size;
+ uint64_t align;
+ uint32_t flags;
+ uint8_t data;
+ uint32_t iter;
+ uint32_t i;
+
+ shm = odp_shm_lookup(MEM_NAME);
+ glob_data = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(glob_data);
+
+ /* wait for general GO! */
+ odp_barrier_wait(&glob_data->test_barrier1);
+
+ /*
+ * at each iteration: pick up a random index for
+ * glob_data->stress[index]: If the entry is free, allocated mem
+ * randomly. If it is already allocated, make checks and free it:
+ * Note that different tread can allocate or free a given block
+ */
+ for (iter = 0; iter < STRESS_ITERATION; iter++) {
+ /* get 4 random bytes from which index, size ,align, flags
+ * and data will be derived:
+ */
+ odp_random_data(random_bytes, STRESS_RANDOM_SZ, 0);
+ index = random_bytes[0] & (STRESS_SIZE - 1);
+
+ odp_spinlock_lock(&glob_data->stress_lock);
+
+ switch (glob_data->stress[index].state) {
+ case STRESS_FREE:
+ /* allocated a new block for this entry */
+
+ glob_data->stress[index].state = STRESS_BUSY;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+
+ size = (random_bytes[1] + 1) << 6; /* up to 16Kb */
+ /* we just play with the VA flag. randomly setting
+ * the mlock flag may exceed user ulimit -l
+ */
+ flags = random_bytes[2] & ODP_SHM_SINGLE_VA;
+ align = (random_bytes[3] + 1) << 6;/* up to 16Kb */
+ data = random_bytes[4];
+
+ snprintf(glob_data->stress[index].name, NAME_LEN,
+ "%s-%09d", MEM_NAME, index);
+ shm = odp_shm_reserve(glob_data->stress[index].name,
+ size, align, flags);
+ glob_data->stress[index].shm = shm;
+ if (shm == ODP_SHM_INVALID) { /* out of mem ? */
+ odp_spinlock_lock(&glob_data->stress_lock);
+ glob_data->stress[index].state = STRESS_ALLOC;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+ continue;
+ }
+
+ address = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(address);
+ glob_data->stress[index].address = address;
+ glob_data->stress[index].flags = flags;
+ glob_data->stress[index].size = size;
+ glob_data->stress[index].align = align;
+ glob_data->stress[index].data_val = data;
+
+ /* write some data: writing each byte would be a
+ * waste of time: just make sure each page is reached */
+ for (i = 0; i < size; i += 256)
+ address[i] = (data++) & 0xFF;
+ odp_spinlock_lock(&glob_data->stress_lock);
+ glob_data->stress[index].state = STRESS_ALLOC;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+
+ break;
+
+ case STRESS_ALLOC:
+ /* free the block for this entry */
+
+ glob_data->stress[index].state = STRESS_BUSY;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+ shm = glob_data->stress[index].shm;
+
+ if (shm == ODP_SHM_INVALID) { /* out of mem ? */
+ odp_spinlock_lock(&glob_data->stress_lock);
+ glob_data->stress[index].state = STRESS_FREE;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+ continue;
+ }
+
+ CU_ASSERT(odp_shm_lookup(glob_data->stress[index].name)
+ != 0);
+
+ address = odp_shm_addr(shm);
+ CU_ASSERT_PTR_NOT_NULL(address);
+
+ align = glob_data->stress[index].align;
+ if (align) {
+ align = glob_data->stress[index].align;
+ CU_ASSERT(((uintptr_t)address & (align - 1))
+ == 0)
+ }
+
+ flags = glob_data->stress[index].flags;
+ if (flags & ODP_SHM_SINGLE_VA)
+ CU_ASSERT(glob_data->stress[index].address ==
+ address)
+
+ /* check that data is reachable and correct: */
+ data = glob_data->stress[index].data_val;
+ size = glob_data->stress[index].size;
+ for (i = 0; i < size; i += 256) {
+ CU_ASSERT(address[i] == (data & 0xFF));
+ data++;
+ }
+
+ CU_ASSERT(!odp_shm_free(glob_data->stress[index].shm));
+
+ odp_spinlock_lock(&glob_data->stress_lock);
+ glob_data->stress[index].state = STRESS_FREE;
+ odp_spinlock_unlock(&glob_data->stress_lock);
+
+ break;
+
+ case STRESS_BUSY:
+ default:
+ odp_spinlock_unlock(&glob_data->stress_lock);
+ break;
+ }
+ }
+
+ fflush(stdout);
+ return CU_get_number_of_failures();
+}
+
+/*
+ * stress tests
+ */
+void shmem_test_stress(void)
+{
+ pthrd_arg thrdarg;
+ odp_shm_t shm;
+ odp_shm_t globshm;
+ shared_test_data_t *glob_data;
+ odp_cpumask_t unused;
+ uint32_t i;
+
+ globshm = odp_shm_reserve(MEM_NAME, sizeof(shared_test_data_t),
+ 0, 0);
+ CU_ASSERT(ODP_SHM_INVALID != globshm);
+ glob_data = odp_shm_addr(globshm);
+ CU_ASSERT_PTR_NOT_NULL(glob_data);
+
+ thrdarg.numthrds = odp_cpumask_default_worker(&unused, 0);
+ if (thrdarg.numthrds > MAX_WORKERS)
+ thrdarg.numthrds = MAX_WORKERS;
+
+ glob_data->nb_threads = thrdarg.numthrds;
+ odp_barrier_init(&glob_data->test_barrier1, thrdarg.numthrds);
+ odp_spinlock_init(&glob_data->stress_lock);
+
+ /* before starting the threads, mark all entries as free: */
+ for (i = 0; i < STRESS_SIZE; i++)
+ glob_data->stress[i].state = STRESS_FREE;
+
+ /* create threads */
+ odp_cunit_thread_create(run_test_stress, &thrdarg);
+
+ /* wait for all thread endings: */
+ CU_ASSERT(odp_cunit_thread_exit(&thrdarg) >= 0);
+
+ /* release left overs: */
+ for (i = 0; i < STRESS_SIZE; i++) {
+ shm = glob_data->stress[i].shm;
+ if ((glob_data->stress[i].state == STRESS_ALLOC) &&
+ (glob_data->stress[i].shm != ODP_SHM_INVALID)) {
+ CU_ASSERT(odp_shm_lookup(glob_data->stress[i].name) ==
+ shm);
+ CU_ASSERT(!odp_shm_free(shm));
+ }
+ }
+
+ CU_ASSERT(0 == odp_shm_free(globshm));
+
+ /* check that no memory is left over: */
}
odp_testinfo_t shmem_suite[] = {
- ODP_TEST_INFO(shmem_test_odp_shm_sunnyday),
+ ODP_TEST_INFO(shmem_test_basic),
+ ODP_TEST_INFO(shmem_test_reserve_after_fork),
+ ODP_TEST_INFO(shmem_test_singleva_after_fork),
+ ODP_TEST_INFO(shmem_test_stress),
ODP_TEST_INFO_NULL,
};
diff --git a/test/common_plat/validation/api/shmem/shmem.h b/test/common_plat/validation/api/shmem/shmem.h
index a5893d9..092aa80 100644
--- a/test/common_plat/validation/api/shmem/shmem.h
+++ b/test/common_plat/validation/api/shmem/shmem.h
@@ -10,7 +10,10 @@
#include <odp_cunit_common.h>
/* test functions: */
-void shmem_test_odp_shm_sunnyday(void);
+void shmem_test_basic(void);
+void shmem_test_reserve_after_fork(void);
+void shmem_test_singleva_after_fork(void);
+void shmem_test_stress(void);
/* test arrays: */
extern odp_testinfo_t shmem_suite[];
commit 02c58efd7bd80ca0d7656e867c0ea70d39e17169
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:26 2016 +0100
linux-gen: shm: new ODP_SHM_SINGLE_VA flag implementation
This flag guarentess the unicity the the block address on all ODP threads.
The patch just exposes the _ODP_ISHM_SINGLE_VA flag of the internal memory
allocator, ishm.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/odp_shared_memory.c b/platform/linux-generic/odp_shared_memory.c
index 9e916e9..2377f16 100644
--- a/platform/linux-generic/odp_shared_memory.c
+++ b/platform/linux-generic/odp_shared_memory.c
@@ -43,6 +43,7 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align,
/* set internal ishm flags according to API flags: */
flgs |= (flags & ODP_SHM_PROC) ? _ODP_ISHM_EXPORT : 0;
+ flgs |= (flags & ODP_SHM_SINGLE_VA) ? _ODP_ISHM_SINGLE_VA : 0;
/* all mem reserved through this interface is requested to be locked: */
flgs |= (flags & _ODP_ISHM_LOCK);
commit a3013bbd8d534b856693873e46fa95cefa824756
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:25 2016 +0100
api: shm: add flags to shm_reserve and function to find external mem
The ODP_SHM_SINGLE_VA flag is created: when set (at odp_shm_reserve()),
this flag guarantees that all ODP threads sharing this memory
block will see the block at the same address (regadless of ODP
thread type -pthread vs process- or fork time)
The flag ODP_SHM_EXPORT is added: when passed at odp_shm_reserve() time
the memory block becomes visible to other ODP instances.
The function odp_shm_import() is added: this function enables to
reserve block of memories exported by other ODP instances (using the
ODP_SHM_EXPORT flag).
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Reviewed-by: Petri Savolainen <petri.savolainen(a)nokia.com>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/include/odp/api/spec/shared_memory.h b/include/odp/api/spec/shared_memory.h
index 8c76807..885751d 100644
--- a/include/odp/api/spec/shared_memory.h
+++ b/include/odp/api/spec/shared_memory.h
@@ -14,6 +14,7 @@
#ifndef ODP_API_SHARED_MEMORY_H_
#define ODP_API_SHARED_MEMORY_H_
#include <odp/visibility_begin.h>
+#include <odp/api/init.h>
#ifdef __cplusplus
extern "C" {
@@ -43,12 +44,25 @@ extern "C" {
#define ODP_SHM_NAME_LEN 32
/*
- * Shared memory flags
+ * Shared memory flags:
*/
-
-/* Share level */
-#define ODP_SHM_SW_ONLY 0x1 /**< Application SW only, no HW access */
-#define ODP_SHM_PROC 0x2 /**< Share with external processes */
+#define ODP_SHM_SW_ONLY 0x1 /**< Application SW only, no HW access */
+#define ODP_SHM_PROC 0x2 /**< Share with external processes */
+/**
+ * Single virtual address
+ *
+ * When set, this flag guarantees that all ODP threads sharing this
+ * memory block will see the block at the same address - regardless
+ * of ODP thread type (e.g. pthread vs. process (or fork process time)).
+ */
+#define ODP_SHM_SINGLE_VA 0x4
+/**
+ * Export memory
+ *
+ * When set, the memory block becomes visible to other ODP instances
+ * through odp_shm_import().
+ */
+#define ODP_SHM_EXPORT 0x08
/**
* Shared memory block info
@@ -135,6 +149,28 @@ int odp_shm_free(odp_shm_t shm);
*/
odp_shm_t odp_shm_lookup(const char *name);
+/**
+ * Import a block of shared memory, exported by another ODP instance
+ *
+ * This call creates a new handle for accessing a shared memory block created
+ * (with ODP_SHM_EXPORT flag) by another ODP instance. An instance may have
+ * only a single handle to the same block. Application must not access the
+ * block after freeing the handle. When an imported handle is freed, only
+ * the calling instance is affected. The exported block may be freed only
+ * after all other instances have stopped accessing the block.
+ *
+ * @param remote_name Name of the block, in the remote ODP instance
+ * @param odp_inst Remote ODP instance, as returned by odp_init_global()
+ * @param local_name Name given to the block, in the local ODP instance
+ * May be NULL, if the application doesn't need a name
+ * (for a lookup).
+ *
+ * @return A handle to access a block exported by another ODP instance.
+ * @retval ODP_SHM_INVALID on failure
+ */
+odp_shm_t odp_shm_import(const char *remote_name,
+ odp_instance_t odp_inst,
+ const char *local_name);
/**
* Shared memory block address
commit f452a9e04b0da3e71f86d8bb02370b7f86ec0098
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:24 2016 +0100
linux-gen: push internal flag definition
File platform/linux-generic/include/odp_shm_internal.h exposes shm
internals used by IPC. The bits used by the internal flags are moved
to make room for more "official" values.
The platform/linux-generic/include/odp_shm_internal.h file should really
be removed when _ishm is used, but as long as we have the current IPC,
removing the file would break compilation.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/include/odp_shm_internal.h b/platform/linux-generic/include/odp_shm_internal.h
index 30e60f7..8bd105d 100644
--- a/platform/linux-generic/include/odp_shm_internal.h
+++ b/platform/linux-generic/include/odp_shm_internal.h
@@ -16,8 +16,8 @@ extern "C" {
#define SHM_DEVNAME_MAXLEN (ODP_SHM_NAME_LEN + 16)
#define SHM_DEVNAME_FORMAT "/odp-%d-%s" /* /dev/shm/odp-<pid>-<name> */
-#define _ODP_SHM_PROC_NOCREAT 0x4 /**< Do not create shm if not exist */
-#define _ODP_SHM_O_EXCL 0x8 /**< Do not create shm if exist */
+#define _ODP_SHM_PROC_NOCREAT 0x40 /**< Do not create shm if not exist */
+#define _ODP_SHM_O_EXCL 0x80 /**< Do not create shm if exist */
#ifdef __cplusplus
}
commit 3665147240b4df0b322629f47ca0cd10ed97082d
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:23 2016 +0100
linux-gen: use ishm as north API mem allocator
The odp shared_memory API is changed to use the ODP internal memory
allocator: _ishm.
_ishm supports memory sharing between processes, regardless of fork time.
The test testing the ODP_SHM_PROC flag is also changed to cope with the
new OS sharing interface used by _ishm (link in /tmp).
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index 2f29d3d..6a80d9d 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -60,7 +60,6 @@ enum init_stage {
SYSINFO_INIT,
FDSERVER_INIT,
ISHM_INIT,
- SHM_INIT,
THREAD_INIT,
POOL_INIT,
QUEUE_INIT,
@@ -90,10 +89,6 @@ int odp_thread_init_local(odp_thread_type_t type);
int odp_thread_term_local(void);
int odp_thread_term_global(void);
-int odp_shm_init_global(void);
-int odp_shm_term_global(void);
-int odp_shm_init_local(void);
-
int odp_pool_init_global(void);
int odp_pool_init_local(void);
int odp_pool_term_global(void);
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index 6e58ab6..d40a83c 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -123,12 +123,6 @@ int odp_init_global(odp_instance_t *instance,
}
stage = ISHM_INIT;
- if (odp_shm_init_global()) {
- ODP_ERR("ODP shm init failed.\n");
- goto init_failed;
- }
- stage = SHM_INIT;
-
if (odp_thread_init_global()) {
ODP_ERR("ODP thread init failed.\n");
goto init_failed;
@@ -282,13 +276,6 @@ int _odp_term_global(enum init_stage stage)
}
/* Fall through */
- case SHM_INIT:
- if (odp_shm_term_global()) {
- ODP_ERR("ODP shm term failed.\n");
- rc = -1;
- }
- /* Fall through */
-
case ISHM_INIT:
if (_odp_ishm_term_global()) {
ODP_ERR("ODP ishm term failed.\n");
@@ -346,12 +333,6 @@ int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
}
stage = ISHM_INIT;
- if (odp_shm_init_local()) {
- ODP_ERR("ODP shm local init failed.\n");
- goto init_fail;
- }
- stage = SHM_INIT;
-
if (odp_thread_init_local(thr_type)) {
ODP_ERR("ODP thread local init failed.\n");
goto init_fail;
diff --git a/platform/linux-generic/odp_shared_memory.c b/platform/linux-generic/odp_shared_memory.c
index 550af27..9e916e9 100644
--- a/platform/linux-generic/odp_shared_memory.c
+++ b/platform/linux-generic/odp_shared_memory.c
@@ -4,434 +4,88 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <odp_posix_extensions.h>
-
-#include <odp/api/shared_memory.h>
-#include <odp_internal.h>
-#include <odp/api/spinlock.h>
-#include <odp/api/align.h>
-#include <odp/api/system_info.h>
-#include <odp/api/debug.h>
-#include <odp_shm_internal.h>
-#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
#include <odp_config_internal.h>
-
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <asm/mman.h>
-#include <fcntl.h>
-
-#include <stdio.h>
+#include <odp/api/debug.h>
+#include <odp/api/std_types.h>
+#include <odp/api/shared_memory.h>
+#include <_ishm_internal.h>
#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
ODP_STATIC_ASSERT(ODP_CONFIG_SHM_BLOCKS >= ODP_CONFIG_POOLS,
"ODP_CONFIG_SHM_BLOCKS < ODP_CONFIG_POOLS");
-typedef struct {
- char name[ODP_SHM_NAME_LEN];
- uint64_t size;
- uint64_t align;
- uint64_t alloc_size;
- void *addr_orig;
- void *addr;
- int huge;
- odp_shm_t hdl;
- uint32_t flags;
- uint64_t page_sz;
- int fd;
-
-} odp_shm_block_t;
-
-
-typedef struct {
- odp_shm_block_t block[ODP_CONFIG_SHM_BLOCKS];
- odp_spinlock_t lock;
-
-} odp_shm_table_t;
-
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-
-/* Global shared memory table */
-static odp_shm_table_t *odp_shm_tbl;
-
-
static inline uint32_t from_handle(odp_shm_t shm)
{
return _odp_typeval(shm) - 1;
}
-
static inline odp_shm_t to_handle(uint32_t index)
{
return _odp_cast_scalar(odp_shm_t, index + 1);
}
-
-int odp_shm_init_global(void)
-{
- void *addr;
-
-#ifndef MAP_HUGETLB
- ODP_DBG("NOTE: mmap does not support huge pages\n");
-#endif
-
- addr = mmap(NULL, sizeof(odp_shm_table_t),
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-
- if (addr == MAP_FAILED)
- return -1;
-
- odp_shm_tbl = addr;
-
- memset(odp_shm_tbl, 0, sizeof(odp_shm_table_t));
- odp_spinlock_init(&odp_shm_tbl->lock);
-
- return 0;
-}
-
-int odp_shm_term_global(void)
-{
- int ret;
-
- ret = munmap(odp_shm_tbl, sizeof(odp_shm_table_t));
- if (ret)
- ODP_ERR("unable to munmap\n.");
-
- return ret;
-}
-
-
-int odp_shm_init_local(void)
-{
- return 0;
-}
-
int odp_shm_capability(odp_shm_capability_t *capa)
{
memset(capa, 0, sizeof(odp_shm_capability_t));
capa->max_blocks = ODP_CONFIG_SHM_BLOCKS;
- capa->max_size = 0;
- capa->max_align = 0;
+ capa->max_size = 0;
+ capa->max_align = 0;
return 0;
}
-static int find_block(const char *name, uint32_t *index)
-{
- uint32_t i;
-
- for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
- if (strcmp(name, odp_shm_tbl->block[i].name) == 0) {
- /* found it */
- if (index != NULL)
- *index = i;
-
- return 1;
- }
- }
-
- return 0;
-}
-
-int odp_shm_free(odp_shm_t shm)
-{
- uint32_t i;
- int ret;
- odp_shm_block_t *block;
- char shm_devname[SHM_DEVNAME_MAXLEN];
-
- if (shm == ODP_SHM_INVALID) {
- ODP_DBG("odp_shm_free: Invalid handle\n");
- return -1;
- }
-
- i = from_handle(shm);
-
- if (i >= ODP_CONFIG_SHM_BLOCKS) {
- ODP_DBG("odp_shm_free: Bad handle\n");
- return -1;
- }
-
- odp_spinlock_lock(&odp_shm_tbl->lock);
-
- block = &odp_shm_tbl->block[i];
-
- if (block->addr == NULL) {
- ODP_DBG("odp_shm_free: Free block\n");
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return 0;
- }
-
- ret = munmap(block->addr_orig, block->alloc_size);
- if (0 != ret) {
- ODP_DBG("odp_shm_free: munmap failed: %s, id %u, addr %p\n",
- strerror(errno), i, block->addr_orig);
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return -1;
- }
-
- if (block->flags & ODP_SHM_PROC || block->flags & _ODP_SHM_PROC_NOCREAT) {
- int shm_ns_id;
-
- if (odp_global_data.ipc_ns)
- shm_ns_id = odp_global_data.ipc_ns;
- else
- shm_ns_id = odp_global_data.main_pid;
-
- snprintf(shm_devname, SHM_DEVNAME_MAXLEN,
- SHM_DEVNAME_FORMAT, shm_ns_id, block->name);
- ret = shm_unlink(shm_devname);
- if (0 != ret) {
- ODP_DBG("odp_shm_free: shm_unlink failed\n");
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return -1;
- }
- }
- memset(block, 0, sizeof(odp_shm_block_t));
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return 0;
-}
-
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align,
uint32_t flags)
{
- uint32_t i;
- char shm_devname[SHM_DEVNAME_MAXLEN];
- odp_shm_block_t *block;
- void *addr;
- int fd = -1;
- int map_flag = MAP_SHARED;
- /* If already exists: O_EXCL: error, O_TRUNC: truncate to zero */
- int oflag = O_RDWR;
- uint64_t alloc_size;
- uint64_t page_sz, huge_sz;
-#ifdef MAP_HUGETLB
- int need_huge_page = 0;
- uint64_t alloc_hp_size;
-#endif
-
- page_sz = odp_sys_page_size();
- alloc_size = size + align;
+ int block_index;
+ int flgs = 0; /* internal ishm flags */
-#ifdef MAP_HUGETLB
- huge_sz = odp_sys_huge_page_size();
- need_huge_page = (huge_sz && alloc_size > page_sz);
- /* munmap for huge pages requires sizes round up by page */
- alloc_hp_size = (size + align + (huge_sz - 1)) & (-huge_sz);
-#endif
+ /* set internal ishm flags according to API flags: */
+ flgs |= (flags & ODP_SHM_PROC) ? _ODP_ISHM_EXPORT : 0;
- if (flags & ODP_SHM_PROC)
- oflag |= O_CREAT | O_TRUNC;
- if (flags & _ODP_SHM_O_EXCL)
- oflag |= O_EXCL;
+ /* all mem reserved through this interface is requested to be locked: */
+ flgs |= (flags & _ODP_ISHM_LOCK);
- if (flags & (ODP_SHM_PROC | _ODP_SHM_PROC_NOCREAT)) {
- int shm_ns_id;
-
- if (odp_global_data.ipc_ns)
- shm_ns_id = odp_global_data.ipc_ns;
- else
- shm_ns_id = odp_global_data.main_pid;
-
- need_huge_page = 0;
-
- /* Creates a file to /dev/shm/odp */
- snprintf(shm_devname, SHM_DEVNAME_MAXLEN,
- SHM_DEVNAME_FORMAT, shm_ns_id, name);
- fd = shm_open(shm_devname, oflag,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (fd == -1) {
- ODP_DBG("%s: shm_open failed.\n", shm_devname);
- return ODP_SHM_INVALID;
- }
- } else {
- map_flag |= MAP_ANONYMOUS;
- }
-
- odp_spinlock_lock(&odp_shm_tbl->lock);
-
- if (find_block(name, NULL)) {
- /* Found a block with the same name */
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- ODP_DBG("name \"%s\" already used.\n", name);
+ block_index = _odp_ishm_reserve(name, size, -1, align, flgs, flags);
+ if (block_index >= 0)
+ return to_handle(block_index);
+ else
return ODP_SHM_INVALID;
- }
-
- for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
- if (odp_shm_tbl->block[i].addr == NULL) {
- /* Found free block */
- break;
- }
- }
-
- if (i > ODP_CONFIG_SHM_BLOCKS - 1) {
- /* Table full */
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- ODP_DBG("%s: no more blocks.\n", name);
- return ODP_SHM_INVALID;
- }
-
- block = &odp_shm_tbl->block[i];
-
- block->hdl = to_handle(i);
- addr = MAP_FAILED;
-
-#ifdef MAP_HUGETLB
- /* Try first huge pages */
- if (need_huge_page) {
- if ((flags & ODP_SHM_PROC) &&
- (ftruncate(fd, alloc_hp_size) == -1)) {
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- ODP_DBG("%s: ftruncate huge pages failed.\n", name);
- return ODP_SHM_INVALID;
- }
-
- addr = mmap(NULL, alloc_hp_size, PROT_READ | PROT_WRITE,
- map_flag | MAP_HUGETLB, fd, 0);
- if (addr == MAP_FAILED) {
- ODP_DBG(" %s:\n"
- "\tNo huge pages, fall back to normal pages,\n"
- "\tcheck: /proc/sys/vm/nr_hugepages.\n", name);
- } else {
- block->alloc_size = alloc_hp_size;
- block->huge = 1;
- block->page_sz = huge_sz;
- }
- }
-#endif
-
- /* Use normal pages for small or failed huge page allocations */
- if (addr == MAP_FAILED) {
- if ((flags & ODP_SHM_PROC) &&
- (ftruncate(fd, alloc_size) == -1)) {
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- ODP_ERR("%s: ftruncate failed.\n", name);
- return ODP_SHM_INVALID;
- }
-
- addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
- map_flag, fd, 0);
- if (addr == MAP_FAILED) {
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- ODP_DBG("%s mmap failed.\n", name);
- return ODP_SHM_INVALID;
- } else {
- block->alloc_size = alloc_size;
- block->huge = 0;
- block->page_sz = page_sz;
- }
- }
-
- block->addr_orig = addr;
-
- /* move to correct alignment */
- addr = ODP_ALIGN_ROUNDUP_PTR(addr, align);
-
- strncpy(block->name, name, ODP_SHM_NAME_LEN - 1);
- block->name[ODP_SHM_NAME_LEN - 1] = 0;
- block->size = size;
- block->align = align;
- block->flags = flags;
- block->fd = fd;
- block->addr = addr;
+}
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return block->hdl;
+int odp_shm_free(odp_shm_t shm)
+{
+ return _odp_ishm_free_by_index(from_handle(shm));
}
odp_shm_t odp_shm_lookup(const char *name)
{
- uint32_t i;
- odp_shm_t hdl;
-
- odp_spinlock_lock(&odp_shm_tbl->lock);
-
- if (find_block(name, &i) == 0) {
- odp_spinlock_unlock(&odp_shm_tbl->lock);
- return ODP_SHM_INVALID;
- }
-
- hdl = odp_shm_tbl->block[i].hdl;
- odp_spinlock_unlock(&odp_shm_tbl->lock);
-
- return hdl;
+ return to_handle(_odp_ishm_lookup_by_name(name));
}
-
void *odp_shm_addr(odp_shm_t shm)
{
- uint32_t i;
-
- i = from_handle(shm);
-
- if (i > (ODP_CONFIG_SHM_BLOCKS - 1))
- return NULL;
-
- return odp_shm_tbl->block[i].addr;
+ return _odp_ishm_address(from_handle(shm));
}
-
int odp_shm_info(odp_shm_t shm, odp_shm_info_t *info)
{
- odp_shm_block_t *block;
- uint32_t i;
+ _odp_ishm_info_t ishm_info;
- i = from_handle(shm);
-
- if (i > (ODP_CONFIG_SHM_BLOCKS - 1))
+ if (_odp_ishm_info(from_handle(shm), &ishm_info))
return -1;
- block = &odp_shm_tbl->block[i];
-
- info->name = block->name;
- info->addr = block->addr;
- info->size = block->size;
- info->page_size = block->page_sz;
- info->flags = block->flags;
+ info->name = ishm_info.name;
+ info->addr = ishm_info.addr;
+ info->size = ishm_info.size;
+ info->page_size = ishm_info.page_size;
+ info->flags = ishm_info.user_flags;
return 0;
}
-
void odp_shm_print_all(void)
{
- int i;
-
- ODP_PRINT("\nShared memory\n");
- ODP_PRINT("--------------\n");
- ODP_PRINT(" page size: %"PRIu64" kB\n",
- odp_sys_page_size() / 1024);
- ODP_PRINT(" huge page size: %"PRIu64" kB\n",
- odp_sys_huge_page_size() / 1024);
- ODP_PRINT("\n");
-
- ODP_PRINT(" id name kB align huge addr\n");
-
- for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
- odp_shm_block_t *block;
-
- block = &odp_shm_tbl->block[i];
-
- if (block->addr) {
- ODP_PRINT(" %2i %-24s %4"PRIu64" %4"PRIu64
- " %2c %p\n",
- i,
- block->name,
- block->size/1024,
- block->align,
- (block->huge ? '*' : ' '),
- block->addr);
- }
- }
-
- ODP_PRINT("\n");
+ _odp_ishm_status("Memory allocation status:");
}
diff --git a/test/linux-generic/validation/api/shmem/shmem_linux.c b/test/linux-generic/validation/api/shmem/shmem_linux.c
index 212a6c1..9ab0e2b 100644
--- a/test/linux-generic/validation/api/shmem/shmem_linux.c
+++ b/test/linux-generic/validation/api/shmem/shmem_linux.c
@@ -45,12 +45,69 @@
#include <sys/mman.h>
#include <libgen.h>
#include <linux/limits.h>
+#include <inttypes.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> */
-#define MAX_FIFO_WAIT 30 /* Max time waiting for the fifo (sec) */
+#define ODP_APP_NAME "shmem_odp" /* name of the odp program, in this dir */
+#define DEVNAME_FMT "/tmp/odp-%" PRIu64 "-shm-%s" /* odp-<pid>-shm-<name> */
+#define MAX_FIFO_WAIT 30 /* Max time waiting for the fifo (sec) */
+
+/*
+ * read the attributes of a externaly shared mem object:
+ * input: ext_odp_pid, blockname: the remote ODP instance and the exported
+ * block name to be searched.
+ * Output: filename: the memory block underlaying file to be opened
+ * (the given buffer should be big enough i.e. at
+ * least ISHM_FILENAME_MAXLEN bytes)
+ * The 3 following parameters are really here for debug
+ * as they are really meaningles in a non-odp process:
+ * len: the block real length (bytes, multiple of page sz)
+ * flags: the _ishm flags setting the block was created with
+ * align: the alignement setting the block was created with
+ *
+ * return 0 on success, non zero on error
+ */
+static int read_shmem_attribues(uint64_t ext_odp_pid, const char *blockname,
+ char *filename, uint64_t *len,
+ uint32_t *flags, uint32_t *align)
+{
+ char shm_attr_filename[PATH_MAX];
+ FILE *export_file;
+
+ sprintf(shm_attr_filename, DEVNAME_FMT, ext_odp_pid, blockname);
+
+ /* O_CREAT flag not given => failure if shm_attr_filename does not
+ * already exist */
+ export_file = fopen(shm_attr_filename, "r");
+ if (export_file == NULL)
+ return -1;
+
+ if (fscanf(export_file, "ODP exported shm block info: ") != 0)
+ goto export_file_read_err;
+
+ if (fscanf(export_file, "ishm_blockname: %*s ") != 0)
+ goto export_file_read_err;
+
+ if (fscanf(export_file, "file: %s ", filename) != 1)
+ goto export_file_read_err;
+
+ if (fscanf(export_file, "length: %" PRIu64 " ", len) != 1)
+ goto export_file_read_err;
+
+ if (fscanf(export_file, "flags: %" PRIu32 " ", flags) != 1)
+ goto export_file_read_err;
+
+ if (fscanf(export_file, "align: %" PRIu32 " ", align) != 1)
+ goto export_file_read_err;
+
+ fclose(export_file);
+ return 0;
+
+export_file_read_err:
+ fclose(export_file);
+ return -1;
+}
void test_success(char *fifo_name, int fd, pid_t odp_app)
{
@@ -91,12 +148,15 @@ int main(int argc __attribute__((unused)), char *argv[])
char prg_name[PATH_MAX];
char odp_name[PATH_MAX];
int nb_sec;
- int size;
+ uint64_t size;
pid_t odp_app;
char *odp_params = NULL;
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_devname[PATH_MAX];/* shared mem device name.*/
+ uint64_t len;
+ uint32_t flags;
+ uint32_t align;
int shm_fd;
test_shared_linux_data_t *addr;
@@ -130,26 +190,28 @@ 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);
+ /* read the shared memory attributes (includes the shm filename): */
+ if (read_shmem_attribues(odp_app, ODP_SHM_NAME,
+ shm_devname, &len, &flags, &align) != 0)
+ test_failure(fifo_name, fifo_fd, odp_app);
- /* O_CREAT flag not given => failure if shm_devname does not already
+ /* open the shm filename (which is either on /tmp or on hugetlbfs)
+ * 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);
+ shm_fd = 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);
+ test_failure(fifo_name, fifo_fd, odp_app);
+
+ /* linux ODP guarantees page size alignement. Larger alignment may
+ * fail as 2 different processes will have fully unrelated
+ * virtual spaces.
+ */
+ size = sizeof(test_shared_linux_data_t);
- /* 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);
+ test_failure(fifo_name, fifo_fd, odp_app);
/* check that we see what the ODP application wrote in the memory */
if ((addr->foo == TEST_SHARE_FOO) && (addr->bar == TEST_SHARE_BAR))
commit 6794ac225910c56d93fa3cf464644b633ee35f32
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:22 2016 +0100
linux-gen: _ishm: allow memory alloc/free at global init/term
_ishm.c assumed that both _ishm_init_global() and _ishm_init_local()
had been run to work properly. This assumption turns out the be a problem
if _ishm is to be used as main memory allocator, as many modules
init_global functions assume the availability of the odp_reserve()
function before any init_local function is called.
Likewise, many term_global() functions assume the availability
of the odp_shm_free() function after all odp_term_local() have run.
This patch runs _ishm_init_local() in advance for the main ODP thread
and postpones the execution of_ishm_term_local() to init_global()
time for the main process, hence making the ishm_reserve()
and ishm_free() functions available at init_global/term_global time.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index e3ab8b4..eb94306 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -156,7 +156,6 @@ typedef struct ishm_block {
char name[ISHM_NAME_MAXLEN]; /* name for the ishm block (if any) */
char filename[ISHM_FILENAME_MAXLEN]; /* name of the .../odp-* file */
char exptname[ISHM_FILENAME_MAXLEN]; /* name of the export file */
- int main_odpthread; /* The thread which did the initial reserve*/
uint32_t user_flags; /* any flags the user want to remember. */
uint32_t flags; /* block creation flags. */
uint64_t user_len; /* length, as requested at reserve time. */
@@ -178,6 +177,7 @@ typedef struct ishm_block {
typedef struct {
odp_spinlock_t lock;
uint64_t dev_seq; /* used when creating device names */
+ uint32_t odpthread_cnt; /* number of running ODP threads */
ishm_block_t block[ISHM_MAX_NB_BLOCKS];
} ishm_table_t;
static ishm_table_t *ishm_tbl;
@@ -864,7 +864,6 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
new_block->user_flags = user_flags;
new_block->seq++;
new_block->refcnt = 1;
- new_block->main_odpthread = odp_thread_id();
new_block->start = addr; /* only for SINGLE_VA*/
/* the allocation succeeded: update the process local view */
@@ -907,10 +906,8 @@ static int block_free(int block_index)
proc_index = procfind_block(block_index);
if (proc_index >= 0) {
- /* close the fd, unless if it was externaly provided */
- if ((block->filename[0] != 0) ||
- (odp_thread_id() != block->main_odpthread))
- close(ishm_proctable->entry[proc_index].fd);
+ /* close the related fd */
+ close(ishm_proctable->entry[proc_index].fd);
/* remove the mapping and possible fragment */
do_unmap(ishm_proctable->entry[proc_index].start,
@@ -1201,12 +1198,62 @@ int _odp_ishm_info(int block_index, _odp_ishm_info_t *info)
return 0;
}
+static int do_odp_ishm_init_local(void)
+{
+ int i;
+ int block_index;
+
+ /*
+ * the ishm_process table is local to each linux process
+ * Check that no other linux threads (of same or ancestor processes)
+ * have already created the table, and create it if needed.
+ * We protect this with the general ishm lock to avoid
+ * init race condition of different running threads.
+ */
+ odp_spinlock_lock(&ishm_tbl->lock);
+ ishm_tbl->odpthread_cnt++; /* count ODPthread (pthread or process) */
+ if (!ishm_proctable) {
+ ishm_proctable = malloc(sizeof(ishm_proctable_t));
+ if (!ishm_proctable) {
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ return -1;
+ }
+ memset(ishm_proctable, 0, sizeof(ishm_proctable_t));
+ }
+ if (syscall(SYS_gettid) != getpid())
+ ishm_proctable->thrd_refcnt++; /* new linux thread */
+ else
+ ishm_proctable->thrd_refcnt = 1;/* new linux process */
+
+ /*
+ * if this ODP thread is actually a new linux process, (as opposed
+ * to a pthread), i.e, we just forked, then all shmem blocks
+ * of the parent process are mapped into this child by inheritance.
+ * (The process local table is inherited as well). We hence have to
+ * increase the process refcount for each of the inherited mappings:
+ */
+ if (syscall(SYS_gettid) == getpid()) {
+ for (i = 0; i < ishm_proctable->nb_entries; i++) {
+ block_index = ishm_proctable->entry[i].block_index;
+ ishm_tbl->block[block_index].refcnt++;
+ }
+ }
+
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ return 0;
+}
+
int _odp_ishm_init_global(void)
{
void *addr;
void *spce_addr;
int i;
+ if ((getpid() != odp_global_data.main_pid) ||
+ (syscall(SYS_gettid) != getpid()))
+ ODP_ERR("odp_init_global() must be performed by the main "
+ "ODP process!\n.");
+
if (!odp_global_data.hugepage_info.default_huge_page_dir)
ODP_DBG("NOTE: No support for huge pages\n");
else
@@ -1223,6 +1270,7 @@ int _odp_ishm_init_global(void)
ishm_tbl = addr;
memset(ishm_tbl, 0, sizeof(ishm_table_t));
ishm_tbl->dev_seq = 0;
+ ishm_tbl->odpthread_cnt = 0;
odp_spinlock_init(&ishm_tbl->lock);
/* allocate space for the internal shared mem fragment table: */
@@ -1263,7 +1311,13 @@ int _odp_ishm_init_global(void)
ishm_ftbl->fragment[ISHM_NB_FRAGMNTS - 1].next = NULL;
ishm_ftbl->unused_fragmnts = &ishm_ftbl->fragment[1];
- return 0;
+ /*
+ * We run _odp_ishm_init_local() directely here to give the
+ * possibility to run shm_reserve() before the odp_init_local()
+ * is performed for the main thread... Many init_global() functions
+ * indeed assume the availability of odp_shm_reserve()...:
+ */
+ return do_odp_ishm_init_local();
init_glob_err3:
if (munmap(ishm_ftbl, sizeof(ishm_ftable_t)) < 0)
@@ -1277,80 +1331,28 @@ init_glob_err1:
int _odp_ishm_init_local(void)
{
- int i;
- int block_index;
-
/*
- * the ishm_process table is local to each linux process
- * Check that no other linux threads (of same or ancestor processes)
- * have already created the table, and create it if needed.
- * We protect this with the general ishm lock to avoid
- * init race condition of different running threads.
+ * Do not re-run this for the main ODP process, as it has already
+ * been done in advance at _odp_ishm_init_global() time:
*/
- odp_spinlock_lock(&ishm_tbl->lock);
- if (!ishm_proctable) {
- ishm_proctable = malloc(sizeof(ishm_proctable_t));
- if (!ishm_proctable) {
- odp_spinlock_unlock(&ishm_tbl->lock);
- return -1;
- }
- memset(ishm_proctable, 0, sizeof(ishm_proctable_t));
- }
- if (syscall(SYS_gettid) != getpid())
- ishm_proctable->thrd_refcnt++; /* new linux thread */
- else
- ishm_proctable->thrd_refcnt = 1;/* new linux process */
+ if ((getpid() == odp_global_data.main_pid) &&
+ (syscall(SYS_gettid) == getpid()))
+ return 0;
- /*
- * if this ODP thread is actually a new linux process, (as opposed
- * to a pthread), i.e, we just forked, then all shmem blocks
- * of the parent process are mapped into this child by inheritance.
- * (The process local table is inherited as well). We hence have to
- * increase the process refcount for each of the inherited mappings:
- */
- if (syscall(SYS_gettid) == getpid()) {
- for (i = 0; i < ishm_proctable->nb_entries; i++) {
- block_index = ishm_proctable->entry[i].block_index;
- ishm_tbl->block[block_index].refcnt++;
- }
- }
-
- odp_spinlock_unlock(&ishm_tbl->lock);
- return 0;
+ return do_odp_ishm_init_local();
}
-int _odp_ishm_term_global(void)
-{
- int ret = 0;
-
- /* free the fragment table */
- if (munmap(ishm_ftbl, sizeof(ishm_ftable_t)) < 0) {
- ret = -1;
- ODP_ERR("unable to munmap fragment table\n.");
- }
- /* free the block table */
- if (munmap(ishm_tbl, sizeof(ishm_table_t)) < 0) {
- ret = -1;
- ODP_ERR("unable to munmap main table\n.");
- }
-
- /* free the reserved VA space */
- if (_odp_ishmphy_unbook_va())
- ret = -1;
-
- return ret;
-}
-
-int _odp_ishm_term_local(void)
+static int do_odp_ishm_term_local(void)
{
int i;
int proc_table_refcnt = 0;
int block_index;
ishm_block_t *block;
- odp_spinlock_lock(&ishm_tbl->lock);
procsync();
+ ishm_tbl->odpthread_cnt--; /* decount ODPthread (pthread or process) */
+
/*
* The ishm_process table is local to each linux process
* Check that no other linux threads (of this linux process)
@@ -1390,10 +1392,56 @@ int _odp_ishm_term_local(void)
ishm_proctable = NULL;
}
- odp_spinlock_unlock(&ishm_tbl->lock);
return 0;
}
+int _odp_ishm_term_local(void)
+{
+ int ret;
+
+ odp_spinlock_lock(&ishm_tbl->lock);
+
+ /* postpone last thread term to allow free() by global term functions:*/
+ if (ishm_tbl->odpthread_cnt == 1) {
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ return 0;
+ }
+
+ ret = do_odp_ishm_term_local();
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ return ret;
+}
+
+int _odp_ishm_term_global(void)
+{
+ int ret = 0;
+
+ if ((getpid() != odp_global_data.main_pid) ||
+ (syscall(SYS_gettid) != getpid()))
+ ODP_ERR("odp_term_global() must be performed by the main "
+ "ODP process!\n.");
+
+ /* perform the last thread terminate which was postponed: */
+ ret = do_odp_ishm_term_local();
+
+ /* free the fragment table */
+ if (munmap(ishm_ftbl, sizeof(ishm_ftable_t)) < 0) {
+ ret |= -1;
+ ODP_ERR("unable to munmap fragment table\n.");
+ }
+ /* free the block table */
+ if (munmap(ishm_tbl, sizeof(ishm_table_t)) < 0) {
+ ret |= -1;
+ ODP_ERR("unable to munmap main table\n.");
+ }
+
+ /* free the reserved VA space */
+ if (_odp_ishmphy_unbook_va())
+ ret |= -1;
+
+ return ret;
+}
+
/*
* Print the current ishm status (allocated blocks and VA space map)
* Return the number of allocated blocks (including those not mapped
@@ -1437,13 +1485,12 @@ int _odp_ishm_status(const char *title)
flags[2] = 0;
huge = (ishm_tbl->block[i].huge) ? 'H' : '.';
proc_index = procfind_block(i);
- ODP_DBG("%-3d: name:%-.24s file:%-.24s tid:%-3d"
+ ODP_DBG("%-3d: name:%-.24s file:%-.24s"
" flags:%s,%c len:0x%-08lx"
" user_len:%-8ld seq:%-3ld refcnt:%-4d\n",
i,
ishm_tbl->block[i].name,
ishm_tbl->block[i].filename,
- ishm_tbl->block[i].main_odpthread,
flags, huge,
ishm_tbl->block[i].len,
ishm_tbl->block[i].user_len,
commit 04537e7c3942664fe61fe9adaeb95b6afcb6e36c
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:21 2016 +0100
linux-gen: _ishm: create description file for external memory sharing
A new flag called _ODP_ISHM_EXPORT is added to _ishm. When this flag is
specified at reserve() time, an extra file
("/tmp/odp-<pid>-shm-<blockname>", where <pid> is the process ID of the
main ODP instatiation process and <blockname> is the block name given at
reserve time) is created, describing to the underlying block attributes.
This file is meant to be used by processes external to ODP willing to
share this memory.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index 3371d94..e3ab8b4 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -99,6 +99,14 @@
#define ISHM_FILENAME_NORMAL_PAGE_DIR "/tmp"
/*
+ * when the memory is to be shared with an external entity (such as another
+ * ODP instance or an OS process not part of this ODP instance) then a
+ * export file is created describing the exported memory: this defines the
+ * location and the filename format of this description file
+ */
+#define ISHM_EXPTNAME_FORMAT "/tmp/odp-%d-shm-%s"
+
+/*
* At worse case the virtual space gets so fragmented that there is
* a unallocated fragment between each allocated fragment:
* In that case, the number of fragments to take care of is twice the
@@ -107,6 +115,17 @@
#define ISHM_NB_FRAGMNTS (ISHM_MAX_NB_BLOCKS * 2 + 1)
/*
+ * when a memory block is to be exported outside its ODP instance,
+ * an block 'attribute file' is created in /tmp/odp-<pid>-shm-<name>.
+ * The information given in this file is according to the following:
+ */
+#define EXPORT_FILE_LINE1_FMT "ODP exported shm block info:"
+#define EXPORT_FILE_LINE2_FMT "ishm_blockname: %s"
+#define EXPORT_FILE_LINE3_FMT "file: %s"
+#define EXPORT_FILE_LINE4_FMT "length: %" PRIu64
+#define EXPORT_FILE_LINE5_FMT "flags: %" PRIu32
+#define EXPORT_FILE_LINE6_FMT "align: %" PRIu32
+/*
* A fragment describes a piece of the shared virtual address space,
* and is allocated only when allocation is done with the _ODP_ISHM_SINGLE_VA
* flag:
@@ -136,6 +155,7 @@ typedef struct ishm_fragment {
typedef struct ishm_block {
char name[ISHM_NAME_MAXLEN]; /* name for the ishm block (if any) */
char filename[ISHM_FILENAME_MAXLEN]; /* name of the .../odp-* file */
+ char exptname[ISHM_FILENAME_MAXLEN]; /* name of the export file */
int main_odpthread; /* The thread which did the initial reserve*/
uint32_t user_flags; /* any flags the user want to remember. */
uint32_t flags; /* block creation flags. */
@@ -380,7 +400,8 @@ static void free_fragment(ishm_fragment_t *fragmnt)
* or /mnt/huge/odp-<pid>-<sequence_or_name> (for huge pages)
* Return the new file descriptor, or -1 on error.
*/
-static int create_file(int block_index, int huge, uint64_t len)
+static int create_file(int block_index, int huge, uint64_t len,
+ uint32_t flags, uint32_t align)
{
char *name;
int fd;
@@ -388,6 +409,7 @@ static int create_file(int block_index, int huge, uint64_t len)
char seq_string[ISHM_FILENAME_MAXLEN]; /* used to construct filename*/
char filename[ISHM_FILENAME_MAXLEN];/* filename in /tmp/ or /mnt/huge */
int oflag = O_RDWR | O_CREAT | O_TRUNC; /* flags for open */
+ FILE *export_file;
new_block = &ishm_tbl->block[block_index];
name = new_block->name;
@@ -429,9 +451,48 @@ static int create_file(int block_index, int huge, uint64_t len)
strncpy(new_block->filename, filename, ISHM_FILENAME_MAXLEN - 1);
+ /* if _ODP_ISHM_EXPORT is set, create a description file for
+ * external ref:
+ */
+ if (flags & _ODP_ISHM_EXPORT) {
+ snprintf(new_block->exptname, ISHM_FILENAME_MAXLEN,
+ ISHM_EXPTNAME_FORMAT,
+ odp_global_data.main_pid,
+ (name && name[0]) ? name : seq_string);
+ export_file = fopen(new_block->exptname, "w");
+ if (export_file == NULL) {
+ ODP_ERR("open failed: err=%s.\n",
+ strerror(errno));
+ new_block->exptname[0] = 0;
+ } else {
+ fprintf(export_file, EXPORT_FILE_LINE1_FMT "\n");
+ fprintf(export_file, EXPORT_FILE_LINE2_FMT "\n", name);
+ fprintf(export_file, EXPORT_FILE_LINE3_FMT "\n",
+ new_block->filename);
+ fprintf(export_file, EXPORT_FILE_LINE4_FMT "\n", len);
+ fprintf(export_file, EXPORT_FILE_LINE5_FMT "\n", flags);
+ fprintf(export_file, EXPORT_FILE_LINE6_FMT "\n", align);
+
+ fclose(export_file);
+ }
+ } else {
+ new_block->exptname[0] = 0;
+ }
+
return fd;
}
+/* delete the files related to a given ishm block: */
+static void delete_file(ishm_block_t *block)
+{
+ /* remove the .../odp-* file, unless fd was external: */
+ if (block->filename[0] != 0)
+ unlink(block->filename);
+ /* also remove possible description file (if block was exported): */
+ if (block->exptname[0] != 0)
+ unlink(block->exptname);
+}
+
/*
* performs the mapping, possibly allocating a fragment of the pre-reserved
* VA space if the _ODP_ISHM_SINGLE_VA flag was given.
@@ -456,7 +517,7 @@ static void *do_map(int block_index, uint64_t len, uint32_t align,
* unless a fd was already given
*/
if (*fd < 0) {
- *fd = create_file(block_index, huge, len);
+ *fd = create_file(block_index, huge, len, flags, align);
if (*fd < 0)
return NULL;
} else {
@@ -471,7 +532,7 @@ static void *do_map(int block_index, uint64_t len, uint32_t align,
if (new_block->filename[0]) {
close(*fd);
*fd = -1;
- unlink(new_block->filename);
+ delete_file(new_block);
}
return NULL;
}
@@ -486,7 +547,7 @@ static void *do_map(int block_index, uint64_t len, uint32_t align,
if (new_block->filename[0]) {
close(*fd);
*fd = -1;
- unlink(new_block->filename);
+ delete_file(new_block);
}
return NULL;
}
@@ -867,9 +928,8 @@ static int block_free(int block_index)
do_unmap(NULL, 0, block->flags, block_index);
}
- /* remove the .../odp-* file, unless fd was external: */
- if (block->filename[0] != 0)
- unlink(block->filename);
+ /* remove all files related to this block: */
+ delete_file(block);
/* deregister the file descriptor from the file descriptor server. */
_odp_fdserver_deregister_fd(FD_SRV_CTX_ISHM, block_index);
diff --git a/platform/linux-generic/include/_ishm_internal.h b/platform/linux-generic/include/_ishm_internal.h
index 3231b60..f5de26e 100644
--- a/platform/linux-generic/include/_ishm_internal.h
+++ b/platform/linux-generic/include/_ishm_internal.h
@@ -14,6 +14,7 @@ extern "C" {
/* flags available at ishm_reserve: */
#define _ODP_ISHM_SINGLE_VA 1
#define _ODP_ISHM_LOCK 2
+#define _ODP_ISHM_EXPORT 4 /*create export descr file in /tmp */
/**
* Shared memory block info
commit cc8303560e95a12790103364240e2581cf3213bb
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:20 2016 +0100
linux-gen: init: removing possible obsolete ODP files at startup
When an ODP program is killed, some odp files may remain in /tmp and
the huge page mount point. As signal KILL cannot be caught, there is not
much one can do to prevent that.
But when an new odp session is started, all files prefixed with the opd
prefix ("odp-<PID>-") can be safely removed as the PID is unique and
therefore, there cannot be another ODP instance with the same PID.
This patch does this cleanup at startup.
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index d4a8e09..6e58ab6 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -10,15 +10,71 @@
#include <odp_internal.h>
#include <odp_schedule_if.h>
#include <string.h>
+#include <stdio.h>
+#include <linux/limits.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define _ODP_FILES_FMT "odp-%d-"
+#define _ODP_TMPDIR "/tmp"
struct odp_global_data_s odp_global_data;
+/* remove all files staring with "odp-<pid>" from a directory "dir" */
+static int cleanup_files(const char *dirpath, int odp_pid)
+{
+ struct dirent *e;
+ DIR *dir;
+ char prefix[PATH_MAX];
+ char *fullpath;
+ int d_len = strlen(dirpath);
+ int p_len;
+ int f_len;
+
+ dir = opendir(dirpath);
+ if (!dir) {
+ /* ok if the dir does not exist. no much to delete then! */
+ ODP_DBG("opendir failed for %s: %s\n",
+ dirpath, strerror(errno));
+ return 0;
+ }
+ snprintf(prefix, PATH_MAX, _ODP_FILES_FMT, odp_pid);
+ p_len = strlen(prefix);
+ while ((e = readdir(dir)) != NULL) {
+ if (strncmp(e->d_name, prefix, p_len) == 0) {
+ f_len = strlen(e->d_name);
+ fullpath = malloc(d_len + f_len + 2);
+ if (fullpath == NULL) {
+ closedir(dir);
+ return -1;
+ }
+ snprintf(fullpath, PATH_MAX, "%s/%s",
+ dirpath, e->d_name);
+ ODP_DBG("deleting obsolete file: %s\n", fullpath);
+ if (unlink(fullpath))
+ ODP_ERR("unlink failed for %s: %s\n",
+ fullpath, strerror(errno));
+ free(fullpath);
+ }
+ }
+ closedir(dir);
+
+ return 0;
+}
+
int odp_init_global(odp_instance_t *instance,
const odp_init_t *params,
const odp_platform_init_t *platform_params)
{
+ char *hpdir;
+
memset(&odp_global_data, 0, sizeof(struct odp_global_data_s));
odp_global_data.main_pid = getpid();
+ cleanup_files(_ODP_TMPDIR, odp_global_data.main_pid);
+
if (platform_params)
odp_global_data.ipc_ns = platform_params->ipc_ns;
@@ -49,6 +105,10 @@ int odp_init_global(odp_instance_t *instance,
ODP_ERR("ODP system_info init failed.\n");
goto init_failed;
}
+ hpdir = odp_global_data.hugepage_info.default_huge_page_dir;
+ /* cleanup obsolete huge page files, if any */
+ if (hpdir)
+ cleanup_files(hpdir, odp_global_data.main_pid);
stage = SYSINFO_INIT;
if (_odp_fdserver_init_global()) {
commit ac4ba826d777262b1f25944a4ceb840469ad0bd0
Author: Christophe Milard <christophe.milard(a)linaro.org>
Date: Thu Nov 24 17:22:19 2016 +0100
linux-gen: _ishm: fix for alignment request matching page size
There is no reason to toggle the _ODP_ISHM_SINGLE_VA flag
when the alignment exactly matches the page size.
This just results in wasting the odp-common virtual space
Signed-off-by: Christophe Milard <christophe.milard(a)linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer(a)linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index f4aa6d3..3371d94 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -756,7 +756,7 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
* the same address every where, otherwise alignment may be
* be wrong for some process */
hp_align = align;
- if (hp_align < odp_sys_huge_page_size())
+ if (hp_align <= odp_sys_huge_page_size())
hp_align = odp_sys_huge_page_size();
else
flags |= _ODP_ISHM_SINGLE_VA;
@@ -777,7 +777,7 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
* size then we have to make sure the block will be mapped at
* the same address every where, otherwise alignment may be
* be wrong for some process */
- if (align < odp_sys_page_size())
+ if (align <= odp_sys_page_size())
align = odp_sys_page_size();
else
flags |= _ODP_ISHM_SINGLE_VA;
-----------------------------------------------------------------------
Summary of changes:
doc/users-guide/users-guide.adoc | 68 +-
include/odp/api/spec/shared_memory.h | 46 +-
platform/linux-generic/_ishm.c | 460 ++++++++++----
platform/linux-generic/include/_ishm_internal.h | 6 +
platform/linux-generic/include/odp_internal.h | 5 -
platform/linux-generic/include/odp_shm_internal.h | 4 +-
platform/linux-generic/odp_init.c | 79 ++-
platform/linux-generic/odp_shared_memory.c | 412 ++----------
test/common_plat/validation/api/shmem/shmem.c | 687 ++++++++++++++++++++-
test/common_plat/validation/api/shmem/shmem.h | 5 +-
test/linux-generic/validation/api/shmem/.gitignore | 3 +-
.../linux-generic/validation/api/shmem/Makefile.am | 22 +-
.../validation/api/shmem/shmem_linux.c | 220 +++++--
.../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 +++
.../api/shmem/{shmem_odp.h => shmem_odp2.h} | 2 +-
17 files changed, 1520 insertions(+), 604 deletions(-)
rename test/linux-generic/validation/api/shmem/{shmem_odp.c => shmem_odp1.c} (81%)
copy 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
rename test/linux-generic/validation/api/shmem/{shmem_odp.h => shmem_odp2.h} (76%)
hooks/post-receive
--
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via 020c91ca5367e971cbfc493c5b92f65ec72a43e7 (commit)
via 01fc389137187cabd79a9e87319cd6c462cc6015 (commit)
via ab57009c2ddcc6ddeb0c180ce8800ebbf723ac8f (commit)
via 9c8ab9126181e5457f5711075b97ca9ec9a20fc8 (commit)
via 9ad380fa0a113b90e26518b7d659213f05264841 (commit)
via b3b97530679ed0fe6f975986270a3fa7d4c59a72 (commit)
via 99117760f8bed0d8351c35a2c037e288d5a9280a (commit)
via a560c609e78716421e782aa388805937d177ef0e (commit)
via 524987a32f9873e59ce265ffba6e831e756a2441 (commit)
via ab966018496e7ebb0d1532d6c5c119b9db7d56fa (commit)
from 90ac2ecbf8aec6d4f876d161b3844c199527c33e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 020c91ca5367e971cbfc493c5b92f65ec72a43e7
Merge: 90ac2ec 01fc389
Author: Maxim Uvarov <maxim.uvarov(a)linaro.org>
Date: Fri Nov 18 22:05:46 2016 +0300
Merge tag 'v1.11.0.0_monarch'
Monarch Long Term Stable v1.11.0.0
Signed-off-by: Maxim Uvarov <maxim.uvarov(a)linaro.org>
-----------------------------------------------------------------------
Summary of changes:
CHANGELOG | 122 ++++++++++++++++++++++++++++++
configure.ac | 2 +-
platform/linux-generic/odp_traffic_mngr.c | 3 +
3 files changed, 126 insertions(+), 1 deletion(-)
hooks/post-receive
--