I recently got a snippet of code in Linux kernel:
static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
__acquires(&info->lock)
__releases(&info->lock)
{
...
}
What confused me is the two __functions following static int fb_mmap() right before "{",
a).What is the purpose of the two __funtions?
b).Why in that position?
c).Why do they have the prefix "__"?
d).Are there other examples similar to this?
Not everything ending with a pair of parenthesis is a function (call). In this case they are parameterized macro expansions. The macros are defined as
#define __acquires(x) __attribute__((context(x,0,1)))
#define __releases(x) __attribute__((context(x,1,0)))
in file include/linux/compiler.h in the kernel build tree.
The purpose of those macros expanding into attribute definitions is to annotate the function symbols with information about which locking structures the function will acquire (i.e. lock) and release (i.e. unlock). The purpose of those in particular is debugging locking mechanisms (the Linux kernel contains some code that allows it to detect potential deadlock situations and report on this).
https://en.wikipedia.org/wiki/Sparse
__attribute__ is a keyword specific to the GCC compiler, that allows to assign, well, attributes to a given symbol
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#Function-Attributes
Since macros are expanded at the text level, before the compiler is even looking at it, the result for your particular snippet, that the actual compilers sees would be
static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
__attribute__((context(&info->lock,0,1)))
__attribute__((context(&info->lock,1,0)))
{
…
}
Those macros start with a double underscore __ to indicate, that they are part of the compiler environment. All identifiers starting with one or two underscores are reserved for the compiler environment implementation. In the case of the Linux kernel, because Linux is a operating system kernel that does not (because it simply is not availible) use the standard library, it's natural for it, do define it's own compiler environment definitions, private to it. Hence the two underscores to indicate, that this is compiler environment/implementation specific stuff.
They're probably macros defined with #define. You should look for the definition of such macros and see what they expand to. They might expand to some pragma giving hints to the compiler; they might expand to nothing giving hints to the developers or some analysis tool. The meaning might vary
The __attribute__ these macros evaluate to are compiler-specific features. man gcc explains some of the uses.
The prefix __ typically is used to avoid name clashes; double underscore as prefix and postfix mark an identifier as being used by the compiler itself.
More on gcc attributes can be found here.
More on the kernel use of these can be found here.
Those are macro's defined as
# define __acquires(x) __attribute__((context(x,0,1)))
# define __releases(x) __attribute__((context(x,1,0)))
in Linux/include/linux/compiler.h
Related
The LLVM libc++ headers have a macro, used in function declarations, named _LIBCPP_INLINE_VISIBILITY.
I don't understand what it means; I looked at its definition, and it says:
// Just so we can migrate to the new macros gradually.
#define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI
... and this second macro has no definition I can find. So, what does _LIBCPP_INLINE_VISIBILITY mean and what is it typically expanded into?
(Thanks, #Ruslan)
The intent is to hide functions marked with it from appearing in dynamic libraries ("hide from the ABI"). This used to be done by making such functions inline only, but now, the clang attribute attribute((internal_linkage)) is used; that's the definition of _LIBCPP_HIDE_FROM_ABI.
As for the inline-for-invisibility macro _LIBCPP_INLINE_VISIBILITY - what you're seeing is it being redefined to what its name should have been to being with.
I was trying to understand how mallopt() works in glibc, but unable to understand the use of LIBC_PROBE macro used in the function mallopt(). The definition of LIBC_PROBE is creating another macro LIBC_PROBE_1 and again it is creating another one STAP_PROBE##n. In case of mallopt() it is STAP_PROBE3(a1, a2, a3). After this there no clue how STAP_PROBE3 going to work ?
Source file: https://github.com/lattera/glibc/blob/master/malloc/malloc.c (line:5141).
From include/stap-probe.h:
Without USE_STAP_PROBE, that does nothing but evaluates all
its arguments (to prevent bit rot, unlike e.g. assert).
Systemtap's header defines the macros STAP_PROBE (provider, name) and
STAP_PROBEn (provider, name, arg1, ..., argn). For "provider" we paste
in MODULE_NAME (libc, libpthread, etc.) automagically.
The format of the arg parameters is discussed here:
https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
The precise details of how register names are specified is
architecture specific and can be found in the gdb and SystemTap
source code. */
So:
Don't worry about it -- it's not important for understanding how malloopt() works.
If you really care, read the wiki article referenced above, and look for how the macro is defined in SystemTap sources (SystemTap is entirely separate project from GLIBC).
The source code for busybox's syslogd implementation contains some annotations I'm unfamiliar with. The language is C, not C++.
int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int syslogd_main(int argc UNUSED_PARAM, char **argv)
Specifically, MAIN_EXTERNALLY_VISIBLE and UNUSED_PARAM.
What exactly are these annotations doing? Where can I read more about them and other annotations?
Are these part of the C standard, or are they compiler extensions? If they are compiler extensions, how widely supported are they?
I assume the first one is why this file doesn't have a main() function. If these are compiler extensions rather than part of the standard, does this mean this file can't be meaningfully compiled as-is by a compiler that adheres only to the C standard?
Why did they declare a prototype of the syslogd_main function immediately before the full definition? Can the MAIN_EXTERNALLY_VISIBLE annotation only be applied to function prototypes?
1. What exactly are these annotations doing?
See include/platform.h and include/libbb.h
UNUSED_PARAM expands to __attribute__ ((__unused__)). It specifies the variable (argc in your example) as "possibly unused" and disables the "unused variable" warning.
From the GCC manual [Specifying Attributes of Variables]:
unused
This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable.
MAIN_EXTERNALLY_VISIBLE expands to EXTERNALLY_VISIBLE and then to __attribute__(( visibility("default") )). It controls the visibility of the function.
From the GCC manual [Declaring Attributes of Functions]:
... On ELF, default visibility means that the declaration is visible to other modules and, in shared libraries, means that the declared entity may be overridden.
From include/libbb.h:
/* We need to export XXX_main from libbusybox
* only if we build "individual" binaries
*/
#if ENABLE_FEATURE_INDIVIDUAL
#define MAIN_EXTERNALLY_VISIBLE EXTERNALLY_VISIBLE
#else
#define MAIN_EXTERNALLY_VISIBLE
#endif
2. Are these part of the C standard, or ...?
No, those are macros defined in the BusyBox project.
3. I assume the first one is why this file doesn't have a main() function. ...
No. BusyBox combines many utilities into a single executable. That explains the "lack of a main() function" in syslogd.c.
4. Why did they declare a prototype of the syslogd_main function immediately before the full definition? ...
From the GCC manual [Declaring Attributes of Functions]:
The keyword __attribute__ allows you to specify special attributes when making a declaration.
I'm reading the Linux Device Drivers 3rd Edition book online and I'm having trouble understanding the initialization macro for atomic variables:
static atomic_t foobar = ATOMIC_INIT(1);
I've looked through the source code for the Linux kernel v3.2, but I've only come up with two definitions:
#define ATOMIC_INIT(i) { (i) }
and
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
The second version of the definition for the macro seems to be functionally the same as the first -- in fact, it seems redundant to even have an explicit cast when the value would be implicitly cast anyway to atomic_t. Why are there two versions of the definition?
Is the purpose of the ATOMIC_INIT macro just to keep code from breaking if the atomic_t structure changes in a future release of the Linux kernel?
Many atomic operations must be implemented separately for each architecture.
The purpose of the various macros and functions in atomic.h is to hide the differences between architectures.
In practice, all architectures use a single 32-bit variable to implement atomic_t, so there is no practical difference in the various ATOMIC_INIT macros; all the interesting stuff happens in the operations.
But the internals might change (and did change once for 32-bit SPARC), so you always should use the offical API.
The difference between the two different forms of ATOMIC_INIT is that the first can only be used in initializations, the second can be used in initializations and assignments. At a first glance this sounds as if the second would be preferable, but it has an important use case where it can't be applied: block scope variables that are declared with static storage specification. In block scope
static atomic_t foobar = ((atomic_t) { (1) });
would be invalid for standard C, because the initializer would not be a compile time constant expression. (In file scope the compound literal would be statically allocated so it would work, there.)
I remember vaguely a discussion on the kernel list that mentioned that gcc has an extension that allows such code, and that this is one of the reasons they don't move on to C99 but stick to gnu89 as a C dialect.
I'm somewhat confused by #define statements. In libraries, they seem to be a means of communication across different files, with lots of #ifdefs and #ifndefs.
Having said that, I now have two files file1.c and file2.c compiled together, with #define TEST 10 inside file2.c. Yet, when I use TEST inside file2.c the compiler gives the following error message:
'TEST' undeclared (first use in this function)
Are #define directives global?
#defines are not global, they are just a substitution where ever they are used (if declared in the same compile unit)
They are not globals, they are not symbols, they are irrelevant at linkage, they are only relevant at pre-compilation.
#defined macros are global in that they do not follow normal C scoping rules. The textual substitution from the macro will be applied (almost) anywhere the macro name appears after its #define. (Notable exceptions are if the macro name is part of a comment or part of a string literal.)
If you define a macro in a header file, any file that #includes that header file will inherit that macro (whether desired or not), unless the file explicitly undefines it afterward with #undef.
In your example, file2.c does not know about the TEST macro. How would it know to pick up the #define from file1.c? By magic? Since macros perform textual substitution on the source code, there is no representation of them in the generated object files. file2.c therefore needs to know that substitution rule itself, and if you want that shared across multiple files, that #define needs to live in a common header file that your .c files #include.
If you're asking specifically about how many of the #ifdefs that you see in libraries work, many of them are likely checking against pre-defined macro names provided by the compilation environment. For example, a C99 compiler defines a __STDC_VERSION__ macro that specifies the language version; a Microsoft compiler defines an _MSC_VER macro. (Often these predefined macros start with leading underscores since those names are reserved for the compiler.)
Additionally, most compilers allow defining simple macros as command-line arguments. For example, you might compile your code via gcc -DNDEBUG file1.c to compile file.c with NDEBUG defined to disable asserts.
In case somebody reads this later, and to add some practical information:
Some environments like atmel, vs, or iar, allow you to define global #define directives. They basically pass these defined values to the precompiler in some commandline format.
You can do the same in batch commands or makefiles, etc.
Arduino always adds a board variant (usually located at hardware\arduino\variants) to all compilations. At that point you can create a new board that contains your global define directives, and use it that way. For example, you can define a mega2560(debug) board out of the original mega2560 that contains some debug directives. You will add a reference to that variant in "boards.txt", by copy pasting some text, and properly modifying it.
At the end of the day, you will have to give that global hfile or global directive to the compiler in one way or another.
you should make a file1.h and put your defines there. Then in file2.c
#include "file1.h"
easy as a pie :)