+
+ pthread_mutex_lock(&nvdev->lock);
+ if (nvbo->name) {
+ if (atomic_read(&nvbo->refcnt)) {
+ /*
+ * bo has been revived by a race with
+ * nouveau_bo_prime_handle_ref, or nouveau_bo_name_ref.
+ *
+ * In theory there's still a race possible with
+ * nouveau_bo_wrap, but when using this function
+ * the lifetime of the handle is probably already
+ * handled in another way. If there are races
+ * you're probably using nouveau_bo_wrap wrong.
+ */
+ pthread_mutex_unlock(&nvdev->lock);
+ return;
+ }
+ DRMLISTDEL(&nvbo->head);
+ /*
+ * This bo has to be closed with the lock held because gem
+ * handles are not refcounted. If a shared bo is closed and
+ * re-opened in another thread a race against
+ * DRM_IOCTL_GEM_OPEN or drmPrimeFDToHandle might cause the
+ * bo to be closed accidentally while re-importing.
+ */
+ drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ pthread_mutex_unlock(&nvdev->lock);
+ } else {
+ DRMLISTDEL(&nvbo->head);
+ pthread_mutex_unlock(&nvdev->lock);
+ drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ }