LWN.net Logo

 


 
Recent Features

LWN.net Weekly Edition for March 18, 2004

LWN.net Weekly Edition for March 11, 2004

The annotated SCO stock price chart

A grumpy editor's calendar search

LWN.net Weekly Edition for March 4, 2004

Printable page
 

 

Driver porting: miscellaneous changes

This article is part of the LWN Porting Drivers to 2.6 series.
This article serves as a sort of final resting place for various small changes in the kernel programming API which do not fit elsewhere.

No more kdev_t

The kdev_t type has been removed from the kernel; everything which works with device numbers should now use the dev_t type. As part of this change, dev_t has been expanded to 32 bits; 12 bits for the major number, and 20 for the minor number.

If your driver uses the i_rdev field of the inode structure, there are a couple of new macros you can use:

    unsigned int iminor(struct inode *inode);
    unsigned int imajor(struct inode *inode);

Consider using these while fixing your code; the next time the type of i_rdev changes, you will be happier.

malloc.h

The include file <linux/malloc.h> has long been a synonym for <linux/slab.h>. In 2.5, malloc.h was removed, and all code should include slab.h directly.

Designated initializers

In the 2.3 development cycle, much effort went into converting code to the (non-standard) gcc designated initializer format for structures:
    static struct some_structure = {
	field1:  value,
	field2:  value
    };
In 2.5, the decision was made to go to the ANSI C standard initializer format, and all of that code was reworked again. The non-standard format still works, for now, but it is worth the effort to make the change anyway. The standard format looks like:
    static struct some_structure = {
	.field1 = value,
	.field2 = value,
	...
    };

The min() and max() macros

A common step in the development of most C programmers, shortly after they learn to include stdio.h seems to be the definition of macros like:
    #define max(a,b) ((a) > (b) ? (a) : (b))
In 2.5, it was noted that a number of kernel developers had seemingly not moved beyond that stage, and there was an unbelievable number of min() and max() definitions sprinkled throughout the kernel source. These definitions were not only redundant - they were unsafe. A max() macro as defined above has the usual problem with side effects; it also is not type-safe, especially when signed and unsigned values are used.

Linus initially added his own definition of min() and max() which added a third argument - an explicit type. That change upset people badly enough that some put substantial amounts of time into developing two-argument versions that are type and side-effect safe. The result now lives in <linux/kernel.h>, and should be used in preference to any locally-defined version.

Dependent read barriers

(Added February 24, 2003).

On most architectures, reads from memory will not be reordered across a data dependency. Consider this code fragment:

    int *a, *b, x;

    a = b;
    x = *a;

Here, you would expect that *a would yield the value pointed to by b; it would be surprising to have the read of *a reordered in front of the assignment to a. Some architectures can do just that sort of reordering, however. One could ensure that such reordering does not happen by inserting a rmb() (read memory barrier) between the two assignment. But that would reduce performance needlessly on many systems. So a new barrier, read_barrier_depends(), has been added in this case. It should only be used in situations where data dependencies exist. On architectures where data dependencies will force ordering, read_barrier_depends() will do nothing. On other architectures, it expands into a regular read barrier. See this patch posting for more information.

User-mode helpers

(Added February 28, 2003).

The prototype of call_usermodehelper() has changed:

    int call_usermodehelper(char *path, char **argv, char **envp, 
                            int wait);

The new wait flag controls whether call_usermodehelper() returns before the user-mode process exits. If wait is set to a non-zero value, the function will wait for the process to finish its work, and the return value will be what the process itself returned. Otherwise the return is immediate, and the return value only indicates whether the user-mode process was successfully started or not.

Note that the older exec_usermodehelper() function has been removed from the 2.5 kernel.

New request_module() prototype

(Added May 20, 2003).

As of 2.5.70, the prototype of request_module() has changed. This function now takes a printf-style argument list. As a result, code which used to look like:

    char module_name[32];

    sprintf(module_name, "foo-device-%d", number);
    request_module(module_name);

can now be rewritten as:

    request_module("foo-device-%d", number);

Most in-kernel code has already been changed to do things the new way.

devfs

We'll not go into the details here, but it is worth noting that devfs has been through extensive changes, and will likely see more changes yet before 2.6.0 is released. If your driver uses devfs, it will certainly need updating.

Note also that devfs has been officially marked as "deprecated."


Post a comment

  Driver porting: miscellaneous changes, designated inits
(Posted Mar 14, 2003 23:28 UTC (Fri) by dougg) (Post reply)

With regard to designated initializers they were
introduced in C99. Formally you are correct as
C89 has been displaced as the ANSI (and ISO) C
standard by C99 (ISO9899-1999) but many people
may not realize that.

Copyright (©) 2003, Eklektix, Inc.
Linux (®) is a registered trademark of Linus Torvalds
Powered by Rackspace Managed Hosting.