torvalds/linux
Patterns and conventions
The kernel has its own dialect of C, with strict and well-known idioms. New contributors get pushback faster on style than on substance. The canonical reference is Documentation/process/coding-style.rst. This page summarizes the most-used patterns.
Coding style
- Tabs for indentation, 8-column wide.
- Lines wrap at 80 columns softly — wider lines are accepted when wrapping hurts readability.
- Braces on the same line for control flow; on a new line for function definitions.
- One declaration per line. No multi-variable declarations.
- Lowercase, underscore-separated names. No CamelCase.
- Macros uppercase. Constants either
UPPER_CASEorkFooBar-style only in driver-specific code. - No typedefs for plain structs; keep
struct foovisible. - Avoid trailing whitespace. checkpatch will yell.
A canonical example of style and structure: mm/slab_common.c and fs/inode.c.
Error handling
The kernel uses goto for cleanup. A function that acquires N resources has N+1 labels at the bottom, each one undoing the corresponding resource:
int do_something(void)
{
int ret;
void *p1, *p2;
p1 = alloc_p1();
if (!p1)
return -ENOMEM;
p2 = alloc_p2();
if (!p2) {
ret = -ENOMEM;
goto err_p1;
}
ret = use(p1, p2);
if (ret)
goto err_p2;
return 0;
err_p2:
free_p2(p2);
err_p1:
free_p1(p1);
return ret;
}This is idiomatic and expected. Don't try to avoid goto; reviewers will ask you to use it.
Errors are negative errno values: -ENOMEM, -EINVAL, -EAGAIN, etc. See include/uapi/asm-generic/errno-base.h and errno.h.
ERR_PTR(), IS_ERR(), PTR_ERR() — encode an errno in a pointer return value. Used widely:
struct foo *foo_get(...)
{
if (bad)
return ERR_PTR(-EINVAL);
...
}
struct foo *f = foo_get(...);
if (IS_ERR(f))
return PTR_ERR(f);Memory allocation
kmalloc(size, GFP_KERNEL)— small (<= page) allocations.kzalloc(size, GFP_KERNEL)— zero-initialized.kvmalloc(size, GFP_KERNEL)— large allocations that may be physically discontiguous.vmalloc()— guaranteed virtually contiguous.kmem_cache_*— slab caches for repeatedly-allocated fixed-size objects.__GFP_NOWAIT,GFP_ATOMIC— don't sleep (e.g. interrupt context).GFP_NOIO,GFP_NOFS— used in storage / filesystem code paths to avoid recursion.
Always check the return for NULL. Always free in reverse order of allocation. The kfree counterpart of kmalloc/kzalloc/kvmalloc is kfree/kfree_sensitive/kvfree.
Locking
Pick the lightest lock that gives you the guarantees you need:
| Primitive | Use when |
|---|---|
RCU (rcu_read_lock/rcu_dereference/synchronize_rcu) |
Reads vastly outnumber writes; structures are linked together |
seqlock_t |
Simple data; readers can retry; few writers |
spinlock_t |
Short critical section; possibly IRQ context |
mutex |
Sleeping critical section; process context only |
rwlock_t / rw_semaphore |
Many readers; few writers; readers may sleep (semaphore) or not (rwlock) |
completion |
One-shot wait for an event |
Use *_irqsave/_irqrestore variants when the lock is taken from both process and interrupt contexts.
Annotate lock relationships with __must_hold(), __acquires(), __releases() so sparse can verify them.
Concurrency primitives
READ_ONCE()/WRITE_ONCE()— compiler barriers around a single load/store.smp_*barriers — explicit memory ordering.atomic_t,atomic64_t, and the_relaxed/_acquire/_releasevariants.cmpxchg()and friends.- Per-CPU variables and
this_cpu_*accessors.
Do not roll your own. Read Documentation/atomic_t.txt and Documentation/memory-barriers.txt.
Common helper macros
container_of(ptr, type, member)— get the struct from a pointer to one of its members. The single most-used macro in the kernel.ARRAY_SIZE(x)— element count of a stack array.min(),max(),clamp()— type-safe.BUILD_BUG_ON()— compile-time assertion.WARN_ON(),WARN_ON_ONCE()— runtime assertion that prints a backtrace but does not panic.BUG_ON()— panic. Use sparingly; many subsystems forbid it.unlikely(),likely()— branch prediction hints.
Annotations and attributes
__init— function discarded after boot. Save space.__exit— for module unload.__must_check— caller must use the return value.__user— pointer points into user space; sparse will warn if you deref it directly.__kernel,__iomem— address-space markers.noinline,__always_inline— control inlining.
Per-subsystem conventions
Most subsystems publish their own conventions in Documentation/. Examples:
Documentation/networking/netdev-FAQ.rst— networking patches.Documentation/process/submitting-drivers.rst— driver submissions.Documentation/filesystems/porting.rst— VFS API changes.Documentation/RCU/checklist.rst— RCU usage rules.
When in doubt, look at recent commits to the same file: git log -10 -- path/to/file.c. Match their style and trailers.
Don'ts
- Don't add new global variables without thinking through serialization.
- Don't add userspace-style abstractions (no inheritance trees, no smart pointers).
- Don't use floating point in the kernel (FP regs are not always saved on context switch).
- Don't use
volatileto "fix" a concurrency bug. Use the proper memory model. - Don't ignore checkpatch and sparse.
- Don't break the user-space ABI.
Related pages
- Development workflow — how to send the patch.
- Tooling — checkpatch and sparse.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.