Open-Source Wikis

/

Linux

/

How to contribute

/

Patterns and conventions

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_CASE or kFooBar-style only in driver-specific code.
  • No typedefs for plain structs; keep struct foo visible.
  • 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/_release variants.
  • 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 volatile to "fix" a concurrency bug. Use the proper memory model.
  • Don't ignore checkpatch and sparse.
  • Don't break the user-space ABI.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Patterns and conventions – Linux wiki | Factory