FreeBSD/sys/dev/drm2/drm_fops.c
/**
 * Release file.
 *
 * \param inode device inode
 * \param file_priv DRM file private.
 * \return zero on success or a negative number on failure.
 *
 * If the hardware lock is held then free it, and take it again for the kernel
 * context since it's necessary to reclaim buffers. Unlink the file private
 * data from its list and free it. Decreases the open count and if it reaches
 * zero calls drm_lastclose().
 */
Release file.
\param inode device inode
\param file_priv DRM file private.
\return zero on success or a negative number on failure.

If the hardware lock is held then free it, and take it again for the kernel
context since it's necessary to reclaim buffers. Unlink the file private
data from its list and free it. Decreases the open count and if it reaches
zero calls drm_lastclose().
Release file . \ param inode device inode \ param file_priv DRM file private . \ return zero on success or a negative number on failure . If the hardware lock is held then free it and take it again for the kernel context since it ' s necessary to reclaim buffers . Unlink the file private data from its list and free it . Decreases the open count and if it reaches zero calls drm_lastclose () .
void drm_release(void *data)
{
	struct drm_file *file_priv = data;
	struct drm_device *dev = file_priv->minor->dev;
	sx_xlock(&drm_global_mutex);
	DRM_DEBUG("open_count = %d\n", dev->open_count);
	if (dev->driver->preclose)
		dev->driver->preclose(dev, file_priv);
	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
		  DRM_CURRENTPID,
		  (long)file_priv->minor->device,
		  dev->open_count);
	if (file_priv->magic)
		(void) drm_remove_magic(file_priv->master, file_priv->magic);
	if (file_priv->minor->master)
		drm_master_release(dev, file_priv);
	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
		drm_core_reclaim_buffers(dev, file_priv);
	drm_events_release(file_priv);
	seldrain(&file_priv->event_poll);
	if (dev->driver->driver_features & DRIVER_MODESET)
		drm_fb_release(file_priv);
	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_release(dev, file_priv);
#ifdef FREEBSD_NOTYET
	mutex_lock(&dev->ctxlist_mutex);
	if (!list_empty(&dev->ctxlist)) {
		struct drm_ctx_list *pos, *n;
		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
			if (pos->tag == file_priv &&
			    pos->handle != DRM_KERNEL_CONTEXT) {
				if (dev->driver->context_dtor)
					dev->driver->context_dtor(dev,
								  pos->handle);
				drm_ctxbitmap_free(dev, pos->handle);
				list_del(&pos->head);
				kfree(pos);
				--dev->ctx_count;
			}
		}
	}
	mutex_unlock(&dev->ctxlist_mutex);
#endif 
	DRM_LOCK(dev);
	if (file_priv->is_master) {
		struct drm_master *master = file_priv->master;
		struct drm_file *temp;
		list_for_each_entry(temp, &dev->filelist, lhead) {
			if ((temp->master == file_priv->master) &&
			    (temp != file_priv))
				temp->authenticated = 0;
		}
		if (master->lock.hw_lock) {
			if (dev->sigdata.lock == master->lock.hw_lock)
				dev->sigdata.lock = NULL;
			master->lock.hw_lock = NULL;
			master->lock.file_priv = NULL;
			DRM_WAKEUP_INT(&master->lock.lock_queue);
		}
		if (file_priv->minor->master == file_priv->master) {
			if (dev->driver->master_drop)
				dev->driver->master_drop(dev, file_priv, true);
			drm_master_put(&file_priv->minor->master);
		}
	}
	drm_master_put(&file_priv->master);
	file_priv->is_master = 0;
	list_del(&file_priv->lhead);
	DRM_UNLOCK(dev);
	if (dev->driver->postclose)
		dev->driver->postclose(dev, file_priv);
#ifdef FREEBSD_NOTYET
	if (drm_core_check_feature(dev, DRIVER_PRIME))
		drm_prime_destroy_file_private(&file_priv->prime);
