vlmcd: Complete pending requests after "flushing"
[archipelago] / xseg / xtypes / xlock.h
index 54b6258..17f8a17 100644 (file)
@@ -1,6 +1,42 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
 #ifndef _XLOCK_H
 #define _XLOCK_H
 
+#include <sys/util.h>
+
 #define MFENCE() __sync_synchronize()
 #define BARRIER() __asm__ __volatile__ ("" ::: "memory")
 #define __pause() __asm__ __volatile__ ("pause\n");
 
 #define Noone ((unsigned long)-1)
 
+#define XLOCK_SANITY_CHECKS
+#define XLOCK_CONGESTION_NOTIFY
+
+#ifdef XLOCK_SANITY_CHECKS
+#define MAX_VALID_OWNER 65536 /* we are not gonna have more ports than that */
+#endif /* XLOCK_SANITY_CHECKS */
+
+#ifdef XLOCK_CONGESTION_NOTIFY
+#define MIN_SHIFT 20
+#define MAX_SHIFT ((sizeof(unsigned long) * 8) -1)
+#endif /* XLOCK_CONGESTION_NOTIFY */
+
 struct xlock {
-       long owner;
-} __attribute__ ((aligned (16))); /* support up to 128bit longs */
+       unsigned long owner;
+};
+//} __attribute__ ((aligned (16))); /* support up to 128bit longs */
 
 static inline unsigned long xlock_acquire(struct xlock *lock, unsigned long who)
 {
+       unsigned long owner;
+#ifdef XLOCK_CONGESTION_NOTIFY
+       unsigned long times = 1;
+       unsigned long shift = MIN_SHIFT;
+#endif /* XLOCK_CONGESTION_NOTIFY */
+
        for (;;) {
-               for (; *(volatile unsigned long *)(&lock->owner) != Noone; )
+               for (; (owner = *(volatile unsigned long *)(&lock->owner) != Noone);){
+#ifdef XLOCK_SANITY_CHECKS
+                       if (owner > MAX_VALID_OWNER){
+                               XSEGLOG("xlock %lx corrupted. Lock owner %lu",
+                                               (unsigned long) lock, owner);
+                               XSEGLOG("Resetting xlock %lx to Noone", 
+                                               (unsigned long) lock);
+                               lock->owner = Noone;
+                       }
+#endif /* XLOCK_SANITY_CHECKS */
+#ifdef XLOCK_CONGESTION_NOTIFY
+                       if (!(times & ((1<<shift) -1))){
+                               XSEGLOG("xlock %lx spinned for %llu times"
+                                       "\n\t who: %lu, owner: %lu",
+                                       (unsigned long) lock, times,
+                                       who, owner);
+                               if (shift < MAX_SHIFT)
+                                       shift++;
+//                             xseg_printtrace();
+                       }
+                       times++;
+#endif /* XLOCK_CONGESTION_NOTIFY */
                        __pause();
+               }
 
                if (__sync_bool_compare_and_swap(&lock->owner, Noone, who))
                        break;
        }
+#ifdef XLOCK_SANITY_CHECKS
+       if (lock->owner > MAX_VALID_OWNER){
+               XSEGLOG("xlock %lx locked with INVALID lock owner %lu",
+                               (unsigned long) lock, lock->owner);
+       }
+#endif /* XLOCK_SANITY_CHECKS */
 
        return who;
 }
 
+static inline unsigned long xlock_try_lock(struct xlock *lock, unsigned long who)
+{
+       unsigned long owner;
+       owner = *(volatile unsigned long *)(&lock->owner);
+       if (owner == Noone)
+               return __sync_bool_compare_and_swap(&lock->owner, Noone, who);
+       return 0;
+}
+
 static inline void xlock_release(struct xlock *lock)
 {
+       BARRIER();
+       /*
+#ifdef XLOCK_SANITY_CHECKS
+       if (lock->owner > MAX_VALID_OWNER){
+               XSEGLOG("xlock %lx releasing lock with INVALID lock owner %lu",
+                               (unsigned long) lock, lock->owner);
+       }
+#endif 
+       */
+       /* XLOCK_SANITY_CHECKS */
        lock->owner = Noone;
 }