diff --git a/freedreno/freedreno_device.c b/freedreno/freedreno_device.c index 6486983d..23e086bb 100644 --- a/freedreno/freedreno_device.c +++ b/freedreno/freedreno_device.c @@ -135,6 +135,16 @@ struct fd_device * fd_device_new(int fd) return dev; } +/* like fd_device_new() but creates it's own private dup() of the fd + * which is close()d when the device is finalized. + */ +struct fd_device * fd_device_new_dup(int fd) +{ + struct fd_device *dev = fd_device_new(dup(fd)); + dev->closefd = 1; + return dev; +} + struct fd_device * fd_device_ref(struct fd_device *dev) { atomic_inc(&dev->refcnt); @@ -147,6 +157,8 @@ static void fd_device_del_impl(struct fd_device *dev) drmHashDestroy(dev->handle_table); drmHashDestroy(dev->name_table); drmHashDelete(dev_table, dev->fd); + if (dev->closefd) + close(dev->fd); dev->funcs->destroy(dev); } diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h index 6a40ab8f..f3a01aff 100644 --- a/freedreno/freedreno_drmif.h +++ b/freedreno/freedreno_drmif.h @@ -72,6 +72,7 @@ enum fd_param_id { */ struct fd_device * fd_device_new(int fd); +struct fd_device * fd_device_new_dup(int fd); struct fd_device * fd_device_ref(struct fd_device *dev); void fd_device_del(struct fd_device *dev); diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index 061d807e..d5cf9f97 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -84,6 +84,8 @@ struct fd_device { struct fd_bo_bucket cache_bucket[14 * 4]; int num_buckets; time_t time; + + int closefd; /* call close(fd) upon destruction */ }; void fd_cleanup_bo_cache(struct fd_device *dev, time_t time);