I was just going over some kernel code, I noticed that rb->__rb_parent_color = (unsigned long)p | color;
is kinda wired. The first field of a struct is accessed by casting the pointer and not by using the field name.
Here is the definition of that struct, as you can see the color is the first attribute, so simply casting (unsigned long)p
will give us the same as rb->__rb_parent_color
. But why did the developers choose to do it this way and not using the ->
?
The only reason I can think of is compiler optimizations that are not done when using rb->__rb_parent_color
, but find this hard to believe cause it seems like the compiler will, in both cases, calculate the same offset without problems.
struct rb_node *p
is not dereferenced. Read it again: this code casts the address to an unsigned long
.
This is relying on the fact that object addresses are aligned such that the bottom bit (at least) of the address is guaranteed to be un-used, so it packs the colour into that bit. So __rb_parent_color
here does not mean the parent’s color: it means the parent pointer and its color are stored in this field.
Read the __rb_parent
and __rb_color
macros above to see how the field is used. (__rb_parent
actually implies the bottom 2 bits are un-used, giving 4-byte alignment, but nothing seems to use the second bit either way.)
1