Move the Weston os_create_anonymous_file code from egl/wayland into util, add support for Linux memfd and FreeBSD SHM_ANON, use that code in anv instead of explicit memfd calls for portability. --- configure.ac | 2 +- meson.build | 4 +- src/egl/drivers/dri2/platform_wayland.c | 118 +------------------------ src/intel/vulkan/anv_allocator.c | 21 +---- src/intel/vulkan/anv_gem_stubs.c | 15 +--- src/util/Makefile.sources | 1 + src/util/anon_file.h | 150 ++++++++++++++++++++++++++++++++ src/util/meson.build | 1 + 8 files changed, 163 insertions(+), 149 deletions(-) create mode 100644 src/util/anon_file.h
diff --git a/configure.ac b/configure.ac index 7c1fbe0ed1..0801b10118 100644 --- a/configure.ac +++ b/configure.ac @@ -849,10 +849,10 @@ fi AC_HEADER_MAJOR AC_CHECK_HEADER([xlocale.h], [DEFINES="$DEFINES -DHAVE_XLOCALE_H"]) AC_CHECK_HEADER([sys/sysctl.h], [DEFINES="$DEFINES -DHAVE_SYS_SYSCTL_H"]) +AC_CHECK_HEADER([linux/memfd.h], [DEFINES="$DEFINES -DHAVE_LINUX_MEMFD_H"]) AC_CHECK_FUNC([strtof], [DEFINES="$DEFINES -DHAVE_STRTOF"]) AC_CHECK_FUNC([mkostemp], [DEFINES="$DEFINES -DHAVE_MKOSTEMP"]) AC_CHECK_FUNC([timespec_get], [DEFINES="$DEFINES -DHAVE_TIMESPEC_GET"]) -AC_CHECK_FUNC([memfd_create], [DEFINES="$DEFINES -DHAVE_MEMFD_CREATE"]) AC_MSG_CHECKING([whether strtod has locale support]) AC_LINK_IFELSE([AC_LANG_SOURCE([[ diff --git a/meson.build b/meson.build index a80137bcf9..9cf0d9c415 100644 --- a/meson.build +++ b/meson.build @@ -859,13 +859,13 @@ elif cc.has_header_symbol('sys/mkdev.h', 'major') pre_args += '-DMAJOR_IN_MKDEV' endif -foreach h : ['xlocale.h', 'sys/sysctl.h', 'linux/futex.h'] +foreach h : ['xlocale.h', 'sys/sysctl.h', 'linux/futex.h', 'linux/memfd.h'] if cc.has_header(h) pre_args += '-DHAVE_@0@'.format(h.to_upper().underscorify()) endif endforeach -foreach f : ['strtof', 'mkostemp', 'posix_memalign', 'timespec_get', 'memfd_create'] +foreach f : ['strtof', 'mkostemp', 'posix_memalign', 'timespec_get'] if cc.has_function(f) pre_args += '-DHAVE_@0@'.format(f.to_upper()) endif diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index d221728ff2..6e4710e3b6 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -43,6 +43,7 @@ #include "egl_dri2_fallbacks.h" #include "loader.h" #include "util/u_vector.h" +#include "util/anon_file.h" #include "eglglobals.h" #include <wayland-client.h> @@ -1477,121 +1478,6 @@ dri2_wl_swrast_get_stride_for_format(int format, int w) return 4 * w; } -/* - * Taken from weston shared/os-compatibility.c - */ - -#ifndef HAVE_MKOSTEMP - -static int -set_cloexec_or_close(int fd) -{ - long flags; - - if (fd == -1) - return -1; - - flags = fcntl(fd, F_GETFD); - if (flags == -1) - goto err; - - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; - - return fd; - -err: - close(fd); - return -1; -} - -#endif - -/* - * Taken from weston shared/os-compatibility.c - */ - -static int -create_tmpfile_cloexec(char *tmpname) -{ - int fd; - -#ifdef HAVE_MKOSTEMP - fd = mkostemp(tmpname, O_CLOEXEC); - if (fd >= 0) - unlink(tmpname); -#else - fd = mkstemp(tmpname); - if (fd >= 0) { - fd = set_cloexec_or_close(fd); - unlink(tmpname); - } -#endif - - return fd; -} - -/* - * Taken from weston shared/os-compatibility.c - * - * Create a new, unique, anonymous file of the given size, and - * return the file descriptor for it. The file descriptor is set - * CLOEXEC. The file is immediately suitable for mmap()'ing - * the given size at offset zero. - * - * The file should not have a permanent backing store like a disk, - * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. - * - * The file name is deleted from the file system. - * - * The file is suitable for buffer sharing between processes by - * transmitting the file descriptor over Unix sockets using the - * SCM_RIGHTS methods. - * - * If the C library implements posix_fallocate(), it is used to - * guarantee that disk space is available for the file at the - * given size. If disk space is insufficent, errno is set to ENOSPC. - * If posix_fallocate() is not supported, program may receive - * SIGBUS on accessing mmap()'ed file contents instead. - */ -static int -os_create_anonymous_file(off_t size) -{ - static const char templ[] = "/mesa-shared-XXXXXX"; - const char *path; - char *name; - int fd; - int ret; - - path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - errno = ENOENT; - return -1; - } - - name = malloc(strlen(path) + sizeof(templ)); - if (!name) - return -1; - - strcpy(name, path); - strcat(name, templ); - - fd = create_tmpfile_cloexec(name); - - free(name); - - if (fd < 0) - return -1; - - ret = ftruncate(fd, size); - if (ret < 0) { - close(fd); - return -1; - } - - return fd; -} - static EGLBoolean dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf, @@ -1609,7 +1495,7 @@ dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf, size_map = h * stride; /* Create a sharable buffer */ - fd = os_create_anonymous_file(size_map); + fd = os_create_anonymous_file(size_map, NULL); if (fd < 0) return EGL_FALSE; diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index fe14d6cfab..7e7e88ad77 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -25,13 +25,13 @@ #include <unistd.h> #include <limits.h> #include <assert.h> -#include <linux/memfd.h> #include <sys/mman.h> #include "anv_private.h" #include "util/hash_table.h" #include "util/simple_mtx.h" +#include "util/anon_file.h" #ifdef HAVE_VALGRIND #define VG_NOACCESS_READ(__ptr) ({ \ @@ -109,14 +109,6 @@ struct anv_mmap_cleanup { #define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0}) -#ifndef HAVE_MEMFD_CREATE -static inline int -memfd_create(const char *name, unsigned int flags) -{ - return syscall(SYS_memfd_create, name, flags); -} -#endif - static inline uint32_t ilog2_round_up(uint32_t value) { @@ -252,18 +244,13 @@ anv_block_pool_init(struct anv_block_pool *pool, pool->bo_flags = bo_flags; anv_bo_init(&pool->bo, 0, 0); - pool->fd = memfd_create("block pool", MFD_CLOEXEC); - if (pool->fd == -1) - return vk_error(VK_ERROR_INITIALIZATION_FAILED); - /* Just make it 2GB up-front. The Linux kernel won't actually back it * with pages until we either map and fault on one of them or we use * userptr and send a chunk of it off to the GPU. */ - if (ftruncate(pool->fd, BLOCK_POOL_MEMFD_SIZE) == -1) { - result = vk_error(VK_ERROR_INITIALIZATION_FAILED); - goto fail_fd; - } + pool->fd = os_create_anonymous_file(BLOCK_POOL_MEMFD_SIZE, "block pool"); + if (pool->fd == -1) + return vk_error(VK_ERROR_INITIALIZATION_FAILED); if (!u_vector_init(&pool->mmap_cleanups, round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), diff --git a/src/intel/vulkan/anv_gem_stubs.c b/src/intel/vulkan/anv_gem_stubs.c index 26eb5c8a61..56e2bad9bc 100644 --- a/src/intel/vulkan/anv_gem_stubs.c +++ b/src/intel/vulkan/anv_gem_stubs.c @@ -21,32 +21,21 @@ * IN THE SOFTWARE. */ -#include <linux/memfd.h> #include <sys/mman.h> #include <sys/syscall.h> +#include "util/anon_file.h" #include "anv_private.h" -#ifndef HAVE_MEMFD_CREATE -static inline int -memfd_create(const char *name, unsigned int flags) -{ - return syscall(SYS_memfd_create, name, flags); -} -#endif - uint32_t anv_gem_create(struct anv_device *device, uint64_t size) { - int fd = memfd_create("fake bo", MFD_CLOEXEC); + int fd = os_create_anonymous_file(size, "fake bo"); if (fd == -1) return 0; assert(fd != 0); - if (ftruncate(fd, size) == -1) - return 0; - return fd; } diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources index effc2c72cb..8ef7b7ab87 100644 --- a/src/util/Makefile.sources +++ b/src/util/Makefile.sources @@ -1,4 +1,5 @@ MESA_UTIL_FILES := \ + anon_file.h \ bitscan.c \ bitscan.h \ bitset.h \ diff --git a/src/util/anon_file.h b/src/util/anon_file.h new file mode 100644 index 0000000000..ef05c6311f --- /dev/null +++ b/src/util/anon_file.h @@ -0,0 +1,150 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * Copyright © 2018 Greg V + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Based on weston shared/os-compatibility.c + */ + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef __FreeBSD__ +#include <sys/mman.h> +#elif HAVE_LINUX_MEMFD_H +#define _GNU_SOURCE +#include <sys/syscall.h> +#include <linux/memfd.h> +#endif + + +#if !(defined(__FreeBSD__) || defined(HAVE_LINUX_MEMFD_H) || defined(HAVE_MKOSTEMP)) +static int +set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + +err: + close(fd); + return -1; +} +#endif + +#if !(defined(__FreeBSD__) || defined(HAVE_LINUX_MEMFD_H)) +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#if HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} +#endif + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * An optional name for debugging can be provided as the second argument. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * If memfd or SHM_ANON is supported, the filesystem is not touched at all. + * Otherwise, the file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + */ +static int +os_create_anonymous_file(off_t size, MAYBE_UNUSED char *debug_name) +{ + int fd, ret; +#ifdef __FreeBSD__ + fd = shm_open(SHM_ANON, O_CREAT | O_RDWR | O_CLOEXEC, 0600); +#elif HAVE_LINUX_MEMFD_H + if (!debug_name) + debug_name = "mesa-shared"; + fd = syscall(SYS_memfd_create, debug_name, MFD_CLOEXEC); +#else + const char *path; + char *name; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + if (debug_name) + asprintf(&name, "%s/mesa-shared-%s-XXXXXX", path, debug_name); + else + asprintf(&name, "%s/mesa-shared-XXXXXX", path); + if (!name) + return -1; + + fd = create_tmpfile_cloexec(name); + + free(name); +#endif + + if (fd < 0) + return -1; + + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } + + return fd; +} diff --git a/src/util/meson.build b/src/util/meson.build index a64e9a79ef..00d2018f2d 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -23,6 +23,7 @@ inc_util = include_directories('.') subdir('xmlpool') files_mesa_util = files( + 'anon_file.h', 'bitscan.c', 'bitscan.h', 'bitset.h', -- 2.15.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev