atomics: Move atomics/recounting support to separate files
[strongswan.git] / src / libstrongswan / utils / utils.c
index 0f12b58..8a52d04 100644 (file)
 #include <limits.h>
 #include <dirent.h>
 #include <time.h>
+#ifndef WIN32
+# include <signal.h>
+#endif
 
 #include <library.h>
 #include <utils/debug.h>
 #include <utils/chunk.h>
 #include <collections/enumerator.h>
-#include <threading/spinlock.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
 
 ENUM(status_names, SUCCESS, NEED_MORE,
        "SUCCESS",
@@ -56,6 +60,50 @@ ENUM(status_names, SUCCESS, NEED_MORE,
 /**
  * Described in header.
  */
+void* malloc_align(size_t size, u_int8_t align)
+{
+       u_int8_t pad;
+       void *ptr;
+
+       if (align == 0)
+       {
+               align = 1;
+       }
+       ptr = malloc(align + sizeof(pad) + size);
+       if (!ptr)
+       {
+               return NULL;
+       }
+       /* store padding length just before data, down to the allocation boundary
+        * to do some verification during free_align() */
+       pad = align - ((uintptr_t)ptr % align);
+       memset(ptr, pad, pad);
+       return ptr + pad;
+}
+
+/**
+ * Described in header.
+ */
+void free_align(void *ptr)
+{
+       u_int8_t pad, *pos;
+
+       pos = ptr - 1;
+       /* verify padding to check any corruption */
+       for (pad = *pos; (void*)pos >= ptr - pad; pos--)
+       {
+               if (*pos != pad)
+               {
+                       DBG1(DBG_LIB, "!!!! invalid free_align() !!!!");
+                       return;
+               }
+       }
+       free(ptr - pad);
+}
+
+/**
+ * Described in header.
+ */
 void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
 {
        int m, i;
@@ -107,6 +155,25 @@ void memwipe_noinline(void *ptr, size_t n)
 /**
  * Described in header.
  */
+bool memeq_const(const void *x, const void *y, size_t len)
+{
+       const u_char *a, *b;
+       u_int bad = 0;
+       size_t i;
+
+       a = (const u_char*)x;
+       b = (const u_char*)y;
+
+       for (i = 0; i < len; i++)
+       {
+               bad |= a[i] != b[i];
+       }
+       return !bad;
+}
+
+/**
+ * Described in header.
+ */
 void *memstr(const void *haystack, const char *needle, size_t n)
 {
        const u_char *pos = haystack;
@@ -222,6 +289,84 @@ char* strreplace(const char *str, const char *search, const char *replace)
        return res;
 }
 
+#ifdef WIN32
+
+/**
+ * Flag to indicate signaled wait_sigint()
+ */
+static bool sigint_signaled = FALSE;
+
+/**
+ * Condvar to wait in wait_sigint()
+ */
+static condvar_t *sigint_cond;
+
+/**
+ * Mutex to check signaling()
+ */
+static mutex_t *sigint_mutex;
+
+/**
+ * Control handler to catch ^C
+ */
+static BOOL WINAPI handler(DWORD dwCtrlType)
+{
+       switch (dwCtrlType)
+       {
+               case CTRL_C_EVENT:
+               case CTRL_BREAK_EVENT:
+               case CTRL_CLOSE_EVENT:
+                       sigint_mutex->lock(sigint_mutex);
+                       sigint_signaled = TRUE;
+                       sigint_cond->signal(sigint_cond);
+                       sigint_mutex->unlock(sigint_mutex);
+                       return TRUE;
+               default:
+                       return FALSE;
+       }
+}
+
+/**
+ * Windows variant
+ */
+void wait_sigint()
+{
+       SetConsoleCtrlHandler(handler, TRUE);
+
+       sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+       sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+       sigint_mutex->lock(sigint_mutex);
+       while (!sigint_signaled)
+       {
+               sigint_cond->wait(sigint_cond, sigint_mutex);
+       }
+       sigint_mutex->unlock(sigint_mutex);
+
+       sigint_mutex->destroy(sigint_mutex);
+       sigint_cond->destroy(sigint_cond);
+}
+
+#else /* !WIN32 */
+
+/**
+ * Unix variant
+ */
+void wait_sigint()
+{
+       sigset_t set;
+       int sig;
+
+       sigemptyset(&set);
+       sigaddset(&set, SIGINT);
+       sigaddset(&set, SIGTERM);
+
+       sigprocmask(SIG_BLOCK, &set, NULL);
+       sigwait(&set, &sig);
+}
+
+#endif
+
 /**
  * Described in header.
  */
@@ -578,78 +723,6 @@ void nop()
 {
 }
 
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-
-/**
- * Spinlock for ref_get/put
- */
-static spinlock_t *ref_lock;
-
-/**
- * Increase refcount
- */
-refcount_t ref_get(refcount_t *ref)
-{
-       refcount_t current;
-
-       ref_lock->lock(ref_lock);
-       current = ++(*ref);
-       ref_lock->unlock(ref_lock);
-
-       return current;
-}
-
-/**
- * Decrease refcount
- */
-bool ref_put(refcount_t *ref)
-{
-       bool more_refs;
-
-       ref_lock->lock(ref_lock);
-       more_refs = --(*ref) > 0;
-       ref_lock->unlock(ref_lock);
-       return !more_refs;
-}
-
-/**
- * Current refcount
- */
-refcount_t ref_cur(refcount_t *ref)
-{
-       refcount_t current;
-
-       ref_lock->lock(ref_lock);
-       current = *ref;
-       ref_lock->unlock(ref_lock);
-
-       return current;
-}
-
-/**
- * Spinlock for all compare and swap operations.
- */
-static spinlock_t *cas_lock;
-
-/**
- * Compare and swap if equal to old value
- */
-#define _cas_impl(name, type) \
-bool cas_##name(type *ptr, type oldval, type newval) \
-{ \
-       bool swapped; \
-       cas_lock->lock(cas_lock); \
-       if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
-       cas_lock->unlock(cas_lock); \
-       return swapped; \
-}
-
-_cas_impl(bool, bool)
-_cas_impl(ptr, void*)
-
-#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-
 #ifdef HAVE_FMEMOPEN_FALLBACK
 
 static int fmemread(chunk_t *cookie, char *buf, int size)
@@ -702,12 +775,7 @@ void utils_init()
 #ifdef WIN32
        windows_init();
 #endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-       ref_lock = spinlock_create();
-       cas_lock = spinlock_create();
-#endif
-
+       atomics_init();
        strerror_init();
 }
 
@@ -719,12 +787,7 @@ void utils_deinit()
 #ifdef WIN32
        windows_deinit();
 #endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-       ref_lock->destroy(ref_lock);
-       cas_lock->destroy(cas_lock);
-#endif
-
+       atomics_deinit();
        strerror_deinit();
 }