Kernel development
A Note to Kernel Page Readers
For the next two weeks, the normal Kernel Page editor will be away having a good time on the beach. Please bear with your temporary guest editor as he tries to make sense of the complexities of the Linux Kernel development process. A few of the below patches may be mis-categorized.
Brief items
Kernel release status
The current development kernel is 2.5.74, which was released by Linus on July 2. The summary says: "Updates all over, the patch itself is big largely because of a MIPS/MIPS64 merge (and SH, for that matter). Network driver updates, USB updates, PnP, SCTP, s390, you name it. See the changelog for more details."
The current stable kernel is 2.4.21.
Marcelo has released the second 2.4.22 prepatch. This one includes some network driver updates, a big aic7xxx update, and many other fixes.
Status 2.5
Guillaume Boissiere has posted a 2.5 status summary.2.5.73-mm3 Released
Andrew Morton has released 2.5.73-mm3.
Kernel development news
perfctr-2.6.0-pre1 released
Mikael Pettersson has released a new version of perfctr, the Linux/x86 performance monitoring counters driver.
Driver porting
Using read-copy-update
This article is part of the LWN Porting Drivers to 2.6 series. |
The first step in using RCU within a subsystem is to define a structure containing the data to be protected. Often that structure already exists; for example, RCU has been retrofitted into the dentry cache (using struct dentry), the network routing cache (struct rtable), and several other, similar contexts. The structures need to be allocated dynamically and accessed via a pointer - RCU cannot be used with static structures.
Code which reads data structures protected by RCU need only take a couple of simple precautions:
- A call to rcu_read_lock() should be made before accessing
the data, and rcu_read_unlock() should be called afterward.
This call disables preemption (and does nothing else) - a fast but
necessary operation for RCU to work properly. These calls (along with
the rest of the RCU definitions) are found in
<linux/rcupdate.h>.
- The code must not sleep while the "RCU read lock" is held.
Thus, code which reads an RCU-protected data structure will look something like:
struct my_stuff *stuff; rcu_read_lock(); stuff = find_the_stuff(args...); do_something_with(stuff); /* Cannot sleep */ do_something_else_with(stuff); /* ditto */ rcu_read_unlock();
The write side of RCU is a little more complicated, but not that difficult. To update a data structure, the code starts by allocating a new copy of that structure, and filling in the new information. The code should then replace the pointer to the outdated structure with the new one, keeping a copy of the old pointer. After this operation, kernel code running on any other processor will find the new version of the structure. The old one cannot yet be freed, however, since it is possible that another processor is still using it.
The code should arrange to dispose of the old structure when it is known that it cannot be referenced anywhere else in the system. That is done through a call to call_rcu():
void call_rcu(struct rcu_head *head, void (*func)(void *arg), void *arg);
The calling code must provide an rcu_head structure, but need not initialize it in any way. Usually, that structure is embedded within the larger structure protected by RCU. The function func will be called when the structure can be safely freed, with arg as its one argument. All that func need do, normally, is call something like kfree() to free up the structure.
The RCU algorithm works by waiting until every processor in the system has scheduled at least once. Since the rules require that references to RCU-protected structures cannot be held over sleeps, no processor can possibly hold a reference to an old structure after it has scheduled. When all processors have scheduled (after the pointer change), references to the old structure can not exist, and the structure can be freed.
For what it's worth, the RCU code exports the "wait for everybody to schedule" functionality, should it be useful elsewhere. To perform this wait, one need only make a call to synchronize_kernel().
Patches and updates
Kernel trees
Architecture-specific
Build system
Core kernel code
Development tools
Device drivers
Documentation
Filesystems and block I/O
Memory management
Networking
Benchmarks and bugs
Miscellaneous
Page editor: Forrest Cook
Next page:
Distributions>>