[Mesa-dev] [PATCH 1/2] RFC i965: Bypass a couple of libraries for syscall on x84_64
Chris Wilson
chris at chris-wilson.co.uk
Mon Jun 19 11:32:19 UTC 2017
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 <chris at chris-wilson.co.uk>
Cc: Kenneth Graunke <kenneth at whitecape.org>
Cc: Matt Turner <mattst88 at gmail.com>
Cc: Jason Ekstrand <jason.ekstrand at 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
More information about the mesa-dev
mailing list