static inline unsigned int atomic_dec_uint_lock_if_zero(volatile unsigned int *ptr, kmutex_t interlock) { unsigned int old, new; do { old = *ptr; KASSERT(0 < old); if (old == 1) { mutex_enter(interlock); new = atomic_add_int_nv(ptr, -1); if (new == 0) return 0; mutex_exit(interlock); return new; } new = (old - 1); } while (atomic_cas_uint(ptr, old, new) != old); return new; } #if examples void vref(struct vnode *vp) { const unsigned int usecnt __unused = atomic_inc_uint_nv(&vp->v_usecount); KASSERT(1 < usecnt); } void vrele(struct vnode *vp) { if (atomic_dec_uint_lock_if_zero(&vp->v_usecnt, vp->v_interlock)) return; KASSERT(mutex_owned(vp->v_interlock)); /* ...rest of vrelel... */ } #endif