From: Ben Pfaff Date: Tue, 6 Aug 2013 21:57:19 +0000 (-0700) Subject: ovs-thread: New function ovsthread_id_self(). X-Git-Tag: sliver-openvswitch-2.0.90-1~32^2~19 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=6878fada586a8ed5f45a50f9c8834dcf06bdc1f5;p=sliver-openvswitch.git ovs-thread: New function ovsthread_id_self(). I foresee a need for possibly large numbers of instances of "struct seq" (which is introduced in an upcoming patch). Each struct seq needs some per-thread data. POSIX has pthread_key_t for this, but the number of keys can be fairly limited, to as few as 128. It is reasonable to work around this by using a hash table indexed on the current thread. That only works if one can get a thread identifier that is hashable (pthread_t is not). This patch introduces a hashable thread identifier. Signed-off-by: Ben Pfaff --- diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index d0ec9ec6c..055d66ae3 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -169,18 +169,49 @@ ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_) ovs_abort(error, "pthread_cond_wait failed"); } } + +DEFINE_EXTERN_PER_THREAD_DATA(ovsthread_id, 0); + +struct ovsthread_aux { + void *(*start)(void *); + void *arg; +}; + +static void * +ovsthread_wrapper(void *aux_) +{ + static atomic_uint next_id = ATOMIC_VAR_INIT(1); + + struct ovsthread_aux *auxp = aux_; + struct ovsthread_aux aux; + unsigned int id; + + atomic_add(&next_id, 1, &id); + *ovsthread_id_get() = id; + + aux = *auxp; + free(auxp); + + return aux.start(aux.arg); +} void xpthread_create(pthread_t *threadp, pthread_attr_t *attr, void *(*start)(void *), void *arg) { + struct ovsthread_aux *aux; pthread_t thread; int error; forbid_forking("multiple threads exist"); multithreaded = true; - error = pthread_create(threadp ? threadp : &thread, attr, start, arg); + aux = xmalloc(sizeof *aux); + aux->start = start; + aux->arg = arg; + + error = pthread_create(threadp ? threadp : &thread, attr, + ovsthread_wrapper, aux); if (error) { ovs_abort(error, "pthread_create failed"); } diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index abe479ae6..e644832b2 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -501,6 +501,23 @@ ovsthread_once_start(struct ovsthread_once *once) ((ONCE)->done ? false : ({ OVS_MACRO_LOCK((&ONCE->mutex)); true; })) #endif +/* Thread ID. + * + * pthread_t isn't so nice for some purposes. Its size and representation are + * implementation dependent, which means that there is no way to hash it. + * This thread ID avoids the problem. + */ + +DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); + +/* Returns a per-thread identifier unique within the lifetime of the + * process. */ +static inline unsigned int +ovsthread_id_self(void) +{ + return *ovsthread_id_get(); +} + void assert_single_threaded_at(const char *where); #define assert_single_threaded() assert_single_threaded_at(SOURCE_LOCATOR)