I've been looking through a program called hickit, and at one point (count.c, function starts at line 105), and they call a macros function (kavl_insert) from the Klib library as follows:
static void hk_count_nei2_core(int32_t n_pairs, struct cnt_nei2_aux *a, int r1, int r2)
{
struct cnt_nei2_aux *root = 0;
int32_t i, j, left;
unsigned cl;
left = 0;
kavl_insert(nei2, &root, &a[0], 0);
...
Looking at the Klib library (more specifically, in kavl.h), this function (I think) is defined as follows:
#define __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \
__scope __type *kavl_insert_##suf(__type **root_, __type *x, unsigned *cnt_) { \
Later on in the kavl.h file there is this standalone line (line 322):
#define kavl_insert(suf, proot, x, cnt) kavl_insert_##suf(proot, x, cnt)
I don't have much technical knowledge with C (just learned parts as they were relevant), and I'm wondering how this works. The casing is different, and there is the "__" precursor in the #define line. How does this work?
The first __KAVL_INSERT macro is used to declare functions which all start with the same prefix (kavl_insert_) and end with the specified suffix (parameter suf).
So, when you see this:
__KAVL_INSERT(foo, static, int, null, null)
preprocessor will replace it with a function with the appropriate name, scope, and parameter types:
static int *kavl_insert_foo(int **root_, int *x, unsigned *cnt_) { \
/* actual function body ... */ \
/* with lots of trailing backshashes ... */ \
/* because it's the only way to create ... */ \
/* a multiline macro in C */ \
}
The lowercase kavl_insert macro, on the other hand:
kavl_insert(foo, &something, &whatever, 0);
simply expands to the actual function call, i.e. it's equivalent to calling the function defined above:
kavl_insert_foo(&something, &whatever, 0);
The idea behind this kind of macros is usually to create a generic type-safe data structure in C, using the preprocessor, like the klib library of various generic data structures.
Related
I found a header to define hashtable with the following code :
#ifndef HASH_H
#define HASH_H
#define DEFINE_HASHTABLE(name, type, key, h_list, hashfunc)\
\
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
{\
unsigned long i;\
hashtable = (struct list*)malloc(size * sizeof (struct list_head));\
if (!hashtable)\
return -1;\
for (i = 0; i < size; i++)\
INIT_LIST_HEAD(&hashtable[i]);\
return 0;\
}\
\
static inline void hashtable_add(type *elem)\
{\
struct list_head *head = hashtable + hashfunc(elem->key);\
list_add(&elem->h_list, head);\
}\
\
static inline void hashtable_del(type *elem)\
{\
list_del(&elem->h_list);\
}\
\
static inline type * hashtable_find(unsigned long key)\
{\
type *elem;\
struct list_head *head = hashtable + hashfunc(key);\
\
list_for_each_entry(elem, head, h_list){\
if (elem->key == key) \
return elem; \
}\
return NULL;\
}
#endif /* _HASH_H */
I never seen a header file such this one. What is the advantage of this way to write a header (I mean full macro)? Is it about genericity or things like that?
It's a way to try to ensure that all the hash function calls have their inline request granted, i.e. to reduce the number of function calls when doing hash table operations.
It's just an attempt, it can't guarantee that the functions will be inlined, but by making them static the chance at least improves. See this question for lots of discussion about this, in particular #Christoph's answer here.
Note that it will only work once per C file, since there's no "unique" part added to the function names.
If you do:
#include "hash.h"
DEFINE_HASHTABLE(foo, /* rest of arguments */);
DEFINE_HASHTABLE(bar, /* another bunch of args */);
you will get compilation errors, since all the hashtable_ functions will be defined twice. The macro writer could improve this by adding the name to all the things defined (variables and functions) by the set of macros.
I.e. this:
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
should become something like:
static list *hashtable_ ##name;\
\
static int hashtable_ ##name ##_init(size_t size)\
and so on (where name is the first macro argument, i.e. the foo and bar from my example usage above).
I'm trying to work through an issue on a third party library. The issue is the library uses GCC's nested functions buried in a macro, and Clang does not support nested functions and has no plans to do so (cf., Clang Bug 6378 - error: illegal storage class on function).
Here's the macro that's the pain point for me and Clang:
#define RAII_VAR(vartype, varname, initval, dtor) \
/* Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 */ \
auto void _dtor_ ## varname (vartype * v); \
void _dtor_ ## varname (vartype * v) { dtor(*v); } \
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
And here's how its used (from the code comments):
* void do_stuff(const char *name)
* {
* RAII_VAR(struct mything *, thing, find_mything(name), ao2_cleanup);
* if (!thing) {
* return;
* }
* if (error) {
* return;
* }
* do_stuff_with_thing(thing);
* }
The Clang User Manual states to use C++ and a lambda function to emulate. I'm not sure that's the best strategy, and a C project will likely not accept a C++ patch (they would probably tar and feather me first).
Is there a way to rewrite the macro so that's its (1) more accommodating to Clang, and (2) preserves original function semantics?
Clang doesn't support GCC nested functions, but it does support Objective C-style "blocks", even in C mode:
void f(void * d) {
void (^g)(void *) = ^(void * d){ };
g(d);
}
You need to invoke it with the clang command rather than gcc, and also (?) pass -fblocks -lBlocksRuntime to the compiler.
You can't use a block as a cleanup value directly, since it has to be a function name, so (stealing ideas from here) you need to add a layer of indirection. Define a single function to clean up void blocks, and make your RAII'd variable the block that you want to run at the end of the scope:
typedef void (^cleanup_block)(void);
static inline void do_cleanup(cleanup_block * b) { (*b)(); }
void do_stuff(const char *name) {
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ };
}
Because blocks form closures, you can then place the operations on your variables to cleanup directly inside that block...
void do_stuff(const char *name) {
struct mything * thing;
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ ao2_cleanup(thing); };
}
...and that should run at the end of the scope as before, being invoked by the cleanup on the block. Rearrange the macro and add a __LINE__ so it works with multiple declarations:
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A##B
#define RAII_VAR(vartype, varname, initval, dtor) \
vartype varname = (initval); \
cleanup_block __attribute__((cleanup(do_cleanup))) CAT(__b_, __LINE__) = ^{ dtor(varname); };
void do_stuff(const char *name) {
RAII_VAR(struct mything *, thing, NULL, ao2_cleanup);
...
Something like that, anyway.
I believe you can do this without using a clang-specific version, I'd try something like this (untested, may require a few extra casts):
struct __destructor_data {
void (*func)(void *);
void **data;
}
static inline __destructor(struct __destructor_data *data)
{
data->func(*data->data);
}
#define RAII_VAR(vartype, varname, initval, dtor) \
vartype varname = initval; \
__attribute((cleanup(__destructor))) \
struct __destructor_data __dd ## varname = \
{ dtor, &varname };
In our project we have a gcc-specific _auto_(dtor) macro that precedes the normal variable declaration, e.g.:
_auto_(free) char *str = strdup("hello");
In this case our macro can't add anything after the variable declaration and also doesn't know the name of the variable, so to avoid using gcc-specific nested functions I came up with the following hackish version in case this helps anyone:
static void *__autodestruct_value = NULL;
static void (*__autodestruct_dtor)(void *) = NULL;
static inline void __autodestruct_save_dtor(void **dtor)
{
__autodestruct_dtor = *dtor;
__autodestruct_dtor(__autodestruct_value);
}
static inline void __autodestruct_save_value(void *data)
{
__autodestruct_value = *(void **) data;
}
#define __AUTODESTRUCT(var, func) \
__attribute((cleanup(__autodestruct_save_dtor))) \
void *__dtor ## var = (void (*)(void *))(func); \
__attribute((cleanup(__autodestruct_save_value)))
#define _AUTODESTRUCT(var, func) \
__AUTODESTRUCT(var, func)
#define _auto_(func) \
_AUTODESTRUCT(__COUNTER__, func)
This is hackish because it depends on the order the destructors are called by the compiler being the reverse of the order of the declarations, and it has a few obvious downsides compared to the gcc-specific version but it works with both compilers.
Building on the answers above, here's my hack to allow clang to compile nested procedures written in gcc-extension style. I needed this myself to support a source-to-source translator for an Algol-like language (Imp) which makes heavy use of nested procedures.
#if defined(__clang__)
#define _np(name, args) (^name)args = ^args
#define auto
#elif defined(__GNUC__)
#define _np(name, args) name args
#else
#error Nested functions not supported
#endif
int divide(int a, int b) {
#define replace(args...) _np(replace, (args))
auto int replace(int x, int y, int z) {
#undef replace
if (x == y) return z; else return x;
};
return a / replace(b,0,1);
}
int main(int argc, char **argv) {
int a = 6, b = 0;
fprintf(stderr, "a / b = %d\n", divide(a, b));
return 0;
}
I have a C program in which I need to create a whole family of functions which have the same signatures and bodies, and differ only in their types. What I would like to do is define a macro which generates all of those functions for me, as otherwise I will spend a long time copying and modifying the original functions. As an example, one of the functions I need to generate looks like this:
int copy_key__sint_(void *key, void **args, int argc, void **out {
if ((*out = malloc(sizeof(int))) {
return 1;
}
**((_int_ **) out) = *((_int_ *) key);
return 0;
}
The idea is that I could call a macro, GENERATE_FUNCTIONS("int", "sint") or something like this, and have it generate this function. The italicized parts are what need to be plugged in.
Is this possible?
I don't understand the example function that you are giving very well, but using macros for the task is relatively easy. Just you wouldn't give strings to the macro as arguments but tokens:
#define DECLARE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg)
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
}
You may then use this to declare the functions in a header file
DECLARE_MY_COPY_FUNCTION(unsigned, toto);
DECLARE_MY_COPY_FUNCTION(double, hui);
and define them in a .c file:
DEFINE_MY_COPY_FUNCTION(unsigned, toto);
DEFINE_MY_COPY_FUNCTION(double, hui);
In this version as stated here you might get warnings on superfluous `;'. But you can get rid of them by adding dummy declarations in the macros like this
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
} \
enum { dummy_enum_for_copy_function_ ## SUFFIX }
Try something like this (I just tested the compilation, but not the result in an executed program):
#include "memory.h"
#define COPY_KEY(type, name) \
type name(void *key, void **args, int argc, void **out) { \
if (*out = malloc(sizeof(type))) { \
return 1; \
} \
**((type **) out) = *((type *) key); \
return 0; \
} \
COPY_KEY(int, copy_key_sint)
For more on the subject of generic programming in C, read this blog wich contains a few examples and also this book which contains interesting solutions to the problem for basic data structures and algorithm.
That should work. To create copy_key_sint, use copy_key_ ## sint.
If you can't get this to work with CPP, then write a small C program which generates a C source file.
Wouldn't a macro which just takes sizeof(*key) and calls a single function that uses memcpy be a lot cleaner (less preprocessor abuse and code bloat) than making a new function for each type just so it can do a native assignment rather than memcpy?
My view is that the whole problem is your attempt to apply C++ thinking to C. C has memcpy for a very good reason.
I'm trying to design a portable API in ANSI C89/ISO C90 to access a wireless networking device on a serial interface. The library will have multiple network layers, and various versions need to run on embedded devices as small as an 8-bit micro with 32K of code and 2K of data, on up to embedded devices with a megabyte or more of code and data.
In most cases, the target processor will have a single network interface and I'll want to use a single global structure with all state information for that device. I don't want to pass a pointer to that structure through the network layers.
In a few cases (e.g., device with more resources that needs to live on two networks) I will interface to multiple devices, each with their own global state, and will need to pass a pointer to that state (or an index to a state array) through the layers.
I came up with two possible solutions, but neither one is particularly pretty. Keep in mind that the full driver will potentially be 20,000 lines or more, cover multiple files, and contain hundreds of functions.
The first solution requires a macro that discards the first parameter for every function that needs to access the global state:
// network.h
typedef struct dev_t {
int var;
long othervar;
char name[20];
} dev_t;
#ifdef IF_MULTI
#define foo_function( x, a, b, c) _foo_function( x, a, b, c)
#define bar_function( x) _bar_function( x)
#else
extern dev_t DEV;
#define IFACE (&DEV)
#define foo_function( x, a, b, c) _foo_function( a, b, c)
#define bar_function( x) _bar_function( )
#endif
int bar_function( dev_t *IFACE);
int foo_function( dev_t *IFACE, int a, long b, char *c);
// network.c
#ifndef IF_MULTI
dev_t DEV;
#endif
int bar_function( dev_t *IFACE)
{
memset( IFACE, 0, sizeof *IFACE);
return 0;
}
int foo_function( dev_t *IFACE, int a, long b, char *c)
{
bar_function( IFACE);
IFACE->var = a;
IFACE->othervar = b;
strcpy( IFACE->name, c);
return 0;
}
The second solution defines macros to use in the function declarations:
// network.h
typedef struct dev_t {
int var;
long othervar;
char name[20];
} dev_t;
#ifdef IF_MULTI
#define DEV_PARAM_ONLY dev_t *IFACE
#define DEV_PARAM DEV_PARAM_ONLY,
#else
extern dev_t DEV;
#define IFACE (&DEV)
#define DEV_PARAM_ONLY void
#define DEV_PARAM
#endif
int bar_function( DEV_PARAM_ONLY);
// I don't like the missing comma between DEV_PARAM and arg2...
int foo_function( DEV_PARAM int a, long b, char *c);
// network.c
#ifndef IF_MULTI
dev_t DEV;
#endif
int bar_function( DEV_PARAM_ONLY)
{
memset( IFACE, 0, sizeof *IFACE);
return 0;
}
int foo_function( DEV_PARAM int a, long b, char *c)
{
bar_function( IFACE);
IFACE->var = a;
IFACE->othervar = b;
strcpy( IFACE->name, c);
return 0;
}
The C code to access either method remains the same:
// multi.c - example of multiple interfaces
#define IF_MULTI
#include "network.h"
dev_t if0, if1;
int main()
{
foo_function( &if0, -1, 3.1415926, "public");
foo_function( &if1, 42, 3.1415926, "private");
return 0;
}
// single.c - example of a single interface
#include "network.h"
int main()
{
foo_function( 11, 1.0, "network");
return 0;
}
Is there a cleaner method that I haven't figured out? I lean toward the second since it should be easier to maintain, and it's clearer that there's some macro magic in the parameters to the function. Also, the first method requires prefixing the function names with "_" when I want to use them as function pointers.
I really do want to remove the parameter in the "single interface" case to eliminate unnecessary code to push the parameter onto the stack, and to allow the function to access the first "real" parameter in a register instead of loading it from the stack. And, if at all possible, I don't want to have to maintain two separate codebases.
Thoughts? Ideas? Examples of something similar in existing code?
(Note that using C++ isn't an option, since some of the planned targets don't have a C++ compiler available.)
I like your second solution. I just prefer declaring every function twice rather than have that PARAM macro in the public header. I much prefer to put macro hijinks in the hidden C file.
// common header
#ifdef IF_MULTI
int foo_func1(dev_t* if, int a);
int foo_func2(dev_t* if, int a, int b);
int foo_func3(dev_t* if);
#else
int foo_func1(int a);
int foo_func2(int a, int b);
int foo_func3();
#endif
// your C file
#ifdef IF_MULTI
#define IF_PARM dev_t* if,
#define GET_IF() (if)
#else
dev_t global_if;
#define IF_PARM
#define GET_IF() (&global_if)
#endif
int foo_func1(IF_PARM int a)
{
GET_IF()->x = a;
return GET_IF()->status;
}
int foo_func2(IF_PARM int a, int b)
int foo_func3(IF_PARM);
Here's a solution that won't work if you have threads (or switch interfaces on re-entrance or something like that), but it is a clean interface, and it might work for you.
You could have your single instance functions using a global DEV, and have your multi interface functions set this global and call their single instance counterparts.
For example:
dev_t *DEV;
int foo_function(int x, int y)
{
/* DEV->whatever; */
return DEV->status;
}
int foo_function_multi(dev_t *IFACE, int x, int y)
{
DEV = IFACE;
return foo_function(x, y);
}
Another option is to use variadic args, and pass and fetch an extra arg (which contains the interface to use) #ifdef MULTI, but that's horrible because you lose your type safety, and would prevent passing the arg in a register which you possibly care quite a bit about on your platform. Also, all functions with variadic args must have at least one named argument, and your question is all about avoiding arguments! But anyway:
#ifndef MULTI
dev_t *DEV;
#endif
int foo(int x, int y, ...)
{
#ifdef MULTI
va_list args;
va_start(args, y);
dev_t *DEV = va_arg(args, (dev_t*));
va_end(args);
#endif
/* DEV->whatever */
return DEV->status;
}
// call from single
int quux()
{
int status = foo(23, 17);
}
// call from multi
int quux()
{
int status = foo(23, 17, &if0);
}
Personally I prefer your first solution :-)
This will work on gcc:
#ifdef TOMSAPI_SMALL
#define TOMSAPI_ARGS( dev, ...) (__VA_ARGS__)
#else // ! TOMSAPI_SMALL
#define TOMSAPI_ARGS( dev, ...) (dev, ## __VA_ARGS__)
#endif // TOMSAPI_SMALL
#ifdef TOMSAPI_SMALL
#define TOMSAPI_DECLARE_DEVP(local_dev_ptr) device_t * local_dev_ptr = &global_dev; NULL
// The trailing NULL is to make the compiler make you put a ; after calling the macro,
// but without allowing something that would mess up the declaration if you forget the ;
// You can't use the do{...}while(0) trick for a variable declaration.
#else // ! TOMSAPI_SMALL
#define TOMSAPI_DECLARE_DEVP(local_dev_ptr) device_t * local_dev_ptr = arg_dev; NULL
#endif // TOMSAPI_SMALL
and then
int tomsapi_init TOMSAPI(device_t *arg_dev, void * arg_for_illustration_purposes ) {
TOMSAPI_DECLARE_DEVP( my_dev );
my_dev->stuff = arg_for_illustration_purposes;
return 0;
}
Using this method you would have to ensure that all of your API functions used the same name for the device pointer, but all of your function definitions and declarations would look like they needed the full number of arguments. If this were not important to you you could do:
#ifdef TOMSAPI_SMALL
#define TOMSAPI_ARGS(...) (__VA_ARGS__)
#else // ! TOMSAPI_SMALL
#define TOMSAPI_ARGS(...) (device_t *dev, ## __VA_ARGS__)
#endif // TOMSAPI_SMALL
#ifdef TOMSAPI_SMALL
#define TOMSAPI_DECLARE_DEVP() device_t * dev = &global_dev; NULL
#else // ! TOMSAPI_SMALL
#define TOMSAPI_DECLARE_DEVP(local_dev_ptr) NULL
#endif // TOMSAPI_SMALL
and then
int tomsapi_init TOMSAPI(void * arg_for_illustration_purposes ) {
dev->stuff = arg_for_illustration_purposes;
return 0;
}
But this ends up looking like dev is never declared to someone reading your code.
All of that being said, you may find that on the single device small platform that using a global device struct ends up costing more than passing the pointer around due to the number of times the address of this struct will have to be reloaded. This is more likely if you API is stacked (some of your functions call other of your functions and pass them the dev pointer), uses a lot of tail recursion, and/or your platform uses registers for passing most arguments rather than the stack.
EDIT:
I just realized that there could be a problem with this method if you have api functions which take no additional arguments, even if you do use the ## operator if your compiler wants to force you to say int foo(void) for functions that take no arguments.
is there a magic variable in gcc holding a pointer to the current function ?
I would like to have a kind of table containing for each function pointer a set of information.
I know there's a __func__ variable containing the name of the current function as a string but not as a function pointer.
This is not to call the function then but just to be used as an index.
EDIT
Basically what i would like to do is being able to run nested functions just before the execution of the current function (and also capturing the return to perform some things.)
Basically, this is like __cyg_profile_func_enter and __cyg_profile_func_exit (the instrumentation functions)... But the problem is that these instrumentation functions are global and not function-dedicated.
EDIT
In the linux kernel, you can use unsigned long kallsyms_lookup_name(const char *name) from include/linux/kallsyms.h ... Note that the CONFIG_KALLSYMS option must be activated.
void f() {
void (*fpointer)() = &f;
}
Here's a trick that gets the address of the caller, it can probably be cleaned up a bit.
Relies on a GCC extension for getting a label's value.
#include <stdio.h>
#define MKLABEL2(x) label ## x
#define MKLABEL(x) MKLABEL2(x)
#define CALLFOO do { MKLABEL(__LINE__): foo(&&MKLABEL(__LINE__));} while(0)
void foo(void *addr)
{
printf("Caller address %p\n", addr);
}
int main(int argc, char **argv)
{
CALLFOO;
return 0;
}
#define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__))
And compile your program like
gcc -rdynamic -o foo foo.c -ldl
I think you could build your table using strings (the function names) as keys, then look up by comparing with the __func__ builtin variable.
To enforce having a valid function name, you could use a macro that gets the function pointer, does some dummy operation with it (e.g. assigning it to a compatible function type temporary variable) to check that it's indeed a valid function identifier, and then stringifies (with #) the function name before being used as a key.
UPDATE:
What I mean is something like:
typedef struct {
char[MAX_FUNC_NAME_LENGTH] func_name;
//rest of the info here
} func_info;
func_info table[N_FUNCS];
#define CHECK_AND_GET_FUNC_NAME(f) ({void (*tmp)(int); tmp = f; #f})
void fill_it()
{
int i = -1;
strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(foo));
strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(bar));
//fill the rest
}
void lookup(char *name) {
int i = -1;
while(strcmp(name, table[++i]));
//now i points to your entry, do whatever you need
}
void foo(int arg) {
lookup(__func__);
//do something
}
void bar(int arg) {
lookup(__func__);
//do something
}
(the code might need some fixes, I haven't tried to compile it, it's just to illustrate the idea)
I also had the problem that I needed the current function's address when I created a macro template coroutine abstraction that people can use like modern coroutine language features (await and async). It compensates for a missing RTOS when there is a central loop which schedules different asynchronous functions as (cooperative) tasks. Turning interrupt handlers into asynchronous functions even causes race conditions like in a preemptive multi-tasking system.
I noticed that I need to know the caller function's address for the final return address of a coroutine (which is not return address of the initial call of course). Only asynchronous functions need to know their own address so that they can pass it as hidden first argument in an AWAIT() macro. Since instrumenting the code with a macro solution is as simple as just defining the function it suffices to have an async-keyword-like macro.
This is a solution with GCC extensions:
#define _VARGS(...) _VARGS0(__VA_ARGS__)
#define _VARGS0(...) ,##__VA_ARGS__
typedef union async_arg async_arg_t;
union async_arg {
void (*caller)(void*);
void *retval;
};
#define ASYNC(FUNCNAME, FUNCARGS, ...) \
void FUNCNAME (async_arg_t _arg _VARGS FUNCARGS) \
GENERATOR( \
void (*const THIS)(void*) = (void*) &FUNCNAME;\
static void (*CALLER)(void*), \
CALLER = _arg.caller; \
__VA_ARGS__ \
)
#define GENERATOR(INIT,...) { \
__label__ _entry, _start, _end; \
static void *_state = (void*)0; \
INIT; \
_entry:; \
if (_state - &&_start <= &&_end - &&_start) \
goto *_state; \
_state = &&_start; \
_start:; \
__VA_ARGS__; \
_end: _state = &&_entry; \
}
#define AWAIT(FUNCNAME,...) ({ \
__label__ _next; \
_state = &&_next; \
return FUNCNAME((async_arg_t)THIS,##__VA_ARGS__);\
_next: _arg.retval; \
})
#define _I(...) __VA_ARGS__
#define IF(COND,THEN) _IF(_I(COND),_I(THEN))
#define _IF(COND,THEN) _IF0(_VARGS(COND),_I(THEN))
#define _IF0(A,B) _IF1(A,_I(B),)
#define _IF1(A,B,C,...) C
#define IFNOT(COND,ELSE) _IFNOT(_I(COND),_I(ELSE))
#define _IFNOT(COND,ELSE) _IFNOT0(_VARGS(COND),_I(ELSE))
#define _IFNOT0(A,B) _IFNOT1(A,,_I(B))
#define _IFNOT1(A,B,C,...) C
#define IF_ELSE(COND,THEN,ELSE) IF(_I(COND),_I(THEN))IFNOT(_I(COND),_I(ELSE))
#define WAIT(...) ({ \
__label__ _next; \
_state = &&_next; \
IF_ELSE(_I(__VA_ARGS__), \
static __typeof__(__VA_ARGS__) _value;\
_value = (__VA_ARGS__); \
return; \
_next: _value; \
, return; _next:;) \
})
#define YIELD(...) do { \
__label__ _next; \
_state = &&_next; \
return IF(_I(__VA_ARGS__),(__VA_ARGS__));\
_next:; \
} while(0)
#define RETURN(VALUE) do { \
_state = &&_entry; \
if (CALLER != 0) \
CALLER((void*)(VALUE +0));\
return; \
} while(0)
#define ASYNCALL(FUNC, ...) FUNC ((void*)0,__VA_ARGS__)
I know, a more portable (and maybe secure) solution would use the switch-case statement instead of label addresses but I think, gotos are more efficient than switch-case-statements. It also has the advantage that you can use the macros within any other control structures easily and break will have no unexpected effects.
You can use it like this:
#include <stdint.h>
int spi_start_transfer(uint16_t, void *, uint16_t, void(*)());
#define SPI_ADDR_PRESSURE 0x24
ASYNC(spi_read_pressure, (void* dest, uint16_t num),
void (*callback)(void) = (void*)THIS; //see here! THIS == &spi_read_pressure
int status = WAIT(spi_start_transfer(SPI_ADDR_PRESSURE,dest,num,callback));
RETURN(status);
)
int my_gen() GENERATOR(static int i,
while(1) {
for(i=0; i<5; i++)
YIELD(i);
}
)
extern volatile int a;
ASYNC(task_read, (uint16_t threshold),
while(1) {
static uint16_t pressure;
int status = (int)AWAIT(spi_read_pressure, &pressure, sizeof pressure);
if (pressure > threshold) {
a = my_gen();
}
}
)
You must use AWAIT to call asynchronous functions for return value and ASYNCALL without return value. AWAIT can only be called by ASYNC-functions. You can use WAIT with or without value. WAIT results in the expression which was given as argument, which is returned AFTER the function is resumed. WAIT can be used in ASYNC-functions only. Keeping the argument with WAIT wastes one new piece of static memory for each WAIT() call with argument though so it is recommended to use WAIT() without argument. It could be improved, if all WAIT calls would use the same single static variable for the entire function.
It is only a very simple version of a coroutine abstraction. This implementation cannot have nested or intertwinned calls of the same function because all static variables comprise one static stack frame.
If you want to solve this problem, you also need to distinguish resuming an old and starting a new function call. You can add details like a stack-frame queue at the function start in the ASYNC macro. Create a custom struct for each function's stack frame (which also can be done within the macro and an additional macro argument). This custom stack frame type is loaded from a queue when entering the macro, is stored back when exiting it or is removed when the call finishes.
You could use a stack frame index as alternative argument in the async_arg_t union. When the argument is an address, it starts a new call or when given a stack frame index it resumes an old call. The stack frame index or continuation must be passed as user-defined argument to the callback that resumes the coroutine.
If you went for C++ the following information might help you:
Objects are typed, functors are functions wrapped as objects, RTTI allows the identification of type at runtime.
Functors carry a runtime overhead with them, and if this is a problem for you I would suggest hard-coding the knowledge using code-generation or leveraging a OO-heirarchy of functors.
No, the function is not aware of itself. You will have to build the table you are talking about yourself, and then if you want a function to be aware of itself you will have to pass the index into the global table (or the pointer of the function) as a parameter.
Note: if you want to do this you should have a consistent naming scheme of the parameter.
If you want to do this in a 'generic' way, then you should use the facilities you already mention (__cyg_profile_func*) since that is what they are designed for. Anything else will have to be as ad hoc as your profile.
Honestly, doing things the generic way (with a filter) is probably less error prone than any new method that you will insert on-the-fly.
You can capture this information with setjmp(). Since it saves enough information to return to your current function, it must include that information in the provided jmp_buf.
This structure is highly nonportable, but you mention GCC explicitly so that's probably not a blocking issue. See this GCC/x86 example to get an idea how it roughly works.
If you want to do code generation I would recomend GSLGen from Imatix. It uses XML to structure a model of your code and then a simple PHP like top-down generation language to spit out the code -- it has been used to generate C code.
I have personally been toying arround with lua to generate code.
static const char * const cookie = __FUNCTION__;
__FUNCTION__ will be stored at the text segment at your binary and a pointer will always be unique and valid.
Another option, if portability is not an issue, would be to tweak the GCC source-code... any volunteers?!
If all you need is a unique identifier for each function, then at the start of every function, put this:
static const void * const cookie = &cookie;
The value of cookie is then guaranteed to be a value uniquely identifying that function.