[v6,3/6] shm: use workaround if mremap is not available

Submitted by Leonid Bobrov on Feb. 25, 2019, 6:08 p.m.

Details

Message ID 20190225180825.61830-3-mazocomp@disroot.org
State Superseded
Headers show
Series "Series without cover letter" ( rev: 1 ) in Wayland

Not browsing as part of any series.

Commit Message

Leonid Bobrov Feb. 25, 2019, 6:08 p.m.
From: Imre Vadász <ivadasz@dragonflybsd.org>

Signed-off-by: Leonid Bobrov <mazocomp@disroot.org>
---
 configure.ac      |  4 ++++
 src/wayland-shm.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

Patch hide | download patch | download mbox

diff --git a/configure.ac b/configure.ac
index c0f1c37..dcefc78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,10 @@  AC_SUBST(GCC_CFLAGS)
 AC_CHECK_HEADERS([sys/prctl.h])
 AC_CHECK_FUNCS([accept4 mkostemp posix_fallocate prctl])
 
+# mremap() and sys/mman.h are needed for the shm
+AC_CHECK_FUNCS([mremap])
+AC_CHECK_HEADERS([sys/mman.h])
+
 # waitid() and signal.h are needed for the test suite.
 AC_CHECK_FUNCS([waitid])
 AC_CHECK_HEADERS([signal.h])
diff --git a/src/wayland-shm.c b/src/wayland-shm.c
index 4191231..5bfdece 100644
--- a/src/wayland-shm.c
+++ b/src/wayland-shm.c
@@ -40,6 +40,9 @@ 
 #include <assert.h>
 #include <signal.h>
 #include <pthread.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
 
 #include "wayland-util.h"
 #include "wayland-private.h"
@@ -84,7 +87,24 @@  shm_pool_finish_resize(struct wl_shm_pool *pool)
 	if (pool->size == pool->new_size)
 		return;
 
+#ifdef HAVE_MREMAP
 	data = mremap(pool->data, pool->size, pool->new_size, MREMAP_MAYMOVE);
+#else
+	int32_t osize = (pool->size + PAGE_SIZE - 1) & ~PAGE_MASK;
+	if (pool->new_size <= osize) {
+		pool->size = pool->new_size;
+		return;
+	}
+	data = mmap(pool->data + osize, pool->new_size - osize, PROT_READ,
+		    MAP_SHARED | MAP_TRYFIXED, pool->fd, osize);
+	if (data == MAP_FAILED) {
+		munmap(pool->data, pool->size);
+		data = mmap(NULL, pool->new_size, PROT_READ, MAP_SHARED, pool->fd, 0);
+	} else {
+		pool->size = pool->new_size;
+		return;
+	}
+#endif
 	if (data == MAP_FAILED) {
 		wl_resource_post_error(pool->resource,
 				       WL_SHM_ERROR_INVALID_FD,
@@ -495,6 +515,7 @@  sigbus_handler(int signum, siginfo_t *info, void *context)
 	sigbus_data->fallback_mapping_used = 1;
 
 	/* This should replace the previous mapping */
+#ifdef HAVE_MREMAP
 	if (mmap(pool->data, pool->size,
 		 PROT_READ | PROT_WRITE,
 		 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
@@ -502,6 +523,15 @@  sigbus_handler(int signum, siginfo_t *info, void *context)
 		reraise_sigbus();
 		return;
 	}
+#else
+	if (mmap(pool->data, pool->size,
+		 PROT_READ,
+		 MAP_PRIVATE | MAP_FIXED | MAP_ANON,
+		 0, 0) == MAP_FAILED) {
+		reraise_sigbus();
+		return;
+	}
+#endif
 }
 
 static void