2005-04-17 02:20:36 +04:00
/*
* kref . c - library routines for handling generic reference counted objects
*
* Copyright ( C ) 2004 Greg Kroah - Hartman < greg @ kroah . com >
* Copyright ( C ) 2004 IBM Corp .
*
* based on lib / kobject . c which was :
* Copyright ( C ) 2002 - 2003 Patrick Mochel < mochel @ osdl . org >
*
* This file is released under the GPLv2 .
*
*/
# include <linux/kref.h>
# include <linux/module.h>
/**
* kref_init - initialize object .
* @ kref : object in question .
*/
void kref_init ( struct kref * kref )
{
atomic_set ( & kref - > refcount , 1 ) ;
2007-04-02 16:47:59 +04:00
smp_mb ( ) ;
2005-04-17 02:20:36 +04:00
}
/**
* kref_get - increment refcount for object .
* @ kref : object .
*/
void kref_get ( struct kref * kref )
{
WARN_ON ( ! atomic_read ( & kref - > refcount ) ) ;
atomic_inc ( & kref - > refcount ) ;
2007-04-02 16:47:59 +04:00
smp_mb__after_atomic_inc ( ) ;
2005-04-17 02:20:36 +04:00
}
/**
* kref_put - decrement refcount for object .
* @ kref : object .
* @ release : pointer to the function that will clean up the object when the
* last reference to the object is released .
* This pointer is required , and it is not acceptable to pass kfree
* in as this function .
*
* Decrement the refcount , and if 0 , call release ( ) .
* Return 1 if the object was removed , otherwise return 0. Beware , if this
* function returns 0 , you still can not count on the kref from remaining in
* memory . Only use the return value if you want to see if the kref is now
* gone , not present .
*/
int kref_put ( struct kref * kref , void ( * release ) ( struct kref * kref ) )
{
WARN_ON ( release = = NULL ) ;
WARN_ON ( release = = ( void ( * ) ( struct kref * ) ) kfree ) ;
2006-12-20 00:01:29 +03:00
if ( atomic_dec_and_test ( & kref - > refcount ) ) {
2005-04-17 02:20:36 +04:00
release ( kref ) ;
return 1 ;
}
return 0 ;
}
EXPORT_SYMBOL ( kref_init ) ;
EXPORT_SYMBOL ( kref_get ) ;
EXPORT_SYMBOL ( kref_put ) ;