[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH] build: work around older systemtap header



2011/7/1 Eric Blake <eblake redhat com>:
> Systemtap 1.2 <sys/sdt.h> tried to expand STAP_PROBE3 into an
> initialization:
>  volatile __typeof__(arg) foo = arg;
> but that fails if arg was declared as 'char arg[100]'.
> Rather than make all callers to PROBE deal with the stupidity
> of <sys/sdt.h>, we instead make PROBE cast away the problem.
> Some of this preprocessor abuse copies ideas in src/libvirt.c.
>
> * daemon/libvirtd.h (PROBE): Add casts to all arguments, using...
> (VIR_ADD_CASTS, VIR_ADD_CAST, VIR_ADD_CAST2, VIR_ADD_CAST3)
> (VIR_ADD_CAST_EXPAND, VIR_ADD_CAST_PASTE, VIR_COUNT_ARGS)
> (VIR_ARG5, PROBE_EXPAND): New macros.
> Reported by Wen Congyang.
> ---
>
> This took me entirely too long to come up with.  It works for me
> with systemtap 1.4; if I can get feedback from systemtap 1.2 and
> 1.3 users, then I'll gladly apply it, and we can forget about
> having to do stupid casts or other workarounds at every PROBE
> client.

It still compiled with systemtap 1.3.

>  daemon/libvirtd.h |   32 +++++++++++++++++++++++++++++++-
>  1 files changed, 31 insertions(+), 1 deletions(-)
>
> diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
> index 6c604fc..2f0987e 100644
> --- a/daemon/libvirtd.h
> +++ b/daemon/libvirtd.h
> @@ -46,11 +46,41 @@
>  #   define LIBVIRTD_PROBES_H
>  #   include "probes.h"
>  #  endif /* LIBVIRTD_PROBES_H */
> +
> +/* Systemtap 1.2 headers have a bug where they cannot handle a
> + * variable declared with array type.  Work around this by casting all
> + * arguments.  This is some gross use of the preprocessor because
> + * PROBE is a var-arg macro, but it is better than the alternative of
> + * making all callers to PROBE have to be aware of the issues.  And
> + * hopefully, if we ever add a call to PROBE with other than 2 or 3
> + * end arguments, you can figure out the pattern to extend this hack.
> + */
> +#  define VIR_COUNT_ARGS(...) VIR_ARG5(__VA_ARGS__, 4, 3, 2, 1)
> +#  define VIR_ARG5(_1, _2, _3, _4, _5, ...) _5
> +#  define VIR_ADD_CAST_EXPAND(a, b, ...) VIR_ADD_CAST_PASTE(a, b, __VA_ARGS__)
> +#  define VIR_ADD_CAST_PASTE(a, b, ...) a##b(__VA_ARGS__)

Took me a moment to figure it out, but I think I've got it.

> +/* The double cast is necessary to silence gcc warnings; any pointer
> + * can safely go to intptr_t and back to void *, which collapses
> + * arrays into pointers; while any integer can be widened to intptr_t
> + * then cast to void *.  */
> +#  define VIR_ADD_CAST(a) ((void *)(intptr_t)(a))

Is this really true? What about a long long value (64bit) on a 32bit
platform? intptr_t and void* are only 32bit on a 32bit platform,
aren't they?

-- 
Matthias Bolte
http://photron.blogspot.com


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]