DragonFly BSD
DragonFly kernel List (threaded) for 2010-12
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Super Light Weight Reference counting


From: Venkatesh Srinivas <me@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 21 Dec 2010 12:20:24 -0500

Hi,

I had a need for a very light-weight reference counting system in
kernel (much lighter than sysref), so I came up with:

ref.h :=====================
cat struct kref {
	void		*priv;
	int		refcount;
};

typedef struct kref *kref_t;

void kref_init(struct kref *ref, void *priv1, int count);
void kref_inc(struct kref *ref);
void kref_dec(struct kref *ref, void (*deconstruct)(void*, void*), void *priv2);

kern_ref.c :=========================

#include <sys/atomic.h>

void
kref_init(struct kref *ref, void *priv, int count)
{
	ref->refcount = count;
	ref->priv = priv;
}

void
kref_inc(struct kref *ref)
{
	atomic_add_int(&ref->refcount, 1);
}

void
kref_dec(struct kref *ref, void (*deconstruct)(void *, void *), void *priv2)
{
	int val;

	val = atomic_fetchadd_int(&ref->refcount, -1);
	if (val == 1)
		deconstruct(ref->priv, priv2);
}

--------

The intended lifecycle for something would be :

struct thing {
   struct kref ref;
};

struct thing *thingy = kmalloc(sizeof(struct thing), M_AWESOME);

kref_init(&thingy->ref, thingy, 1);
. ..
kref_inc(&thingy->ref);
. ..
kref_dec(&thingy->ref, kfree, M_AWESOME);
. ..
kref_dec(&thingy->ref, kfree, M_AWESOME);
    Object is freed! (The deconstructor is called on the 1 -> 0
transition (the last one out turns off the lights))

Since "an object cannot synchronize its own visibility", kref_inc and
kref_dec must be synchronized at a higher level; directly using them
invites races (imagine entering a kref_inc ; you compute the address
of the refcount; then a concurrent kref_dec frees the structure. then
you go ahead and LOCK ADD. oops.)

Aggelos Economopoulos suggested on IRC the rename from kern_ref to
kref, suggested moving the deconstructor from a per-ref field to an
argument to kref_dec, and that references only needed one priv pointer
(the original had two, to support kfree).

Any criticisms or thoughts would be very welcome!

Thanks,
-- vs



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]