Gcc core extension linuxforum

Source: Internet
Author: User
Article Title: gcc core extension linuxforum. Linux is a technology channel of the IT lab in China. Including desktop applications, Linux system management, kernel research, embedded systems, open source, and some other basic classification. gnc cc is a very powerful cross-platform C compiler, which provides a lot of extensions to the C language, these extensions provide strong support for optimization, target code layout, and more secure checks. In this article, the C language that supports GNU extension is called gnu c.

The Linux kernel code uses a lot of gnu c extensions, so that the only compiler that can compile the Linux kernel is gnu cc. In the past, it even occurred that the Linux kernel was compiled using a special gnu cc version. This article is a summary of the gnu c extension used by the Linux kernel. I hope you can find a preliminary answer from this article when you encounter unintelligible syntaxes and semantics when reading the kernel source code, for more information, see gcc.info. The example in this article is taken from Linux 2.4.18.

Statement expression

Gnu c regards compound statements contained in parentheses as an expression called a statement expression, which can appear in any allowed expression, you can use loops and local variables in statement expressions. Originally, they can only be used in compound statements. For example:

+++ Include/linux/kernel. h
159: # define min_t (type, x, y )\
160: ({type _ x = (x); type _ y = (y); _ x <_ y? _ X: _ y ;})
+++ Net/ipv4/tcp_output.c
654: int full_space = min_t (int, tp-> window_clamp, tcp_full_space (sk ));

The last statement of a compound statement should be an expression, and its value will be the value of this statement expression. A secure macro for minimum value is defined here. In Standard C, it is usually defined:

# Define min (x, y) (x) <(y )? (X): (y ))

This definition calculates x and y twice. When the parameter has side effects, incorrect results are generated. The statement expression is used to calculate the parameter only once, avoiding possible errors. Statement expressions are usually used for macro definition.


Typeof

To use the macro defined in the previous section, you need to know the parameter type. You can use typeof to define a more general macro without having to know the parameter type in advance. For example:

+++ Include/linux/kernel. h
141: # define min (x, y )({\
142: const typeof (x) _ x = (x );\
143: const typeof (y) _ y = (y );\
144: (void) (& _ x = & _ y );\
145: _ x <_ y? _ X: _ y ;})

Here, typeof (x) indicates the value type of x. Row 142nd defines a local Variable _ x with the same type as x and converts it to x, note that the function of row 144th is to check whether the x and y parameters are of the same type. Typeof can be used in any type and is usually used for macro definition.


Zero-length Array

Gnu c allows zero-length arrays. This feature is useful when defining the header structure of a variable-length object. For example:

+++ Include/linux/minix_fs.h
85: struct minix_dir_entry {
86: _ 2010inode;
87: char name [0];
88 :};

The last element of the structure is defined as a zero-length array, which does not occupy the space of the structure. In standard C, the length of the array must be defined as 1, and the calculation object size is complicated during allocation.


Variable Parameter macro

In gnu c, macros can accept variable parameters, just like functions, such:

