From 00eda33d64fe76acb928e450b30a1384bc4b404f Mon Sep 17 00:00:00 2001
From: Martin Karsten <mkarsten@uwaterloo.ca>
Date: Wed, 20 Jun 2018 11:00:34 -0400
Subject: [PATCH] - separate BargingSemaphore class into benaphore and proper
 barging semaphore elements

---
 src/generic/Benaphore.h    |  9 ++++++---
 src/runtime/BlockingSync.h | 36 +++++++++++++++---------------------
 2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/src/generic/Benaphore.h b/src/generic/Benaphore.h
index 47af2d7..6f2f0fd 100644
--- a/src/generic/Benaphore.h
+++ b/src/generic/Benaphore.h
@@ -34,9 +34,12 @@ public:
     sem.reset(0);
   }
 
-  bool P() {
-    if (__atomic_sub_fetch(&counter, 1, __ATOMIC_SEQ_CST) < 0) return sem.P();
-    return true;
+  template<typename... Args>
+  bool P(const Args&... a) {
+    if (__atomic_sub_fetch(&counter, 1, __ATOMIC_SEQ_CST) >= 0) return true;
+    if (sem.P(a...)) return true;
+    V();
+    return false;
   }
 
   void V() {
diff --git a/src/runtime/BlockingSync.h b/src/runtime/BlockingSync.h
index 4ef4041..8af41f0 100644
--- a/src/runtime/BlockingSync.h
+++ b/src/runtime/BlockingSync.h
@@ -17,6 +17,7 @@
 #ifndef _BlockingSync_h_
 #define _BlockingSync_h_ 1
 
+#include "generic/Benaphore.h"
 #include "runtime/StackContext.h"
 
 #include <list>
@@ -183,7 +184,7 @@ inline void TimerQueueGeneric<Lock>::checkExpiry(const Time& now) {
   lock.release();
   for (auto f : fireList) {                          // timeout lock released
     f.second->cancelSync(f.first);                   // can acquire event locks
-    f.first->resume();
+    f.first->resume<true>();
     Runtime::debugB( "Stack ", FmtHex(f.first), " timed out");
   }
 }
@@ -323,43 +324,36 @@ public:
 
 template<typename Lock, typename BQ = BlockingQueue<Lock>>
 class BargingSemaphore {
-  ssize_t counter;
   Lock lock;
-  ssize_t waiters;
+  ssize_t counter;
   BQ bq;
 
   bool internalP(bool wait, const Time& timeout = Time::zero()) {
-    if (__atomic_sub_fetch(&counter, 1, __ATOMIC_SEQ_CST) >= 0) return true;
-    lock.acquire();
-    waiters += 1;
-    if (waiters > 0) {
-      if (!bq.block(lock, wait, timeout)) {
-        internalV();
-        return false;
-      }
-    } else {
-      lock.release();
+    for (;;) {
+      lock.acquire();
+      if (counter >= 1) break;
+      if (!bq.block(lock, wait, timeout)) return false;
     }
+    counter -= 1;
+    lock.release();
     return true;
   }
 
   StackContext* internalV(bool resumeNow = true) {
-    if (__atomic_add_fetch(&counter, 1, __ATOMIC_SEQ_CST) > 0) return nullptr;
     ScopedLock<Lock> al(lock);
-    waiters -= 1;
+    counter += 1;
     return bq.unblock(resumeNow);
   }
 
 public:
-  explicit BargingSemaphore(ssize_t c = 0) : counter(c), waiters(0) {}
+  explicit BargingSemaphore(ssize_t c = 0) : counter(0) {}
   bool empty() { return bq.empty(); }
   bool open() { return getValue() >= 1; }
-  ssize_t getValue() { return __atomic_load_n(&counter, __ATOMIC_RELAXED); }
+  ssize_t getValue() { return counter; }
 
   void reset(ssize_t c = 0) {
     lock.acquire();
     counter = c;
-    waiters = 0;
     bq.clear(lock);
   }
 
@@ -416,7 +410,7 @@ public:
   }
 };
 
-template<typename Semaphore, bool OwnerLock = false, size_t SpinStart = 4, size_t SpinEnd = 1024>
+template<typename Semaphore, bool OwnerLock, size_t SpinStart, size_t SpinEnd>
 class BargingMutex {
   StackContext* owner;
   Semaphore sem;
@@ -487,9 +481,9 @@ template<typename Lock>
 #if TESTING_MUTEX_FIFO
 class Mutex : public FifoMutex<Lock> {};
 #elif TESTING_MUTEX_SPIN
-class Mutex : public BargingMutex<BargingSemaphore<Lock>> {};
+class Mutex : public BargingMutex<Benaphore<BargingSemaphore<Lock>>, false, 4, 1024> {};
 #else
-class Mutex : public BargingMutex<BargingSemaphore<Lock>, false, 1, 0> {};
+class Mutex : public BargingMutex<Benaphore<BargingSemaphore<Lock>>, false, 1, 0> {};
 #endif
 
 // simple blocking RW lock: release alternates; new readers block when writer waits -> no starvation
-- 
GitLab