1.\" 2.\" Copyright (c) 2009 Hudson River Trading LLC 3.\" Written by: John H. Baldwin <jhb@FreeBSD.org> 4.\" All rights reserved. 5.\" 6.\" Copyright (c) 2019 The FreeBSD Foundation 7.\" 8.\" Parts of this documentation was written by 9.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship 10.\" from the FreeBSD Foundation. 11.\" 12.\" Redistribution and use in source and binary forms, with or without 13.\" modification, are permitted provided that the following conditions 14.\" are met: 15.\" 1. Redistributions of source code must retain the above copyright 16.\" notice, this list of conditions and the following disclaimer. 17.\" 2. Redistributions in binary form must reproduce the above copyright 18.\" notice, this list of conditions and the following disclaimer in the 19.\" documentation and/or other materials provided with the distribution. 20.\" 21.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" SUCH DAMAGE. 32.\" 33.Dd October 12, 2022 34.Dt REFCOUNT 9 35.Os 36.Sh NAME 37.Nm refcount , 38.Nm refcount_init , 39.Nm refcount_acquire , 40.Nm refcount_release 41.Nd manage a simple reference counter 42.Sh SYNOPSIS 43.In sys/param.h 44.In sys/refcount.h 45.Ft void 46.Fn refcount_init "volatile u_int *count" "u_int value" 47.Ft u_int 48.Fn refcount_load "volatile u_int *count" 49.Ft u_int 50.Fn refcount_acquire "volatile u_int *count" 51.Ft bool 52.Fn refcount_acquire_checked "volatile u_int *count" 53.Ft bool 54.Fn refcount_acquire_if_not_zero "volatile u_int *count" 55.Ft bool 56.Fn refcount_release "volatile u_int *count" 57.Ft bool 58.Fn refcount_release_if_last "volatile u_int *count" 59.Ft bool 60.Fn refcount_release_if_not_last "volatile u_int *count" 61.Sh DESCRIPTION 62The 63.Nm 64functions provide an API to manage a simple reference counter. 65The caller provides the storage for the counter in an unsigned integer. 66A pointer to this integer is passed via 67.Fa count . 68Usually the counter is used to manage the lifetime of an object and is 69stored as a member of the object. 70.Pp 71Currently all functions are implemented as static inline. 72.Pp 73The 74.Fn refcount_init 75function is used to set the initial value of the counter to 76.Fa value . 77It is normally used when creating a reference-counted object. 78.Pp 79The 80.Fn refcount_load 81function returns a snapshot of the counter value. 82This value may immediately become out-of-date in the absence of external 83synchronization. 84.Fn refcount_load 85should be used instead of relying on the properties of the 86.Vt volatile 87qualifier. 88.Pp 89The 90.Fn refcount_acquire 91function is used to acquire a new reference. 92It returns the counter value before the new reference was acquired. 93The caller is responsible for ensuring that it holds a valid reference 94while obtaining a new reference. 95For example, 96if an object is stored on a list and the list holds a reference on the 97object, then holding a lock that protects the list provides sufficient 98protection for acquiring a new reference. 99.Pp 100The 101.Fn refcount_acquire_checked 102variant performs the same operation as 103.Fn refcount_acquire , 104but additionally checks that the 105.Fa count 106value does not overflow as result of the operation. 107It returns 108.Dv true 109if the reference was sucessfully obtained, and 110.Dv false 111if it was not, due to the overflow. 112.Pp 113The 114.Fn refcount_acquire_if_not_zero 115function is yet another variant of 116.Fn refcount_acquire , 117which only obtains the reference when some reference already exists. 118In other words, 119.Fa *count 120must be already greater than zero for the function to succeed, in which 121case the return value is 122.Dv true , 123otherwise 124.Dv false 125is returned. 126.Pp 127The 128.Fn refcount_release 129function is used to release an existing reference. 130The function returns true if the reference being released was 131the last reference; 132otherwise, it returns false. 133.Pp 134The 135.Fn refcount_release_if_last 136and 137.Fn refcount_release_if_not_last 138functions are variants of 139.Fn refcount_release 140which only drop the reference when it is or is not the last reference, 141respectively. 142In other words, 143.Fn refcount_release_if_last 144returns 145.Dv true 146when 147.Fa *count 148is equal to one, in which case it is decremented to zero. 149Otherwise, 150.Fa *count 151is not modified and the function returns 152.Dv false . 153Similarly, 154.Fn refcount_release_if_not_last 155returns 156.Dv true 157when 158.Fa *count 159is greater than one, in which case 160.Fa *count 161is decremented. 162Otherwise, if 163.Fa *count 164is equal to one, the reference is not released and the function returns 165.Dv false . 166.Pp 167Note that these routines do not provide any inter-CPU synchronization or 168data protection for managing the counter. 169The caller is responsible for any additional synchronization needed by 170consumers of any containing objects. 171In addition, 172the caller is also responsible for managing the life cycle of any containing 173objects including explicitly releasing any resources when the last reference 174is released. 175.Pp 176The 177.Fn refcount_release 178unconditionally executes a release fence (see 179.Xr atomic 9 ) before releasing the reference, which 180synchronizes with an acquire fence executed right before 181returning the 182.Dv true 183value. 184This ensures that the destructor, supposedly executed by the caller after 185the last reference was dropped, sees all updates done during the lifetime 186of the object. 187.Sh RETURN VALUES 188The 189.Nm refcount_release 190function returns true when releasing the last reference and false when 191releasing any other reference. 192.Sh HISTORY 193These functions were introduced in 194.Fx 6.0 . 195