Browse Source

Merge pull request #6420 from julek-wolfssl/atomic-use-macro

Implement atomic operations interface
JacobBarthelmeh 1 year ago
parent
commit
235dc95b27
2 changed files with 102 additions and 9 deletions
  1. 61 1
      wolfcrypt/src/wc_port.c
  2. 41 8
      wolfssl/wolfcrypt/wc_port.h

+ 61 - 1
wolfcrypt/src/wc_port.c

@@ -1155,7 +1155,67 @@ int wc_strncasecmp(const char *s1, const char *s2, size_t n)
 }
 #endif /* USE_WOLF_STRNCASECMP */
 
-#if !defined(SINGLE_THREADED) && !defined(HAVE_C___ATOMIC)
+#ifdef WOLFSSL_ATOMIC_OPS
+
+#ifdef HAVE_C___ATOMIC
+/* Atomic ops using standard C lib */
+#ifdef __cplusplus
+/* C++ using direct calls to compiler built-in functions */
+void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i)
+{
+    *c = i;
+}
+
+int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i)
+{
+    return __atomic_fetch_add(c, i, __ATOMIC_RELAXED);
+}
+
+int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i)
+{
+    return __atomic_fetch_sub(c, i, __ATOMIC_RELAXED);
+}
+#else
+/* Default C Implementation */
+void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i)
+{
+    atomic_init(c, i);
+}
+
+int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i)
+{
+    return atomic_fetch_add_explicit(c, i, memory_order_relaxed);
+}
+
+int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i)
+{
+    return atomic_fetch_sub_explicit(c, i, memory_order_relaxed);
+}
+#endif /* __cplusplus */
+
+#elif defined(_MSC_VER)
+
+/* Default C Implementation */
+void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i)
+{
+    *c = i;
+}
+
+int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i)
+{
+    return (int)_InterlockedExchangeAdd(c, (long)i);
+}
+
+int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i)
+{
+    return (int)_InterlockedExchangeAdd(c, (long)-i);
+}
+
+#endif
+
+#endif /* WOLFSSL_ATOMIC_OPS */
+
+#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_ATOMIC_OPS)
 void wolfSSL_RefInit(wolfSSL_Ref* ref, int* err)
 {
     int ret = wc_InitMutex(&ref->mutex);

+ 41 - 8
wolfssl/wolfcrypt/wc_port.h

@@ -298,12 +298,46 @@
     typedef wolfSSL_Mutex wolfSSL_RwLock;
 #endif
 
+#ifndef WOLFSSL_NO_ATOMICS
+#ifdef HAVE_C___ATOMIC
+#ifdef __cplusplus
+#if defined(__GNUC__) && defined(__ATOMIC_RELAXED)
+    /* C++ using direct calls to compiler built-in functions */
+    typedef volatile int wolfSSL_Atomic_Int;
+    #define WOLFSSL_ATOMIC_OPS
+#endif
+#else
+    /* Default C Implementation */
+    #include <stdatomic.h>
+    typedef atomic_int wolfSSL_Atomic_Int;
+    #define WOLFSSL_ATOMIC_OPS
+#endif
+#elif defined(_MSC_VER)
+    /* Use MSVC compiler intrinsics for atomic ops */
+    #include <intrin.h>
+    typedef volatile long wolfSSL_Atomic_Int;
+    #define WOLFSSL_ATOMIC_OPS
+#endif
+#endif /* WOLFSSL_NO_ATOMICS */
+
+#ifdef WOLFSSL_ATOMIC_OPS
+    WOLFSSL_LOCAL void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i);
+    /* Fetch* functions return the value of the counter immediately preceding
+     * the effects of the function. */
+    WOLFSSL_LOCAL int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i);
+    WOLFSSL_LOCAL int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i);
+#endif
+
 /* Reference counting. */
 typedef struct wolfSSL_Ref {
-#if !defined(SINGLE_THREADED) && !defined(HAVE_C___ATOMIC)
+#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_ATOMIC_OPS)
     wolfSSL_Mutex mutex;
 #endif
+#ifdef WOLFSSL_ATOMIC_OPS
+    wolfSSL_Atomic_Int count;
+#else
     int count;
+#endif
 } wolfSSL_Ref;
 
 #ifdef SINGLE_THREADED
@@ -326,25 +360,24 @@ typedef struct wolfSSL_Ref {
         *(err) = 0;                          \
     } while(0)
 
-#elif defined(HAVE_C___ATOMIC)
+#elif defined(WOLFSSL_ATOMIC_OPS)
 
 #define wolfSSL_RefInit(ref, err)            \
     do {                                     \
-        (ref)->count = 1;                    \
+        wolfSSL_Atomic_Int_Init(&(ref)->count, 1); \
         *(err) = 0;                          \
     } while(0)
 #define wolfSSL_RefFree(ref)
 #define wolfSSL_RefInc(ref, err)             \
     do {                                     \
-        __atomic_fetch_add(&(ref)->count, 1, \
-            __ATOMIC_RELAXED);               \
+        (void)wolfSSL_Atomic_Int_FetchAdd(&(ref)->count, 1); \
         *(err) = 0;                          \
     } while(0)
 #define wolfSSL_RefDec(ref, isZero, err)     \
     do {                                     \
-        __atomic_fetch_sub(&(ref)->count, 1, \
-            __ATOMIC_RELAXED);               \
-        *(isZero) = ((ref)->count == 0);     \
+        int __prev = wolfSSL_Atomic_Int_FetchSub(&(ref)->count, 1); \
+        /* __prev holds the value of count before subtracting 1 */ \
+        *(isZero) = (__prev == 1);     \
         *(err) = 0;                          \
     } while(0)