11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2932fb06b0898f5883200f1da2e00075f0d70ba9cRobert P. J. Day * kref.h - library routines for handling generic reference counted objects
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 IBM Corp.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on kobject.h which was:
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002-2003 Open Source Development Labs
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPLv2.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef _KREF_H_
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _KREF_H_
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
186261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman#include <linux/bug.h>
196261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman#include <linux/atomic.h>
2067175b855bfd6ed95ffeff95532173c07de6432dJames Bottomley#include <linux/kernel.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct kref {
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_t refcount;
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
264af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra/**
274af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * kref_init - initialize object.
284af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @kref: object in question.
294af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra */
304af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstrastatic inline void kref_init(struct kref *kref)
314af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra{
324af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	atomic_set(&kref->refcount, 1);
334af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra}
344af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra
354af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra/**
364af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * kref_get - increment refcount for object.
374af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @kref: object.
384af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra */
394af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstrastatic inline void kref_get(struct kref *kref)
404af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra{
414af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	WARN_ON(!atomic_read(&kref->refcount));
424af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	atomic_inc(&kref->refcount);
434af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra}
444af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra
454af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra/**
4647dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra * kref_sub - subtract a number of refcounts for object.
474af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @kref: object.
4847dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra * @count: Number of recounts to subtract.
494af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @release: pointer to the function that will clean up the object when the
504af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *	     last reference to the object is released.
514af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *	     This pointer is required, and it is not acceptable to pass kfree
526261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     in as this function.  If the caller does pass kfree to this
536261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     function, you will be publicly mocked mercilessly by the kref
546261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     maintainer, and anyone else who happens to notice it.  You have
556261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     been warned.
564af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *
5747dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra * Subtract @count from the refcount, and if 0, call release().
584af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * Return 1 if the object was removed, otherwise return 0.  Beware, if this
594af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * function returns 0, you still can not count on the kref from remaining in
604af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * memory.  Only use the return value if you want to see if the kref is now
614af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * gone, not present.
624af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra */
6347dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstrastatic inline int kref_sub(struct kref *kref, unsigned int count,
6447dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra	     void (*release)(struct kref *kref))
654af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra{
664af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	WARN_ON(release == NULL);
674af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra
6847dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra	if (atomic_sub_and_test((int) count, &kref->refcount)) {
694af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra		release(kref);
704af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra		return 1;
714af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	}
724af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra	return 0;
734af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra}
744af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra
754af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra/**
7647dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra * kref_put - decrement refcount for object.
774af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @kref: object.
784af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * @release: pointer to the function that will clean up the object when the
794af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *	     last reference to the object is released.
804af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *	     This pointer is required, and it is not acceptable to pass kfree
816261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     in as this function.  If the caller does pass kfree to this
826261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     function, you will be publicly mocked mercilessly by the kref
836261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     maintainer, and anyone else who happens to notice it.  You have
846261ddee70174372d6a75601f40719b7a5392f3fGreg Kroah-Hartman *	     been warned.
854af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra *
8647dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra * Decrement the refcount, and if 0, call release().
874af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * Return 1 if the object was removed, otherwise return 0.  Beware, if this
884af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * function returns 0, you still can not count on the kref from remaining in
894af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * memory.  Only use the return value if you want to see if the kref is now
904af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra * gone, not present.
914af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra */
9247dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstrastatic inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
934af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra{
9447dbd7d90ad80edb67822f327241edcab8f3f46fPeter Zijlstra	return kref_sub(kref, 1, release);
954af679cd7cbb0a0d8774b5cdb34bffcaa4e86e52Peter Zijlstra}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* _KREF_H_ */
97