1219820Sjeff/*- 2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc. 3219820Sjeff * Copyright (c) 2010 iX Systems, Inc. 4219820Sjeff * Copyright (c) 2010 Panasas, Inc. 5289578Shselasky * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. 6289578Shselasky * Copyright (c) 2013 Fran��ois Tigeot 7219820Sjeff * All rights reserved. 8219820Sjeff * 9219820Sjeff * Redistribution and use in source and binary forms, with or without 10219820Sjeff * modification, are permitted provided that the following conditions 11219820Sjeff * are met: 12219820Sjeff * 1. Redistributions of source code must retain the above copyright 13219820Sjeff * notice unmodified, this list of conditions, and the following 14219820Sjeff * disclaimer. 15219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 16219820Sjeff * notice, this list of conditions and the following disclaimer in the 17219820Sjeff * documentation and/or other materials provided with the distribution. 18219820Sjeff * 19219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29289644Shselasky * 30289644Shselasky * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/kref.h 329961 2018-02-25 10:25:47Z hselasky $ 31219820Sjeff */ 32219820Sjeff#ifndef _LINUX_KREF_H_ 33219820Sjeff#define _LINUX_KREF_H_ 34219820Sjeff 35278681Shselasky#include <sys/types.h> 36219820Sjeff#include <sys/refcount.h> 37219820Sjeff 38290335Shselasky#include <linux/compiler.h> 39300497Shselasky#include <linux/kernel.h> 40300497Shselasky#include <linux/mutex.h> 41300497Shselasky 42289578Shselasky#include <asm/atomic.h> 43289578Shselasky 44219820Sjeffstruct kref { 45289578Shselasky atomic_t refcount; 46219820Sjeff}; 47219820Sjeff 48219820Sjeffstatic inline void 49219820Sjeffkref_init(struct kref *kref) 50219820Sjeff{ 51219820Sjeff 52289578Shselasky refcount_init(&kref->refcount.counter, 1); 53219820Sjeff} 54219820Sjeff 55329961Shselaskystatic inline unsigned int 56329961Shselaskykref_read(const struct kref *kref) 57329961Shselasky{ 58329961Shselasky 59329961Shselasky return (atomic_read(&kref->refcount)); 60329961Shselasky} 61329961Shselasky 62219820Sjeffstatic inline void 63219820Sjeffkref_get(struct kref *kref) 64219820Sjeff{ 65219820Sjeff 66289578Shselasky refcount_acquire(&kref->refcount.counter); 67219820Sjeff} 68219820Sjeff 69219820Sjeffstatic inline int 70219820Sjeffkref_put(struct kref *kref, void (*rel)(struct kref *kref)) 71219820Sjeff{ 72219820Sjeff 73289578Shselasky if (refcount_release(&kref->refcount.counter)) { 74219820Sjeff rel(kref); 75219820Sjeff return 1; 76219820Sjeff } 77219820Sjeff return 0; 78219820Sjeff} 79219820Sjeff 80289578Shselaskystatic inline int 81289578Shselaskykref_sub(struct kref *kref, unsigned int count, 82289578Shselasky void (*rel)(struct kref *kref)) 83289578Shselasky{ 84289578Shselasky 85289578Shselasky while (count--) { 86289578Shselasky if (refcount_release(&kref->refcount.counter)) { 87289578Shselasky rel(kref); 88289578Shselasky return 1; 89289578Shselasky } 90289578Shselasky } 91289578Shselasky return 0; 92289578Shselasky} 93289578Shselasky 94289578Shselaskystatic inline int __must_check 95289578Shselaskykref_get_unless_zero(struct kref *kref) 96289578Shselasky{ 97289578Shselasky 98289578Shselasky return atomic_add_unless(&kref->refcount, 1, 0); 99289578Shselasky} 100289578Shselasky 101300497Shselaskystatic inline int kref_put_mutex(struct kref *kref, 102300497Shselasky void (*release)(struct kref *kref), struct mutex *lock) 103300497Shselasky{ 104300497Shselasky WARN_ON(release == NULL); 105300497Shselasky if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { 106300497Shselasky mutex_lock(lock); 107300497Shselasky if (unlikely(!atomic_dec_and_test(&kref->refcount))) { 108300497Shselasky mutex_unlock(lock); 109300497Shselasky return 0; 110300497Shselasky } 111300497Shselasky release(kref); 112300497Shselasky return 1; 113300497Shselasky } 114300497Shselasky return 0; 115300497Shselasky} 116300497Shselasky 117270710Shselasky#endif /* _LINUX_KREF_H_ */ 118