[ovs-dev] [PATCHv16 1/2] ovs-thread: Add pthread spin lock support.

Ilya Maximets i.maximets at samsung.com
Mon Jul 15 14:28:44 UTC 2019


On 13.07.2019 2:50, William Tu wrote:
> The patch adds the basic spin lock functions:
> ovs_spin_{lock, try_lock, unlock, init, destroy}.
> OSX does not support pthread spin lock, so make it
> linux only.

IIUC, pthread spinlock requires some specific glibc verions (>= 2.2)
so it could be not supported even on Linux. Instead of checking
_POSIX_C_SOURCE version, I think it's better to just check for
pthread_spin_lock function in configure script with AC_CHECK_FUNC and
check for the resulted macro.
Additionally we could check for this macro while checking AF_XDP support
to not enable it if we have no spinlocks.

What do you think?

Best regards, Ilya Maximets.

> 
> Signed-off-by: William Tu <u9012063 at gmail.com>
> ---
>  include/openvswitch/thread.h | 22 ++++++++++++++++++++++
>  lib/ovs-thread.c             | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 53 insertions(+)
> 
> diff --git a/include/openvswitch/thread.h b/include/openvswitch/thread.h
> index 2987db37c9dc..14cc9ad73900 100644
> --- a/include/openvswitch/thread.h
> +++ b/include/openvswitch/thread.h
> @@ -33,6 +33,13 @@ struct OVS_LOCKABLE ovs_mutex {
>      const char *where;          /* NULL if and only if uninitialized. */
>  };
>  
> +#ifdef __linux__
> +struct OVS_LOCKABLE ovs_spin {
> +    pthread_spinlock_t lock;
> +    const char *where;          /* NULL if and only if uninitialized. */
> +};
> +#endif
> +
>  /* "struct ovs_mutex" initializer. */
>  #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
>  #define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, \
> @@ -70,6 +77,21 @@ int ovs_mutex_trylock_at(const struct ovs_mutex *mutex, const char *where)
>  
>  void ovs_mutex_cond_wait(pthread_cond_t *, const struct ovs_mutex *mutex)
>      OVS_REQUIRES(mutex);
> +
> +#ifdef __linux__
> +void ovs_spin_init(const struct ovs_spin *);
> +void ovs_spin_destroy(const struct ovs_spin *);
> +void ovs_spin_unlock(const struct ovs_spin *spin) OVS_RELEASES(spin);
> +void ovs_spin_lock_at(const struct ovs_spin *spin, const char *where)
> +    OVS_ACQUIRES(spin);
> +#define ovs_spin_lock(spin) \
> +        ovs_spin_lock_at(spin, OVS_SOURCE_LOCATOR)
> +
> +int ovs_spin_trylock_at(const struct ovs_spin *spin, const char *where)
> +    OVS_TRY_LOCK(0, spin);
> +#define ovs_spin_trylock(spin) \
> +        ovs_spin_trylock_at(spin, OVS_SOURCE_LOCATOR)
> +#endif
>  
>  /* Convenient once-only execution.
>   *
> diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c
> index 159d87e5b0ca..29a0b9e57acd 100644
> --- a/lib/ovs-thread.c
> +++ b/lib/ovs-thread.c
> @@ -75,6 +75,9 @@ static bool multithreaded;
>  LOCK_FUNCTION(mutex, lock);
>  LOCK_FUNCTION(rwlock, rdlock);
>  LOCK_FUNCTION(rwlock, wrlock);
> +#ifdef __linux__
> +LOCK_FUNCTION(spin, lock);
> +#endif
>  
>  #define TRY_LOCK_FUNCTION(TYPE, FUN) \
>      int \
> @@ -103,6 +106,9 @@ LOCK_FUNCTION(rwlock, wrlock);
>  TRY_LOCK_FUNCTION(mutex, trylock);
>  TRY_LOCK_FUNCTION(rwlock, tryrdlock);
>  TRY_LOCK_FUNCTION(rwlock, trywrlock);
> +#ifdef __linux__
> +TRY_LOCK_FUNCTION(spin, trylock);
> +#endif
>  
>  #define UNLOCK_FUNCTION(TYPE, FUN, WHERE) \
>      void \
> @@ -125,6 +131,10 @@ UNLOCK_FUNCTION(mutex, unlock, "<unlocked>");
>  UNLOCK_FUNCTION(mutex, destroy, NULL);
>  UNLOCK_FUNCTION(rwlock, unlock, "<unlocked>");
>  UNLOCK_FUNCTION(rwlock, destroy, NULL);
> +#ifdef __linux__
> +UNLOCK_FUNCTION(spin, unlock, "<unlocked>");
> +UNLOCK_FUNCTION(spin, destroy, NULL);
> +#endif
>  
>  #define XPTHREAD_FUNC1(FUNCTION, PARAM1)                \
>      void                                                \
> @@ -268,6 +278,27 @@ ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_)
>      }
>  }
>  
> +#ifdef __linux__
> +static void
> +ovs_spin_init__(const struct ovs_spin *l_, int pshared)
> +{
> +    struct ovs_spin *l = CONST_CAST(struct ovs_spin *, l_);
> +    int error;
> +
> +    l->where = "<unlocked>";
> +    error = pthread_spin_init(&l->lock, pshared);
> +    if (OVS_UNLIKELY(error)) {
> +        ovs_abort(error, "pthread_spin_failed");
> +    }
> +}
> +
> +void
> +ovs_spin_init(const struct ovs_spin *spin)
> +{
> +    ovs_spin_init__(spin, PTHREAD_PROCESS_PRIVATE);
> +}
> +#endif
> +
>  /* Initializes the 'barrier'.  'size' is the number of threads
>   * expected to hit the barrier. */
>  void
> 


More information about the dev mailing list