Documentation: Add coding style
This is the old wiki page https://www.coreboot.org/Coding_Style coverted from mediawiki to markdown. Change-Id: Id56a8b7500121c4d9c18bc0b6bbc2c05402268dc Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/30834 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
parent
19f5201463
commit
a35904b29c
|
@ -0,0 +1,938 @@
|
||||||
|
# Coding Style
|
||||||
|
|
||||||
|
This is a short document describing the preferred coding style for the
|
||||||
|
coreboot project. It is in many ways exactly the same as the Linux
|
||||||
|
kernel coding style. In fact, most of this document has been copied from
|
||||||
|
the [Linux kernel coding style](http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/Documentation/CodingStyle?id=HEAD)
|
||||||
|
|
||||||
|
Please at least consider the points made here.
|
||||||
|
|
||||||
|
First off, I'd suggest printing out a copy of the GNU coding standards,
|
||||||
|
and NOT read it. Burn them, it's a great symbolic gesture.
|
||||||
|
|
||||||
|
Anyway, here goes:
|
||||||
|
|
||||||
|
## Indentation
|
||||||
|
|
||||||
|
Tabs are 8 characters, and thus indentations are also 8 characters.
|
||||||
|
There are heretic movements that try to make indentations 4 (or even 2!)
|
||||||
|
characters deep, and that is akin to trying to define the value of PI to
|
||||||
|
be 3.
|
||||||
|
|
||||||
|
Rationale: The whole idea behind indentation is to clearly define where
|
||||||
|
a block of control starts and ends. Especially when you've been looking
|
||||||
|
at your screen for 20 straight hours, you'll find it a lot easier to
|
||||||
|
see how the indentation works if you have large indentations.
|
||||||
|
|
||||||
|
Now, some people will claim that having 8-character indentations makes
|
||||||
|
the code move too far to the right, and makes it hard to read on a
|
||||||
|
80-character terminal screen. The answer to that is that if you need
|
||||||
|
more than 3 levels of indentation, you're screwed anyway, and should
|
||||||
|
fix your program.
|
||||||
|
|
||||||
|
In short, 8-char indents make things easier to read, and have the added
|
||||||
|
benefit of warning you when you're nesting your functions too deep.
|
||||||
|
Heed that warning.
|
||||||
|
|
||||||
|
The preferred way to ease multiple indentation levels in a switch
|
||||||
|
statement is to align the "switch" and its subordinate "case" labels
|
||||||
|
in the same column instead of "double-indenting" the "case" labels.
|
||||||
|
E.g.:
|
||||||
|
|
||||||
|
```c
|
||||||
|
switch (suffix) {
|
||||||
|
case 'G':
|
||||||
|
case 'g':
|
||||||
|
mem <<= 30;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
case 'm':
|
||||||
|
mem <<= 20;
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
case 'k':
|
||||||
|
mem <<= 10;
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't put multiple statements on a single line unless you have
|
||||||
|
something to hide:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (condition) do_this;
|
||||||
|
do_something_everytime;
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't put multiple assignments on a single line either. Kernel coding
|
||||||
|
style is super simple. Avoid tricky expressions.
|
||||||
|
|
||||||
|
Outside of comments, documentation and except in Kconfig, spaces are
|
||||||
|
never used for indentation, and the above example is deliberately
|
||||||
|
broken.
|
||||||
|
|
||||||
|
Get a decent editor and don't leave whitespace at the end of lines.
|
||||||
|
|
||||||
|
## Breaking long lines and strings
|
||||||
|
|
||||||
|
Coding style is all about readability and maintainability using commonly
|
||||||
|
available tools.
|
||||||
|
|
||||||
|
The limit on the length of lines is 80 columns and this is a strongly
|
||||||
|
preferred limit.
|
||||||
|
|
||||||
|
Statements longer than 80 columns will be broken into sensible chunks,
|
||||||
|
unless exceeding 80 columns significantly increases readability and does
|
||||||
|
not hide information. Descendants are always substantially shorter than
|
||||||
|
the parent and are placed substantially to the right. The same applies
|
||||||
|
to function headers with a long argument list. However, never break
|
||||||
|
user-visible strings such as printk messages, because that breaks the
|
||||||
|
ability to grep for them.
|
||||||
|
|
||||||
|
## Placing Braces and Spaces
|
||||||
|
|
||||||
|
The other issue that always comes up in C styling is the placement of
|
||||||
|
braces. Unlike the indent size, there are few technical reasons to
|
||||||
|
choose one placement strategy over the other, but the preferred way, as
|
||||||
|
shown to us by the prophets Kernighan and Ritchie, is to put the opening
|
||||||
|
brace last on the line, and put the closing brace first, thusly:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (x is true) {
|
||||||
|
we do y
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This applies to all non-function statement blocks (if, switch, for,
|
||||||
|
while, do). E.g.:
|
||||||
|
|
||||||
|
```c
|
||||||
|
switch (action) {
|
||||||
|
case KOBJ_ADD:
|
||||||
|
return "add";
|
||||||
|
case KOBJ_REMOVE:
|
||||||
|
return "remove";
|
||||||
|
case KOBJ_CHANGE:
|
||||||
|
return "change";
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
However, there is one special case, namely functions: they have the
|
||||||
|
opening brace at the beginning of the next line, thus:
|
||||||
|
|
||||||
|
```c
|
||||||
|
int function(int x)
|
||||||
|
{
|
||||||
|
body of function
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Heretic people all over the world have claimed that this inconsistency
|
||||||
|
is ... well ... inconsistent, but all right-thinking people know that
|
||||||
|
(a) K&R are _right_ and (b) K&R are right. Besides, functions are
|
||||||
|
special anyway (you can't nest them in C).
|
||||||
|
|
||||||
|
Note that the closing brace is empty on a line of its own, _except_ in
|
||||||
|
the cases where it is followed by a continuation of the same statement,
|
||||||
|
ie a "while" in a do-statement or an "else" in an if-statement, like
|
||||||
|
this:
|
||||||
|
|
||||||
|
```c
|
||||||
|
do {
|
||||||
|
body of do-loop
|
||||||
|
} while (condition);
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (x == y) {
|
||||||
|
..
|
||||||
|
} else if (x > y) {
|
||||||
|
...
|
||||||
|
} else {
|
||||||
|
....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rationale: K&R.
|
||||||
|
|
||||||
|
Also, note that this brace-placement also minimizes the number of empty
|
||||||
|
(or almost empty) lines, without any loss of readability. Thus, as the
|
||||||
|
supply of new-lines on your screen is not a renewable resource (think
|
||||||
|
25-line terminal screens here), you have more empty lines to put
|
||||||
|
comments on.
|
||||||
|
|
||||||
|
Do not unnecessarily use braces where a single statement will do.
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (condition)
|
||||||
|
action();
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (condition)
|
||||||
|
do_this();
|
||||||
|
else
|
||||||
|
do_that();
|
||||||
|
```
|
||||||
|
|
||||||
|
This does not apply if only one branch of a conditional statement is a
|
||||||
|
single statement; in the latter case use braces in both branches:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (condition) {
|
||||||
|
do_this();
|
||||||
|
do_that();
|
||||||
|
} else {
|
||||||
|
otherwise();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Spaces
|
||||||
|
|
||||||
|
Linux kernel style for use of spaces depends (mostly) on
|
||||||
|
function-versus-keyword usage. Use a space after (most) keywords. The
|
||||||
|
notable exceptions are sizeof, typeof, alignof, and __attribute__,
|
||||||
|
which look somewhat like functions (and are usually used with
|
||||||
|
parentheses in Linux, although they are not required in the language, as
|
||||||
|
in: "sizeof info" after "struct fileinfo info;" is declared).
|
||||||
|
|
||||||
|
So use a space after these keywords:
|
||||||
|
|
||||||
|
```
|
||||||
|
if, switch, case, for, do, while
|
||||||
|
```
|
||||||
|
|
||||||
|
but not with sizeof, typeof, alignof, or __attribute__. E.g.,
|
||||||
|
|
||||||
|
```c
|
||||||
|
s = sizeof(struct file);
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not add spaces around (inside) parenthesized expressions. This
|
||||||
|
example is
|
||||||
|
|
||||||
|
- bad*:
|
||||||
|
|
||||||
|
```c
|
||||||
|
s = sizeof( struct file );
|
||||||
|
```
|
||||||
|
|
||||||
|
When declaring pointer data or a function that returns a pointer type,
|
||||||
|
the preferred use of '*' is adjacent to the data name or function
|
||||||
|
name and not adjacent to the type name. Examples:
|
||||||
|
|
||||||
|
```c
|
||||||
|
char *linux_banner;
|
||||||
|
unsigned long long memparse(char *ptr, char **retptr);
|
||||||
|
char *match_strdup(substring_t *s);
|
||||||
|
```
|
||||||
|
|
||||||
|
Use one space around (on each side of) most binary and ternary
|
||||||
|
operators, such as any of these:
|
||||||
|
|
||||||
|
```
|
||||||
|
= + - < > * / % | & ^ <= >= == != ? :
|
||||||
|
```
|
||||||
|
|
||||||
|
but no space after unary operators:
|
||||||
|
|
||||||
|
```
|
||||||
|
& * + - ~ ! sizeof typeof alignof __attribute__ defined
|
||||||
|
```
|
||||||
|
|
||||||
|
no space before the postfix increment & decrement unary operators:
|
||||||
|
|
||||||
|
```
|
||||||
|
++ --
|
||||||
|
```
|
||||||
|
|
||||||
|
no space after the prefix increment & decrement unary operators:
|
||||||
|
|
||||||
|
```
|
||||||
|
++ --
|
||||||
|
```
|
||||||
|
|
||||||
|
and no space around the '.' and "->" structure member operators.
|
||||||
|
|
||||||
|
Do not leave trailing whitespace at the ends of lines. Some editors with
|
||||||
|
"smart" indentation will insert whitespace at the beginning of new
|
||||||
|
lines as appropriate, so you can start typing the next line of code
|
||||||
|
right away. However, some such editors do not remove the whitespace if
|
||||||
|
you end up not putting a line of code there, such as if you leave a
|
||||||
|
blank line. As a result, you end up with lines containing trailing
|
||||||
|
whitespace.
|
||||||
|
|
||||||
|
Git will warn you about patches that introduce trailing whitespace, and
|
||||||
|
can optionally strip the trailing whitespace for you; however, if
|
||||||
|
applying a series of patches, this may make later patches in the series
|
||||||
|
fail by changing their context lines.
|
||||||
|
|
||||||
|
### Naming
|
||||||
|
|
||||||
|
C is a Spartan language, and so should your naming be. Unlike Modula-2
|
||||||
|
and Pascal programmers, C programmers do not use cute names like
|
||||||
|
ThisVariableIsATemporaryCounter. A C programmer would call that variable
|
||||||
|
"tmp", which is much easier to write, and not the least more difficult
|
||||||
|
to understand.
|
||||||
|
|
||||||
|
HOWEVER, while mixed-case names are frowned upon, descriptive names for
|
||||||
|
global variables are a must. To call a global function "foo" is a
|
||||||
|
shooting offense.
|
||||||
|
|
||||||
|
GLOBAL variables (to be used only if you _really_ need them) need to
|
||||||
|
have descriptive names, as do global functions. If you have a function
|
||||||
|
that counts the number of active users, you should call that
|
||||||
|
"count_active_users()" or similar, you should _not_ call it
|
||||||
|
"cntusr()".
|
||||||
|
|
||||||
|
Encoding the type of a function into the name (so-called Hungarian
|
||||||
|
notation) is brain damaged - the compiler knows the types anyway and can
|
||||||
|
check those, and it only confuses the programmer. No wonder MicroSoft
|
||||||
|
makes buggy programs.
|
||||||
|
|
||||||
|
LOCAL variable names should be short, and to the point. If you have some
|
||||||
|
random integer loop counter, it should probably be called "i". Calling
|
||||||
|
it "loop_counter" is non-productive, if there is no chance of it
|
||||||
|
being mis-understood. Similarly, "tmp" can be just about any type of
|
||||||
|
variable that is used to hold a temporary value.
|
||||||
|
|
||||||
|
If you are afraid to mix up your local variable names, you have another
|
||||||
|
problem, which is called the function-growth-hormone-imbalance syndrome.
|
||||||
|
See chapter 6 (Functions).
|
||||||
|
|
||||||
|
## Typedefs
|
||||||
|
|
||||||
|
Please don't use things like "vps_t".
|
||||||
|
|
||||||
|
It's a _mistake_ to use typedef for structures and pointers. When you
|
||||||
|
see a
|
||||||
|
|
||||||
|
```c
|
||||||
|
vps_t a;
|
||||||
|
```
|
||||||
|
|
||||||
|
in the source, what does it mean?
|
||||||
|
|
||||||
|
In contrast, if it says
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct virtual_container *a;
|
||||||
|
```
|
||||||
|
|
||||||
|
you can actually tell what "a" is.
|
||||||
|
|
||||||
|
Lots of people think that typedefs "help readability". Not so. They
|
||||||
|
are useful only for:
|
||||||
|
|
||||||
|
(a) totally opaque objects (where the typedef is actively used to
|
||||||
|
_hide_ what the object is).
|
||||||
|
|
||||||
|
Example: "pte_t" etc. opaque objects that you can only access using
|
||||||
|
the proper accessor functions.
|
||||||
|
|
||||||
|
NOTE! Opaqueness and "accessor functions" are not good in themselves.
|
||||||
|
The reason we have them for things like pte_t etc. is that there really
|
||||||
|
is absolutely _zero_ portably accessible information there.
|
||||||
|
|
||||||
|
(b) Clear integer types, where the abstraction _helps_ avoid confusion
|
||||||
|
whether it is "int" or "long".
|
||||||
|
|
||||||
|
u8/u16/u32 are perfectly fine typedefs, although they fit into category
|
||||||
|
(d) better than here.
|
||||||
|
|
||||||
|
NOTE! Again - there needs to be a _reason_ for this. If something is
|
||||||
|
"unsigned long", then there's no reason to do
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef unsigned long myflags_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
but if there is a clear reason for why it under certain circumstances
|
||||||
|
might be an "unsigned int" and under other configurations might be
|
||||||
|
"unsigned long", then by all means go ahead and use a typedef.
|
||||||
|
|
||||||
|
(c) when you use sparse to literally create a _new_ type for
|
||||||
|
type-checking.
|
||||||
|
|
||||||
|
(d) New types which are identical to standard C99 types, in certain
|
||||||
|
exceptional circumstances.
|
||||||
|
|
||||||
|
Although it would only take a short amount of time for the eyes and
|
||||||
|
brain to become accustomed to the standard types like 'uint32_t',
|
||||||
|
some people object to their use anyway.
|
||||||
|
|
||||||
|
Therefore, the Linux-specific 'u8/u16/u32/u64' types and their signed
|
||||||
|
equivalents which are identical to standard types are permitted --
|
||||||
|
although they are not mandatory in new code of your own.
|
||||||
|
|
||||||
|
When editing existing code which already uses one or the other set of
|
||||||
|
types, you should conform to the existing choices in that code.
|
||||||
|
|
||||||
|
(e) Types safe for use in userspace.
|
||||||
|
|
||||||
|
In certain structures which are visible to userspace, we cannot require
|
||||||
|
C99 types and cannot use the 'u32' form above. Thus, we use __u32
|
||||||
|
and similar types in all structures which are shared with userspace.
|
||||||
|
|
||||||
|
Maybe there are other cases too, but the rule should basically be to
|
||||||
|
NEVER EVER use a typedef unless you can clearly match one of those
|
||||||
|
rules.
|
||||||
|
|
||||||
|
In general, a pointer, or a struct that has elements that can reasonably
|
||||||
|
be directly accessed should _never_ be a typedef.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
Functions should be short and sweet, and do just one thing. They should
|
||||||
|
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
|
||||||
|
as we all know), and do one thing and do that well.
|
||||||
|
|
||||||
|
The maximum length of a function is inversely proportional to the
|
||||||
|
complexity and indentation level of that function. So, if you have a
|
||||||
|
conceptually simple function that is just one long (but simple)
|
||||||
|
case-statement, where you have to do lots of small things for a lot of
|
||||||
|
different cases, it's OK to have a longer function.
|
||||||
|
|
||||||
|
However, if you have a complex function, and you suspect that a
|
||||||
|
less-than-gifted first-year high-school student might not even
|
||||||
|
understand what the function is all about, you should adhere to the
|
||||||
|
maximum limits all the more closely. Use helper functions with
|
||||||
|
descriptive names (you can ask the compiler to in-line them if you think
|
||||||
|
it's performance-critical, and it will probably do a better job of it
|
||||||
|
than you would have done).
|
||||||
|
|
||||||
|
Another measure of the function is the number of local variables. They
|
||||||
|
shouldn't exceed 5-10, or you're doing something wrong. Re-think the
|
||||||
|
function, and split it into smaller pieces. A human brain can generally
|
||||||
|
easily keep track of about 7 different things, anything more and it gets
|
||||||
|
confused. You know you're brilliant, but maybe you'd like to
|
||||||
|
understand what you did 2 weeks from now.
|
||||||
|
|
||||||
|
In source files, separate functions with one blank line. If the function
|
||||||
|
is exported, the EXPORT* macro for it should follow immediately after
|
||||||
|
the closing function brace line. E.g.:
|
||||||
|
|
||||||
|
```c
|
||||||
|
int system_is_up(void)
|
||||||
|
{
|
||||||
|
return system_state == SYSTEM_RUNNING;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(system_is_up);
|
||||||
|
```
|
||||||
|
|
||||||
|
In function prototypes, include parameter names with their data types.
|
||||||
|
Although this is not required by the C language, it is preferred in
|
||||||
|
Linux because it is a simple way to add valuable information for the
|
||||||
|
reader.
|
||||||
|
|
||||||
|
## Centralized exiting of functions
|
||||||
|
|
||||||
|
Albeit deprecated by some people, the equivalent of the goto statement
|
||||||
|
is used frequently by compilers in form of the unconditional jump
|
||||||
|
instruction.
|
||||||
|
|
||||||
|
The goto statement comes in handy when a function exits from multiple
|
||||||
|
locations and some common work such as cleanup has to be done. If there
|
||||||
|
is no cleanup needed then just return directly.
|
||||||
|
|
||||||
|
The rationale is:
|
||||||
|
|
||||||
|
- unconditional statements are easier to understand and follow
|
||||||
|
- nesting is reduced
|
||||||
|
- errors by not updating individual exit points when making
|
||||||
|
modifications are prevented
|
||||||
|
- saves the compiler work to optimize redundant code away ;)
|
||||||
|
|
||||||
|
```c
|
||||||
|
int fun(int a)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
char *buffer = kmalloc(SIZE);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (condition1) {
|
||||||
|
while (loop1) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
result = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
...
|
||||||
|
out:
|
||||||
|
kfree(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commenting
|
||||||
|
|
||||||
|
Comments are good, but there is also a danger of over-commenting. NEVER
|
||||||
|
try to explain HOW your code works in a comment: it's much better to
|
||||||
|
write the code so that the _working_ is obvious, and it's a waste of
|
||||||
|
time to explain badly written code.
|
||||||
|
|
||||||
|
Generally, you want your comments to tell WHAT your code does, not HOW.
|
||||||
|
Also, try to avoid putting comments inside a function body: if the
|
||||||
|
function is so complex that you need to separately comment parts of it,
|
||||||
|
you should probably go back to chapter 6 for a while. You can make small
|
||||||
|
comments to note or warn about something particularly clever (or ugly),
|
||||||
|
but try to avoid excess. Instead, put the comments at the head of the
|
||||||
|
function, telling people what it does, and possibly WHY it does it.
|
||||||
|
|
||||||
|
When commenting the kernel API functions, please use the kernel-doc
|
||||||
|
format. See the files Documentation/kernel-doc-nano-HOWTO.txt and
|
||||||
|
scripts/kernel-doc for details.
|
||||||
|
|
||||||
|
coreboot style for comments is the C89 "/* ... */" style. You may
|
||||||
|
use C99-style "// ..." comments.
|
||||||
|
|
||||||
|
The preferred style for *short* (multi-line) comments is:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* This is the preferred style for short multi-line
|
||||||
|
comments in the Linux kernel source code.
|
||||||
|
Please use it consistently. */
|
||||||
|
```
|
||||||
|
|
||||||
|
The preferred style for *long* (multi-line) comments is:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/*
|
||||||
|
* This is the preferred style for multi-line
|
||||||
|
* comments in the Linux kernel source code.
|
||||||
|
* Please use it consistently.
|
||||||
|
*
|
||||||
|
* Description: A column of asterisks on the left side,
|
||||||
|
* with beginning and ending almost-blank lines.
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also important to comment data, whether they are basic types or
|
||||||
|
derived types. To this end, use just one data declaration per line (no
|
||||||
|
commas for multiple data declarations). This leaves you room for a small
|
||||||
|
comment on each item, explaining its use.
|
||||||
|
|
||||||
|
## You've made a mess of it
|
||||||
|
That's OK, we all do. You've probably been told by your long-time Unix user
|
||||||
|
helper that "GNU emacs" automatically formats the C sources for you, and
|
||||||
|
you've noticed that yes, it does do that, but the defaults it uses are less
|
||||||
|
than desirable (in fact, they are worse than random typing - an infinite
|
||||||
|
number of monkeys typing into GNU emacs would never make a good program).
|
||||||
|
|
||||||
|
So, you can either get rid of GNU emacs, or change it to use saner values.
|
||||||
|
To do the latter, you can stick the following in your .emacs file:
|
||||||
|
|
||||||
|
```lisp
|
||||||
|
(defun c-lineup-arglist-tabs-only (ignored)
|
||||||
|
"Line up argument lists by tabs, not spaces"
|
||||||
|
(let* ((anchor (c-langelem-pos c-syntactic-element))
|
||||||
|
(column (c-langelem-2nd-pos c-syntactic-element))
|
||||||
|
(offset (- (1+ column) anchor))
|
||||||
|
(steps (floor offset c-basic-offset)))
|
||||||
|
(* (max steps 1)
|
||||||
|
c-basic-offset)))
|
||||||
|
|
||||||
|
(add-hook 'c-mode-common-hook
|
||||||
|
(lambda ()
|
||||||
|
;; Add kernel style
|
||||||
|
(c-add-style
|
||||||
|
"linux-tabs-only"
|
||||||
|
'("linux" (c-offsets-alist
|
||||||
|
(arglist-cont-nonempty
|
||||||
|
c-lineup-gcc-asm-reg
|
||||||
|
c-lineup-arglist-tabs-only))))))
|
||||||
|
|
||||||
|
(add-hook 'c-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(let ((filename (buffer-file-name)))
|
||||||
|
;; Enable kernel mode for the appropriate files
|
||||||
|
(when (and filename
|
||||||
|
(string-match (expand-file-name "~/src/linux-trees")
|
||||||
|
filename))
|
||||||
|
(setq indent-tabs-mode t)
|
||||||
|
(c-set-style "linux-tabs-only")))))
|
||||||
|
```
|
||||||
|
|
||||||
|
This will make emacs go better with the kernel coding style for C files
|
||||||
|
below ~/src/linux-trees.
|
||||||
|
|
||||||
|
But even if you fail in getting emacs to do sane formatting, not
|
||||||
|
everything is lost: use "indent".
|
||||||
|
|
||||||
|
Now, again, GNU indent has the same brain-dead settings that GNU emacs
|
||||||
|
has, which is why you need to give it a few command line options.
|
||||||
|
However, that's not too bad, because even the makers of GNU indent
|
||||||
|
recognize the authority of K&R (the GNU people aren't evil, they are
|
||||||
|
just severely misguided in this matter), so you just give indent the
|
||||||
|
options "-kr -i8" (stands for "K&R, 8 character indents"), or use
|
||||||
|
"scripts/Lindent", which indents in the latest style.
|
||||||
|
|
||||||
|
"indent" has a lot of options, and especially when it comes to comment
|
||||||
|
re-formatting you may want to take a look at the man page. But remember:
|
||||||
|
"indent" is not a fix for bad programming.
|
||||||
|
|
||||||
|
## Kconfig configuration files
|
||||||
|
|
||||||
|
For all of the Kconfig* configuration files throughout the source tree,
|
||||||
|
the indentation is somewhat different. Lines under a "config"
|
||||||
|
definition are indented with one tab, while help text is indented an
|
||||||
|
additional two spaces. Example:
|
||||||
|
|
||||||
|
```kconfig
|
||||||
|
config AUDIT
|
||||||
|
bool "Auditing support"
|
||||||
|
depends on NET
|
||||||
|
help
|
||||||
|
Enable auditing infrastructure that can be used with another
|
||||||
|
kernel subsystem, such as SELinux (which requires this for
|
||||||
|
logging of avc messages output). Does not do system-call
|
||||||
|
auditing without CONFIG_AUDITSYSCALL.
|
||||||
|
```
|
||||||
|
|
||||||
|
Seriously dangerous features (such as write support for certain
|
||||||
|
filesystems) should advertise this prominently in their prompt string:
|
||||||
|
|
||||||
|
```kconfig
|
||||||
|
config ADFS_FS_RW
|
||||||
|
bool "ADFS write support (DANGEROUS)"
|
||||||
|
depends on ADFS_FS
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
For full documentation on the configuration files, see the file
|
||||||
|
Documentation/kbuild/kconfig-language.txt.
|
||||||
|
|
||||||
|
Data structures
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Data structures that have visibility outside the single-threaded
|
||||||
|
environment they are created and destroyed in should always have
|
||||||
|
reference counts. In the kernel, garbage collection doesn't exist (and
|
||||||
|
outside the kernel garbage collection is slow and inefficient), which
|
||||||
|
means that you absolutely _have_ to reference count all your uses.
|
||||||
|
|
||||||
|
Reference counting means that you can avoid locking, and allows multiple
|
||||||
|
users to have access to the data structure in parallel - and not having
|
||||||
|
to worry about the structure suddenly going away from under them just
|
||||||
|
because they slept or did something else for a while.
|
||||||
|
|
||||||
|
Note that locking is _not_ a replacement for reference counting.
|
||||||
|
Locking is used to keep data structures coherent, while reference
|
||||||
|
counting is a memory management technique. Usually both are needed, and
|
||||||
|
they are not to be confused with each other.
|
||||||
|
|
||||||
|
Many data structures can indeed have two levels of reference counting,
|
||||||
|
when there are users of different "classes". The subclass count counts
|
||||||
|
the number of subclass users, and decrements the global count just once
|
||||||
|
when the subclass count goes to zero.
|
||||||
|
|
||||||
|
Examples of this kind of "multi-level-reference-counting" can be found
|
||||||
|
in memory management ("struct mm_struct": mm_users and mm_count),
|
||||||
|
and in filesystem code ("struct super_block": s_count and
|
||||||
|
s_active).
|
||||||
|
|
||||||
|
Remember: if another thread can find your data structure, and you don't
|
||||||
|
have a reference count on it, you almost certainly have a bug.
|
||||||
|
|
||||||
|
Macros, Enums and RTL
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Names of macros defining constants and labels in enums are capitalized.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define CONSTANT 0x12345
|
||||||
|
```
|
||||||
|
|
||||||
|
Enums are preferred when defining several related constants.
|
||||||
|
|
||||||
|
CAPITALIZED macro names are appreciated but macros resembling functions
|
||||||
|
may be named in lower case.
|
||||||
|
|
||||||
|
Generally, inline functions are preferable to macros resembling
|
||||||
|
functions.
|
||||||
|
|
||||||
|
Macros with multiple statements should be enclosed in a do - while
|
||||||
|
block:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define macrofun(a, b, c) \
|
||||||
|
do { \
|
||||||
|
if (a == 5) \
|
||||||
|
do_this(b, c); \
|
||||||
|
} while (0)
|
||||||
|
```
|
||||||
|
|
||||||
|
Things to avoid when using macros:
|
||||||
|
|
||||||
|
1) macros that affect control flow:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define FOO(x) \
|
||||||
|
do { \
|
||||||
|
if (blah(x) < 0) \
|
||||||
|
return -EBUGGERED; \
|
||||||
|
} while(0)
|
||||||
|
```
|
||||||
|
|
||||||
|
is a *very* bad idea. It looks like a function call but exits the
|
||||||
|
"calling" function; don't break the internal parsers of those who
|
||||||
|
will read the code.
|
||||||
|
|
||||||
|
2) macros that depend on having a local variable with a magic name:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define FOO(val) bar(index, val)
|
||||||
|
```
|
||||||
|
|
||||||
|
might look like a good thing, but it's confusing as hell when one reads
|
||||||
|
the code and it's prone to breakage from seemingly innocent changes.
|
||||||
|
|
||||||
|
3) macros with arguments that are used as l-values: FOO(x) = y; will
|
||||||
|
bite you if somebody e.g. turns FOO into an inline function.
|
||||||
|
|
||||||
|
4) forgetting about precedence: macros defining constants using
|
||||||
|
expressions must enclose the expression in parentheses. Beware of
|
||||||
|
similar issues with macros using parameters.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define CONSTANT 0x4000
|
||||||
|
#define CONSTEXP (CONSTANT | 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
The cpp manual deals with macros exhaustively. The gcc internals manual
|
||||||
|
also covers RTL which is used frequently with assembly language in the
|
||||||
|
kernel.
|
||||||
|
|
||||||
|
Printing kernel messages
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Kernel developers like to be seen as literate. Do mind the spelling of
|
||||||
|
kernel messages to make a good impression. Do not use crippled words
|
||||||
|
like "dont"; use "do not" or "don't" instead. Make the messages
|
||||||
|
concise, clear, and unambiguous.
|
||||||
|
|
||||||
|
Kernel messages do not have to be terminated with a period.
|
||||||
|
|
||||||
|
Printing numbers in parentheses (%d) adds no value and should be
|
||||||
|
avoided.
|
||||||
|
|
||||||
|
There are a number of driver model diagnostic macros in
|
||||||
|
<linux/device.h> which you should use to make sure messages are
|
||||||
|
matched to the right device and driver, and are tagged with the right
|
||||||
|
level: dev_err(), dev_warn(), dev_info(), and so forth. For messages
|
||||||
|
that aren't associated with a particular device, <linux/printk.h>
|
||||||
|
defines pr_debug() and pr_info().
|
||||||
|
|
||||||
|
Coming up with good debugging messages can be quite a challenge; and
|
||||||
|
once you have them, they can be a huge help for remote troubleshooting.
|
||||||
|
Such messages should be compiled out when the DEBUG symbol is not
|
||||||
|
defined (that is, by default they are not included). When you use
|
||||||
|
dev_dbg() or pr_debug(), that's automatic. Many subsystems have
|
||||||
|
Kconfig options to turn on -DDEBUG. A related convention uses
|
||||||
|
VERBOSE_DEBUG to add dev_vdbg() messages to the ones already enabled
|
||||||
|
by DEBUG.
|
||||||
|
|
||||||
|
Allocating memory
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
coreboot provides a single general purpose memory allocator: malloc()
|
||||||
|
|
||||||
|
The preferred form for passing a size of a struct is the following:
|
||||||
|
|
||||||
|
```c
|
||||||
|
p = malloc(sizeof(*p));
|
||||||
|
```
|
||||||
|
|
||||||
|
The alternative form where struct name is spelled out hurts readability
|
||||||
|
and introduces an opportunity for a bug when the pointer variable type
|
||||||
|
is changed but the corresponding sizeof that is passed to a memory
|
||||||
|
allocator is not.
|
||||||
|
|
||||||
|
Casting the return value which is a void pointer is redundant. The
|
||||||
|
conversion from void pointer to any other pointer type is guaranteed by
|
||||||
|
the C programming language.
|
||||||
|
|
||||||
|
You should contain your memory usage to stack variables whenever
|
||||||
|
possible. Only use malloc() as a last resort. In ramstage, you may also
|
||||||
|
be able to get away with using static variables. Never use malloc()
|
||||||
|
outside of ramstage.
|
||||||
|
|
||||||
|
Since coreboot only runs for a very short time, there is no memory
|
||||||
|
deallocator, although a corresponding free() is offered. It is a no-op.
|
||||||
|
Use of free() is not required though it is accepted. It is useful when
|
||||||
|
sharing code with other codebases that make use of free().
|
||||||
|
|
||||||
|
The inline disease
|
||||||
|
------------------
|
||||||
|
|
||||||
|
There appears to be a common misperception that gcc has a magic "make
|
||||||
|
me faster" speedup option called "inline". While the use of inlines
|
||||||
|
can be appropriate (for example as a means of replacing macros, see
|
||||||
|
Chapter 12), it very often is not. Abundant use of the inline keyword
|
||||||
|
leads to a much bigger kernel, which in turn slows the system as a whole
|
||||||
|
down, due to a bigger icache footprint for the CPU and simply because
|
||||||
|
there is less memory available for the pagecache. Just think about it; a
|
||||||
|
pagecache miss causes a disk seek, which easily takes 5 milliseconds.
|
||||||
|
There are a LOT of cpu cycles that can go into these 5 milliseconds.
|
||||||
|
|
||||||
|
A reasonable rule of thumb is to not put inline at functions that have
|
||||||
|
more than 3 lines of code in them. An exception to this rule are the
|
||||||
|
cases where a parameter is known to be a compiletime constant, and as a
|
||||||
|
result of this constantness you *know* the compiler will be able to
|
||||||
|
optimize most of your function away at compile time. For a good example
|
||||||
|
of this later case, see the kmalloc() inline function.
|
||||||
|
|
||||||
|
Often people argue that adding inline to functions that are static and
|
||||||
|
used only once is always a win since there is no space tradeoff. While
|
||||||
|
this is technically correct, gcc is capable of inlining these
|
||||||
|
automatically without help, and the maintenance issue of removing the
|
||||||
|
inline when a second user appears outweighs the potential value of the
|
||||||
|
hint that tells gcc to do something it would have done anyway.
|
||||||
|
|
||||||
|
Function return values and names
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Functions can return values of many different kinds, and one of the most
|
||||||
|
common is a value indicating whether the function succeeded or failed.
|
||||||
|
Such a value can be represented as an error-code integer (-Exxx =
|
||||||
|
failure, 0 = success) or a "succeeded" boolean (0 = failure, non-zero
|
||||||
|
= success).
|
||||||
|
|
||||||
|
Mixing up these two sorts of representations is a fertile source of
|
||||||
|
difficult-to-find bugs. If the C language included a strong distinction
|
||||||
|
between integers and booleans then the compiler would find these
|
||||||
|
mistakes for us... but it doesn't. To help prevent such bugs, always
|
||||||
|
follow this convention:
|
||||||
|
|
||||||
|
If the name of a function is an action or an imperative command,
|
||||||
|
the function should return an error-code integer. If the name
|
||||||
|
is a predicate, the function should return a "succeeded" boolean.
|
||||||
|
|
||||||
|
For example, "add work" is a command, and the add_work() function
|
||||||
|
returns 0 for success or -EBUSY for failure. In the same way, "PCI
|
||||||
|
device present" is a predicate, and the pci_dev_present() function
|
||||||
|
returns 1 if it succeeds in finding a matching device or 0 if it
|
||||||
|
doesn't.
|
||||||
|
|
||||||
|
All EXPORTed functions must respect this convention, and so should all
|
||||||
|
public functions. Private (static) functions need not, but it is
|
||||||
|
recommended that they do.
|
||||||
|
|
||||||
|
Functions whose return value is the actual result of a computation,
|
||||||
|
rather than an indication of whether the computation succeeded, are not
|
||||||
|
subject to this rule. Generally they indicate failure by returning some
|
||||||
|
out-of-range result. Typical examples would be functions that return
|
||||||
|
pointers; they use NULL or the ERR_PTR mechanism to report failure.
|
||||||
|
|
||||||
|
Don't re-invent the kernel macros
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
The header file include/linux/kernel.h contains a number of macros that
|
||||||
|
you should use, rather than explicitly coding some variant of them
|
||||||
|
yourself. For example, if you need to calculate the length of an array,
|
||||||
|
take advantage of the macro
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
```
|
||||||
|
|
||||||
|
There are also min() and max() macros that do strict type checking if
|
||||||
|
you need them. Feel free to peruse that header file to see what else is
|
||||||
|
already defined that you shouldn't reproduce in your code.
|
||||||
|
|
||||||
|
Editor modelines and other cruft
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Some editors can interpret configuration information embedded in source
|
||||||
|
files, indicated with special markers. For example, emacs interprets
|
||||||
|
lines marked like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
-*- mode: c -*-
|
||||||
|
```
|
||||||
|
|
||||||
|
Or like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
|
||||||
|
End:
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
Vim interprets markers that look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
/* vim:set sw=8 noet */
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not include any of these in source files. People have their own
|
||||||
|
personal editor configurations, and your source files should not
|
||||||
|
override them. This includes markers for indentation and mode
|
||||||
|
configuration. People may use their own custom mode, or may have some
|
||||||
|
other magic method for making indentation work correctly.
|
||||||
|
|
||||||
|
Inline assembly
|
||||||
|
---------------
|
||||||
|
|
||||||
|
In architecture-specific code, you may need to use inline assembly to
|
||||||
|
interface with CPU or platform functionality. Don't hesitate to do so
|
||||||
|
when necessary. However, don't use inline assembly gratuitously when C
|
||||||
|
can do the job. You can and should poke hardware from C when possible.
|
||||||
|
|
||||||
|
Consider writing simple helper functions that wrap common bits of inline
|
||||||
|
assembly, rather than repeatedly writing them with slight variations.
|
||||||
|
Remember that inline assembly can use C parameters.
|
||||||
|
|
||||||
|
Large, non-trivial assembly functions should go in .S files, with
|
||||||
|
corresponding C prototypes defined in C header files. The C prototypes
|
||||||
|
for assembly functions should use "asmlinkage".
|
||||||
|
|
||||||
|
You may need to mark your asm statement as volatile, to prevent GCC from
|
||||||
|
removing it if GCC doesn't notice any side effects. You don't always
|
||||||
|
need to do so, though, and doing so unnecessarily can limit
|
||||||
|
optimization.
|
||||||
|
|
||||||
|
When writing a single inline assembly statement containing multiple
|
||||||
|
instructions, put each instruction on a separate line in a separate
|
||||||
|
quoted string, and end each string except the last with nt to
|
||||||
|
properly indent the next instruction in the assembly output:
|
||||||
|
|
||||||
|
```c
|
||||||
|
asm ("magic %reg1, #42nt"
|
||||||
|
"more_magic %reg2, %reg3"
|
||||||
|
: /* outputs */ : /* inputs */ : /* clobbers */);
|
||||||
|
```
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
|
||||||
|
The C Programming Language, Second Edition by Brian W. Kernighan and
|
||||||
|
Dennis M. Ritchie. Prentice Hall, Inc., 1988. ISBN 0-13-110362-8
|
||||||
|
(paperback), 0-13-110370-9 (hardback). URL:
|
||||||
|
<http://cm.bell-labs.com/cm/cs/cbook/>
|
||||||
|
|
||||||
|
The Practice of Programming by Brian W. Kernighan and Rob Pike.
|
||||||
|
Addison-Wesley, Inc., 1999. ISBN 0-201-61586-X. URL:
|
||||||
|
<http://cm.bell-labs.com/cm/cs/tpop/>
|
||||||
|
|
||||||
|
GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
|
||||||
|
gcc internals and indent, all available from
|
||||||
|
<http://www.gnu.org/manual/>
|
||||||
|
|
||||||
|
WG14 is the international standardization working group for the
|
||||||
|
programming language C, URL: <http://www.open-std.org/JTC1/SC22/WG14/>
|
||||||
|
|
||||||
|
Kernel CodingStyle, by greg@kroah.com at OLS 2002:
|
||||||
|
<http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/>
|
|
@ -9,6 +9,7 @@ Contents:
|
||||||
|
|
||||||
* [Getting Started](getting_started/index.md)
|
* [Getting Started](getting_started/index.md)
|
||||||
* [Rookie Guide](lessons/index.md)
|
* [Rookie Guide](lessons/index.md)
|
||||||
|
* [Coding Style](coding_style.md)
|
||||||
* [Code of Conduct](code_of_conduct.md)
|
* [Code of Conduct](code_of_conduct.md)
|
||||||
* [Timestamps](timestamp.md)
|
* [Timestamps](timestamp.md)
|
||||||
* [Intel IFD Binary Extraction](Binary_Extraction.md)
|
* [Intel IFD Binary Extraction](Binary_Extraction.md)
|
||||||
|
|
Loading…
Reference in New Issue