Hello together,

attached is a patch to implement refcount handling
using atomic memory operations if supported by
the compiler (gcc >= 4.1) and platform.

It was really tricky to get the configure.in part right
as __sync_fetch_and_add() is defined on i386
but will result in a link error later on.

Call configure with:

./configure CFLAGS="-march=i586"

to enable the new code.

The code is untested as I don't have a strongswan 4.x setup yet.
It compiles cleanly though ;-)

Cheers,
Thomas
--- strongswan-4.2.9/configure.in	2008-11-16 23:34:47.000000000 +0100
+++ strongswan-4.2.9.no_threads/configure.in	2008-12-02 00:58:43.000000000 +0100
@@ -948,6 +960,27 @@ dnl ==============================
 dnl  build Makefiles
 dnl ==============================
 
+AC_MSG_CHECKING(for gcc atomic memory operations)
+AC_TRY_RUN(
+[
+  int main()
+  {
+    volatile int ref = 1;
+
+    __sync_fetch_and_add (&ref, 1);
+    __sync_sub_and_fetch (&ref, 1);
+
+    /* Make sure test fails on i386 as the operations above are not supported */
+    __sync_val_compare_and_swap(&ref, 1, 0);
+
+    return ref;
+  }
+],[
+AC_MSG_RESULT(yes)
+AC_DEFINE(HAVE_GCC_ATOMIC_OPERATIONS, 1, [Enable if your gcc supports atomic memory operations])
+], [AC_MSG_RESULT(no. Try running configure f.e. with CFLAGS="-march=i586" if you are on x86)])
+
+
 AC_OUTPUT(
 	Makefile
 	src/Makefile
--- strongswan-4.2.9/src/libstrongswan/utils.c	2008-12-01 23:42:13.000000000 +0100
+++ strongswan-4.2.9.no_threads/src/libstrongswan/utils.c	2008-12-02 00:21:14.000000000 +0100
@@ -20,7 +20,6 @@
 
 #include <sys/stat.h>
 #include <string.h>
-#include <pthread.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <dirent.h>
@@ -29,6 +28,10 @@
 #include <enum.h>
 #include <debug.h>
 
+#ifndef HAVE_GCC_ATOMIC_OPERATIONS
+  #include <pthread.h>
+#endif
+
 ENUM(status_names, SUCCESS, DESTROY_ME,
 	"SUCCESS",
 	"FAILED",
@@ -130,6 +133,12 @@ void nop()
 {
 }
 
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+/**
+ * We use fast atomic memory operations if supported
+ * by the compiler (gcc > 4.1) and platform.
+ */
+#else
 /**
  * We use a single mutex for all refcount variables. This
  * is not optimal for performance, but the critical section
@@ -137,34 +146,39 @@ void nop()
  * TODO: Consider to include a mutex in each refcount_t variable.
  */
 static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
 
 /**
- * Described in header.
- * 
- * TODO: May be implemented with atomic CPU instructions
- * instead of a mutex.
+ * Increase refcount
  */
 void ref_get(refcount_t *ref)
 {
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+	__sync_fetch_and_add(ref, 1);
+#else
 	pthread_mutex_lock(&ref_mutex);
 	(*ref)++;
 	pthread_mutex_unlock(&ref_mutex);
+#endif
 }
 
 /**
- * Described in header.
- * 
- * TODO: May be implemented with atomic CPU instructions
- * instead of a mutex.
+ * Decrease refcount
+ * @return true if refcount is zero, false otherwise
  */
 bool ref_put(refcount_t *ref)
 {
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+	refcount_t more_refs = __sync_sub_and_fetch(ref, 1);
+	return (more_refs == 0);
+#else
 	bool more_refs;
 	
 	pthread_mutex_lock(&ref_mutex);
 	more_refs = --(*ref);
 	pthread_mutex_unlock(&ref_mutex);
 	return !more_refs;
+#endif
 }
 
 /**
_______________________________________________
Users mailing list
Users@lists.strongswan.org
https://lists.strongswan.org/mailman/listinfo/users

Reply via email to