+++ Include/linux/kernel. h
110: # define pr_debug (fmt, arg ...)\
111: printk (KERN_DEBUG fmt, # arg)

Here, arg indicates the remaining parameters, which can be zero or multiple. These parameters and the comma between them constitute the arg value, replacing arg during macro extension, for example:

Pr_debug ("% s: % d", filename, line)

Extended

Printk ("<7>" "% s: % d", filename, line)

The reason for using ## is that when processing arg does not match any parameter, the arg value is blank. In this case, the GNUC Preprocessor discards the comma before ##.

Pr_debug ("success! \ N ")

Extended

Printk ("<7>" success! \ N ")

Note that there is no comma at the end.


Label element

Standard C requires that the initial value of an array or structure variable must appear in a fixed order. In gnu c, the initialization value can appear in any order by specifying the index or structure domain name. The method for specifying an array INDEX is to write '[INDEX] =' before the initialization value. to specify a range, use the format of '[FIRST... LAST] ='. For example:

++ Arch/i386/kernel/irq. c
1079: static unsigned long irq_affinity [NR_IRQS] = {[0... NR_IRQS-1] = ~ 0UL };

Convert all elements of the array ~ 0UL, which can be seen as a shorthand form. To specify a structure element, write 'fieldname: 'before the element value. For example:

+++ Fs/ext2/file. c
41: struct file_operations ext2_file_operations = {
42: llseek: generic_file_llseek,
43: read: generic_file_read,
44: write: generic_file_write,
45: ioctl: ext2_ioctl,
46: mmap: generic_file_mmap,
47: open: generic_file_open,
48: release: ext2_release_file,
49: fsync: ext2_sync_file,
50 };

Initialize the element llseek of the structure ext2_file_operations to generic_file_llseek, the element read initializes genenric_file_read, and so on. I think this is one of the best features of the GNU C extension. When the structure definition changes and the element offset changes, this initialization method still ensures the correctness of known elements. For elements that are not in initialization, the initial value is 0.


Case range

Gnu c allows you to specify a continuous range value in a case label. For example:

+++ Arch/i386/kernel/irq. c
1062: case '0'... '9': c-= '0'; break;
1063: case 'A'... 'F': c-= 'a'-10; break;
1064: case 'A'... 'F': c-= 'a'-10; break;

Case '0'... '9 ':

Equivalent

Case '0': case '1': case '2': case '3': case '4 ':
Case '5': case '6': case '7': case '8': case '9 ':


Declared special attributes

Gnu c allows you to declare special attributes of functions, variables, and types for manual code optimization and more careful code checks. To specify a declared attribute, write it after the declaration
_ Attribute _ (ATTRIBUTE ))

ATTRIBUTE is an ATTRIBUTE description. Multiple Attributes are separated by commas. Gnu c supports more than a dozen attributes. The most common attributes are described here:

* Noreturn

The noreturn attribute is used for a function, indicating that the function is never returned. This allows the compiler to generate slightly optimized code. The most important thing is to eliminate unnecessary warning information, such as the variable that is not initially optimized. For example:

+++ Include/linux/kernel. h
47: # define ATTRIB_NORET _ attribute _ (noreturn ))....
61: asmlinkage NORET_TYPE void do_exit (long error_code)
ATTRIB_NORET;

  * Format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)

The format attribute is used by the function, indicating that the function uses printf, scanf, or strftime-style parameters. The most common mistake with this type of function is that the format string does not match the parameter, specifying the format attribute allows the compiler to check the parameter type based on the format string. For example:

+++ Include/linux/kernel. h?
89: asmlinkage int printk (const char * fmt ,...)
90: _ attribute _ (format (printf, 1, 2 )));

Indicates that the first parameter is a format string, and the parameters are checked based on the format string from the second parameter.

* Unused

The unused attribute is used for functions and variables, indicating that the function or variable may not be used. This attribute can prevent the compiler from generating warning information.

  * Section ("section-name ")

Attribute section is used for functions and variables. Generally, the compiler places the function in. text section, put the variables in. data or. bss section. With the section attribute, the compiler can place functions or variables in the specified section. For example:

+++ Include/linux/init. h
78: # define _ init _ attribute _ (_ section _ (". text. init ")))
79: # define _ exit _ attribute _ (unused, _ section _ (". text. exit ")))
80: # define _ initdata _ attribute _ (_ section _ (". data. init ")))
81: # define _ exitdata _ attribute _ (unused, _ section _ (". data. exit ")))
82: # define _ initsetup _ attribute _ (unused ,__ section _ (". setup. init ")))
83: # define _ init_call _ attribute _ (unused ,__ section _ (". initcall. init ")))
84: # define _ exit_call _ attribute _ (unused ,__ section _ (". exitcall. exit ")))

The connector can arrange the code or data of the same section together. The Linux kernel prefers this technology. For example, the initialization code of the system is arranged in a separate section, after initialization, you can release this part of memory.

* Aligned (ALIGNMENT)

The aligned attribute is used for variables, structures, or union types. It specifies the aligned quantity of variables, structure fields, structures, or associations, in bytes. For example:

++ Include/asm-i386/processor. h
294: struct i387_fxsave_struct {
295: unsigned short cwd;
296: unsigned short swd;
297: unsigned short twd;
298: unsigned short fop;
299: long fip;
300: long fcs;
301: long foo;
......
308: }__ attribute _ (aligned (16 )));

