X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fovs-thread.h;h=2e9a937f585b9ca44182abd1c9e2ca64266441a6;hb=6b59b543;hp=5c1e8390372a4a35fb1b9b6d5c098712b908fe39;hpb=ea6f3f9a49ad9d671fa226dd33a14b7f287c6602;p=sliver-openvswitch.git diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index 5c1e83903..2e9a937f5 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -77,14 +77,30 @@ void xpthread_mutexattr_destroy(pthread_mutexattr_t *); void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); -/* Read-write lock. */ +/* Read-write lock. + * + * An ovs_rwlock does not support recursive readers, because POSIX allows + * taking the reader lock recursively to deadlock when a thread is waiting on + * the write-lock. (NetBSD does deadlock.) glibc rwlocks in their default + * configuration do not deadlock, but ovs_rwlock_init() initializes rwlocks as + * non-recursive (which will deadlock) for two reasons: + * + * - glibc only provides fairness to writers in this mode. + * + * - It's better to find bugs in the primary Open vSwitch target rather + * than exposing them only to porters. */ struct OVS_LOCKABLE ovs_rwlock { pthread_rwlock_t lock; const char *where; }; /* Initializer. */ +#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +#define OVS_RWLOCK_INITIALIZER \ + { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, NULL } +#else #define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, NULL } +#endif /* ovs_rwlock functions analogous to pthread_rwlock_*() functions. * @@ -95,6 +111,13 @@ void ovs_rwlock_init(const struct ovs_rwlock *); void ovs_rwlock_destroy(const struct ovs_rwlock *); void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock); +/* Wrappers for pthread_rwlockattr_*() that abort the process on any error. */ +void xpthread_rwlockattr_init(pthread_rwlockattr_t *); +void xpthread_rwlockattr_destroy(pthread_rwlockattr_t *); +#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +void xpthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int kind); +#endif + void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where) OVS_ACQ_WRLOCK(rwlock); #define ovs_rwlock_wrlock(rwlock) \ @@ -123,17 +146,6 @@ void xpthread_cond_destroy(pthread_cond_t *); void xpthread_cond_signal(pthread_cond_t *); void xpthread_cond_broadcast(pthread_cond_t *); -#ifdef __CHECKER__ -/* Replace these functions by the macros already defined in the - * annotations, because the macro definitions have correct semantics for the - * conditional acquisition that can't be captured in a function annotation. - * The difference in semantics from pthread_*() to xpthread_*() does not matter - * because sparse is not a compiler. */ -#define xpthread_mutex_trylock pthread_mutex_trylock -#define xpthread_rwlock_tryrdlock pthread_rwlock_tryrdlock -#define xpthread_rwlock_trywrlock pthread_rwlock_trywrlock -#endif - void xpthread_key_create(pthread_key_t *, void (*destructor)(void *)); void xpthread_key_delete(pthread_key_t); void xpthread_setspecific(pthread_key_t, const void *);