sparse' is a tool for spotting bad variable uses in the Linux kernel It allows pointers, etc., to be annotated as to whether they point to user space or kernel space, whether I/O or whatever. Running make C=1 enables sparse checking.

On 15 September, Linux wrote this about some new features:

On Wed, 15 Sep 2004, Roland Dreier wrote:
>
> Linus, while we're on the subject of new sparse checks, could you give
> a quick recap of the semantics of the new __leXX types (and what
> __bitwise means to sparse)? I don't think I've ever seen this stuff
> described on LKML.

[ The bitwise checks are actually by Al Viro, but I'll explain the basic
idea. Al is Cc'd so that he can add any corrections or extensions. ]

Sparse allows a number of extra type qualifiers, including address spaces and various random extra restrictions on what you can do with them. There are context bits that allow you to use a symbol or type only in certain contexts, for example, and there are type qualifiers like noderef that just say that a pointer cannot be dereferenced (it looks exactly like a pointer in all other respects, but trying to actually access anything through it will cause a sparse warning).

The bitwise attribute is very much like the noderef one, in that it restricts how you can use an expression of that type. Unlike noderef, it's designed for integer types, though. In fact, sparse will refuse to apply the bitwise attribute to non-integer types.

As the name suggests, a bitwise expression is one that is restricted to only a certain bitwise operations that make sense within that class. In particular, you can't mix a bitwise class with a normal integer expression (the constant zero happens to be special, since it's safe for all bitwise ops), and in fact you can't even mix it with another bitwise expression of a different type.

And when I say "different"', I mean even slightly different. Each typedef  creates a type of its own, and will thus create a bitwise type that is not compatible with anything else. So if you declare

the two variables i and j are not compatible, simply because they were declared separately, while in the case of

they are compatible. The above is a horribly contrived example, as it shows an extreme case that doesn't make much sense, but it shows how bitwise always creates its own new class.
Normally you'd always use __bitwise in a typedef, which effectively makes that particular typedef one single bitwise class. After that, you can obviously declare any number of variables in that class.

Now apart from the classes having to match, bitwise as its name suggests, also restricts all operations within that class to a subset of bit-safe operations. For example, addition isn't bit-safe, since clearly the carry-chain moves bits around. But you can do normal bit-wise operations, and you can compare the values against other values in the same class, since those are all bit-safe.

Oh, as an example of something that isn't obviously bit-safe: look out for things like bit negation: doing a ~ is ok on a bitwise int type, but it is not ok on a bitwise short or char. Why? Because on a bitwise int you actually stay within the type. But doing the same thing on a short or char will move outside the type by virtue of setting the high bits (normal C semantics: a short gets promoted to an int, so doing a bitwise negation on a short will actually set the high bits).

So as far as sparse is concerned, a bitwise type is not really so much about endianness as it is about making sure bits are never lost or moved around.

For example, you can use the bitwise operation to verify the __GFP_XXX  mask bits. Right now they are just regular integers, which means that you can write

and the compiler will not notice anything wrong. But something is seriously wrong: the GFP_KERNEL should be the second argument. If we mark it to be a bitwise type (which it is), that bug would have been noticed immediately, and you could still do all the operations that are valid of GFP_xxx values.

See the usage?

In the byte-order case, what we have is:

and if you think about the above rules about what is acceptable for bitwise types, you'll likely immediately notice that it automatically means

See?

In short, bitwise is about more than just byte-order, but the semantics of bitwise-restricted ops happen to be the semantics that are valid for byte-order operations too.

Oh, btw, right now you only get the warnings from sparse if you use -Wbitwise on the command line. Without that, sparse will ignore the bitwise attribute.

IA64wiki: SparseAnnotations (last edited 2009-12-10 03:13:48 by localhost)

Gelato@UNSW is sponsored by
the University of New South Wales National ICT Australia The Gelato Federation Hewlett-Packard Company Australian Research Council
Please contact us with any questions or comments.