mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-12 02:05:54 +00:00
* 0day explit mitigation * Memory corruption prevention * Privilege escalation prevention * Buffer over flow prevention * File System corruption defense * Thread escape prevention This may very well be the most intensive inclusion to BrooklynR. This will not be part of an x86 suite nor it will be released as tool kit. The security core toolkit will remain part of kernel base.
139 lines
4.3 KiB
C
139 lines
4.3 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>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mutex.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)
|
|
{
|
|
/* If refcount was 0 before incrementing then we have a race
|
|
* condition when this kref is freeing by some other thread right now.
|
|
* In this case one should use kref_get_unless_zero()
|
|
*/
|
|
WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2);
|
|
}
|
|
|
|
/**
|
|
* 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))
|
|
{
|
|
BUG_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);
|
|
}
|
|
|
|
static inline int kref_put_mutex(struct kref *kref,
|
|
void (*release)(struct kref *kref),
|
|
struct mutex *lock)
|
|
{
|
|
WARN_ON(release == NULL);
|
|
if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) {
|
|
mutex_lock(lock);
|
|
if (unlikely(!atomic_dec_and_test(&kref->refcount))) {
|
|
mutex_unlock(lock);
|
|
return 0;
|
|
}
|
|
release(kref);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* kref_get_unless_zero - Increment refcount for object unless it is zero.
|
|
* @kref: object.
|
|
*
|
|
* Return non-zero if the increment succeeded. Otherwise return 0.
|
|
*
|
|
* This function is intended to simplify locking around refcounting for
|
|
* objects that can be looked up from a lookup structure, and which are
|
|
* removed from that lookup structure in the object destructor.
|
|
* Operations on such objects require at least a read lock around
|
|
* lookup + kref_get, and a write lock around kref_put + remove from lookup
|
|
* structure. Furthermore, RCU implementations become extremely tricky.
|
|
* With a lookup followed by a kref_get_unless_zero *with return value check*
|
|
* locking in the kref_put path can be deferred to the actual removal from
|
|
* the lookup structure and RCU lookups become trivial.
|
|
*/
|
|
static inline int __must_check kref_get_unless_zero(struct kref *kref)
|
|
{
|
|
return atomic_add_unless(&kref->refcount, 1, 0);
|
|
}
|
|
#endif /* _KREF_H_ */
|