andersch.dev

<2024-06-08 Sat>
[ linux os ]

Linux

Linux is an open-source, Unix-like, POSIX-compliant kernel. The name Linux is also commonly used to describe operating systems that are based on the kernel.

container_of and __same_type macro

The macro container_of is used extensively (>20.000 times) in the Linux kernel to get a pointer to the struct containing the given member.

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)((char *)__mptr - offsetof(type,member));})

It uses the GNU C extension of statement expressions.

It is used to enable the functionality of various datastructures (e.g. lists and queues) without wrapping the type into them (as would be done in C++ using templates, e.g. std::list<MyType>)

Since Linux has moved to use C11, the macro also includes a static_assert type check.

/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

/* new C11 version */
#define container_of(ptr, type, member) ({                        \
      void *__mptr = (void *)(ptr);                               \
      _Static_assert(__same_type(*(ptr), ((type *)0)->member) ||  \
              __same_type(*(ptr), void),                          \
              "pointer type mismatch in container_of()");         \
      ((type *)(__mptr - offsetof(type, member))); })

int main()
{
    const char  a;
    char   b;

    if   (__same_type(a,b)) { printf("yes\n"); }
    else                    { printf("no\n");  }
}

Resources