proposed changes look good.
comment needed regarding the reason for internally managed per-thread data
(limitation of Posix' PTHREAD_KEYS_MAX)

Kais


On Tue, Aug 6, 2013 at 4:56 PM, Ben Pfaff <b...@nicira.com> wrote:

> DEFINE_PER_THREAD_DATA always declared its data item as "static", meaning
> that it was only directly visible within a single translation unit.
> This commit adds additional forms of per-thread data that allow the data
> to be accessible from multiple translation units.
>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  lib/ovs-thread.h |   94
> ++++++++++++++++++++++++++++++++++++++++++++----------
>  lib/random.c     |    2 +-
>  lib/timeval.c    |    2 +-
>  lib/util.c       |    4 ++-
>  lib/vlog.c       |    2 +-
>  5 files changed, 84 insertions(+), 20 deletions(-)
>
> diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h
> index 0d54a43..abe479a 100644
> --- a/lib/ovs-thread.h
> +++ b/lib/ovs-thread.h
> @@ -193,7 +193,15 @@ void xpthread_create(pthread_t *, pthread_attr_t *,
> void *(*)(void *), void *);
>   * cross-thread access?     yes                no                yes
>   */
>
> -/* DEFINE_PER_THREAD_DATA(TYPE, NAME, INITIALIZER).
> +/* For static data, use this macro in a source file:
> + *
> + *    DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER).
> + *
> + * For global data, "declare" the data in the header and "define" it in
> + * the source file, with:
> + *
> + *    DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME).
> + *    DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER).
>   *
>   * One should prefer to use POSIX per-thread data, via pthread_key_t,
> when its
>   * performance is acceptable, because of its portability (see the table
> above).
> @@ -231,23 +239,40 @@ void xpthread_create(pthread_t *, pthread_attr_t *,
> void *(*)(void *), void *);
>  #error
>  #endif
>
> -#define DEFINE_PER_THREAD_DATA(TYPE, NAME, ...)                 \
> -    typedef TYPE NAME##_type;                                   \
> -    static thread_local NAME##_type NAME##_var = __VA_ARGS__;   \
> -                                                                \
> -    static NAME##_type *                                        \
> -    NAME##_get_unsafe(void)                                     \
> -    {                                                           \
> -        return &NAME##_var;                                     \
> -    }                                                           \
> -                                                                \
> -    static NAME##_type *                                        \
> -    NAME##_get(void)                                            \
> -    {                                                           \
> -        return NAME##_get_unsafe();                             \
> +#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...)                  \
> +    typedef TYPE NAME##_type;                                           \
> +                                                                        \
> +    static NAME##_type *                                                \
> +    NAME##_get_unsafe(void)                                             \
> +    {                                                                   \
> +        static thread_local NAME##_type var = __VA_ARGS__;              \
> +        return &var;                                                    \
> +    }                                                                   \
> +                                                                        \
> +    static NAME##_type *                                                \
> +    NAME##_get(void)                                                    \
> +    {                                                                   \
> +        return NAME##_get_unsafe();                                     \
>      }
> +#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME)                      \
> +    typedef TYPE NAME##_type;                                           \
> +    extern thread_local NAME##_type NAME##_var;                         \
> +                                                                        \
> +    static inline NAME##_type *                                         \
> +    NAME##_get_unsafe(void)                                             \
> +    {                                                                   \
> +        return &NAME##_var;                                             \
> +    }                                                                   \
> +                                                                        \
> +    static inline NAME##_type *                                         \
> +    NAME##_get(void)                                                    \
> +    {                                                                   \
> +        return NAME##_get_unsafe();                                     \
> +    }
> +#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...)         \
> +    thread_local NAME##_type NAME##_var = __VA_ARGS__;
>  #else  /* no C implementation support for thread-local storage  */
> -#define DEFINE_PER_THREAD_DATA(TYPE, NAME, ...)                         \
> +#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...)                  \
>      typedef TYPE NAME##_type;                                           \
>      static pthread_key_t NAME##_key;                                    \
>                                                                          \
> @@ -282,6 +307,43 @@ void xpthread_create(pthread_t *, pthread_attr_t *,
> void *(*)(void *), void *);
>          }                                                               \
>          return value;                                                   \
>      }
> +#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME)                      \
> +    typedef TYPE NAME##_type;                                           \
> +    static pthread_key_t NAME##_key;                                    \
> +                                                                        \
> +    static inline NAME##_type *                                         \
> +    NAME##_get_unsafe(void)                                             \
> +    {                                                                   \
> +        return pthread_getspecific(NAME##_key);                         \
> +    }                                                                   \
> +                                                                        \
> +    NAME##_type *NAME##_get(void);
> +#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...)                        \
> +    static void                                                         \
> +    NAME##_once_init(void)                                              \
> +    {                                                                   \
> +        if (pthread_key_create(&NAME##_key, free)) {                    \
> +            abort();                                                    \
> +        }                                                               \
> +    }                                                                   \
> +                                                                        \
> +    NAME##_type *                                                       \
> +    NAME##_get(void)                                                    \
> +    {                                                                   \
> +        static pthread_once_t once = PTHREAD_ONCE_INIT;                 \
> +        NAME##_type *value;                                             \
> +                                                                        \
> +        pthread_once(&once, NAME##_once_init);                          \
> +        value = NAME##_get_unsafe();                                    \
> +        if (!value) {                                                   \
> +            static const NAME##_type initial_value = __VA_ARGS__;       \
> +                                                                        \
> +            value = xmalloc(sizeof *value);                             \
> +            *value = initial_value;                                     \
> +            xpthread_setspecific(NAME##_key, value);                    \
> +        }                                                               \
> +        return value;                                                   \
> +    }
>  #endif
>
>  /* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME).
> diff --git a/lib/random.c b/lib/random.c
> index da29fd0..d6f7d9d 100644
> --- a/lib/random.c
> +++ b/lib/random.c
> @@ -39,7 +39,7 @@
>   * cryptographic-quality randomness. */
>
>  /* Current random state. */
> -DEFINE_PER_THREAD_DATA(uint32_t, seed, 0);
> +DEFINE_STATIC_PER_THREAD_DATA(uint32_t, seed, 0);
>
>  static uint32_t random_next(void);
>
> diff --git a/lib/timeval.c b/lib/timeval.c
> index 05da99e..faf8e7b 100644
> --- a/lib/timeval.c
> +++ b/lib/timeval.c
> @@ -65,7 +65,7 @@ static long long int deadline = LLONG_MAX;
>
>  /* Monotonic time, in milliseconds, at which the last call to time_poll()
> woke
>   * up. */
> -DEFINE_PER_THREAD_DATA(long long int, last_wakeup, 0);
> +DEFINE_STATIC_PER_THREAD_DATA(long long int, last_wakeup, 0);
>
>  static void set_up_timer(void);
>  static void set_up_signal(int flags);
> diff --git a/lib/util.c b/lib/util.c
> index 1751c6f..76c33cd 100644
> --- a/lib/util.c
> +++ b/lib/util.c
> @@ -46,7 +46,9 @@ DEFINE_PER_THREAD_MALLOCED_DATA(char *, subprogram_name);
>  static char *program_version;
>
>  /* Buffer used by ovs_strerror(). */
> -DEFINE_PER_THREAD_DATA(struct { char s[128]; }, strerror_buffer, { "" });
> +DEFINE_STATIC_PER_THREAD_DATA(struct { char s[128]; },
> +                              strerror_buffer,
> +                              { "" });
>
>  void
>  ovs_assert_failure(const char *where, const char *function,
> diff --git a/lib/vlog.c b/lib/vlog.c
> index 26d0e6c..ac229b4 100644
> --- a/lib/vlog.c
> +++ b/lib/vlog.c
> @@ -100,7 +100,7 @@ static struct facility facilities[VLF_N_FACILITIES] = {
>  };
>
>  /* Sequence number for the message currently being composed. */
> -DEFINE_PER_THREAD_DATA(unsigned int, msg_num, 0);
> +DEFINE_STATIC_PER_THREAD_DATA(unsigned int, msg_num, 0);
>
>  /* VLF_FILE configuration.
>   *
> --
> 1.7.10.4
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to