Team LiB
Previous Section Next Section

Reference Counts

One of the primary features provided by kobjects is a unified reference counting system. After initialization, the kobject's reference count is set to one. So long as the reference count is nonzero, the object continues to exist in memory and is said to be pinned. Any code that holds a reference to the object first elevates the reference count. When the code is finished with the object, the reference count is decremented. Bumping the reference count is called getting a reference to the object, and decrementing the reference count is called putting reference to the object. When the reference count reaches zero, the object may be destroyed and any associated memory freed.

Incrementing the reference count is done via kobject_get():

struct kobject * kobject_get(struct kobject *kobj);

This function returns a pointer to the kobject or NULL on failure.

Decrementing the reference count is done via kobject_put():

void kobject_put(struct kobject *kobj);

If the provided kobject's reference count reaches zero, the release function pointed at by the ktype associated with the kobject is invoked.

krefs

Internally, the kobject reference counting is provided by the kref structure, which is defined in <linux/kref.h>:

struct kref {
        atomic_t refcount;
};

The lone member is an atomic variable used to hold the reference count. A structure is used simply to provide type checking. Before using a kref, you must initialize it via kref_init():

void kref_init(struct kref *kref)
{
        atomic_set(&kref->refcount, 1);
}

As you can see, this function simply initializes the internal atomic_t to one. Consequently, krefs are pinned with a reference count of one as soon as they are initialized; this is the same behavior as kobjects.

To obtain a reference to a kref, use kref_get():

void kref_get(struct kref *kref)
{
        WARN_ON(!atomic_read(&kref->refcount));
        atomic_inc(&kref->refcount);
}

This function bumps the reference count. It has no return value. To drop a reference to a kref, use kref_put():

void kref_put(struct kref *kref, void (*release) (struct kref *kref))
{
        WARN_ON(release == NULL);
        WARN_ON(release == (void (*)(struct kref *))kfree);

        if (atomic_dec_and_test(&kref->refcount))
                release(kref);
}

This function drops the reference count by one and calls the provided release() function if the count is now zero. As noted by the ominous WARN_ON() statement, the provided release() function cannot simply be kfree(), but must be a specialized function that accepts struct kref as its lone argument and has no return value.

Rather than having kernel code implement its own reference counting via atomic_t types and simple "get" and "put" wrapper functions, developers are encouraged to use the kref type and its helpers to provide a common and known-correct reference counting mechanism in the kernel.

All these functions are defined in lib/kref.c and declared in <linux/kref.h>.

    Team LiB
    Previous Section Next Section