pthread_spin_* wrappers to be used for extremely small critical sections.
Signed-off-by: Jarno Rajahalme <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev