2

This is part of a code initializing a character driver. See how class_create function is used. The returned value dev_class is used for the device_create function in the next statement.

static struct class *dev_class;

static int __init chr_driver_init(void)
{
 ....(skip) ....
/* creating struct class */
if ((dev_class = class_create(THIS_MODULE, "axpu_class")) == NULL) {
    printk(KERN_INFO "cannot create the struct class...\n");
    goto r_class;
}

if ((device_create(dev_class, NULL, dev, NULL, "axpu_device")) == NULL) {
    printk(KERN_INFO "cannot create the device ..\n");
    goto r_device;
}

I thought this class_create is a function, but I just now found this class_create is defined like this : in linux-5.4.0/include/linux/device.h

/* This is a #define to keep the compiler from merging different
 * instances of the __key variable */
#define class_create(owner, name)       \
({                      \
    static struct lock_class_key __key; \
    __class_create(owner, name, &__key);    \
}) 

I checked the __class_create function returns struct class * type data. So if we replace the macro, the original calling code dev_class = class_create(THIS_MODULE, "axpu_class") becomes :

dev_class = ({
    static struct lock_class_key __key; \
    __class_create(THIS_MODULE, "axpu_class", &__key);
})

So, this means a block of codes enclosed by { and } returns the value that the last statement (or function) returns. I didn't know this type of operation. How is this done and what is the rule?

Chan Kim
  • 5,177
  • 12
  • 57
  • 112
  • It is a GNU extension, not standard C: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html – user17732522 Feb 28 '22 at 15:01
  • 1
    Overall, Linux kernel & drivers tend to be very badly written code, relying heavily on gcc non-standard extensions. It's not a place to go look for inspiration. – Lundin Feb 28 '22 at 15:12

0 Answers0