On linux/x86_64, calling into the kernel is just a single instruction with the parameters passed via registers. We can therefre shortcircuit a couple of library indirections around ioctl() which as much as the switch into the kernel itself. Aside from the PLT indirection, libc's ioctl() has a slight impedance mismatch with the kernel interface in that it converts the -errno return into -1 + errno, which we immediately convert back into -errno for ourselves!
Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Kenneth Graunke <kenn...@whitecape.org> Cc: Matt Turner <matts...@gmail.com> Cc: Jason Ekstrand <jason.ekstr...@intel.com> --- src/intel/common/sys_ioctl.h | 37 +++++++++++++ src/mesa/drivers/dri/i965/brw_bufmgr.c | 99 ++++++++++++++-------------------- 2 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 src/intel/common/sys_ioctl.h diff --git a/src/intel/common/sys_ioctl.h b/src/intel/common/sys_ioctl.h new file mode 100644 index 0000000000..69880650e3 --- /dev/null +++ b/src/intel/common/sys_ioctl.h @@ -0,0 +1,37 @@ +#ifndef SYS_IOCTL_H +#define SYS_IOCTL_H + +#include <sys/syscall.h> +#include <sys/ioctl.h> +#include <errno.h> + +static inline long __sys_ioctl(int fd, unsigned long cmd, void *arg) +{ + long result; + +#if defined(__linux__) && defined(__GNUC__) && defined (__x86_64__) + __asm__("syscall" + : "=a" (result) + : "0" (__NR_ioctl), "D" (fd), "S" (cmd), "d" (arg) + : "cc", "rcx", "r11", "memory"); +#else + result = ioctl(fd, cmd, arg); + if (result == -1) + result = -errno; +#endif + + return result; +} + +static inline long sys_ioctl(int fd, unsigned long cmd, void *arg) +{ + long result; + + do { + result = __sys_ioctl(fd, cmd, arg); + } while (result == -EINTR || result == -EAGAIN); + + return result; +} + +#endif diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c index 98634cc4b6..b1b55d79f0 100644 --- a/src/mesa/drivers/dri/i965/brw_bufmgr.c +++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c @@ -58,6 +58,7 @@ #endif #include "common/gen_debug.h" #include "common/gen_device_info.h" +#include "common/sys_ioctl.h" #include "libdrm_macros.h" #include "main/macros.h" #include "util/macros.h" @@ -204,7 +205,7 @@ __brw_bo_busy(struct brw_bo *bo) /* If we hit an error here, it means that bo->gem_handle is invalid. * Treat it as being idle (busy.busy is left as 0) and move along. */ - drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); + __sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); bo->idle = !busy.busy; return busy.busy; @@ -238,7 +239,7 @@ brw_bo_madvise(struct brw_bo *bo, int state) madv.handle = bo->gem_handle; madv.madv = state; madv.retained = 1; - drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); + sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); return madv.retained; } @@ -267,7 +268,6 @@ bo_alloc_internal(struct brw_bufmgr *bufmgr, { struct brw_bo *bo; unsigned int page_size = getpagesize(); - int ret; struct bo_cache_bucket *bucket; bool alloc_from_cache; uint64_t bo_size; @@ -348,8 +348,7 @@ retry: memclear(create); create.size = bo_size; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CREATE, &create); - if (ret != 0) { + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) { free(bo); goto err; } @@ -453,7 +452,6 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr, const char *name, unsigned int handle) { struct brw_bo *bo; - int ret; struct drm_gem_open open_arg; struct drm_i915_gem_get_tiling get_tiling; @@ -472,10 +470,8 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr, memclear(open_arg); open_arg.name = handle; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_OPEN, &open_arg); - if (ret != 0) { - DBG("Couldn't reference %s handle 0x%08x: %s\n", - name, handle, strerror(errno)); + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + DBG("Couldn't reference %s handle 0x%08x\n", name, handle); bo = NULL; goto out; } @@ -509,8 +505,7 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr, memclear(get_tiling); get_tiling.handle = bo->gem_handle; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); - if (ret != 0) + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) goto err_unref; bo->tiling_mode = get_tiling.tiling_mode; @@ -534,7 +529,6 @@ bo_free(struct brw_bo *bo) struct brw_bufmgr *bufmgr = bo->bufmgr; struct drm_gem_close close; struct hash_entry *entry; - int ret; if (bo->map_cpu) { VG(VALGRIND_FREELIKE_BLOCK(bo->map_cpu, 0)); @@ -558,10 +552,9 @@ bo_free(struct brw_bo *bo) /* Close this object */ memclear(close); close.handle = bo->gem_handle; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_CLOSE, &close); - if (ret != 0) { - DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n", - bo->gem_handle, bo->name, strerror(errno)); + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_CLOSE, &close)) { + DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s)\n", + bo->gem_handle, bo->name); } free(bo); } @@ -668,7 +661,7 @@ __brw_bo_set_caching(struct brw_bo *bo, int caching) .handle = bo->gem_handle, .caching = caching }; - return drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg) == 0; + return sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg) == 0; } void @@ -696,10 +689,9 @@ set_domain(struct brw_context *brw, const char *action, double elapsed = unlikely(brw && brw->perf_debug) ? -get_time() : 0.0; - if (drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &sd) != 0) { - DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s.\n", - __FILE__, __LINE__, bo->gem_handle, read_domains, write_domain, - strerror(errno)); + if (sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &sd)) { + DBG("%s:%d: Error setting memory domains %d (%08x %08x)\n", + __FILE__, __LINE__, bo->gem_handle, read_domains, write_domain); } if (unlikely(brw && brw->perf_debug)) { @@ -726,11 +718,9 @@ brw_bo_map_cpu(struct brw_context *brw, struct brw_bo *bo, unsigned flags) memclear(mmap_arg); mmap_arg.handle = bo->gem_handle; mmap_arg.size = bo->size; - int ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg); - if (ret != 0) { - ret = -errno; - DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", - __FILE__, __LINE__, bo->gem_handle, bo->name, strerror(errno)); + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) { + DBG("%s:%d: Error mapping buffer %d (%s)\n", + __FILE__, __LINE__, bo->gem_handle, bo->name); pthread_mutex_unlock(&bufmgr->lock); return NULL; } @@ -772,10 +762,9 @@ brw_bo_map_gtt(struct brw_context *brw, struct brw_bo *bo, unsigned flags) mmap_arg.handle = bo->gem_handle; /* Get the fake offset back... */ - int ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg); - if (ret != 0) { - DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n", - __FILE__, __LINE__, bo->gem_handle, bo->name, strerror(errno)); + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg)) { + DBG("%s:%d: Error preparing buffer map %d (%s)\n", + __FILE__, __LINE__, bo->gem_handle, bo->name); pthread_mutex_unlock(&bufmgr->lock); return NULL; } @@ -891,12 +880,11 @@ brw_bo_subdata(struct brw_bo *bo, uint64_t offset, pwrite.offset = offset; pwrite.size = size; pwrite.data_ptr = (uint64_t) (uintptr_t) data; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); + ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); if (ret != 0) { - ret = -errno; DBG("%s:%d: Error writing data to buffer %d: " "(%"PRIu64" %"PRIu64") %s .\n", - __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(errno)); + __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(-ret)); } return ret; @@ -915,12 +903,11 @@ brw_bo_get_subdata(struct brw_bo *bo, uint64_t offset, pread.offset = offset; pread.size = size; pread.data_ptr = (uint64_t) (uintptr_t) data; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PREAD, &pread); + ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PREAD, &pread); if (ret != 0) { - ret = -errno; DBG("%s:%d: Error reading data from buffer %d: " "(%"PRIu64" %"PRIu64") %s .\n", - __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(errno)); + __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(-ret)); } return ret; @@ -966,16 +953,11 @@ brw_bo_wait(struct brw_bo *bo, int64_t timeout_ns) { struct brw_bufmgr *bufmgr = bo->bufmgr; struct drm_i915_gem_wait wait; - int ret; memclear(wait); wait.bo_handle = bo->gem_handle; wait.timeout_ns = timeout_ns; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); - if (ret == -1) - return -errno; - - return ret; + return sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); } void @@ -1022,10 +1004,10 @@ bo_set_tiling_internal(struct brw_bo *bo, uint32_t tiling_mode, set_tiling.tiling_mode = tiling_mode; set_tiling.stride = stride; - ret = ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - if (ret == -1) - return -errno; + ret = __sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); + } while (ret == -EINTR || ret == -EAGAIN); + if (ret) + return ret; bo->tiling_mode = set_tiling.tiling_mode; bo->swizzle_mode = set_tiling.swizzle_mode; @@ -1096,7 +1078,7 @@ brw_bo_gem_create_from_prime(struct brw_bufmgr *bufmgr, int prime_fd) memclear(get_tiling); get_tiling.handle = bo->gem_handle; - if (drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) goto err; bo->tiling_mode = get_tiling.tiling_mode; @@ -1135,11 +1117,13 @@ brw_bo_flink(struct brw_bo *bo, uint32_t *name) if (!bo->global_name) { struct drm_gem_flink flink; + int ret; memclear(flink); flink.handle = bo->gem_handle; - if (drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_FLINK, &flink)) - return -errno; + ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_FLINK, &flink); + if (ret) + return ret; pthread_mutex_lock(&bufmgr->lock); if (!bo->global_name) { @@ -1212,14 +1196,10 @@ uint32_t brw_create_hw_context(struct brw_bufmgr *bufmgr) { struct drm_i915_gem_context_create create; - int ret; memclear(create); - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); - if (ret != 0) { - DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", strerror(errno)); - return 0; - } + if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create)) + DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed\n"); return create.ctx_id; } @@ -1230,9 +1210,8 @@ brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id) struct drm_i915_gem_context_destroy d = {.ctx_id = ctx_id }; if (ctx_id != 0 && - drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &d) != 0) { - fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n", - strerror(errno)); + sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &d)) { + DBG("DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed\n"); } } @@ -1245,7 +1224,7 @@ brw_reg_read(struct brw_bufmgr *bufmgr, uint32_t offset, uint64_t *result) memclear(reg_read); reg_read.offset = offset; - ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_REG_READ, ®_read); + ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_REG_READ, ®_read); *result = reg_read.val; return ret; -- 2.11.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev