Online Book Reader

Home Category

Beautiful Code [217]

By Root 5222 0
structure, all the different driver subsystems were unified during the 2.5 kernel development process. They now shared the common core code, which allowed the kernel to show users how all devices were interconnected. This enabled the creation of tools such as udev, which does persistent device naming in a small userspace program, and power management tools, which can walk the tree of devices and shut devices down in the proper order.

The Linux Kernel Driver Model: The Benefits of Working Together > Reduced to Even Smaller Bits

16.2. Reduced to Even Smaller Bits

As the initial driver core rework was happening, another kernel developer, Al Viro, was working on fixing a number of issues regarding object reference counting in the virtual filesystem layer.

The main problem with structures in multithreaded programs written in the C language is that it's very hard to determine when it is safe to free up any memory used by a structure. The Linux kernel is a massively multithreaded program that must properly handle hostile users as well as large numbers of processors all running at the same time. Because of this, reference counting on any structure that can be found by more than one thread is a necessity.

The struct device structure was one such reference-counted structure. It had a single field that was used to determine when it was safe to free the structure:

atomic_t refcount;

When the structure was initialized, this field was set to 1. Whenever any code wished to use the structure, it had to first increment the reference count by calling the function get_ device, which checked that the reference count was valid and incremented the reference count of the structure:

static inline void get_device(struct device * dev)

{

BUG_ON(!atomic_read(&dev->refcount));

atomic_inc(&dev->refcount);

}

Similarly, when a thread was finished with the structure, it decremented the reference count by calling put_device, which was a bit more complex:

void put_device(struct device * dev)

{

if (!atomic_dec_and_lock(&dev->refcount,&device_lock))

return;

...

/* Tell the driver to clean up after itself.

* Note that we likely didn't allocate the device,

*so this is the driver's chance to free that up...

*/

if (dev->driver && dev->driver->remove)

dev->driver->remove(dev,REMOVE_FREE_RESOURCES);

}

This function decremented the reference count and then, if it was the last user of the object, would tell the object to clean itself up and call a function that was previously set up to free it from the system.

Al Viro liked the unification of the struct device structure, the virtual filesystem that showed all of the different devices and how they were linked together, and the automatic reference counting. The only problem was that his virtual filesystem core did not work on "devices," nor did it have "drivers" that would attach to these objects. So, he decided to refactor things a bit and make the code simpler.

Al convinced Pat to create something called struct kobject. This structure had the basic properties of the struct device structure, but was smaller and did not have the "driver" and "device" relationship. It contained the following fields:

struct kobject {

char name[KOBJ_NAME_LEN];

atomic_t refcount;

struct list_head entry;

struct kobject *parent;

struct subsystem *subsys;

struct dentry *dentry;

};

This structure is a type of empty object. It has only the very basic ability to be reference-counted and to be inserted into a hierarchy of objects. The struct device structure could now include this smaller struct kobject "base" structure to inherit all of its functionality:

struct device {

struct list_head g_list; /* node in depth-first order list */

struct list_head node; /* node in sibling list */

struct list_head bus_list; /* node in bus's list */

struct list_head driver_list;

struct list_head children;

struct list_head intf_list;

struct device *parent;

struct kobject kobj;

char bus_id[BUS_ID_SIZE]; /* position on parent bus */

Return Main Page Previous Page Next Page

®Online Book Reader