看板 DFBSD_kernel 關於我們 聯絡資訊
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