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. --- src/egl/drivers/dri2/platform_wayland.c | 116 +--------------------- 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 | 169 ++++++++++++++++++++++++++++++++ src/util/meson.build | 1 + 6 files changed, 178 insertions(+), 145 deletions(-) create mode 100644 src/util/anon_file.h
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index d221728ff2..2e47fe5b15 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, diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index fe14d6cfab..aa669359d7 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); + 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..d4dd11c506 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); 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 104ecae8ed..f30a063630 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..fa8642dc98 --- /dev/null +++ b/src/util/anon_file.h @@ -0,0 +1,169 @@ +/* + * 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 + +#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 + + +#ifndef __FreeBSD__ + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_LINUX_MEMFD_H + fd = syscall(SYS_memfd_create, tmpname, MFD_CLOEXEC); +#elif 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. + * + * 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) +{ + int fd, ret; +#ifdef __FreeBSD__ + fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); // shm_open is always CLOEXEC +#else + static const char templ[] = "/mesa-shared-XXXXXX"; + const char *path; + char *name; + + 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); +#endif + + if (fd < 0) + return -1; + +#if defined(HAVE_POSIX_FALLOCATE) && !defined(__FreeBSD__) + do { + ret = posix_fallocate(fd, 0, size); + } while (ret == EINTR); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + do { + ret = ftruncate(fd, size); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} diff --git a/src/util/meson.build b/src/util/meson.build index fa591c92e5..4e9ba14a2c 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