1.\" Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org> 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd August 29, 2018 28.Dt DEV_REFTHREAD 9 29.Os 30.Sh NAME 31.Nm dev_refthread , 32.Nm devvn_refthread , 33.Nm dev_relthread 34.Nd safely access device methods 35.Sh SYNOPSIS 36.In sys/param.h 37.In sys/conf.h 38.Ft "struct cdevsw *" 39.Fn dev_refthread "struct cdev *dev" "int *ref" 40.Ft "struct cdevsw *" 41.Fn devvn_refthread "struct vnode *vp" "struct cdev **devp" "int *ref" 42.Ft void 43.Fn dev_relthread "struct cdev *dev" "int ref" 44.Sh DESCRIPTION 45The 46.Fn dev_refthread 47(or 48.Fn devvn_refthread ) 49and 50.Fn dev_relthread 51routines provide a safe way to access 52.Xr devfs 5 53devices that may be concurrently destroyed by 54.Fn destroy_dev 55(e.g., removable media). 56.Pp 57If successful, 58.Fn dev_refthread 59and 60.Fn devvn_refthread 61acquire a "thread reference" to the associated 62.Vt "struct cdev" 63and return a non-NULL pointer to the cdev's 64.Vt "struct cdevsw" 65method table. 66For the duration of that reference, the cdev's associated private data and 67method table object are valid. 68Destruction of the cdev sleeps until the thread reference is released. 69.Pp 70A reference cannot prevent media removal. 71It is an implementation detail of individual drivers how method calls from 72callers with 73.Fn dev_refthread 74references are handled when the device is 75pending destruction. 76A common behavior for disk devices is to return the 77.Er ENXIO 78status, but that is not required by this KPI. 79.Pp 80The 81.Fn devvn_refthread 82variant of 83.Fn dev_refthread 84extracts the 85.Vt "struct cdev" 86pointer out of the 87.Dv VCHR 88.Xr vnode 9 89automatically before performing the same actions as 90.Fn dev_refthread . 91Additionally, a pointer to the 92.Vt "struct cdev" 93is returned to the caller via 94.Fa "*devp" . 95.Fn devvn_refthread 96correctly handles possible parallel reclamation of the vnode. 97.Pp 98.Fn dev_relthread 99is used to release a reference to a 100.Vt "struct cdev" . 101.Fn dev_relthread 102.Sy must 103only be invoked when the associated invocation of 104.Fn dev_refthread 105or 106.Fn devvn_refthread 107returned a non-NULL 108.Vt "struct cdevsw *" . 109.Sh CONTEXT 110.Vt struct cdev 111objects have two reference counts, 112.Va si_refcount 113and 114.Va si_threadcount . 115The 116.Fn dev_refthread , 117.Fn devvn_refthread , 118and 119.Fn dev_relthread 120functions manipulate the 121.Va si_threadcount . 122The 123.Va si_threadcount 124reference guarantees the liveness of the 125.Vt struct cdev 126object. 127The other 128.Va si_refcount 129reference provides only the weaker guarantee that the memory backing the 130.Vt struct cdev 131has not been freed. 132.Sh RETURN VALUES 133If 134.Fn dev_refthread 135or 136.Fn devvn_refthread 137are unsuccessful, they return 138.Dv NULL . 139.Bf Em 140If these routines are unsuccessful, they do not increment the 141.Vt "struct cdev" 142.Va si_threadcount 143and do not initialize the value pointed to by the 144.Fa "*ref" 145parameter in any way. 146.Ef 147.Sh SEE ALSO 148.Xr devfs 5 , 149.Xr destroy_dev 9 150.Sh CAVEATS 151Do not invoke 152.Fn dev_relthread 153unless the matching refthread routine succeeded! 154