It indicates that the variable of this structure type is 16 bytes aligned. Generally, the compiler selects an appropriate alignment, indicating that the specified alignment is usually caused by System Restrictions, optimizations, and other reasons.

* Packed

The property packed is used for variables and types. When used for variables or structure fields, it indicates that the minimum possible alignment is used. When used for enumeration, structure, or union type, it indicates that the type uses the minimum memory. For example:

++ Include/asm-i386/desc. h
51: struct Xgt_desc_struct {
52: unsigned short size;
53: unsigned long address _ attribute _ (packed ));
54 :};

The domain address will be allocated immediately after the size. Most of the purposes of attribute packed are to define hardware-related structures so that there is no holes between elements due to alignment.


Current function name

Gnu cc predefines two specifiers to save the name of the current FUNCTION, __function _ Save the name of the FUNCTION in the source code _ PRETTY_FUNCTION _ Save the name with language characteristics. In C functions, the two names are the same. In C ++ functions, __pretty_function _ includes additional information such as the function return type, linux Kernel only uses _ FUNCTION __.

+++ Fs/ext2/super. c
98: void ext2_update_dynamic_rev (struct super_block * sb)
99 :{
100: struct ext2_super_block * es = EXT2_SB (sb)-> s_es;
101:
102: if (le32_to_cpu (es-> s_rev_level)> EXT2_GOOD_OLD_REV)
103: return;
104:
105: ext2_warning (sb, _ FUNCTION __,
106: "updating to rev % d because of new feature flag ,"
107: "running e2fsck is recommended ",
108: EXT2_DYNAMIC_REV );

Here _ FUNCTION _ will be replaced with the string "ext2_update_dynamic_rev ". Although _ FUNCTION _ looks similar to _ FILE __in Standard C, _ FUNCTION _ is replaced by the compiler, unlike _ FILE.


Built-in functions

Gnu c provides a large number of built-in functions, many of which are the built-in versions of Standard C library functions, such as memcpy, which share the same functions as the corresponding C library functions. This article does not discuss such functions, the names of other built-in functions usually start with _ builtin.

* _ Builtin_return_address (LEVEL)

The built-in function _ builtin_return_address returns the return address of the current function or its caller. The LEVEL parameter specifies the number of frames to be searched on the stack. 0 indicates the return address of the current function, 1 indicates the return address of the caller of the current function, and so on. For example:

++ Kernel/sched. c
437: printk (KERN_ERR "schedule_timeout: wrong timeout"
438: "value % lx from % p \ n", timeout,
439: _ builtin_return_address (0 ));

   * _ Builtin_constant_p (EXP)

The built-in function _ builtin_constant_p is used to determine whether a value is a compilation constant. If the EXP value of the parameter is a constant, the function returns 1; otherwise, 0. For example:

++ Include/asm-i386/bitops. h
249: # define test_bit (nr, addr )\
250: (_ builtin_constant_p (nr )? \
251: constant_test_bit (nr), (addr )):\
252: variable_test_bit (nr), (addr )))

Many calculations or operations are more optimized when the parameter is a constant. In gnu c, the above method can be used to compile only the constant version or a very few version based on whether the parameter is a constant, in this way, it is both universal and can compile the optimal code when the parameter is a constant.

* _ Builtin_ct (EXP, C)

The built-in function _ builtin_predict CT is used to provide branch prediction information for the compiler. Its return value is the value of the integer expression EXP, and the value of C must be the compile time. For example:

+++ Include/linux/compiler. h
13: # define likely (x) _ builtin_exact CT (x), 1)
14: # define unlikely (x) _ builtin_exact CT (x), 0)
++ Kernel/sched. c
564: if (unlikely (in_interrupt ())){
565: printk ("Scheduling in interrupt \ n ");
566: BUG ();
567 :}

The semantics of this built-in function is that the expected value of EXP is C. The compiler can sort the order of statement blocks according to this information, so that the program can be executed more efficiently as expected. The above example indicates that the target code in the interrupt context rarely occurs. The target code in lines 565th-566 may be placed in a far location to ensure that the target code that is executed frequently is more compact.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.