#include <sys/types.h>
#include <stdbool.h>
#include <time.h>
+#include <unistd.h>
#include "errno.h"
#include "common/gen_aux_map.h"
#include "common/gen_gem.h"
#include "dev/gen_device_info.h"
#include "main/macros.h"
+#include "os/os_mman.h"
#include "util/debug.h"
#include "util/macros.h"
#include "util/hash_table.h"
};
struct iris_bufmgr {
+ /**
+ * List into the list of bufmgr.
+ */
+ struct list_head link;
+
+ uint32_t refcount;
+
int fd;
mtx_t lock;
struct gen_aux_map_context *aux_map_ctx;
};
+static mtx_t global_bufmgr_list_mutex = _MTX_INITIALIZER_NP;
+static struct list_head global_bufmgr_list = {
+ .next = &global_bufmgr_list,
+ .prev = &global_bufmgr_list,
+};
+
static int bo_set_tiling_internal(struct iris_bo *bo, uint32_t tiling_mode,
uint32_t stride);
enum iris_memory_zone memzone,
uint64_t size, uint64_t alignment);
-static uint32_t
-key_hash_uint(const void *key)
-{
- return _mesa_hash_data(key, 4);
-}
-
-static bool
-key_uint_equal(const void *a, const void *b)
-{
- return *((unsigned *) a) == *((unsigned *) b);
-}
-
static struct iris_bo *
find_and_ref_external_bo(struct hash_table *ht, unsigned int key)
{
if (bo->map_cpu && !bo->userptr) {
VG_NOACCESS(bo->map_cpu, bo->size);
- munmap(bo->map_cpu, bo->size);
+ os_munmap(bo->map_cpu, bo->size);
}
if (bo->map_wc) {
VG_NOACCESS(bo->map_wc, bo->size);
- munmap(bo->map_wc, bo->size);
+ os_munmap(bo->map_wc, bo->size);
}
if (bo->map_gtt) {
VG_NOACCESS(bo->map_gtt, bo->size);
- munmap(bo->map_gtt, bo->size);
+ os_munmap(bo->map_gtt, bo->size);
}
if (bo->idle) {
if (p_atomic_cmpxchg(&bo->map_cpu, NULL, map)) {
VG_NOACCESS(map, bo->size);
- munmap(map, bo->size);
+ os_munmap(map, bo->size);
}
}
assert(bo->map_cpu);
if (p_atomic_cmpxchg(&bo->map_wc, NULL, map)) {
VG_NOACCESS(map, bo->size);
- munmap(map, bo->size);
+ os_munmap(map, bo->size);
}
}
assert(bo->map_wc);
}
/* and mmap it. */
- void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
- MAP_SHARED, bufmgr->fd, mmap_arg.offset);
+ void *map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, bufmgr->fd, mmap_arg.offset);
if (map == MAP_FAILED) {
DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
__FILE__, __LINE__, bo->gem_handle, bo->name, strerror(errno));
if (p_atomic_cmpxchg(&bo->map_gtt, NULL, map)) {
VG_NOACCESS(map, bo->size);
- munmap(map, bo->size);
+ os_munmap(map, bo->size);
}
}
assert(bo->map_gtt);
return ret;
}
-void
+static void
iris_bufmgr_destroy(struct iris_bufmgr *bufmgr)
{
/* Free aux-map buffers */
util_vma_heap_finish(&bufmgr->vma_allocator[z]);
}
+ close(bufmgr->fd);
+
free(bufmgr);
}
*
* \param fd File descriptor of the opened DRM device.
*/
-struct iris_bufmgr *
-iris_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+static struct iris_bufmgr *
+iris_bufmgr_create(struct gen_device_info *devinfo, int fd, bool bo_reuse)
{
uint64_t gtt_size = iris_gtt_size(fd);
if (gtt_size <= IRIS_MEMZONE_OTHER_START)
* Don't do this! Ensure that each library/bufmgr has its own device
* fd so that its namespace does not clash with another.
*/
- bufmgr->fd = fd;
+ bufmgr->fd = dup(fd);
+
+ p_atomic_set(&bufmgr->refcount, 1);
if (mtx_init(&bufmgr->lock, mtx_plain) != 0) {
+ close(bufmgr->fd);
free(bufmgr);
return NULL;
}
init_cache_buckets(bufmgr);
bufmgr->name_table =
- _mesa_hash_table_create(NULL, key_hash_uint, key_uint_equal);
+ _mesa_hash_table_create(NULL, _mesa_hash_uint, _mesa_key_uint_equal);
bufmgr->handle_table =
- _mesa_hash_table_create(NULL, key_hash_uint, key_uint_equal);
+ _mesa_hash_table_create(NULL, _mesa_hash_uint, _mesa_key_uint_equal);
if (devinfo->gen >= 12) {
bufmgr->aux_map_ctx = gen_aux_map_init(bufmgr, &aux_map_allocator,
return bufmgr;
}
+static struct iris_bufmgr *
+iris_bufmgr_ref(struct iris_bufmgr *bufmgr)
+{
+ p_atomic_inc(&bufmgr->refcount);
+ return bufmgr;
+}
+
+void
+iris_bufmgr_unref(struct iris_bufmgr *bufmgr)
+{
+ mtx_lock(&global_bufmgr_list_mutex);
+ if (p_atomic_dec_zero(&bufmgr->refcount)) {
+ list_del(&bufmgr->link);
+ iris_bufmgr_destroy(bufmgr);
+ }
+ mtx_unlock(&global_bufmgr_list_mutex);
+}
+
+/**
+ * Gets an already existing GEM buffer manager or create a new one.
+ *
+ * \param fd File descriptor of the opened DRM device.
+ */
+struct iris_bufmgr *
+iris_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+{
+ struct stat st;
+
+ if (fstat(fd, &st))
+ return NULL;
+
+ struct iris_bufmgr *bufmgr = NULL;
+
+ mtx_lock(&global_bufmgr_list_mutex);
+ list_for_each_entry(struct iris_bufmgr, iter_bufmgr, &global_bufmgr_list, link) {
+ struct stat iter_st;
+ if (fstat(iter_bufmgr->fd, &iter_st))
+ continue;
+
+ if (st.st_rdev == iter_st.st_rdev) {
+ assert(iter_bufmgr->bo_reuse == bo_reuse);
+ bufmgr = iris_bufmgr_ref(iter_bufmgr);
+ goto unlock;
+ }
+ }
+
+ bufmgr = iris_bufmgr_create(devinfo, fd, bo_reuse);
+ list_addtail(&bufmgr->link, &global_bufmgr_list);
+
+ unlock:
+ mtx_unlock(&global_bufmgr_list_mutex);
+
+ return bufmgr;
+}
+
+int
+iris_bufmgr_get_fd(struct iris_bufmgr *bufmgr)
+{
+ return bufmgr->fd;
+}
+
void*
iris_bufmgr_get_aux_map_context(struct iris_bufmgr *bufmgr)
{