Add hash of bos using gem name 39/256639/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Thu, 8 Apr 2021 08:47:03 +0000 (17:47 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Thu, 8 Apr 2021 08:53:24 +0000 (17:53 +0900)
when one bo is may times imported by fd in process,
vigs_drm_prime_import_fd create vigs_drm_surface but
gem handle is always the same.
it causes a problem that gem handle is closed even if
another tbm_bo uses it.

Change-Id: I9663ff18422166dd3fefe37a0b35b44ebad83dbc

src/libhal-backend-tbm-vigs/tbm_backend_vigs.c
src/libtbm-vigs/tbm_bufmgr_vigs.c

index 4a9aeb6..011a4fe 100644 (file)
@@ -79,6 +79,8 @@ struct _tbm_vigs_bo {
 /* tbm bufmgr private for vigs */
 struct _tbm_vigs_bufmgr {
        int fd;
+       void *hash_bos;
+
        struct vigs_drm_device *drm_dev;
 };
 
@@ -96,6 +98,20 @@ _tbm_vigs_open_drm(void)
        return fd;
 }
 
+static unsigned int
+_get_name(int fd, unsigned int gem)
+{
+       struct drm_gem_flink arg = {0,};
+
+       arg.handle = gem;
+       if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
+               TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_FLINK gem:%d", gem);
+               return 0;
+       }
+
+       return (unsigned int)arg.name;
+}
+
 static hal_tbm_bo_handle
 get_tbm_bo_handle(struct vigs_drm_surface *sfc, int device)
 {
@@ -297,6 +313,19 @@ tbm_vigs_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size,
        bo_data->bufmgr_data = bufmgr_data;
        bo_data->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_BACKEND_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_data);
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_data->hash_bos, bo_data->sfc->gem.name, (void *)bo_data) < 0)
+               TBM_BACKEND_ERR("Cannot insert bo_data to Hash(%d)\n", bo_data->sfc->gem.name);
+
        TBM_BACKEND_DBG("size = %d, flags = 0x%X", size, flags);
 
        if (error)
@@ -378,6 +407,19 @@ tbm_vigs_bufmgr_alloc_bo_with_format(hal_tbm_bufmgr *bufmgr, int format,  int bo
        bo_data->bufmgr_data = bufmgr_data;
        bo_data->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_BACKEND_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_data);
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_data->hash_bos, bo_data->sfc->gem.name, (void *)bo_data) < 0)
+               TBM_BACKEND_ERR("Cannot insert bo_data to Hash(%d)\n", bo_data->sfc->gem.name);
+
        TBM_BACKEND_DBG("width = %d, height = %d, format = %x, flags = 0x%X bo_idx = %d",
                        width, height, format, flags, bo_idx);
 
@@ -396,6 +438,9 @@ tbm_vigs_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error
        struct vigs_drm_surface *sfc;
        int ret;
        char buf[STRERR_BUFSIZE];
