Online Book Reader

Home Category

Beautiful Code [218]

By Root 5025 0

...

}

The container_of macro is used to cast back from the core kobject, to the main struct device:

#define to_dev(obj) container_of(obj, struct device, kobj)

During this development process, many other people were increasing the robustness of the Linux kernel by allowing it to scale up to larger and larger numbers of processors all running in the same system image.[] Because of this, many other developers were adding reference counts to their structures to properly handle their memory usage. Each developer had to duplicate the ability to initialize, increment, decrement, and clean up the structure. So it was decided that this simple functionality could be taken from the struct kobject and made into its own structure. Thus was the struct kref structure born:

[] The current record for the number of processors with Linux running in a single system image is 4096 processors, so the scalability work has succeeded.

struct kref {

atomic_t refcount;

};

struct kref has only three simple functions: kref_init to initialize the reference count, kref_get to increment the reference count, and kref_put to decrement the reference count. The first two functions are very simple; it is the last one that's a bit interesting:

int 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);

return 1;

}

return 0;

}

The kref_put function has two parameters: a pointer to the struct kref whose reference count you wish to decrement, and a pointer to the function that you wish to have called if this was the last reference held on the object.

The first two lines of the function were added a while after the struct kref was added to the kernel, as a number of programmers were trying to get around the reference counting by passing in either no pointer to a release function or, when they realized that the kernel would complain about that, a pointer to the basic kfree function. (Sad to say, but even these two checks are not enough these days. Some programmers have taken to just creating empty release functions that do not do anything, as they are trying to ignore the reference count altogether. Unfortunately, C doesn't have a simple way to determine whether a pointer to a function really does anything within that function; otherwise, that check would be added to kref_put, too.)

After these two checks are made, the reference count is atomically decremented, and if this is the last reference, the release function is called and 1 is returned. If this is not the last reference on the object, 0 is returned. This return value is used just to determine whether the caller was the last holder of the object, not whether the object is still in memory (it can't guarantee that the object still exists because someone else might come in and release it after the call returns).

With the creation of struct kref, the struct kobject structure was changed to use it:

struct kobject {

char name[KOBJ_NAME_LEN];

struct kref kref;

...

};

With all of these different structures embedded within other structures, the result is that the original struct usb_interface described earlier now contains a struct device, which contains a struct kobject, which contains a struct kref. And who said it was hard to do object-oriented programming in the C language.…

The Linux Kernel Driver Model: The Benefits of Working Together > Scaling Up to Thousands of Devices

16.3. Scaling Up to Thousands of Devices

As Linux runs on everything from cellphones, radio-controlled helicopters, desktops, and servers to 73 percent of the world's largest supercomputers, scaling the driver model was very important and always in the backs of our minds. As development progressed, it was nice to see that the basic structures used to hold devices, struct kobject and struct devices, were relatively small. The number of devices connected to most systems is directly proportional to the size of

Return Main Page Previous Page Next Page

®Online Book Reader