Ver Fonte

SpinLock and tests

Kajetan Johannes Hammerle há 4 meses atrás
pai
commit
d6e7630e19
6 ficheiros alterados com 123 adições e 13 exclusões
  1. 3 2
      CMakeLists.txt
  2. 14 0
      include/core/SpinLock.h
  3. 22 0
      src/SpinLock.c
  4. 5 5
      test/Main.c
  5. 6 6
      test/Tests.h
  6. 73 0
      test/modules/SpinLockTests.c

+ 3 - 2
CMakeLists.txt

@@ -10,12 +10,12 @@ set(SRC
     "src/Plane.c"
     "src/Quaternion.c"
     "src/Random.c"
+    "src/SpinLock.c"
     "src/Utility.c"
     "src/Vector.c"
     #"src/BitArray.cpp"
     #"src/Box.cpp"
     #"src/Frustum.cpp"
-    #"src/SpinLock.cpp"
     #"src/View.cpp"
 )
 
@@ -27,6 +27,7 @@ set(SRC_TESTS
     "test/modules/PlaneTests.c"
     "test/modules/QuaternionTests.c"
     "test/modules/RandomTests.c"
+    "test/modules/SpinLockTests.c"
     "test/modules/UtilityTests.c"
     "test/modules/VectorTests.c"
     #"test/modules/BitArrayTests.cpp"
@@ -39,7 +40,6 @@ set(SRC_TESTS
     #"test/modules/MatrixStackTests.cpp"
     #"test/modules/RingBufferTests.cpp"
     #"test/modules/StackTests.cpp"
-    #"test/modules/ThreadTests.cpp"
     #"test/modules/ViewTests.cpp"
 )
 
@@ -103,6 +103,7 @@ target_sources(core PUBLIC
         ./include/core/Plane.h
         ./include/core/Quaternion.h
         ./include/core/Random.h
+        ./include/core/SpinLock.h
         ./include/core/Types.h
         ./include/core/Utility.h
 #        ./include/core/BitArray.hpp

+ 14 - 0
include/core/SpinLock.h

@@ -0,0 +1,14 @@
+#ifndef CORE_SPIN_LOCK_H
+#define CORE_SPIN_LOCK_H
+
+#include <stdatomic.h>
+
+typedef struct {
+    atomic_bool lock;
+} CoreSpinLock;
+
+void coreInitSpinLock(CoreSpinLock* l);
+void coreLockSpinLock(CoreSpinLock* l);
+void coreUnlockSpinLock(CoreSpinLock* l);
+
+#endif

+ 22 - 0
src/SpinLock.c

@@ -0,0 +1,22 @@
+#include "core/SpinLock.h"
+
+#include <threads.h>
+
+void coreInitSpinLock(CoreSpinLock* l) {
+    atomic_init(&l->lock, false);
+}
+
+void coreLockSpinLock(CoreSpinLock* l) {
+    while(true) {
+        bool expected = false;
+        if(atomic_compare_exchange_weak(&l->lock, &expected, true)) {
+            break;
+        }
+        struct timespec s = {0};
+        thrd_sleep(&s, nullptr);
+    }
+}
+
+void coreUnlockSpinLock(CoreSpinLock* l) {
+    atomic_store(&l->lock, false);
+}

+ 5 - 5
test/Main.c

@@ -33,23 +33,23 @@ int main(int argAmount, const char** args) {
 
     // coreTestBitArray();
     // coreTestBox();
-    coreTestBuffer(light);
     // coreTestComponents();
     // coreTestFrustum();
     // coreTestHashMap(light);
     // coreTestLinkedList(light);
     // coreTestList(light);
     // coreTestMatrixStack(light);
+    // coreTestRingBuffer();
+    // coreTestStack(light);
+    // coreTestView();
+    coreTestBuffer(light);
     coreTestMatrix();
     coreTestPlane();
     coreTestQuaternion();
     coreTestRandom(light);
-    // coreTestRingBuffer();
-    // coreTestStack(light);
-    // coreTestThread();
+    coreTestSpinLock();
     coreTestUtility(light);
     coreTestVector();
-    // coreTestView();
 
     coreLogLevel = CORE_LOG_WARNING;
     CORE_LOG_DEBUG("You won't see this!");

+ 6 - 6
test/Tests.h

@@ -3,6 +3,8 @@
 
 #include "Test.h"
 
+[[noreturn]] void coreTestInvalidAllocate(void);
+[[noreturn]] void coreTestInvalidReallocate(void);
 void coreTestBitArray(void);
 void coreTestBox(void);
 void coreTestBuffer(bool light);
@@ -12,19 +14,17 @@ void coreTestFrustum(void);
 void coreTestHashMap(bool light);
 void coreTestLinkedList(bool light);
 void coreTestList(bool light);
-void coreTestMatrixStack(bool light);
 void coreTestMatrix(void);
+void coreTestMatrixStack(bool light);
 void coreTestPlane(void);
+void coreTestPostCanary(void);
+void coreTestPreCanary(void);
 void coreTestQuaternion(void);
 void coreTestRandom(bool light);
 void coreTestRingBuffer(void);
+void coreTestSpinLock(void);
 void coreTestStack(bool light);
-void coreTestThread(void);
 void coreTestUtility(bool light);
-[[noreturn]] void coreTestInvalidAllocate(void);
-[[noreturn]] void coreTestInvalidReallocate(void);
-void coreTestPreCanary(void);
-void coreTestPostCanary(void);
 void coreTestVector(void);
 void coreTestView(void);
 

+ 73 - 0
test/modules/SpinLockTests.c

@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <threads.h>
+
+#include "../Tests.h"
+#include "core/SpinLock.h"
+#include "core/Utility.h"
+
+typedef struct {
+    mtx_t m;
+    int counter;
+} MutexCounter;
+
+static int incrementMutexCounter(void* p) {
+    MutexCounter* mcp = (MutexCounter*)p;
+    for(int i = 0; i < 10000; i++) {
+        mtx_lock(&mcp->m);
+        mcp->counter++;
+        mtx_unlock(&mcp->m);
+    }
+    return 0;
+}
+
+static void testMutex() {
+    i64 n = -coreNanos();
+
+    MutexCounter mc = {0};
+    mtx_init(&mc.m, mtx_plain);
+    thrd_t t[2];
+    thrd_create(t + 0, incrementMutexCounter, &mc);
+    thrd_create(t + 1, incrementMutexCounter, &mc);
+    thrd_join(t[0], nullptr);
+    thrd_join(t[1], nullptr);
+    CORE_TEST_INT(20000, mc.counter);
+
+    n += coreNanos();
+    printf("%ldns Mutex\n", n);
+}
+
+typedef struct {
+    CoreSpinLock s;
+    int counter;
+} SpinLockCounter;
+
+static int incrementSpinLockCounter(void* p) {
+    SpinLockCounter* mcp = (SpinLockCounter*)p;
+    for(int i = 0; i < 10000; i++) {
+        coreLockSpinLock(&mcp->s);
+        mcp->counter++;
+        coreUnlockSpinLock(&mcp->s);
+    }
+    return 0;
+}
+
+static void testSpinLock() {
+    i64 n = -coreNanos();
+
+    SpinLockCounter sc = {0};
+    coreInitSpinLock(&sc.s);
+    thrd_t t[2];
+    thrd_create(t + 0, incrementSpinLockCounter, &sc);
+    thrd_create(t + 1, incrementSpinLockCounter, &sc);
+    thrd_join(t[0], nullptr);
+    thrd_join(t[1], nullptr);
+    CORE_TEST_INT(20000, sc.counter);
+
+    n += coreNanos();
+    printf("%ldns SpinLock\n", n);
+}
+
+void coreTestSpinLock() {
+    testMutex();
+    testSpinLock();
+}