If we create a shared memory like below:
addr_orig = mmap (NULL, bytes, PROT_NONE,
MAP_ANONYMOUS| MAP_PRIVATE, -1, 0);
addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
If the first mmap() upper is not shared then the first mmap() will
succeed
because these restrictions do not apply to private mappings. The second
mmap() wants a shared memory mapping but the address returned by the
first
one is only page-aligned and not aligned to 16k, or violate cache
aliasing
constraints on MIPS cpu, will lead to second mmap failure.
Signed-off-by: Roy.Li <rongqing.li@xxxxxxxxxxxxx>
---
configure.ac | 25 +++++++++++++++++++++++++
exec/cpg.c | 13 +++++++++----
lib/cpg.c | 10 ++++++++--
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index 523d2cf..d3a9c25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -647,6 +647,31 @@ else
AC_SUBST(VERSCRIPT_LDFLAGS, [""])
fi
+arch_force_shmlba=no
+AC_MSG_CHECKING([for architecture in ${host_cpu}])
+case $host_cpu in
+ sparc*)
+ AC_MSG_RESULT([${host_cpu}])
+ arch_force_shmlba=yes
+ ;;
+ arm*)
+ AC_MSG_RESULT([${host_cpu}])
+ arch_force_shmlba=yes
+ ;;
+ mips*)
+ AC_MSG_RESULT([${host_cpu}])
+ arch_force_shmlba=yes
+ ;;
+ *)
+ AC_MSG_RESULT([${host_cpu}])
+ ;;
+esac
+
+if test $arch_force_shmlba = yes; then
+ AC_DEFINE_UNQUOTED([FORCE_SHM_ALIGN], [1],
+ [shared and fixed mmap must align on cache alias or 16k])
+fi
+
# define global include dirs
INCLUDE_DIRS="$INCLUDE_DIRS -I\$(top_builddir)/include
-I\$(top_srcdir)/include"
INCLUDE_DIRS="$INCLUDE_DIRS -I\$(top_builddir)/include/corosync
-I\$(top_srcdir)/include/corosync"
diff --git a/exec/cpg.c b/exec/cpg.c
index 695f311..04260e0 100644
--- a/exec/cpg.c
+++ b/exec/cpg.c
@@ -1606,6 +1606,7 @@ memory_map (
void *addr_orig;
void *addr;
int32_t res;
+ int flags = MAP_ANONYMOUS;
fd = open (path, O_RDWR, 0600);
@@ -1620,15 +1621,19 @@ memory_map (
goto error_close_unlink;
}
- addr_orig = mmap (NULL, bytes, PROT_NONE,
- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+#ifdef FORCE_SHM_ALIGN
+ flags |= MAP_SHARED;
+#else
+ flags |= MAP_PRIVATE;
+#endif /* FORCE_SHM_ALIGN */
+
+ addr_orig = mmap (NULL, bytes, PROT_NONE, flags, -1, 0);
if (addr_orig == MAP_FAILED) {
goto error_close_unlink;
}
- addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_SHARED, fd, 0);
+ addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE, flags, fd,
0);
if (addr != addr_orig) {
munmap(addr_orig, bytes);
diff --git a/lib/cpg.c b/lib/cpg.c
index b96df4e..7cc3ce9 100644
--- a/lib/cpg.c
+++ b/lib/cpg.c
@@ -737,6 +737,7 @@ memory_map (char *path, const char *file, void
**buf, size_t bytes)
int32_t i;
size_t written;
size_t page_size;
+ int flags = MAP_ANONYMOUS;
snprintf (path, PATH_MAX, "/dev/shm/%s", file);
@@ -772,8 +773,13 @@ retry_write:
}
free (buffer);
- addr_orig = mmap (NULL, bytes, PROT_NONE,
- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+#ifdef FORCE_SHM_ALIGN
+ flags |= MAP_SHARED;
+#else
+ flags |= MAP_PRIVATE;
+#endif /* FORCE_SHM_ALIGN */
+
+ addr_orig = mmap (NULL, bytes, PROT_NONE, flags, -1, 0);
if (addr_orig == MAP_FAILED) {
goto error_close_unlink;