mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![Greg Kroah-Hartman](/assets/img/avatar_default.png)
It turns out that some memory allocators use kobjects, which use krefs, and kref.h was wanting to figure out the address of kfree(), which ended up in a loop. kfree was only being needed for a warning to tell the caller that they were doing something stupid. Now we just move that warning into the comments for the functions, which results in a bit more fun as everyone enjoys digging for people to mock at times of boredom. So, remove the dependancy of slab.h on kref.h, and fix up the other include file as well (we really only need bug.h and atomic.h, not types.h). Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
95 lines
2.9 KiB
C
95 lines
2.9 KiB
C
/*
|
|
* kref.h - library routines for handling generic reference counted objects
|
|
*
|
|
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
|
|
* Copyright (C) 2004 IBM Corp.
|
|
*
|
|
* based on kobject.h which was:
|
|
* Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
|
|
* Copyright (C) 2002-2003 Open Source Development Labs
|
|
*
|
|
* This file is released under the GPLv2.
|
|
*
|
|
*/
|
|
|
|
#ifndef _KREF_H_
|
|
#define _KREF_H_
|
|
|
|
#include <linux/bug.h>
|
|
#include <linux/atomic.h>
|
|
|
|
struct kref {
|
|
atomic_t refcount;
|
|
};
|
|
|
|
/**
|
|
* kref_init - initialize object.
|
|
* @kref: object in question.
|
|
*/
|
|
static inline void kref_init(struct kref *kref)
|
|
{
|
|
atomic_set(&kref->refcount, 1);
|
|
}
|
|
|
|
/**
|
|
* kref_get - increment refcount for object.
|
|
* @kref: object.
|
|
*/
|
|
static inline void kref_get(struct kref *kref)
|
|
{
|
|
WARN_ON(!atomic_read(&kref->refcount));
|
|
atomic_inc(&kref->refcount);
|
|
}
|
|
|
|
/**
|
|
* kref_sub - subtract a number of refcounts for object.
|
|
* @kref: object.
|
|
* @count: Number of recounts to subtract.
|
|
* @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. If the caller does pass kfree to this
|
|
* function, you will be publicly mocked mercilessly by the kref
|
|
* maintainer, and anyone else who happens to notice it. You have
|
|
* been warned.
|
|
*
|
|
* Subtract @count from 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.
|
|
*/
|
|
static inline int kref_sub(struct kref *kref, unsigned int count,
|
|
void (*release)(struct kref *kref))
|
|
{
|
|
WARN_ON(release == NULL);
|
|
|
|
if (atomic_sub_and_test((int) count, &kref->refcount)) {
|
|
release(kref);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 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. If the caller does pass kfree to this
|
|
* function, you will be publicly mocked mercilessly by the kref
|
|
* maintainer, and anyone else who happens to notice it. You have
|
|
* been warned.
|
|
*
|
|
* 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.
|
|
*/
|
|
static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
|
|
{
|
|
return kref_sub(kref, 1, release);
|
|
}
|
|
#endif /* _KREF_H_ */
|