+       struct drm_prime_handle arg = {0, };
+       unsigned int gem;
+       unsigned int name;
 
        if (bufmgr_data == NULL || bufmgr_data->drm_dev ==  NULL) {
                TBM_BACKEND_ERR("bufmgr_data is null\n");
@@ -406,6 +451,34 @@ tbm_vigs_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error
 
        drm_dev = bufmgr_data->drm_dev;
 
+       arg.fd = key;
+       if (drmIoctl(bufmgr_data->drm_dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
+               TBM_BACKEND_ERR("Cannot get gem handle from fd:%d (%s)\n",
+                              arg.fd, strerror_r(errno, buf, STRERR_BUFSIZE));
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return NULL;
+       }
+       gem = arg.handle;
+
+       name = _get_name(bufmgr_data->drm_dev->fd, gem);
+       if (!name) {
+               TBM_BACKEND_ERR("Cannot get name from gem:%d, fd:%d (%s)\n",
+                              gem, key, strerror_r(errno, buf, STRERR_BUFSIZE));
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return NULL;
+       }
+
+       ret = drmHashLookup(bufmgr_data->hash_bos, name, (void **)&bo_data);
+       if (ret == 0) {
+               if (gem == bo_data->sfc->gem.handle) {
+                       if (error)
+                               *error = HAL_TBM_ERROR_NONE;
+                       return (hal_tbm_bo *)bo_data;
+               }
+       }
+
        ret = vigs_drm_prime_import_fd(drm_dev, key, &sfc);
        if (ret != 0) {
                TBM_BACKEND_ERR("vigs_drm_prime_import_fd failed for key %d: %s",
@@ -426,6 +499,19 @@ tbm_vigs_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error
        bo_data->bufmgr_data = bufmgr_data;
        bo_data->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_BACKEND_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_data);
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_data->hash_bos, bo_data->sfc->gem.name, (void *)bo_data) < 0)
+               TBM_BACKEND_ERR("Cannot insert bo_data to Hash(%d)\n", bo_data->sfc->gem.name);
+
        TBM_BACKEND_DBG("bo_data = %p, key = %u handle = %u", bo_data, key, sfc->gem.handle);
 
        if (error)
@@ -453,6 +539,13 @@ tbm_vigs_bufmgr_import_key(hal_tbm_bufmgr *bufmgr, hal_tbm_key key, hal_tbm_erro
 
        drm_dev = bufmgr_data->drm_dev;
 
+       ret = drmHashLookup(bufmgr_data->hash_bos, key, (void **)&bo_data);
+       if (ret == 0) {
+               if (error)
+                       *error = HAL_TBM_ERROR_NONE;
+               return (hal_tbm_bo *)bo_data;
+       }
+
        ret = vigs_drm_surface_open(drm_dev, key, &sfc);
        if (ret != 0) {
                TBM_BACKEND_ERR("vigs_drm_surface_open failed for key %u: %s",
@@ -473,6 +566,19 @@ tbm_vigs_bufmgr_import_key(hal_tbm_bufmgr *bufmgr, hal_tbm_key key, hal_tbm_erro
        bo_data->bufmgr_data = bufmgr_data;
        bo_data->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_BACKEND_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_data);
+               if (error)
+                       *error = HAL_TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_data->hash_bos, bo_data->sfc->gem.name, (void *)bo_data) < 0)
+               TBM_BACKEND_ERR("Cannot insert bo_data to Hash(%d)\n", bo_data->sfc->gem.name);
+
        TBM_BACKEND_DBG("bo_data = %p, key = %u handle = %u", bo_data, key, sfc->gem.handle);
 
        if (error)
@@ -485,15 +591,30 @@ static void
 tbm_vigs_bo_free(hal_tbm_bo *bo)
 {
        tbm_vigs_bo *bo_data = (tbm_vigs_bo *)bo;
+       tbm_vigs_bo *temp;
        struct vigs_drm_surface *sfc;
+       tbm_vigs_bufmgr *bufmgr_data;
+       int ret;
 
        if (!bo_data)
                return;
 
+       bufmgr_data = bo_data->bufmgr_data;
+       if (!bufmgr_data)
+               return;
+
        TBM_BACKEND_DBG("bo_data = %p", bo_data);
 
        sfc = bo_data->sfc;
 
+       /* delete bo from hash */
+       ret = drmHashLookup(bufmgr_data->hash_bos, bo_data->sfc->gem.name,
+                            (void **)&temp);
+       if (ret == 0)
+               drmHashDelete(bufmgr_data->hash_bos, bo_data->sfc->gem.name);
+       else
+               TBM_BACKEND_ERR("Cannot find bo_data to Hash(%d), ret=%d\n", bo_data->sfc->gem.name, ret);
+
        vigs_drm_gem_unref(&sfc->gem);
 }
 
@@ -779,6 +900,8 @@ hal_backend_tbm_vigs_exit(void *data)
 {
        hal_tbm_backend_data *backend_data = (hal_tbm_backend_data *)data;
        tbm_vigs_bufmgr *bufmgr_data;
+       unsigned long key;
+       void *value;
 
        TBM_BACKEND_DBG("enter");
 
@@ -787,6 +910,16 @@ hal_backend_tbm_vigs_exit(void *data)
        bufmgr_data = (tbm_vigs_bufmgr *)backend_data->bufmgr;
        TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, -1);
 
+       if (bufmgr_data->hash_bos) {
+               while (drmHashFirst(bufmgr_data->hash_bos, &key, &value) > 0) {
+                       free(value);
+                       drmHashDelete(bufmgr_data->hash_bos, key);
+               }
+
+               drmHashDestroy(bufmgr_data->hash_bos);
+               bufmgr_data->hash_bos = NULL;
+       }
+
        if (backend_data->bufmgr_funcs)
                free(backend_data->bufmgr_funcs);
        if (backend_data->bo_funcs)
@@ -870,6 +1003,8 @@ hal_backend_tbm_vigs_init(void **data)
                TBM_BACKEND_INFO("A backend requests an authenticated drm_fd.\n");
        }
 
+       bufmgr_data->hash_bos = drmHashCreate();
+
        /* alloc and register bufmgr_funcs */
        bufmgr_funcs = calloc(1, sizeof(struct _hal_tbm_bufmgr_funcs));
        if (!bufmgr_funcs) {
index d2b6d0b..bceb59b 100755 (executable)
@@ -78,6 +78,7 @@ struct _tbm_bo_vigs {
 /* tbm bufmgr private for vigs */
 struct _tbm_bufmgr_vigs {
        struct vigs_drm_device *drm_dev;
+       void *hash_bos;
 
        tbm_backend_bufmgr_func *bufmgr_func;
        tbm_backend_bo_func *bo_func;
@@ -98,6 +99,20 @@ static int _tbm_vigs_open_drm(void)
        return fd;
 }
 
+static unsigned int
+_get_name(int fd, unsigned int gem)
+{
+       struct drm_gem_flink arg = {0,};
+
+       arg.handle = gem;
+       if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
+               TBM_ERR("fail to DRM_IOCTL_GEM_FLINK gem:%d", gem);
+               return 0;
+       }
+
+       return (unsigned int)arg.name;
+}
+
 static tbm_bo_handle get_tbm_bo_handle(struct vigs_drm_surface *sfc, int device)
 {
        tbm_bo_handle bo_handle;
@@ -332,6 +347,19 @@ tbm_vigs_bufmgr_alloc_bo(tbm_backend_bufmgr_data *bufmgr_data, unsigned int size
        bo_vigs->bufmgr_vigs = bufmgr_vigs;
        bo_vigs->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_vigs);
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
+               TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
+
        TBM_DBG("size = %d, flags = 0x%X", size, flags);
 
        if (error)
@@ -413,6 +441,19 @@ tbm_bufmgr_vigs_alloc_bo_with_format(tbm_backend_bufmgr_data *bufmgr_data, int f
        bo_vigs->bufmgr_vigs = bufmgr_vigs;
        bo_vigs->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_vigs);
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
+               TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
+
        TBM_DBG("width = %d, height = %d, format = %x, flags = 0x%X bo_idx = %d",
                        width, height, format, flags, bo_idx);
 
@@ -431,6 +472,9 @@ tbm_vigs_bufmgr_import_fd(tbm_backend_bufmgr_data *bufmgr_data, tbm_fd key, tbm_
        struct vigs_drm_surface *sfc;
        int ret;
        char buf[STRERR_BUFSIZE];
+       struct drm_prime_handle arg = {0, };
+       unsigned int gem;
+       unsigned int name;
 
        if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
                TBM_ERR("bufmgr_data is null\n");
@@ -441,6 +485,34 @@ tbm_vigs_bufmgr_import_fd(tbm_backend_bufmgr_data *bufmgr_data, tbm_fd key, tbm_
 
        drm_dev = bufmgr_vigs->drm_dev;
 
+       arg.fd = key;
+       if (drmIoctl(bufmgr_vigs->drm_dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
+               TBM_ERR("Cannot get gem handle from fd:%d (%s)\n",
+                              arg.fd, strerror_r(errno, buf, STRERR_BUFSIZE));
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return NULL;
+       }
+       gem = arg.handle;
+
+       name = _get_name(bufmgr_vigs->drm_dev->fd, gem);
+       if (!name) {
+               TBM_ERR("Cannot get name from gem:%d, fd:%d (%s)\n",
+                              gem, key, strerror_r(errno, buf, STRERR_BUFSIZE));
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return NULL;
+       }
+
+       ret = drmHashLookup(bufmgr_vigs->hash_bos, name, (void **)&bo_vigs);
+       if (ret == 0) {
+               if (gem == bo_vigs->sfc->gem.handle) {
+                       if (error)
+                               *error = TBM_ERROR_NONE;
+                       return (tbm_backend_bo_data *)bo_vigs;
+               }
+       }
+
        ret = vigs_drm_prime_import_fd(drm_dev, key, &sfc);
        if (ret != 0) {
                TBM_ERR("vigs_drm_prime_import_fd failed for key %d: %s",
@@ -461,6 +533,19 @@ tbm_vigs_bufmgr_import_fd(tbm_backend_bufmgr_data *bufmgr_data, tbm_fd key, tbm_
        bo_vigs->bufmgr_vigs = bufmgr_vigs;
        bo_vigs->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_vigs);
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
+               TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
+
        TBM_DBG("bo_vigs = %p, key = %u handle = %u", bo_vigs, key, sfc->gem.handle);
 
        if (error)
@@ -488,6 +573,13 @@ tbm_vigs_bufmgr_import_key(tbm_backend_bufmgr_data *bufmgr_data, tbm_key key, tb
 
        drm_dev = bufmgr_vigs->drm_dev;
 
+       ret = drmHashLookup(bufmgr_vigs->hash_bos, key, (void **)&bo_vigs);
+       if (ret == 0) {
+               if (error)
+                       *error = TBM_ERROR_NONE;
+               return (tbm_backend_bo_data *)bo_vigs;
+       }
+
        ret = vigs_drm_surface_open(drm_dev, key, &sfc);
        if (ret != 0) {
                TBM_ERR("vigs_drm_surface_open failed for key %u: %s",
@@ -508,6 +600,19 @@ tbm_vigs_bufmgr_import_key(tbm_backend_bufmgr_data *bufmgr_data, tbm_key key, tb
        bo_vigs->bufmgr_vigs = bufmgr_vigs;
        bo_vigs->sfc = sfc;
 
+       ret = vigs_drm_gem_get_name(&sfc->gem);
+       if (ret != 0) {
+               TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
+               vigs_drm_gem_unref(&sfc->gem);
+               free(bo_vigs);
+               if (error)
+                       *error = TBM_ERROR_INVALID_OPERATION;
+               return 0;
+       }
+
+       if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
+               TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
+
        TBM_DBG("bo_vigs = %p, key = %u handle = %u", bo_vigs, key, sfc->gem.handle);
 
        if (error)
@@ -520,15 +625,30 @@ static void
 tbm_vigs_bo_free(tbm_backend_bo_data *bo_data)
 {
        tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
+       tbm_bo_vigs temp;
        struct vigs_drm_surface *sfc;
+       tbm_bufmgr_vigs bufmgr_vigs;
+       int ret;
 
        if (!bo_data)
                return;
 
+       bufmgr_vigs = bo_vigs->bufmgr_vigs;
+       if (!bufmgr_vigs)
+               return;
+
        TBM_DBG("bo_vigs = %p", bo_vigs);
 
        sfc = bo_vigs->sfc;
 
+       /* delete bo from hash */
+       ret = drmHashLookup(bufmgr_vigs->hash_bos, sfc->gem.name,
+                            (void **)&temp);
+       if (ret == 0)
+               drmHashDelete(bufmgr_vigs->hash_bos, sfc->gem.name);
+       else
+               TBM_ERR("Cannot find bo_vigs to Hash(%d), ret=%d\n", sfc->gem.name, ret);
+
        vigs_drm_gem_unref(&sfc->gem);
 }
 
@@ -767,6 +887,8 @@ tbm_vigs_deinit(tbm_backend_bufmgr_data *bufmgr_data)
        struct vigs_drm_device *drm_dev;
        tbm_error_e error;
        tbm_bufmgr bufmgr;
+       unsigned long key;
+       void *value;
 
        TBM_DBG("enter");
 
@@ -781,6 +903,16 @@ tbm_vigs_deinit(tbm_backend_bufmgr_data *bufmgr_data)
        if (!bufmgr)
                return;
 
+       if (bufmgr_vigs->hash_bos) {
+               while (drmHashFirst(bufmgr_vigs->hash_bos, &key, &value) > 0) {
+                       free(value);
+                       drmHashDelete(bufmgr_vigs->hash_bos, key);
+               }
+
+               drmHashDestroy(bufmgr_vigs->hash_bos);
+               bufmgr_vigs->hash_bos = NULL;
+       }
+
        if (tbm_backend_bufmgr_query_display_server(bufmgr, &error)) {
                tbm_drm_helper_wl_auth_server_deinit();
                tbm_drm_helper_unset_tbm_master_fd();
@@ -867,6 +999,8 @@ tbm_vigs_init(tbm_bufmgr bufmgr, tbm_error_e *error)
        bufmgr_vigs->drm_dev = drm_dev;
        g_drm_dev = drm_dev;
 
+       bufmgr_vigs->hash_bos = drmHashCreate();
+
        /* alloc and register bufmgr_funcs */
        bufmgr_func = tbm_backend_bufmgr_alloc_bufmgr_func(bufmgr, &err);
        if (!bufmgr_func) {