To initialize a spinlock in kernel v4.19-rc5 one must use the spin_lock_init macro defined as follows:
#define spin_lock_init(_lock) \
do { \
spinlock_check(_lock); \
raw_spin_lock_init(&(_lock)->rlock); \
} while (0)
The function spinlock_check(_lock) just return &lock->rlock. This article explains that:
The implementation of the spinlock_check is pretty easy, this function just returns the raw_spinlock_t of the given spinlock to be sure that we got exactly normal raw spinlock
I dont't understand how this function performs a check. I was expecting some if statements in a ckeck function. I'm sorry but I'm new to kernel programming.
It doesn't need any if statements because it exists for compile time checking.
You can see here that most spinlock operations are defined as macros, so they are not able to restrict type of their argument.
Consider the following example:
struct not_a_spinlock {
raw_spinlock_t rlock;
};
Without spinlock_check I could use spin_lock_init to initialize it:
struct not_a_spinlock spin;
spin_lock_init(&spin);
But thanks to spinlock_check, this will not work. This makes those macros type-restricted so they act more like functions.
The reason it returns &lock->rlock is due to convenience - its returned value can be passed to the next function.
So it could be worth rewriting the macro from your example as:
#define spin_lock_init(_lock) \
do { \
raw_spin_lock_init(spinlock_check(_lock)); \
} while (0)
Similar techniques can be used with macros to somewhat restrict their argument types, like shown here:
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
In C, we often have to run such code
if (! somefun(x, y, z)) {
perror("somefun")
}
Is it possible to create a macro which, used as follows:
#define chkerr ...
chkerr(somefun(x, y, z));
would compile to the above?
I already know I can use __VA_ARGS__ macro, but this would require me to call it like
chkerr(somefun, x, y, z)
Short variant (you spotted already):
#define chkErr(FUNCTION, ...) \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
}
Be aware that this can impose big problems in nested if/else or similar constructs:
if(x)
chkErr(f, 10, 12) //;
//^ semicolon forgotten!
else
chkErr(f, 12, 10);
would compile to code equivalent to the following:
if(x)
{
if(!f(10, 12))
perror("f");
else if(!f, 12, 10))
perror("f");
}
Quite obviously not what was intended with the if/else written with the macros... So you really should prefer to let it look like a real function (requiring a semicolon):
#define chkErr(FUNCTION, ...) \
do \
{ \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
You would call it like this:
chkErr(someFunction, 10, 12);
In case of error, output would be:
someFunction: <error text>
However, this hides the fact that a function actually gets called, making it more difficult to understand for "outsiders". Same output, not hiding the function call, but requiring one additional comma in between function and arguments (compared to a normal function call):
#define chkErr(FUNCTION, ARGUMENTS) \
do \
{ \
if(!FUNCTION ARGUMENTS) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
chkErr(someFunction,(12, 10));
// ^ (!)
Another variant with the charm of retaining the function call would print out this entire function call:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_CALL); \
} \
} \
while(0)
chkErr(someFunction(10, 12));
In case of error, output would be:
someFunction(10, 12): <error text>
Addendum: If you really want exactly the output as shown in the question and still have the function call retained (without comma in between), you are a little in trouble. Actually, it is possible, but it requires some extra work:
Problem is how the preprocessor operates on macro arguments: Each argument is a token. It can easily combine tokens, but cannot split them.
Leaving out any commas results in the macro accepting one single token, just as in my second variant. Sure, you can stringify it, as I did, but you get the function arguments with. This is a string literal, and as the pre-processor cannot modify string literals, you have to operate on them at runtime.
Next problem then is, though, string literals are unmodifiable. So you need to modify a copy!
The following variant would do all this work for you:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
char function_name[] = #FUNCTION_CALL; \
char* function_name_end = strchr(function_name, '('); \
if(function_name_end) \
*function_name_end = 0; \
perror(function_name); \
} \
} \
while(0)
Well, decide you if it is worth the effort...
By the way - whitespace between function name and opening parenthesis is not eliminated. If you want to be perfect:
unsigned char* end = (unsigned char*) function_name;
while(*end && *end != '(' && !isspace(*end))
++end;
*end = 0;
Or, much nicer (thanks chqrlie for the hint):
function_name[strcspn(function_name, "( \t")] = 0;
Anything else I can think of would require an additional pre-processing step:
#define CAT(X, Y) CAT_(X, Y)
#define CAT_(X, Y) X ## Y
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(CAT(CHK_ERR_TEXT_, __LINE__)); \
} \
} \
while 0
chkErr(function(10, 12));
Ah, huh, this would result in code like this:
if(!function(10, 12))
{
perror(CHK_ERR_TEXT_42);
}
And now, where to get these macros from? Well, the pre-processing, remember? Possibly a perl or python script, e. g. generating an additional header file you'd have to include. You would have to make sure this pre-processing is done every time before the compiler's pre-processor runs.
Well, all not impossible to solve, but I'll leave this to the masochists among us...
C11 6.4.2.2 Predefined identifiers
The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.
You can used it this way:
#define chkErr(exp) do { if (!(exp)) perror(__func__); } while (0)
chkerr(somefun(x, y, z));
Unfortunately, this would produce an error message with the name of the calling function, not somefun. Here is a simple variant that should work and even produce more informative error messages:
#define chkErr(exp) do { if (!(exp)) perror(#exp); } while (0)
chkerr(somefun(x, y, z));
In case somefun(x, y, z) returns a non zero value, the error message will contain the string "somefun(x, y, z)".
You can combine both techniques to give both the offending call and the location:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define chkErr(exp) \
do { if (!(exp)) \
fprintf(stderr, "%s:%d: in function %s, %s failed: %s\n",\
__FILE__, __LINE__, __func__, #exp, strerror(errno)); \
} while (0)
chkerr(somefun(x, y, z));
This assumes somefun() returns 0 or NULL in case of error and set errno accordingly. Note however that most system calls return non zero in case of error.
You can use the original call format:
chkerr(somefun(x, y, z));
With a macro and a helper function:
#define chkerr(fcall) \
if (!fcall) { \
perror(extract_fname(#fcall)); \
}
const char *extract_fname(const char *fcall);
The extract_fname function would get text and return everything until the open parenthesis.
Yes it is possible with an ugly, unsafe variadic macro:
#define chkerr(func, ...) \
if(!func(__VA_ARGS__)) \
{ \
perror(#func); \
}
...
chkerr(somefunc, 1, 2, 3);
But it is a very bad idea.
Call for sanity:
If there was just the original code with the plain if statement, the reader would think "Here they call a function and do some basic error control. Okay, basic stuff. Moving on...". But after the changes, anyone who reads the code will instead freeze and think "WTF is this???".
You can never write a macro that is clearer than the if statement - which makes the if statement superior to the macro.
Some rules to follow:
Function-like macros are dangerous and unreadable. They should only be used as the very last resort.
Avoid inventing your own secret macro language with function-like macros. C programmers who read your code know C. They don't know your secret macro language.
"To avoid typing" is often a poor rationale for program design decisions. Avoiding code repetition is a good rationale, but taking it to the extremes will affect code readability. If you avoid code repetition and make the code more readable at the same time, it is a good thing. If you do it but the code turns less readable, it is hard to justify.
It's not possible to extract just the function name. The C processor sees the literals you pass as single tokens, which can't be manipulated. Your only options are to print the function with arguments like Aconcague suggests or pass the name as a separate parameter:
#define chkErr(FUNCTION_NAME, FUNCTION_CALL) \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_NAME); \
}
chkErr(someFunction, someFunction(10, 12));
There is not much information about this. Is this the one and only way to do comment in C macro definition? Or can I make add comment using another way?
#define TEST(a, b) \
{ \
bool aGb = false;\
bool bGc = false;\
/* comment is here */ \
if (a > b) \
{\
... \
}\
}
You can do this:
#define DOC(ignored)
And combine like so:
#define TEST(a, b) \
{ \
bool aGb = false; \
bool bGc = false; \
DOC((This is a comment, hello world!)) \
if (a > b) \
{ \
... \
} \
}
Naturally you can't use the C99 comment style with //, since it would ignore the rest of the line and prevent you from creating a multi-line macro.
I would personally suggest just getting used to /* comment */ style. For a start, people using syntax-highlighting IDEs with your code won't see the highlighting if you use this DOC macro above.
The only limitation which adds to those already present when commenting "real" C sources is, that you may not add anything on a macro's "source" line after the final backslash.
Currently, I have a scenario much like this:
#define my_macro(var) __builtin_types_compatible_p(typeof(var), foo) ? do_something : do_something_else
However, inadvertently the macro gets passed this parameter:
my_macro(int x);
Which of course fails, because typeof(int x) isn't valid.
Is there a transformation I can apply inside the my_macro which will allow typeof to work on that expression? I cannot change what is passed into the macro, only what happens inside the macro.
So, something like this:
#define my_macro(var) typeof(?? var ??)
Or, is there another expression I should be using here?
Well, I found a way to do it, using yet another GCC extension, this time the statement expression:
#define my_typeof(definition) typeof(({ definition, _def; _def; }))
Which, of course, expands to:
typeof(({ int x, _def; _def; }))
Pretty ugly, but why do I care? It works.
You could handle x or int x separately but to handle both with one macro you would need the ability to parse/separate a space-delimited argument within the C preprocessor. To my knowledge, no such support exists in the C preprocessor. Without such parsing capabilities you must find some other clever way to write a macro that works around this limitation, for example, something in the spirit of my_macro2() in the following code sample:
#include <stdio.h>
#define my_macro1(var) \
do { \
typeof(var) blah; \
printf("sizeof(var)=%d\n", sizeof(blah)); \
} while(0)
#define my_macro2(var) \
do { \
var, newvar_sametype; \
typeof(newvar_sametype) blah; \
printf("sizeof(newvar_sametype)=%d\n", sizeof(blah)); \
} while(0)
int
main()
{
int x;
my_macro1(x);
my_macro2(char y);
return 0;
}
I'm trying to instrument some code to catch and print error messages. Currently I'm using a macro somethng like this:
#define my_function(x) \
switch(function(x)) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
}
Normally, I never capture the function output and this works fine. But I've found a couple cases where I also need the return value of function(). I tried something like the following, but this produces a syntax error.
#define my_function(x) \
do { \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
} while(0)
I could declare a global variable to hold the return value of the function, but that looks ugly and my program is multithreaded, so that's likely to cause problems. I'm hoping there's a better solution out there.
GCC has a feature called statement expressions
So if define macro like
#define FOO(A) ({int retval; retval = do_something(A); retval;})
then you will be able to use it like
foo = FOO(bar);
This is relatively complicated code, there is not much reason to have it in a macro. Make it inline (C99) or static (C89) or both if you really want to place it in a header file. With any reasonable compiler this then should result in the same efficiency as a macro.
A very late reply. But none the less. I agree inline functions are better but MACROs do offer some pretty printing fun you can't get with inline functions. I agree with #qrdl that you can indeed use statement expressions had you restructured your statements a bit. Here is how it would work with a macro -
#define my_function(x, y) ({ \
int __err = 0; \
do { \
__err = function(x, y); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
} while(0); \
__err; \
})
Sorry, this is an edit...
I think you just need the curly braces. No need for the do..while keywords
Make sure that the backslashes are the last characters on each line (no space after).
If you need to get the err value out of the macro, you can just add a parameter
Like so:
#define my_function(x, out) \
{ \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
(*(out)) = _err; \
}
To preserve the pass-by-reference C paradigm, you should call my_function this way:
int output_err;
my_function(num, &output_err);
This way, later, if you decide to make my_function a real function, you don't need to change the call references.
Btw, qrdl's "Statement Expressions" is also a good way to do it.
there is no need to declare variable if your function is returning something then you can directly get that value. For example:
#define FOO(A) do_something(A)
Here do_something returns some integer. Then you can easily use it like:
int a = FOO(a);