Hmmm.....
static inline bool
refcount_dec_local(struct refcount *refcount)
{
unsigned old, new;
do {
old = refcount->rc_value;
if (old == 1) {
/*
* Avoid an atomic if we don't need it. Caller
* guarantees that if the reference count is 1,
* nobody else can acquire new references.
*/
refcount->rc_value = 0;
return true;
}
KASSERT(0 < old);
new = old - 1;
} while (atomic_cas_uint(&refcount->rc_value, old, new) != old);
KASSERT(0 < new);
return false;
}
Maybe I'm just seeing this clearly, but if old == 1, and new = old - 1,
doesn't that mean new = 0? And if so, the guarantee that "if the reference
count is 1 ..." becomes a guarantee to KASSERT(0 < new) ?
Maybe the KASSERT should be (0 <= old) ??
On Sat, 11 Apr 2015, Taylor R Campbell wrote:
I would like to introduce an easy-to-use-correctly abstraction for
MP-safe reference counts. I proposed the attached API, based on many
examples and on discussion with dholland@.
It is designed to address three different use cases:
- Object with lifetime ended by a specific operation which needs to
wait until all users are done.
Example: autoconf device with cdevsw nodes. xyz_detach must wait for
all open files to be closed, and xyz_open/xyz_close must maintain the
reference count and notify xyz_detach when the last close happens.
(We don't exactly do this currently, but that's a bug.)
- Object in global cache with last-user-frees.
Example: vnodes in vcache. Last reference must be dropped under the
same lock as removing the vnode from the vcache or at least marking it
unusable. Otherwise, maintenance of the vnode reference count can be
done with atomic operations.
- Shared objects, not in any global tables, with last-user-frees.
Example: process credentials. Last user just calls kmem_free, no
table or locks involved.
Thoughts?
-------------------------------------------------------------------------
| Paul Goyette | PGP Key fingerprint: | E-mail addresses: |
| (Retired) | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer | | pgoyette at netbsd.org |
-------------------------------------------------------------------------