Added wrapper for POSIX spin locks
authorTobias Brunner <tobias@strongswan.org>
Wed, 4 Jul 2012 07:07:20 +0000 (09:07 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 4 Jul 2012 08:13:49 +0000 (10:13 +0200)
src/libstrongswan/Makefile.am
src/libstrongswan/threading/spinlock.c [new file with mode: 0644]
src/libstrongswan/threading/spinlock.h [new file with mode: 0644]

index 9952603..bbc169c 100644 (file)
@@ -66,6 +66,7 @@ threading/thread.h threading/thread.c \
 threading/thread_value.h threading/thread_value.c \
 threading/mutex.h threading/mutex.c threading/condvar.h  \
 threading/semaphore.h threading/semaphore.c \
+threading/spinlock.h threading/spinlock.c \
 threading/rwlock.h threading/rwlock.c \
 threading/lock_profiler.h \
 utils.h utils.c \
diff --git a/src/libstrongswan/threading/spinlock.c b/src/libstrongswan/threading/spinlock.c
new file mode 100644 (file)
index 0000000..14ac49e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <unistd.h> /* for _POSIX_SPIN_LOCKS */
+#include <pthread.h>
+
+#include <library.h>
+#include <debug.h>
+
+#include "spinlock.h"
+#include "mutex.h"
+#include "lock_profiler.h"
+
+typedef struct private_spinlock_t private_spinlock_t;
+
+/**
+ * private data
+ */
+struct private_spinlock_t {
+
+       /**
+        * public functions
+        */
+       spinlock_t public;
+
+#ifdef _POSIX_SPIN_LOCKS
+
+       /**
+        * wrapped pthread spin lock
+        */
+       pthread_spinlock_t spinlock;
+
+       /**
+        * profiling info, if enabled (the mutex below does profile itself)
+        */
+       lock_profile_t profile;
+
+#else /* _POSIX_SPIN_LOCKS */
+
+       /**
+        * use a mutex if spin locks are not available
+        */
+       mutex_t *mutex;
+
+#endif /* _POSIX_SPIN_LOCKS */
+};
+
+METHOD(spinlock_t, lock, void,
+       private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+       int err;
+
+       profiler_start(&this->profile);
+       err = pthread_spin_lock(&this->spinlock);
+       if (err)
+       {
+               DBG1(DBG_LIB, "!!! SPIN LOCK LOCK ERROR: %s !!!", strerror(err));
+       }
+       profiler_end(&this->profile);
+#else
+       this->mutex->lock(this->mutex);
+#endif
+}
+
+METHOD(spinlock_t, unlock, void,
+       private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+       int err;
+
+       err = pthread_spin_unlock(&this->spinlock);
+       if (err)
+       {
+               DBG1(DBG_LIB, "!!! SPIN LOCK UNLOCK ERROR: %s !!!", strerror(err));
+       }
+#else
+       this->mutex->unlock(this->mutex);
+#endif
+}
+
+METHOD(spinlock_t, destroy, void,
+       private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+       profiler_cleanup(&this->profile);
+       pthread_spin_destroy(&this->spinlock);
+#else
+       this->mutex->destroy(this->mutex);
+#endif
+       free(this);
+}
+
+/*
+ * Described in header
+ */
+spinlock_t *spinlock_create()
+{
+       private_spinlock_t *this;
+
+       INIT(this,
+               .public = {
+                       .lock = _lock,
+                       .unlock = _unlock,
+                       .destroy = _destroy,
+               },
+       );
+
+#ifdef _POSIX_SPIN_LOCKS
+       pthread_spin_init(&this->spinlock, PTHREAD_PROCESS_PRIVATE);
+       profiler_init(&this->profile);
+#else
+       #warning Using mutexes as spin lock alternatives
+       this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+#endif
+
+       return &this->public;
+}
+
+
diff --git a/src/libstrongswan/threading/spinlock.h b/src/libstrongswan/threading/spinlock.h
new file mode 100644 (file)
index 0000000..883980c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup spinlock spinlock
+ * @{ @ingroup threading
+ */
+
+#ifndef THREADING_SPINLOCK_H_
+#define THREADING_SPINLOCK_H_
+
+typedef struct spinlock_t spinlock_t;
+
+/**
+ * Spin lock wrapper implements a lock with low overhead when the lock is held
+ * only for a short time (waiting wastes processor cycles, though).
+ *
+ * If native spin locks are not available regular mutexes are used as fallback.
+ */
+struct spinlock_t {
+
+       /**
+        * Acquire the lock.
+        */
+       void (*lock)(spinlock_t *this);
+
+       /**
+        * Release the lock.
+        */
+       void (*unlock)(spinlock_t *this);
+
+       /**
+        * Destroy the instance.
+        */
+       void (*destroy)(spinlock_t *this);
+};
+
+/**
+ * Create a spin lock instance.
+ *
+ * @return                     unlocked instance
+ */
+spinlock_t *spinlock_create();
+
+#endif /** THREADING_SPINLOCK_H_ @} */
+