#endif 
	free(file_priv, DRM_MEM_FILES);
	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
	mtx_lock(&Giant);
	device_unbusy(dev->dev);
	mtx_unlock(&Giant);
	if (!--dev->open_count) {
		if (atomic_read(&dev->ioctl_count)) {
			DRM_ERROR("Device busy: %d\n",
				  atomic_read(&dev->ioctl_count));
		} else
			drm_lastclose(dev);
	}
	sx_xunlock(&drm_global_mutex);
}
void drm_release ( void * data ) { struct drm_file * file_priv = data ; struct drm_device * dev = file_priv -> minor -> dev ; sx_xlock ( & drm_global_mutex ) ; DRM_DEBUG ( " \n " , dev -> open_count ) ; if ( dev -> driver -> preclose ) dev -> driver -> preclose ( dev , file_priv ) ; DRM_DEBUG ( " \n " , DRM_CURRENTPID , ( long ) file_priv -> minor -> device , dev -> open_count ) ; if ( file_priv -> magic ) ( void ) drm_remove_magic ( file_priv -> master , file_priv -> magic ) ; if ( file_priv -> minor -> master ) drm_master_release ( dev , file_priv ) ; if ( drm_core_check_feature ( dev , DRIVER_HAVE_DMA ) ) drm_core_reclaim_buffers ( dev , file_priv ) ; drm_events_release ( file_priv ) ; seldrain ( & file_priv -> event_poll ) ; if ( dev -> driver -> driver_features & DRIVER_MODESET ) drm_fb_release ( file_priv ) ; if ( dev -> driver -> driver_features & DRIVER_GEM ) drm_gem_release ( dev , file_priv ) ; #ifdef FREEBSD_NOTYET mutex_lock ( & dev -> ctxlist_mutex ) ; if ( ! list_empty ( & dev -> ctxlist ) ) { struct drm_ctx_list * pos , * n ; list_for_each_entry_safe ( pos , n , & dev -> ctxlist , head ) { if ( pos -> tag == file_priv && pos -> handle != DRM_KERNEL_CONTEXT ) { if ( dev -> driver -> context_dtor ) dev -> driver -> context_dtor ( dev , pos -> handle ) ; drm_ctxbitmap_free ( dev , pos -> handle ) ; list_del ( & pos -> head ) ; kfree ( pos ) ; -- dev -> ctx_count ; } } } mutex_unlock ( & dev -> ctxlist_mutex ) ; #endif DRM_LOCK ( dev ) ; if ( file_priv -> is_master ) { struct drm_master * master = file_priv -> master ; struct drm_file * temp ; list_for_each_entry ( temp , & dev -> filelist , lhead ) { if ( ( temp -> master == file_priv -> master ) && ( temp != file_priv ) ) temp -> authenticated = 0 ; } if ( master -> lock . hw_lock ) { if ( dev -> sigdata . lock == master -> lock . hw_lock ) dev -> sigdata . lock = NULL ; master -> lock . hw_lock = NULL ; master -> lock . file_priv = NULL ; DRM_WAKEUP_INT ( & master -> lock . lock_queue ) ; } if ( file_priv -> minor -> master == file_priv -> master ) { if ( dev -> driver -> master_drop ) dev -> driver -> master_drop ( dev , file_priv , true ) ; drm_master_put ( & file_priv -> minor -> master ) ; } } drm_master_put ( & file_priv -> master ) ; file_priv -> is_master = 0 ; list_del ( & file_priv -> lhead ) ; DRM_UNLOCK ( dev ) ; if ( dev -> driver -> postclose ) dev -> driver -> postclose ( dev , file_priv ) ; #ifdef FREEBSD_NOTYET if ( drm_core_check_feature ( dev , DRIVER_PRIME ) ) drm_prime_destroy_file_private ( & file_priv -> prime ) ; #endif free ( file_priv , DRM_MEM_FILES ) ; atomic_inc ( & dev -> counts [ _DRM_STAT_CLOSES ] ) ; mtx_lock ( & Giant ) ; device_unbusy ( dev -> dev ) ; mtx_unlock ( & Giant ) ; if ( ! -- dev -> open_count ) { if ( atomic_read ( & dev -> ioctl_count ) ) { DRM_ERROR ( " \n " , atomic_read ( & dev -> ioctl_count ) ) ; } else drm_lastclose ( dev ) ; } sx_xunlock ( & drm_global_mutex ) ; }
Release file.
Release file .
/* ========================================================
	 * Begin inline drm_release
	 */ /* Release any auth tokens that might point to this file_priv,
	   (do that under the drm_global_mutex) */ /* if the master has gone away we can't do anything with the lock */ /* FREEBSD_NOTYET */ /**
		 * Since the master is disappearing, so is the
		 * possibility to lock.
		 */ /* drop the reference held my the minor */ /* drop the reference held my the file priv */ /* FREEBSD_NOTYET */ /* ========================================================
	 * End inline drm_release
	 */