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