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