pthread_spin_* wrappers to be used for extremely small critical sections.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 lib/ovs-thread.c |   56 ++++++++++++++++++++++++++++++++++++------------------
 lib/ovs-thread.h |   26 +++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c
index a20b2fd..5809721 100644
--- a/lib/ovs-thread.c
+++ b/lib/ovs-thread.c
@@ -44,44 +44,46 @@ static const char *must_not_fork;
 /* True if we created any threads beyond the main initial thread. */
 static bool multithreaded;
 
-#define LOCK_FUNCTION(TYPE, FUN) \
+#define LOCK_FUNCTION(TYPE, PFNAME, FUN)           \
     void \
     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
                             const char *where) \
         OVS_NO_THREAD_SAFETY_ANALYSIS \
     { \
         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
-        int error = pthread_##TYPE##_##FUN(&l->lock); \
+        int error = pthread_##PFNAME##_##FUN(&l->lock); \
         if (OVS_UNLIKELY(error)) { \
-            ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \
+            ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed"); \
         } \
         l->where = where; \
     }
-LOCK_FUNCTION(mutex, lock);
-LOCK_FUNCTION(rwlock, rdlock);
-LOCK_FUNCTION(rwlock, wrlock);
+LOCK_FUNCTION(mutex, mutex, lock);
+LOCK_FUNCTION(rwlock, rwlock, rdlock);
+LOCK_FUNCTION(rwlock, rwlock, wrlock);
+LOCK_FUNCTION(spinlock, spin, lock);
 
-#define TRY_LOCK_FUNCTION(TYPE, FUN) \
+#define TRY_LOCK_FUNCTION(TYPE, PFNAME, FUN)     \
     int \
     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
                             const char *where) \
         OVS_NO_THREAD_SAFETY_ANALYSIS \
     { \
         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
-        int error = pthread_##TYPE##_##FUN(&l->lock); \
+        int error = pthread_##PFNAME##_##FUN(&l->lock); \
         if (OVS_UNLIKELY(error) && error != EBUSY) { \
-            ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \
+            ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed");    \
         } \
         if (!error) { \
             l->where = where; \
         } \
         return error; \
     }
-TRY_LOCK_FUNCTION(mutex, trylock);
-TRY_LOCK_FUNCTION(rwlock, tryrdlock);
-TRY_LOCK_FUNCTION(rwlock, trywrlock);
+TRY_LOCK_FUNCTION(mutex, mutex, trylock);
+TRY_LOCK_FUNCTION(rwlock, rwlock, tryrdlock);
+TRY_LOCK_FUNCTION(rwlock, rwlock, trywrlock);
+TRY_LOCK_FUNCTION(spinlock, spin, trylock);
 
-#define UNLOCK_FUNCTION(TYPE, FUN) \
+#define UNLOCK_FUNCTION(TYPE, PFNAME, FUN)       \
     void \
     ovs_##TYPE##_##FUN(const struct ovs_##TYPE *l_) \
         OVS_NO_THREAD_SAFETY_ANALYSIS \
@@ -89,15 +91,17 @@ TRY_LOCK_FUNCTION(rwlock, trywrlock);
         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
         int error; \
         l->where = NULL; \
-        error = pthread_##TYPE##_##FUN(&l->lock); \
+        error = pthread_##PFNAME##_##FUN(&l->lock); \
         if (OVS_UNLIKELY(error)) { \
-            ovs_abort(error, "pthread_%s_%sfailed", #TYPE, #FUN); \
+            ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed"); \
         } \
     }
-UNLOCK_FUNCTION(mutex, unlock);
-UNLOCK_FUNCTION(mutex, destroy);
-UNLOCK_FUNCTION(rwlock, unlock);
-UNLOCK_FUNCTION(rwlock, destroy);
+UNLOCK_FUNCTION(mutex, mutex, unlock);
+UNLOCK_FUNCTION(mutex, mutex, destroy);
+UNLOCK_FUNCTION(rwlock, rwlock, unlock);
+UNLOCK_FUNCTION(rwlock, rwlock, destroy);
+UNLOCK_FUNCTION(spinlock, spin, unlock);
+UNLOCK_FUNCTION(spinlock, spin, destroy);
 
 #define XPTHREAD_FUNC1(FUNCTION, PARAM1)                \
     void                                                \
@@ -181,6 +185,20 @@ ovs_rwlock_init(const struct ovs_rwlock *l_)
     }
 }
 
+/* Initializes 'lock' as a process private spinlock. */
+void
+ovs_spinlock_init(const struct ovs_spinlock *l_)
+{
+    struct ovs_spinlock *l = CONST_CAST(struct ovs_spinlock *, l_);
+    int error;
+
+    l->where = NULL;
+    error = pthread_spin_init(&l->lock, PTHREAD_PROCESS_PRIVATE);
+    if (OVS_UNLIKELY(error)) {
+        ovs_abort(error, "pthread_spin_init failed");
+    }
+}
+
 void
 ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_)
 {
diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h
index f031894..1115577 100644
--- a/lib/ovs-thread.h
+++ b/lib/ovs-thread.h
@@ -69,6 +69,32 @@ 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);
 
+/* Spinlock */
+struct OVS_LOCKABLE ovs_spinlock {
+    pthread_spinlock_t lock;
+    const char *where;
+};
+
+/* "struct ovs_spinlock" initializer. */
+#define OVS_SPINLOCK_INITIALIZER { PTHREAD_SPINLOCK_INITIALIZER, NULL }
+
+/* ovs_spinlock functions analogous to pthread_spin_*() functions.
+ *
+ * Most of these functions abort the process with an error message on any
+ * error.  ovs_spinlock_trylock() is an exception: it passes through a 0 or
+ * EBUSY return value to the caller and aborts on any other error. */
+void ovs_spinlock_init(const struct ovs_spinlock *);
+void ovs_spinlock_destroy(const struct ovs_spinlock *);
+void ovs_spinlock_unlock(const struct ovs_spinlock *lock) OVS_RELEASES(lock);
+void ovs_spinlock_lock_at(const struct ovs_spinlock *lock, const char *where)
+    OVS_ACQUIRES(lock);
+#define ovs_spinlock_lock(lock) \
+        ovs_spinlock_lock_at(lock, SOURCE_LOCATOR)
+int ovs_spinlock_trylock_at(const struct ovs_spinlock *lock, const char *where)
+    OVS_TRY_LOCK(0, lock);
+#define ovs_spinlock_trylock(lock) \
+        ovs_spinlock_trylock_at(lock, SOURCE_LOCATOR)
+
 /* Read-write lock. */
 struct OVS_LOCKABLE ovs_rwlock {
     pthread_rwlock_t lock;
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to